OSDN Git Service

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