OSDN Git Service

ケケソキ
[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)
21
22
23 /*
24  * A hook for "quit()".
25  *
26  * Close down, then fall back into "quit()".
27  */
28 static void quit_hook(cptr s)
29 {
30         int j;
31
32         /* Scan windows */
33         for (j = 8 - 1; j >= 0; j--)
34         {
35                 /* Unused */
36                 if (!angband_term[j]) continue;
37
38                 /* Nuke it */
39                 term_nuke(angband_term[j]);
40         }
41 }
42
43
44
45 /*
46  * Set the stack size (for the Amiga)
47  */
48 #ifdef AMIGA
49 # include <dos.h>
50 __near long __stack = 32768L;
51 #endif
52
53
54 /*
55  * Set the stack size and overlay buffer (see main-286.c")
56  */
57 #ifdef USE_286
58 # include <dos.h>
59 extern unsigned _stklen = 32768U;
60 extern unsigned _ovrbuffer = 0x1500;
61 #endif
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         /* Drop privs */
77         safe_setuid_drop();
78
79         /* Get an absolute path from the filename */
80         path_parse(dirpath, 1024, PRIVATE_USER_PATH);
81
82         /* Create the ~/.angband/ directory */
83         mkdir(dirpath, 0700);
84
85         /* Build the path to the variant-specific sub-directory */
86         path_build(subdirpath, 1024, dirpath, VERSION_NAME);
87
88         /* Create the directory */
89         mkdir(subdirpath, 0700);
90
91         /* Grab privs */
92         safe_setuid_grab();
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  * Note that the "path" must be "Angband:" for the Amiga, and it
114  * is ignored for "VM/ESA", so I just combined the two.
115  *
116  * Make sure that the path doesn't overflow the buffer.  We have
117  * to leave enough space for the path separator, directory, and
118  * filenames.
119  */
120 static void init_stuff(void)
121 {
122         char path[1024];
123
124 #if defined(AMIGA) || defined(VM)
125
126         /* Hack -- prepare "path" */
127         strcpy(path, "Angband:");
128
129 #else /* AMIGA / VM */
130
131         cptr tail;
132
133         /* Get the environment variable */
134         tail = getenv("ANGBAND_PATH");
135
136         /* Use the angband_path, or a default */
137         strncpy(path, tail ? tail : DEFAULT_PATH, 511);
138
139         /* Make sure it's terminated */
140         path[511] = '\0';
141
142         /* Hack -- Add a path separator (only if needed) */
143         if (!suffix(path, PATH_SEP)) strcat(path, PATH_SEP);
144
145 #endif /* AMIGA / VM */
146
147         /* Initialize */
148         init_file_paths(path);
149 }
150
151
152
153 /*
154  * Handle a "-d<what>=<path>" option
155  *
156  * The "<what>" can be any string starting with the same letter as the
157  * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
158  *
159  * The "<path>" can be any legal path for the given system, and should
160  * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
161  */
162 static void change_path(cptr info)
163 {
164         cptr s;
165
166         /* Find equal sign */
167         s = strchr(info, '=');
168
169         /* Verify equal sign */
170         if (!s) quit_fmt("Try '-d<what>=<path>' not '-d%s'", info);
171
172         /* Analyze */
173         switch (tolower(info[0]))
174         {
175                 case 'a':
176                 {
177                         string_free(ANGBAND_DIR_APEX);
178                         ANGBAND_DIR_APEX = string_make(s+1);
179                         break;
180                 }
181
182                 case 'f':
183                 {
184                         string_free(ANGBAND_DIR_FILE);
185                         ANGBAND_DIR_FILE = string_make(s+1);
186                         break;
187                 }
188
189                 case 'h':
190                 {
191                         string_free(ANGBAND_DIR_HELP);
192                         ANGBAND_DIR_HELP = string_make(s+1);
193                         break;
194                 }
195
196                 case 'i':
197                 {
198                         string_free(ANGBAND_DIR_INFO);
199                         ANGBAND_DIR_INFO = string_make(s+1);
200                         break;
201                 }
202
203                 case 'u':
204                 {
205                         string_free(ANGBAND_DIR_USER);
206                         ANGBAND_DIR_USER = string_make(s+1);
207                         break;
208                 }
209
210                 case 'x':
211                 {
212                         string_free(ANGBAND_DIR_XTRA);
213                         ANGBAND_DIR_XTRA = string_make(s+1);
214                         break;
215                 }
216
217 #ifdef VERIFY_SAVEFILE
218
219                 case 'b':
220                 case 'd':
221                 case 'e':
222                 case 's':
223                 {
224                         quit_fmt("Restricted option '-d%s'", info);
225                 }
226
227 #else /* VERIFY_SAVEFILE */
228
229                 case 'b':
230                 {
231                         string_free(ANGBAND_DIR_BONE);
232                         ANGBAND_DIR_BONE = string_make(s+1);
233                         break;
234                 }
235
236                 case 'd':
237                 {
238                         string_free(ANGBAND_DIR_DATA);
239                         ANGBAND_DIR_DATA = string_make(s+1);
240                         break;
241                 }
242
243                 case 'e':
244                 {
245                         string_free(ANGBAND_DIR_EDIT);
246                         ANGBAND_DIR_EDIT = string_make(s+1);
247                         break;
248                 }
249
250                 case 's':
251                 {
252                         string_free(ANGBAND_DIR_SAVE);
253                         ANGBAND_DIR_SAVE = string_make(s+1);
254                         break;
255                 }
256
257                 case 'z':
258                 {
259                         string_free(ANGBAND_DIR_SCRIPT);
260                         ANGBAND_DIR_SCRIPT = string_make(s+1);
261                         break;
262                 }
263
264 #endif /* VERIFY_SAVEFILE */
265
266                 default:
267                 {
268                         quit_fmt("Bad semantics in '-d%s'", info);
269                 }
270         }
271 }
272
273
274 /*
275  * Simple "main" function for multiple platforms.
276  *
277  * Note the special "--" option which terminates the processing of
278  * standard options.  All non-standard options (if any) are passed
279  * directly to the "init_xxx()" function.
280  */
281 int main(int argc, char *argv[])
282 {
283         int i;
284
285         bool done = FALSE;
286
287         bool new_game = FALSE;
288
289         int show_score = 0;
290
291         cptr mstr = NULL;
292
293         bool args = TRUE;
294
295
296         /* Save the "program name" XXX XXX XXX */
297         argv0 = argv[0];
298
299 #ifdef USE_286
300         /* Attempt to use XMS (or EMS) memory for swap space */
301         if (_OvrInitExt(0L, 0L))
302         {
303                 _OvrInitEms(0, 0, 64);
304         }
305 #endif
306
307
308 #ifdef SET_UID
309
310         /* Default permissions on files */
311         (void)umask(022);
312
313 # ifdef SECURE
314         /* Authenticate */
315         Authenticate();
316 # endif
317
318 #endif
319
320
321         /* Get the file paths */
322         init_stuff();
323
324
325 #ifdef SET_UID
326
327         /* Get the user id (?) */
328         player_uid = getuid();
329
330 #ifdef VMS
331         /* Mega-Hack -- Factor group id */
332         player_uid += (getgid() * 1000);
333 #endif
334
335 # ifdef SAFE_SETUID
336
337 #  ifdef _POSIX_SAVED_IDS
338
339         /* Save some info for later */
340         player_euid = geteuid();
341         player_egid = getegid();
342
343 #  endif
344
345 #  if 0 /* XXX XXX XXX */
346
347         /* Redundant setting necessary in case root is running the game */
348         /* If not root or game not setuid the following two calls do nothing */
349
350         if (setgid(getegid()) != 0)
351         {
352                 quit("setgid(): cannot set permissions correctly!");
353         }
354
355         if (setuid(geteuid()) != 0)
356         {
357                 quit("setuid(): cannot set permissions correctly!");
358         }
359
360 #  endif
361
362 # endif
363
364 #endif
365
366
367 #ifdef SET_UID
368
369         /* Initialize the "time" checker */
370         if (check_time_init() || check_time())
371         {
372                 quit("The gates to Angband are closed (bad time).");
373         }
374
375         /* Initialize the "load" checker */
376         if (check_load_init() || check_load())
377         {
378                 quit("The gates to Angband are closed (bad load).");
379         }
380
381         /* Acquire the "user name" as a default player name */
382 #ifdef ANGBAND_2_8_1
383         user_name(player_name, player_uid);
384 #else /* ANGBAND_2_8_1 */
385         user_name(op_ptr->full_name, player_uid);
386 #endif /* ANGBAND_2_8_1 */
387
388 #ifdef PRIVATE_USER_PATH
389
390         /* Create a directory for the users files. */
391         create_user_dir();
392
393 #endif /* PRIVATE_USER_PATH */
394
395 #endif /* SET_UID */
396
397
398         /* Process the command line arguments */
399         for (i = 1; args && (i < argc); i++)
400         {
401                 /* Require proper options */
402                 if (argv[i][0] != '-') goto usage;
403
404                 /* Analyze option */
405                 switch (argv[i][1])
406                 {
407                         case 'N':
408                         case 'n':
409                         {
410                                 new_game = TRUE;
411                                 break;
412                         }
413
414                         case 'F':
415                         case 'f':
416                         {
417                                 arg_fiddle = TRUE;
418                                 break;
419                         }
420
421                         case 'W':
422                         case 'w':
423                         {
424                                 arg_wizard = TRUE;
425                                 break;
426                         }
427
428                         case 'V':
429                         case 'v':
430                         {
431                                 arg_sound = TRUE;
432                                 break;
433                         }
434
435                         case 'G':
436                         case 'g':
437                         {
438                                 /* HACK - Graphics mode switches on the original tiles */
439                                 arg_graphics = GRAPHICS_ORIGINAL;
440                                 break;
441                         }
442
443                         case 'R':
444                         case 'r':
445                         {
446                                 arg_force_roguelike = TRUE;
447                                 break;
448                         }
449
450                         case 'O':
451                         case 'o':
452                         {
453                                 arg_force_original = TRUE;
454                                 break;
455                         }
456
457                         case 'S':
458                         case 's':
459                         {
460                                 show_score = atoi(&argv[i][2]);
461                                 if (show_score <= 0) show_score = 10;
462                                 break;
463                         }
464
465                         case 'u':
466                         case 'U':
467                         {
468                                 if (!argv[i][2]) goto usage;
469 #ifdef ANGBAND_2_8_1
470                                 strcpy(player_name, &argv[i][2]);
471 #else /* ANGBAND_2_8_1 */
472
473                                 /* Get the savefile name */
474                                 strncpy(op_ptr->full_name, &argv[i][2], 32);
475
476                                 /* Make sure it's terminated */
477                                 op_ptr->full_name[31] = '\0';
478
479 #endif /* ANGBAND_2_8_1 */
480                                 break;
481                         }
482
483                         case 'm':
484                         {
485                                 if (!argv[i][2]) goto usage;
486                                 mstr = &argv[i][2];
487                                 break;
488                         }
489
490                         case 'M':
491                         {
492                                 arg_monochrome = TRUE;
493                                 break;
494                         }
495
496                         case 'd':
497                         case 'D':
498                         {
499                                 change_path(&argv[i][2]);
500                                 break;
501                         }
502
503 #ifdef CHUUKEI
504                         case 'p':
505                         case 'P':
506                         {
507                                 if (!argv[i][2]) goto usage;
508                                 chuukei_server = TRUE;
509                                 if (connect_chuukei_server(&argv[i][2]) < 0) chuukei_server = FALSE;
510                                 break;
511                         }
512
513                         case 'c':
514                         case 'C':
515                         {
516                                 if (!argv[i][2]) goto usage;
517                                 chuukei_client = TRUE;
518                                 connect_chuukei_server(&argv[i][2]);
519                                 break;
520                         }
521 #endif
522
523                         case '-':
524                         {
525                                 argv[i] = argv[0];
526                                 argc = argc - i;
527                                 argv = argv + i;
528                                 args = FALSE;
529                                 break;
530                         }
531
532                         default:
533                         usage:
534                         {
535                                 /* Dump usage information */
536                                 puts("Usage: angband [options] [-- subopts]");
537                                 puts("  -n       Start a new character");
538                                 puts("  -f       Request fiddle mode");
539                                 puts("  -w       Request wizard mode");
540                                 puts("  -v       Request sound mode");
541                                 puts("  -g       Request graphics mode");
542                                 puts("  -o       Request original keyset");
543                                 puts("  -r       Request rogue-like keyset");
544                                 puts("  -M       Request monochrome mode");
545                                 puts("  -s<num>  Show <num> high scores");
546                                 puts("  -u<who>  Use your <who> savefile");
547                                 puts("  -m<sys>  Force 'main-<sys>.c' usage");
548                                 puts("  -d<def>  Define a 'lib' dir sub-path");
549                                 puts("");
550
551 #ifdef USE_X11
552                                 puts("  -mx11    To use X11");
553                                 puts("  --       Sub options");
554                                 puts("  -- -d    Set display name");
555                                 puts("  -- -o    Request old 8x8 tile graphics");
556                                 puts("  -- -a    Request Adam Bolt 16x16 tile graphics");
557                                 puts("  -- -b    Request Bigtile graphics mode");
558                                 puts("  -- -s    Turn off smoothscaling graphics");
559                                 puts("  -- -n#   Number of terms to use");
560                                 puts("");
561 #endif /* USE_X11 */
562
563 #ifdef USE_GCU
564                                 puts("  -mgcu    To use GCU (GNU Curses)");
565 #endif /* USE_GCU */
566
567 #ifdef USE_CAP
568                                 puts("  -mcap    To use CAP (\"Termcap\" calls)");
569 #endif /* USE_CAP */
570
571 #ifdef USE_DOS
572                                 puts("  -mdos    To use DOS (Graphics)");
573 #endif /* USE_DOS */
574
575 #ifdef USE_IBM
576                                 puts("  -mibm    To use IBM (BIOS text mode)");
577 #endif /* USE_IBM */
578
579 #ifdef USE_SLA
580                                 puts("  -msla    To use SLA (SLANG)");
581 #endif /* USE_SLA */
582
583 #ifdef USE_LSL
584                                 puts("  -mlsl    To use LSL (Linux-SVGALIB)");
585 #endif /* USE_LSL */
586
587 #ifdef USE_AMI
588                                 puts("  -mami    To use AMI (Amiga)");
589 #endif /* USE_AMI */
590
591 #ifdef USE_VME
592                                 puts("  -mvme    To use VME (VAX/ESA)");
593 #endif /* USE_VME */
594
595                                 /* Actually abort the process */
596                                 quit(NULL);
597                         }
598                 }
599         }
600
601         /* Hack -- Forget standard args */
602         if (args)
603         {
604                 argc = 1;
605                 argv[1] = NULL;
606         }
607
608
609         /* Process the player name */
610         process_player_name(TRUE);
611
612
613
614         /* Install "quit" hook */
615         quit_aux = quit_hook;
616
617
618         /* Drop privs (so X11 will work correctly) */
619         safe_setuid_drop();
620
621
622 #ifdef USE_XAW
623         /* Attempt to use the "main-xaw.c" support */
624         if (!done && (!mstr || (streq(mstr, "xaw"))))
625         {
626                 extern errr init_xaw(int, char**);
627                 if (0 == init_xaw(argc, argv))
628                 {
629                         ANGBAND_SYS = "xaw";
630                         done = TRUE;
631                 }
632         }
633 #endif
634
635 #ifdef USE_X11
636         /* Attempt to use the "main-x11.c" support */
637         if (!done && (!mstr || (streq(mstr, "x11"))))
638         {
639                 extern errr init_x11(int, char**);
640                 if (0 == init_x11(argc, argv))
641                 {
642                         ANGBAND_SYS = "x11";
643                         done = TRUE;
644                 }
645         }
646 #endif
647
648 #ifdef USE_GCU
649         /* Attempt to use the "main-gcu.c" support */
650         if (!done && (!mstr || (streq(mstr, "gcu"))))
651         {
652                 extern errr init_gcu(int, char**);
653                 if (0 == init_gcu(argc, argv))
654                 {
655                         ANGBAND_SYS = "gcu";
656                         done = TRUE;
657                 }
658         }
659 #endif
660
661 #ifdef USE_CAP
662         /* Attempt to use the "main-cap.c" support */
663         if (!done && (!mstr || (streq(mstr, "cap"))))
664         {
665                 extern errr init_cap(int, char**);
666                 if (0 == init_cap(argc, argv))
667                 {
668                         ANGBAND_SYS = "cap";
669                         done = TRUE;
670                 }
671         }
672 #endif
673
674
675 #ifdef USE_DOS
676         /* Attempt to use the "main-dos.c" support */
677         if (!done && (!mstr || (streq(mstr, "dos"))))
678         {
679                 extern errr init_dos(void);
680                 if (0 == init_dos())
681                 {
682                         ANGBAND_SYS = "dos";
683                         done = TRUE;
684                 }
685         }
686 #endif
687
688 #ifdef USE_IBM
689         /* Attempt to use the "main-ibm.c" support */
690         if (!done && (!mstr || (streq(mstr, "ibm"))))
691         {
692                 extern errr init_ibm(void);
693                 if (0 == init_ibm())
694                 {
695                         ANGBAND_SYS = "ibm";
696                         done = TRUE;
697                 }
698         }
699 #endif
700
701
702 #ifdef USE_EMX
703         /* Attempt to use the "main-emx.c" support */
704         if (!done && (!mstr || (streq(mstr, "emx"))))
705         {
706                 extern errr init_emx(void);
707                 if (0 == init_emx())
708                 {
709                         ANGBAND_SYS = "emx";
710                         done = TRUE;
711                 }
712         }
713 #endif
714
715
716 #ifdef USE_SLA
717         /* Attempt to use the "main-sla.c" support */
718         if (!done && (!mstr || (streq(mstr, "sla"))))
719         {
720                 extern errr init_sla(void);
721                 if (0 == init_sla())
722                 {
723                         ANGBAND_SYS = "sla";
724                         done = TRUE;
725                 }
726         }
727 #endif
728
729
730 #ifdef USE_LSL
731         /* Attempt to use the "main-lsl.c" support */
732         if (!done && (!mstr || (streq(mstr, "lsl"))))
733         {
734                 extern errr init_lsl(void);
735                 if (0 == init_lsl())
736                 {
737                         ANGBAND_SYS = "lsl";
738                         done = TRUE;
739                 }
740         }
741 #endif
742
743
744 #ifdef USE_AMI
745         /* Attempt to use the "main-ami.c" support */
746         if (!done && (!mstr || (streq(mstr, "ami"))))
747         {
748                 extern errr init_ami(void);
749                 if (0 == init_ami())
750                 {
751                         ANGBAND_SYS = "ami";
752                         done = TRUE;
753                 }
754         }
755 #endif
756
757
758 #ifdef USE_VME
759         /* Attempt to use the "main-vme.c" support */
760         if (!done && (!mstr || (streq(mstr, "vme"))))
761         {
762                 extern errr init_vme(void);
763                 if (0 == init_vme())
764                 {
765                         ANGBAND_SYS = "vme";
766                         done = TRUE;
767                 }
768         }
769 #endif
770
771
772         /* Grab privs (dropped above for X11) */
773         safe_setuid_grab();
774
775
776         /* Make sure we have a display! */
777         if (!done) quit("Unable to prepare any 'display module'!");
778
779
780         /* Hack -- If requested, display scores and quit */
781         if (show_score > 0) display_scores(0, show_score);
782
783
784         /* Catch nasty signals */
785         signals_init();
786
787         /* Initialize */
788         init_angband();
789
790         /* Wait for response */
791         pause_line(23);
792
793         /* Play the game */
794         play_game(new_game);
795
796         /* Quit */
797         quit(NULL);
798
799         /* Exit */
800         return (0);
801 }
802
803 #endif
804
805
806