OSDN Git Service

d013b02b5adc67453fafd22137635c874ec4b23a
[hengbandforosx/hengbandosx.git] / src / main.c
1 /* File: main.c */
2
3 /*
4  * Copyright (c) 1997 Ben Harrison, and others
5  *
6  * This software may be copied and distributed for educational, research,
7  * and not for profit purposes provided that this copyright and statement
8  * are included in all such copies.
9  */
10
11 #include "angband.h"
12 #include "core.h"
13 #include "uid-checker.h"
14 #include "files.h"
15 #include "inet.h"
16 #include "init.h"
17 #include "scores.h"
18 #include "term.h"
19
20 /*
21  * Available graphic modes
22  */
23 #define GRAPHICS_NONE       0
24 #define GRAPHICS_ORIGINAL   1
25 #define GRAPHICS_ADAM_BOLT  2
26 #define GRAPHICS_HENGBAND   3
27
28 /*
29  * Some machines have a "main()" function in their "main-xxx.c" file,
30  * all the others use this file for their "main()" function.
31  */
32
33
34 #if !defined(WINDOWS)
35
36 /*
37  * A hook for "quit()".
38  *
39  * Close down, then fall back into "quit()".
40  */
41 static void quit_hook(concptr s)
42 {
43         int j;
44
45         /* Unused */
46         (void)s;
47
48         /* Scan windows */
49         for (j = 8 - 1; j >= 0; j--)
50         {
51                 /* Unused */
52                 if (!angband_term[j]) continue;
53
54                 /* Nuke it */
55                 term_nuke(angband_term[j]);
56         }
57 }
58
59
60 /*
61  * Set the stack size and overlay buffer (see main-286.c")
62  */
63 #ifdef PRIVATE_USER_PATH
64
65 /*
66  * Create an ".angband/" directory in the users home directory.
67  *
68  * ToDo: Add error handling.
69  * ToDo: Only create the directories when actually writing files.
70  */
71 static void create_user_dir(void)
72 {
73         char dirpath[1024];
74         char subdirpath[1024];
75
76         /* Get an absolute path from the filename */
77         path_parse(dirpath, 1024, PRIVATE_USER_PATH);
78
79         /* Create the ~/.angband/ directory */
80         mkdir(dirpath, 0700);
81
82         /* Build the path to the variant-specific sub-directory */
83         path_build(subdirpath, sizeof(subdirpath), dirpath, VERSION_NAME);
84
85         /* Create the directory */
86         mkdir(subdirpath, 0700);
87 }
88
89 #endif /* PRIVATE_USER_PATH */
90
91
92 /*
93  * Initialize and verify the file paths, and the score file.
94  *
95  * Use the ANGBAND_PATH environment var if possible, else use
96  * DEFAULT_PATH, and in either case, branch off appropriately.
97  *
98  * First, we'll look for the ANGBAND_PATH environment variable,
99  * and then look for the files in there.  If that doesn't work,
100  * we'll try the DEFAULT_PATH constant.  So be sure that one of
101  * these two things works...
102  *
103  * We must ensure that the path ends with "PATH_SEP" if needed,
104  * since the "init_file_paths()" function will simply append the
105  * relevant "sub-directory names" to the given path.
106  *
107  * Make sure that the path doesn't overflow the buffer.  We have
108  * to leave enough space for the path separator, directory, and
109  * filenames.
110  */
111 static void init_stuff(void)
112 {
113         char path[1024];
114
115         concptr tail;
116
117         /* Get the environment variable */
118         tail = getenv("ANGBAND_PATH");
119
120         /* Use the angband_path, or a default */
121         strncpy(path, tail ? tail : DEFAULT_PATH, 511);
122
123         /* Make sure it's terminated */
124         path[511] = '\0';
125
126         /* Hack -- Add a path separator (only if needed) */
127         if (!suffix(path, PATH_SEP)) strcat(path, PATH_SEP);
128
129         /* Initialize */
130         init_file_paths(path);
131 }
132
133
134
135 /*
136  * Handle a "-d<what>=<path>" option
137  *
138  * The "<what>" can be any string starting with the same letter as the
139  * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
140  *
141  * The "<path>" can be any legal path for the given system, and should
142  * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
143  */
144 static void change_path(concptr info)
145 {
146         concptr s;
147
148         /* Find equal sign */
149         s = my_strchr(info, '=');
150
151         /* Verify equal sign */
152         if (!s) quit_fmt("Try '-d<what>=<path>' not '-d%s'", info);
153
154         /* Analyze */
155         switch (tolower(info[0]))
156         {
157                 case 'a':
158                 {
159                         string_free(ANGBAND_DIR_APEX);
160                         ANGBAND_DIR_APEX = string_make(s+1);
161                         break;
162                 }
163
164                 case 'f':
165                 {
166                         string_free(ANGBAND_DIR_FILE);
167                         ANGBAND_DIR_FILE = string_make(s+1);
168                         break;
169                 }
170
171                 case 'h':
172                 {
173                         string_free(ANGBAND_DIR_HELP);
174                         ANGBAND_DIR_HELP = string_make(s+1);
175                         break;
176                 }
177
178                 case 'i':
179                 {
180                         string_free(ANGBAND_DIR_INFO);
181                         ANGBAND_DIR_INFO = string_make(s+1);
182                         break;
183                 }
184
185                 case 'u':
186                 {
187                         string_free(ANGBAND_DIR_USER);
188                         ANGBAND_DIR_USER = string_make(s+1);
189                         break;
190                 }
191
192                 case 'x':
193                 {
194                         string_free(ANGBAND_DIR_XTRA);
195                         ANGBAND_DIR_XTRA = string_make(s+1);
196                         break;
197                 }
198
199                 case 'b':
200                 {
201                         string_free(ANGBAND_DIR_BONE);
202                         ANGBAND_DIR_BONE = string_make(s+1);
203                         break;
204                 }
205
206                 case 'd':
207                 {
208                         string_free(ANGBAND_DIR_DATA);
209                         ANGBAND_DIR_DATA = string_make(s+1);
210                         break;
211                 }
212
213                 case 'e':
214                 {
215                         string_free(ANGBAND_DIR_EDIT);
216                         ANGBAND_DIR_EDIT = string_make(s+1);
217                         break;
218                 }
219
220                 case 's':
221                 {
222                         string_free(ANGBAND_DIR_SAVE);
223                         ANGBAND_DIR_SAVE = string_make(s+1);
224                         break;
225                 }
226
227                 case 'z':
228                 {
229                         string_free(ANGBAND_DIR_SCRIPT);
230                         ANGBAND_DIR_SCRIPT = string_make(s+1);
231                         break;
232                 }
233
234                 default:
235                 {
236                         quit_fmt("Bad semantics in '-d%s'", info);
237                 }
238         }
239 }
240
241 static void display_usage(void)
242 {
243         /* Dump usage information */
244         puts("Usage: angband [options] [-- subopts]");
245         puts("  -n       Start a new character");
246         puts("  -f       Request fiddle mode");
247         puts("  -w       Request wizard mode");
248         puts("  -b       Request BGM mode");
249         puts("  -v       Request sound mode");
250         puts("  -g       Request graphics mode");
251         puts("  -o       Request original keyset");
252         puts("  -r       Request rogue-like keyset");
253         puts("  -M       Request monochrome mode");
254         puts("  -s<num>  Show <num> high scores");
255         puts("  -u<who>  Use your <who> savefile");
256         puts("  -m<sys>  Force 'main-<sys>.c' usage");
257         puts("  -d<def>  Define a 'lib' dir sub-path");
258         puts("");
259
260 #ifdef USE_X11
261         puts("  -mx11    To use X11");
262         puts("  --       Sub options");
263         puts("  -- -d    Set display name");
264         puts("  -- -o    Request old 8x8 tile graphics");
265         puts("  -- -a    Request Adam Bolt 16x16 tile graphics");
266         puts("  -- -b    Request Bigtile graphics mode");
267         puts("  -- -s    Turn off smoothscaling graphics");
268         puts("  -- -n#   Number of terms to use");
269         puts("");
270 #endif /* USE_X11 */
271
272 #ifdef USE_GCU
273         puts("  -mgcu    To use GCU (GNU Curses)");
274 #endif /* USE_GCU */
275
276 #ifdef USE_CAP
277         puts("  -mcap    To use CAP (\"Termcap\" calls)");
278 #endif /* USE_CAP */
279
280         /* Actually abort the process */
281         quit(NULL);
282 }
283
284
285 /*
286  * Simple "main" function for multiple platforms.
287  *
288  * Note the special "--" option which terminates the processing of
289  * standard options.  All non-standard options (if any) are passed
290  * directly to the "init_xxx()" function.
291  */
292 int main(int argc, char *argv[])
293 {
294         int i;
295
296         bool done = FALSE;
297         bool new_game = FALSE;
298         int show_score = 0;
299         concptr mstr = NULL;
300         bool args = TRUE;
301
302         /* Save the "program name" XXX XXX XXX */
303         argv0 = argv[0];
304
305 #ifdef SET_UID
306
307         /* Default permissions on files */
308         (void)umask(022);
309
310 #endif
311
312
313         /* Get the file paths */
314         init_stuff();
315
316
317 #ifdef SET_UID
318
319         /* Get the user id (?) */
320         p_ptr->player_uid = getuid();
321
322 #ifdef VMS
323         /* Mega-Hack -- Factor group id */
324         p_ptr->player_uid += (getgid() * 1000);
325 #endif
326
327 # ifdef SAFE_SETUID
328
329 #  ifdef _POSIX_SAVED_IDS
330
331         /* Save some info for later */
332         p_ptr->player_euid = geteuid();
333         p_ptr->player_egid = getegid();
334
335 #  endif
336
337 # endif
338
339 #endif
340
341
342         /* Drop permissions */
343         safe_setuid_drop();
344
345
346 #ifdef SET_UID
347
348         /* Acquire the "user name" as a default player name */
349         user_name(p_ptr->name, p_ptr->player_uid);
350
351 #ifdef PRIVATE_USER_PATH
352
353         /* Create a directory for the users files. */
354         create_user_dir();
355
356 #endif /* PRIVATE_USER_PATH */
357
358 #endif /* SET_UID */
359
360
361         /* Process the command line arguments */
362         for (i = 1; args && (i < argc); i++)
363         {
364                 /* Require proper options */
365                 if (argv[i][0] != '-')
366                 {
367                         display_usage();
368                         continue;
369                 }
370
371                 /* Analyze option */
372                 bool is_usage_needed = FALSE;
373                 switch (argv[i][1])
374                 {
375                         case 'N':
376                         case 'n':
377                         {
378                                 new_game = TRUE;
379                                 break;
380                         }
381                         case 'F':
382                         case 'f':
383                         {
384                                 arg_fiddle = TRUE;
385                                 break;
386                         }
387                         case 'W':
388                         case 'w':
389                         {
390                                 arg_wizard = TRUE;
391                                 break;
392                         }
393                         case 'B':
394                         case 'b':
395                         {
396                                 arg_music = TRUE;
397                                 break;
398                         }
399                         case 'V':
400                         case 'v':
401                         {
402                                 arg_sound = TRUE;
403                                 break;
404                         }
405                         case 'G':
406                         case 'g':
407                         {
408                                 /* HACK - Graphics mode switches on the original tiles */
409                                 arg_graphics = GRAPHICS_ORIGINAL;
410                                 break;
411                         }
412                         case 'R':
413                         case 'r':
414                         {
415                                 arg_force_roguelike = TRUE;
416                                 break;
417                         }
418                         case 'O':
419                         case 'o':
420                         {
421                                 arg_force_original = TRUE;
422                                 break;
423                         }
424                         case 'S':
425                         case 's':
426                         {
427                                 show_score = atoi(&argv[i][2]);
428                                 if (show_score <= 0) show_score = 10;
429                                 break;
430                         }
431                         case 'u':
432                         case 'U':
433                         {
434                                 if (!argv[i][2])
435                                 {
436                                         is_usage_needed = TRUE;
437                                         break;
438                                 }
439
440                                 strcpy(p_ptr->name, &argv[i][2]);
441                                 break;
442                         }
443                         case 'm':
444                         {
445                                 if (!argv[i][2])
446                                 {
447                                         is_usage_needed = TRUE;
448                                         break;
449                                 }
450
451                                 mstr = &argv[i][2];
452                                 break;
453                         }
454                         case 'M':
455                         {
456                                 arg_monochrome = TRUE;
457                                 break;
458                         }
459                         case 'd':
460                         case 'D':
461                         {
462                                 change_path(&argv[i][2]);
463                                 break;
464                         }
465 #ifdef CHUUKEI
466                         case 'p':
467                         case 'P':
468                         {
469                                 if (!argv[i][2])
470                                 {
471                                         is_usage_needed = TRUE;
472                                         break;
473                                 }
474
475                                 chuukei_server = TRUE;
476                                 if (connect_chuukei_server(&argv[i][2]) < 0) chuukei_server = FALSE;
477                                 break;
478                         }
479
480                         case 'c':
481                         case 'C':
482                         {
483                                 if (!argv[i][2])
484                                 {
485                                         is_usage_needed = TRUE;
486                                         break;
487                                 }
488
489                                 chuukei_client = TRUE;
490                                 connect_chuukei_server(&argv[i][2]);
491                                 break;
492                         }
493 #endif
494                         case 'x':
495                         {
496                                 if (!argv[i][2])
497                                 {
498                                         is_usage_needed = TRUE;
499                                         break;
500                                 }
501
502                                 prepare_browse_movie(&argv[i][2]);
503                                 break;
504                         }
505                         case '-':
506                         {
507                                 argv[i] = argv[0];
508                                 argc = argc - i;
509                                 argv = argv + i;
510                                 args = FALSE;
511                                 break;
512                         }
513                         default:
514                         {
515                                 is_usage_needed = TRUE;
516                                 break;
517                         }
518                 }
519
520                 if (!is_usage_needed) continue;
521
522                 display_usage();
523         }
524
525         /* Hack -- Forget standard args */
526         if (args)
527         {
528                 argc = 1;
529                 argv[1] = NULL;
530         }
531
532
533         /* Process the player name */
534         process_player_name(p_ptr,TRUE);
535
536
537
538         /* Install "quit" hook */
539         quit_aux = quit_hook;
540
541
542
543 #ifdef USE_XAW
544         /* Attempt to use the "main-xaw.c" support */
545         if (!done && (!mstr || (streq(mstr, "xaw"))))
546         {
547                 extern errr init_xaw(int, char**);
548                 if (0 == init_xaw(argc, argv))
549                 {
550                         ANGBAND_SYS = "xaw";
551                         done = TRUE;
552                 }
553         }
554 #endif
555
556 #ifdef USE_X11
557         /* Attempt to use the "main-x11.c" support */
558         if (!done && (!mstr || (streq(mstr, "x11"))))
559         {
560                 extern errr init_x11(int, char**);
561                 if (0 == init_x11(argc, argv))
562                 {
563                         ANGBAND_SYS = "x11";
564                         done = TRUE;
565                 }
566         }
567 #endif
568
569 #ifdef USE_GCU
570         /* Attempt to use the "main-gcu.c" support */
571         if (!done && (!mstr || (streq(mstr, "gcu"))))
572         {
573                 extern errr init_gcu(int, char**);
574                 if (0 == init_gcu(argc, argv))
575                 {
576                         ANGBAND_SYS = "gcu";
577                         done = TRUE;
578                 }
579         }
580 #endif
581
582 #ifdef USE_CAP
583         /* Attempt to use the "main-cap.c" support */
584         if (!done && (!mstr || (streq(mstr, "cap"))))
585         {
586                 extern errr init_cap(int, char**);
587                 if (0 == init_cap(argc, argv))
588                 {
589                         ANGBAND_SYS = "cap";
590                         done = TRUE;
591                 }
592         }
593 #endif
594
595         /* Make sure we have a display! */
596         if (!done) quit("Unable to prepare any 'display module'!");
597
598
599         /* Hack -- If requested, display scores and quit */
600         if (show_score > 0) display_scores(0, show_score);
601
602
603         /* Catch nasty signals */
604         signals_init();
605
606         /* Initialize */
607         init_angband(p_ptr);
608
609         /* Wait for response */
610         pause_line(23);
611
612         /* Play the game */
613         play_game(p_ptr, new_game);
614
615         /* Quit */
616         quit(NULL);
617
618         /* Exit */
619         return (0);
620 }
621
622 #endif