OSDN Git Service

[cleanup] clang-formatによる整形
[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/files-util.h"
15 #include "io/inet.h"
16 #include "io/record-play-movie.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_(LIB|VAR)_PATH, and in either case, branch off
102  * appropriately.
103  *
104  * First, we'll look for the ANGBAND_PATH environment variable,
105  * and then look for the files in there.  If that doesn't work,
106  * we'll try the DEFAULT_(LIB|VAR)_PATH constants.  So be sure
107  * that one of these two things works...
108  *
109  * We must ensure that the path ends with "PATH_SEP" if needed,
110  * since the "init_file_paths()" function will simply append the
111  * relevant "sub-directory names" to the given path.
112  *
113  * Make sure that the path doesn't overflow the buffer.  We have
114  * to leave enough space for the path separator, directory, and
115  * filenames.
116  */
117 static void init_stuff(void)
118 {
119     char libpath[1024], varpath[1024];
120
121     concptr tail;
122
123     /* Get the environment variable */
124     tail = getenv("ANGBAND_PATH");
125
126     /* Use the angband_path, or a default */
127     strncpy(libpath, tail ? tail : DEFAULT_LIB_PATH, 511);
128     strncpy(varpath, tail ? tail : DEFAULT_VAR_PATH, 511);
129
130     /* Make sure they're terminated */
131     libpath[511] = '\0';
132     varpath[511] = '\0';
133
134     /* Hack -- Add a path separator (only if needed) */
135     if (!suffix(libpath, PATH_SEP))
136         strcat(libpath, PATH_SEP);
137     if (!suffix(varpath, PATH_SEP))
138         strcat(varpath, PATH_SEP);
139
140     /* Initialize */
141     init_file_paths(libpath, varpath);
142 }
143
144 /*
145  * Handle a "-d<what>=<path>" option
146  *
147  * The "<what>" can be any string starting with the same letter as the
148  * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
149  *
150  * The "<path>" can be any legal path for the given system, and should
151  * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
152  */
153 static void change_path(concptr info)
154 {
155     concptr s;
156
157     /* Find equal sign */
158     s = angband_strchr(info, '=');
159
160     /* Verify equal sign */
161     if (!s)
162         quit_fmt("Try '-d<what>=<path>' not '-d%s'", info);
163
164     /* Analyze */
165     switch (tolower(info[0])) {
166     case 'a': {
167         string_free(ANGBAND_DIR_APEX);
168         ANGBAND_DIR_APEX = string_make(s + 1);
169         break;
170     }
171
172     case 'f': {
173         string_free(ANGBAND_DIR_FILE);
174         ANGBAND_DIR_FILE = string_make(s + 1);
175         break;
176     }
177
178     case 'h': {
179         string_free(ANGBAND_DIR_HELP);
180         ANGBAND_DIR_HELP = string_make(s + 1);
181         break;
182     }
183
184     case 'i': {
185         string_free(ANGBAND_DIR_INFO);
186         ANGBAND_DIR_INFO = string_make(s + 1);
187         break;
188     }
189
190     case 'u': {
191         string_free(ANGBAND_DIR_USER);
192         ANGBAND_DIR_USER = string_make(s + 1);
193         break;
194     }
195
196     case 'x': {
197         string_free(ANGBAND_DIR_XTRA);
198         ANGBAND_DIR_XTRA = string_make(s + 1);
199         break;
200     }
201
202     case 'b': {
203         string_free(ANGBAND_DIR_BONE);
204         ANGBAND_DIR_BONE = string_make(s + 1);
205         break;
206     }
207
208     case 'd': {
209         string_free(ANGBAND_DIR_DATA);
210         ANGBAND_DIR_DATA = string_make(s + 1);
211         break;
212     }
213
214     case 'e': {
215         string_free(ANGBAND_DIR_EDIT);
216         ANGBAND_DIR_EDIT = string_make(s + 1);
217         break;
218     }
219
220     case 's': {
221         string_free(ANGBAND_DIR_SAVE);
222         ANGBAND_DIR_SAVE = string_make(s + 1);
223         break;
224     }
225
226     case 'z': {
227         string_free(ANGBAND_DIR_SCRIPT);
228         ANGBAND_DIR_SCRIPT = string_make(s + 1);
229         break;
230     }
231
232     default: {
233         quit_fmt("Bad semantics in '-d%s'", info);
234     }
235     }
236 }
237
238 static void display_usage(void)
239 {
240     /* Dump usage information */
241     puts("Usage: angband [options] [-- subopts]");
242     puts("  -n       Start a new character");
243     puts("  -f       Request fiddle mode");
244     puts("  -w       Request wizard mode");
245     puts("  -b       Request BGM mode");
246     puts("  -v       Request sound mode");
247     puts("  -g       Request graphics mode");
248     puts("  -o       Request original keyset");
249     puts("  -r       Request rogue-like keyset");
250     puts("  -M       Request monochrome mode");
251     puts("  -s<num>  Show <num> high scores");
252     puts("  -u<who>  Use your <who> savefile");
253     puts("  -m<sys>  Force 'main-<sys>.c' usage");
254     puts("  -d<def>  Define a 'lib' dir sub-path");
255     puts("");
256
257 #ifdef USE_X11
258     puts("  -mx11    To use X11");
259     puts("  --       Sub options");
260     puts("  -- -d    Set display name");
261     puts("  -- -o    Request old 8x8 tile graphics");
262     puts("  -- -a    Request Adam Bolt 16x16 tile graphics");
263     puts("  -- -b    Request Bigtile graphics mode");
264     puts("  -- -s    Turn off smoothscaling graphics");
265     puts("  -- -n#   Number of terms to use");
266     puts("");
267 #endif /* USE_X11 */
268
269 #ifdef USE_GCU
270     puts("  -mgcu    To use GCU (GNU Curses)");
271 #endif /* USE_GCU */
272
273 #ifdef USE_CAP
274     puts("  -mcap    To use CAP (\"Termcap\" calls)");
275 #endif /* USE_CAP */
276
277     /* Actually abort the process */
278     quit(NULL);
279 }
280
281 /*
282  * Simple "main" function for multiple platforms.
283  *
284  * Note the special "--" option which terminates the processing of
285  * standard options.  All non-standard options (if any) are passed
286  * directly to the "init_xxx()" function.
287  */
288 int main(int argc, char *argv[])
289 {
290     int i;
291
292     bool done = FALSE;
293     bool new_game = FALSE;
294     int show_score = 0;
295     concptr mstr = NULL;
296     bool args = TRUE;
297
298     /* Save the "program name" XXX XXX XXX */
299     argv0 = argv[0];
300
301 #ifdef SET_UID
302
303     /* Default permissions on files */
304     (void)umask(022);
305
306 #endif
307
308     /* Get the file paths */
309     init_stuff();
310
311 #ifdef SET_UID
312
313     /* Get the user id (?) */
314     p_ptr->player_uid = getuid();
315
316 #ifdef VMS
317     /* Mega-Hack -- Factor group id */
318     p_ptr->player_uid += (getgid() * 1000);
319 #endif
320
321 #ifdef SAFE_SETUID
322
323 #ifdef _POSIX_SAVED_IDS
324
325     /* Save some info for later */
326     p_ptr->player_euid = geteuid();
327     p_ptr->player_egid = getegid();
328
329 #endif
330
331 #endif
332
333 #endif
334
335     /* Drop permissions */
336     safe_setuid_drop();
337
338 #ifdef SET_UID
339
340     /* Acquire the "user name" as a default player name */
341     user_name(p_ptr->name, p_ptr->player_uid);
342
343 #ifdef PRIVATE_USER_PATH
344
345     /* Create a directory for the users files. */
346     create_user_dir();
347
348 #endif /* PRIVATE_USER_PATH */
349
350 #endif /* SET_UID */
351
352     /* Process the command line arguments */
353     bool browsing_movie = FALSE;
354     for (i = 1; args && (i < argc); i++) {
355         /* Require proper options */
356         if (argv[i][0] != '-') {
357             display_usage();
358             continue;
359         }
360
361         /* Analyze option */
362         bool is_usage_needed = FALSE;
363         switch (argv[i][1]) {
364         case 'N':
365         case 'n': {
366             new_game = TRUE;
367             break;
368         }
369         case 'F':
370         case 'f': {
371             arg_fiddle = TRUE;
372             break;
373         }
374         case 'W':
375         case 'w': {
376             arg_wizard = TRUE;
377             break;
378         }
379         case 'B':
380         case 'b': {
381             arg_music = TRUE;
382             break;
383         }
384         case 'V':
385         case 'v': {
386             arg_sound = TRUE;
387             break;
388         }
389         case 'G':
390         case 'g': {
391             /* HACK - Graphics mode switches on the original tiles */
392             arg_graphics = GRAPHICS_ORIGINAL;
393             break;
394         }
395         case 'R':
396         case 'r': {
397             arg_force_roguelike = TRUE;
398             break;
399         }
400         case 'O':
401         case 'o': {
402             arg_force_original = TRUE;
403             break;
404         }
405         case 'S':
406         case 's': {
407             show_score = atoi(&argv[i][2]);
408             if (show_score <= 0)
409                 show_score = 10;
410             break;
411         }
412         case 'u':
413         case 'U': {
414             if (!argv[i][2]) {
415                 is_usage_needed = TRUE;
416                 break;
417             }
418
419             strcpy(p_ptr->name, &argv[i][2]);
420             break;
421         }
422         case 'm': {
423             if (!argv[i][2]) {
424                 is_usage_needed = TRUE;
425                 break;
426             }
427
428             mstr = &argv[i][2];
429             break;
430         }
431         case 'M': {
432             arg_monochrome = TRUE;
433             break;
434         }
435         case 'd':
436         case 'D': {
437             change_path(&argv[i][2]);
438             break;
439         }
440         case 'x': {
441             if (!argv[i][2]) {
442                 is_usage_needed = TRUE;
443                 break;
444             }
445
446             prepare_browse_movie_with_path_build(&argv[i][2]);
447             browsing_movie = TRUE;
448             break;
449         }
450         case '-': {
451             argv[i] = argv[0];
452             argc = argc - i;
453             argv = argv + i;
454             args = FALSE;
455             break;
456         }
457         default: {
458             is_usage_needed = TRUE;
459             break;
460         }
461         }
462
463         if (!is_usage_needed)
464             continue;
465
466         display_usage();
467     }
468
469     /* Hack -- Forget standard args */
470     if (args) {
471         argc = 1;
472         argv[1] = NULL;
473     }
474
475     /* Process the player name */
476     process_player_name(p_ptr, TRUE);
477
478     /* Install "quit" hook */
479     quit_aux = quit_hook;
480
481 #ifdef USE_XAW
482     /* Attempt to use the "main-xaw.c" support */
483     if (!done && (!mstr || (streq(mstr, "xaw")))) {
484         extern errr init_xaw(int, char **);
485         if (0 == init_xaw(argc, argv)) {
486             ANGBAND_SYS = "xaw";
487             done = TRUE;
488         }
489     }
490 #endif
491
492 #ifdef USE_X11
493     /* Attempt to use the "main-x11.c" support */
494     if (!done && (!mstr || (streq(mstr, "x11")))) {
495         extern errr init_x11(int, char **);
496         if (0 == init_x11(argc, argv)) {
497             ANGBAND_SYS = "x11";
498             done = TRUE;
499         }
500     }
501 #endif
502
503 #ifdef USE_GCU
504     /* Attempt to use the "main-gcu.c" support */
505     if (!done && (!mstr || (streq(mstr, "gcu")))) {
506         extern errr init_gcu(int, char **);
507         if (0 == init_gcu(argc, argv)) {
508             ANGBAND_SYS = "gcu";
509             done = TRUE;
510         }
511     }
512 #endif
513
514 #ifdef USE_CAP
515     /* Attempt to use the "main-cap.c" support */
516     if (!done && (!mstr || (streq(mstr, "cap")))) {
517         extern errr init_cap(int, char **);
518         if (0 == init_cap(argc, argv)) {
519             ANGBAND_SYS = "cap";
520             done = TRUE;
521         }
522     }
523 #endif
524
525     /* Make sure we have a display! */
526     if (!done)
527         quit("Unable to prepare any 'display module'!");
528
529     /* Hack -- If requested, display scores and quit */
530     if (show_score > 0)
531         display_scores(0, show_score);
532
533     /* Catch nasty signals */
534     signals_init();
535
536     /* Initialize */
537     init_angband(p_ptr, process_autopick_file_command, FALSE);
538
539     /* Wait for response */
540     pause_line(23);
541
542     /* Play the game */
543     play_game(p_ptr, new_game, browsing_movie);
544
545     /* Quit */
546     quit(NULL);
547
548     /* Exit */
549     return (0);
550 }
551
552 #endif