OSDN Git Service

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