OSDN Git Service

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