OSDN Git Service

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