OSDN Git Service

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