OSDN Git Service

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