OSDN Git Service

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