OSDN Git Service

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