OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / sys / share / pcmain.c
1 /* NetHack 3.6  pcmain.c        $NHDT-Date: 1543465755 2018/11/29 04:29:15 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.101 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Derek S. Ray, 2015. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* main.c - MSDOS, OS/2, ST, Amiga NetHack */
7
8 #include "hack.h"
9 #include "dlb.h"
10
11 #ifndef NO_SIGNAL
12 #include <signal.h>
13 #endif
14
15 #include <ctype.h>
16
17 #if !defined(AMIGA) && !defined(GNUDOS)
18 #include <sys\stat.h>
19 #else
20 #ifdef GNUDOS
21 #include <sys/stat.h>
22 #endif
23 #endif
24
25 #ifdef __DJGPP__
26 #include <unistd.h> /* for getcwd() prototype */
27 #endif
28
29 char orgdir[PATHLEN]; /* also used in pcsys.c, amidos.c */
30
31 #ifdef TOS
32 boolean run_from_desktop = TRUE; /* should we pause before exiting?? */
33 #ifdef __GNUC__
34 long _stksize = 16 * 1024;
35 #endif
36 #endif
37
38 #ifdef AMIGA
39 extern int bigscreen;
40 void NDECL(preserve_icon);
41 #endif
42
43 STATIC_DCL void FDECL(process_options, (int argc, char **argv));
44 STATIC_DCL void NDECL(nhusage);
45
46 #if defined(MICRO) || defined(OS2)
47 extern void FDECL(nethack_exit, (int));
48 #else
49 #define nethack_exit exit
50 #endif
51
52 #ifdef EXEPATH
53 STATIC_DCL char *FDECL(exepath, (char *));
54 #endif
55
56 int FDECL(main, (int, char **));
57
58 extern boolean FDECL(pcmain, (int, char **));
59
60 #if defined(__BORLANDC__)
61 void NDECL(startup);
62 unsigned _stklen = STKSIZ;
63 #endif
64
65 /* If the graphics version is built, we don't need a main; it is skipped
66  * to help MinGW decide which entry point to choose. If both main and
67  * WinMain exist, the resulting executable won't work correctly.
68  */
69 int
70 #ifndef __MINGW32__ 
71 main(argc, argv)
72 #else
73 mingw_main(argc, argv)
74 #endif
75 int argc;
76 char *argv[];
77 {
78     boolean resuming;
79
80     sys_early_init();
81     resuming = pcmain(argc, argv);
82     moveloop(resuming);
83     nethack_exit(EXIT_SUCCESS);
84     /*NOTREACHED*/
85     return 0;
86 }
87
88 boolean
89 pcmain(argc, argv)
90 int argc;
91 char *argv[];
92 {
93     register int fd;
94     register char *dir;
95 #if defined(MSDOS)
96     char *envp = NULL;
97     char *sptr = NULL;
98 #endif
99 #ifdef NOCWD_ASSUMPTIONS
100     char failbuf[BUFSZ];
101 #endif
102     boolean resuming = FALSE; /* assume new game */
103
104 #ifdef _MSC_VER
105 # ifdef DEBUG
106     /* set these appropriately for VS debugging */
107     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
108     _CrtSetReportMode(_CRT_ERROR,
109                       _CRTDBG_MODE_DEBUG); /* | _CRTDBG_MODE_FILE);*/
110     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
111 /*| _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW);*/
112 /* use STDERR by default
113 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
114 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
115 /* Heap Debugging
116     _CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
117         | _CRTDBG_ALLOC_MEM_DF
118         | _CRTDBG_CHECK_ALWAYS_DF
119         | _CRTDBG_CHECK_CRT_DF
120         | _CRTDBG_DELAY_FREE_MEM_DF
121         | _CRTDBG_LEAK_CHECK_DF);
122     _CrtSetBreakAlloc(1423);
123 */
124 # endif
125 #endif
126
127 #if defined(__BORLANDC__)
128     startup();
129 #endif
130
131 #ifdef TOS
132     long clock_time;
133     if (*argv[0]) { /* only a CLI can give us argv[0] */
134         hname = argv[0];
135         run_from_desktop = FALSE;
136     } else
137 #endif
138         hname = "NetHack"; /* used for syntax messages */
139
140     choose_windows(DEFAULT_WINDOW_SYS);
141
142 #if !defined(AMIGA) && !defined(GNUDOS)
143     /* Save current directory and make sure it gets restored when
144      * the game is exited.
145      */
146     if (getcwd(orgdir, sizeof orgdir) == (char *) 0)
147         error("NetHack: current directory path too long");
148 #ifndef NO_SIGNAL
149     signal(SIGINT,
150            (SIG_RET_TYPE) nethack_exit); /* restore original directory */
151 #endif
152 #endif /* !AMIGA && !GNUDOS */
153
154     dir = nh_getenv("NETHACKDIR");
155     if (dir == (char *) 0)
156         dir = nh_getenv("HACKDIR");
157 #ifdef EXEPATH
158     if (dir == (char *) 0)
159         dir = exepath(argv[0]);
160 #endif
161 #ifdef _MSC_VER
162     if (IsDebuggerPresent()) {
163         static char exepath[_MAX_PATH];
164         /* check if we're running under the debugger so we can get to the right folder anyway */
165         if (dir != (char *)0) {
166             char *top = (char *)0;
167
168             if (strlen(dir) < (_MAX_PATH - 1))
169                 strcpy(exepath, dir);
170             top = strstr(exepath, "\\build\\.\\Debug");
171             if (!top) top = strstr(exepath, "\\build\\.\\Release");
172             if (top) {
173                 *top = '\0';
174                 if (strlen(exepath) < (_MAX_PATH - (strlen("\\binary\\") + 1))) {
175                     Strcat(exepath, "\\binary\\");
176                     if (strlen(exepath) < (PATHLEN - 1)) {
177                         dir = exepath;
178                     }
179                 }
180             }
181         }
182     }
183 #endif
184     if (dir != (char *)0) {
185         int fd;
186         boolean have_syscf = FALSE;
187
188         (void) strncpy(hackdir, dir, PATHLEN - 1);
189         hackdir[PATHLEN - 1] = '\0';
190 #ifdef NOCWD_ASSUMPTIONS
191         {
192             int prefcnt;
193
194             fqn_prefix[0] = (char *) alloc(strlen(hackdir) + 2);
195             Strcpy(fqn_prefix[0], hackdir);
196             append_slash(fqn_prefix[0]);
197             for (prefcnt = 1; prefcnt < PREFIX_COUNT; prefcnt++)
198                 fqn_prefix[prefcnt] = fqn_prefix[0];
199
200 #if defined(MSDOS)
201             /* sysconf should be searched for in this location */
202             envp = nh_getenv("COMMONPROGRAMFILES");
203             if (envp) {
204                 if ((sptr = index(envp, ';')) != 0)
205                     *sptr = '\0';
206                 if (strlen(envp) > 0) {
207                     fqn_prefix[SYSCONFPREFIX] =
208                         (char *) alloc(strlen(envp) + 10);
209                     Strcpy(fqn_prefix[SYSCONFPREFIX], envp);
210                     append_slash(fqn_prefix[SYSCONFPREFIX]);
211                     Strcat(fqn_prefix[SYSCONFPREFIX], "NetHack\\");
212                 }
213             }
214
215             /* okay so we have the overriding and definitive locaton
216             for sysconf, but only in the event that there is not a 
217             sysconf file there (for whatever reason), check a secondary
218             location rather than abort. */
219
220             /* Is there a SYSCF_FILE there? */
221             fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
222             if (fd >= 0) {
223                 /* readable */
224                 close(fd);
225                 have_syscf = TRUE;
226             }
227
228             if (!have_syscf) {
229                 /* No SYSCF_FILE where there should be one, and
230                    without an installer, a user may not be able
231                    to place one there. So, let's try somewhere else... */
232                 fqn_prefix[SYSCONFPREFIX] = fqn_prefix[0];
233
234                 /* Is there a SYSCF_FILE there? */
235                 fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
236                 if (fd >= 0) {
237                     /* readable */
238                     close(fd);
239                     have_syscf = TRUE;
240                 }
241             }
242
243             /* user's home directory should default to this - unless
244              * overridden */
245             envp = nh_getenv("USERPROFILE");
246             if (envp) {
247                 if ((sptr = index(envp, ';')) != 0)
248                     *sptr = '\0';
249                 if (strlen(envp) > 0) {
250                     fqn_prefix[CONFIGPREFIX] =
251                         (char *) alloc(strlen(envp) + 2);
252                     Strcpy(fqn_prefix[CONFIGPREFIX], envp);
253                     append_slash(fqn_prefix[CONFIGPREFIX]);
254                 }
255             }
256 #endif
257         }
258 #endif
259 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
260         chdirx(dir, 1);
261 #endif
262     }
263 #ifdef AMIGA
264 #ifdef CHDIR
265     /*
266      * If we're dealing with workbench, change the directory.  Otherwise
267      * we could get "Insert disk in drive 0" messages. (Must be done
268      * before initoptions())....
269      */
270     if (argc == 0)
271         chdirx(HACKDIR, 1);
272 #endif
273     ami_wininit_data();
274 #endif
275     initoptions();
276
277 #ifdef NOCWD_ASSUMPTIONS
278     if (!validate_prefix_locations(failbuf)) {
279         raw_printf("Some invalid directory locations were specified:\n\t%s\n",
280                    failbuf);
281         nethack_exit(EXIT_FAILURE);
282     }
283 #endif
284
285 #if defined(TOS) && defined(TEXTCOLOR)
286     if (iflags.BIOS && iflags.use_color)
287         set_colors();
288 #endif
289     if (!hackdir[0])
290 #if !defined(LATTICE) && !defined(AMIGA)
291         Strcpy(hackdir, orgdir);
292 #else
293         Strcpy(hackdir, HACKDIR);
294 #endif
295     if (argc > 1) {
296         if (argcheck(argc, argv, ARG_VERSION) == 2)
297             nethack_exit(EXIT_SUCCESS);
298
299         if (argcheck(argc, argv, ARG_DEBUG) == 1) {
300             argc--;
301             argv++;
302         }
303
304         if (argc > 1 && !strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
305             /* avoid matching "-dec" for DECgraphics; since the man page
306              * says -d directory, hope nobody's using -desomething_else
307              */
308             argc--;
309             argv++;
310             dir = argv[0] + 2;
311             if (*dir == '=' || *dir == ':')
312                 dir++;
313             if (!*dir && argc > 1) {
314                 argc--;
315                 argv++;
316                 dir = argv[0];
317             }
318             if (!*dir)
319                 error("Flag -d must be followed by a directory name.");
320             Strcpy(hackdir, dir);
321         }
322         if (argc > 1) {
323             /*
324              * Now we know the directory containing 'record' and
325              * may do a prscore().
326              */
327             if (!strncmp(argv[1], "-s", 2)) {
328 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
329                 chdirx(hackdir, 0);
330 #endif
331 #ifdef SYSCF
332                 initoptions();
333 #endif
334                 prscore(argc, argv);
335                 nethack_exit(EXIT_SUCCESS);
336             }
337
338             /* Don't initialize the window system just to print usage */
339             if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) {
340                 nhusage();
341                 nethack_exit(EXIT_SUCCESS);
342             }
343         }
344     }
345 /*
346  * It seems you really want to play.
347  */
348 #ifdef TOS
349     if (comp_times((long) time(&clock_time)))
350         error("Your clock is incorrectly set!");
351 #endif
352     if (!dlb_init()) {
353         pline(
354             "%s\n%s\n%s\n%s\n\nNetHack was unable to open the required file "
355             "\"%s\".%s",
356             copyright_banner_line(1), copyright_banner_line(2),
357             copyright_banner_line(3), copyright_banner_line(4), DLBFILE,
358             "");
359         error("dlb_init failure.");
360     }
361
362     u.uhp = 1; /* prevent RIP on early quits */
363     u.ux = 0;  /* prevent flush_screen() */
364
365 /* chdir shouldn't be called before this point to keep the
366  * code parallel to other ports.
367  */
368 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
369     chdirx(hackdir, 1);
370 #endif
371
372 #if defined(MSDOS)
373     /* In 3.6.0, several ports process options before they init
374      * the window port. This allows settings that impact window
375      * ports to be specified or read from the sys or user config files.
376      */
377     process_options(argc, argv);
378
379 #endif /* MSDOS */
380
381 #if defined(MSDOS)
382     init_nhwindows(&argc, argv);
383 #else
384     init_nhwindows(&argc, argv);
385     process_options(argc, argv);
386 #endif
387
388 #ifdef MFLOPPY
389     set_lock_and_bones();
390 #ifndef AMIGA
391     copybones(FROMPERM);
392 #endif
393 #endif
394
395     /* strip role,race,&c suffix; calls askname() if plname[] is empty
396        or holds a generic user name like "player" or "games" */
397     plnamesuffix();
398     set_playmode(); /* sets plname to "wizard" for wizard mode */
399 #if 0
400     /* unlike Unix where the game might be invoked with a script
401        which forces a particular character name for each player
402        using a shared account, we always allow player to rename
403        the character during role/race/&c selection */
404     iflags.renameallowed = TRUE;
405 #else
406     /* until the getlock code is resolved, override askname()'s
407        setting of renameallowed; when False, player_selection()
408        won't resent renaming as an option */
409     iflags.renameallowed = FALSE;
410 #endif
411
412 #if defined(PC_LOCKING)
413 /* 3.3.0 added this to support detection of multiple games
414  * under the same plname on the same machine in a windowed
415  * or multitasking environment.
416  *
417  * That allows user confirmation prior to overwriting the
418  * level files of a game in progress.
419  *
420  * Also prevents an aborted game's level files from being
421  * overwritten without confirmation when a user starts up
422  * another game with the same player name.
423  */
424     Strcpy(lock, plname);
425     regularize(lock);
426     getlock();
427 #else        /* What follows is !PC_LOCKING */
428 #ifdef AMIGA /* We'll put the bones & levels in the user specified directory \
429                 -jhsa */
430     Strcat(lock, plname);
431     Strcat(lock, ".99");
432 #else
433 #ifndef MFLOPPY
434     /* I'm not sure what, if anything, is left here, but MFLOPPY has
435      * conflicts with set_lock_and_bones() in files.c.
436      */
437     Strcpy(lock, plname);
438     Strcat(lock, ".99");
439     regularize(lock); /* is this necessary? */
440                       /* not compatible with full path a la AMIGA */
441 #endif
442 #endif
443 #endif /* PC_LOCKING */
444
445     /* Set up level 0 file to keep the game state.
446      */
447     fd = create_levelfile(0, (char *) 0);
448     if (fd < 0) {
449         raw_print("Cannot create lock file");
450     } else {
451         hackpid = 1;
452         write(fd, (genericptr_t) &hackpid, sizeof(hackpid));
453         nhclose(fd);
454     }
455 #ifdef MFLOPPY
456     level_info[0].where = ACTIVE;
457 #endif
458
459     /*
460      *  Initialize the vision system.  This must be before mklev() on a
461      *  new game or before a level restore on a saved game.
462      */
463     vision_init();
464
465     display_gamewindows();
466 /*
467  * First, try to find and restore a save file for specified character.
468  * We'll return here if new game player_selection() renames the hero.
469  */
470 attempt_restore:
471     if ((fd = restore_saved_game()) >= 0) {
472 #ifndef NO_SIGNAL
473         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
474 #endif
475 #ifdef NEWS
476         if (iflags.news) {
477             display_file(NEWS, FALSE);
478             iflags.news = FALSE;
479         }
480 #endif
481 /*JP
482         pline("Restoring save file...");
483 */
484         pline("\83Z\81[\83u\83t\83@\83C\83\8b\82ð\95\9c\8c³\92\86\81D\81D\81D");
485         mark_synch(); /* flush output */
486
487         if (dorecover(fd)) {
488             resuming = TRUE; /* not starting new game */
489             if (discover)
490 /*JP
491                 You("are in non-scoring discovery mode.");
492 */
493                 pline("\94­\8c©\83\82\81[\83h\82Å\82Í\83X\83R\83A\82Í\82Ì\82ç\82È\82¢\82æ\81D");
494             if (discover || wizard) {
495 /*JP
496                 if (yn("Do you want to keep the save file?") == 'n')
497 */
498                 if (yn("\83Z\81[\83u\83t\83@\83C\83\8b\82ð\8ec\82µ\82Ä\82¨\82«\82Ü\82·\82©\81H") == 'n')
499                     (void) delete_savefile();
500                 else {
501                     nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
502                 }
503             }
504         }
505     }
506
507     if (!resuming) {
508         /* new game:  start by choosing role, race, etc;
509            player might change the hero's name while doing that,
510            in which case we try to restore under the new name
511            and skip selection this time if that didn't succeed */
512         if (!iflags.renameinprogress) {
513             player_selection();
514             if (iflags.renameinprogress) {
515 /* player has renamed the hero while selecting role;
516    discard current lock file and create another for
517    the new character name */
518 #if 0 /* this needs to be reconciled with the getlock mess above... */
519             delete_levelfile(0); /* remove empty lock file */
520             getlock();
521 #endif
522                 goto attempt_restore;
523             }
524         }
525         newgame();
526         if (discover)
527 /*JP
528             You("are in non-scoring discovery mode.");
529 */
530             pline("\94­\8c©\83\82\81[\83h\82Å\82Í\83X\83R\83A\82Í\82Ì\82ç\82È\82¢\82æ\81D");
531     }
532
533 #ifndef NO_SIGNAL
534     (void) signal(SIGINT, SIG_IGN);
535 #endif
536 #ifdef OS2
537     gettty(); /* somehow ctrl-P gets turned back on during startup ... */
538 #endif
539     return resuming;
540 }
541
542 STATIC_OVL void
543 process_options(argc, argv)
544 int argc;
545 char *argv[];
546 {
547     int i;
548
549     /*
550      * Process options.
551      */
552     while (argc > 1 && argv[1][0] == '-') {
553         argv++;
554         argc--;
555         switch (argv[0][1]) {
556         case 'a':
557             if (argv[0][2]) {
558                 if ((i = str2align(&argv[0][2])) >= 0)
559                     flags.initalign = i;
560             } else if (argc > 1) {
561                 argc--;
562                 argv++;
563                 if ((i = str2align(argv[0])) >= 0)
564                     flags.initalign = i;
565             }
566             break;
567         case 'D':
568             wizard = TRUE, discover = FALSE;
569             break;
570         case 'X':
571             discover = TRUE, wizard = FALSE;
572             break;
573 #ifdef NEWS
574         case 'n':
575             iflags.news = FALSE;
576             break;
577 #endif
578         case 'u':
579             if (argv[0][2])
580                 (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
581             else if (argc > 1) {
582                 argc--;
583                 argv++;
584                 (void) strncpy(plname, argv[0], sizeof(plname) - 1);
585             } else
586                 raw_print("Player name expected after -u");
587             break;
588 #ifndef AMIGA
589         case 'I':
590         case 'i':
591             if (!strncmpi(argv[0] + 1, "IBM", 3)) {
592                 load_symset("IBMGraphics", PRIMARY);
593                 load_symset("RogueIBM", ROGUESET);
594                 switch_symbols(TRUE);
595             }
596             break;
597         /*      case 'D': */
598         case 'd':
599             if (!strncmpi(argv[0] + 1, "DEC", 3)) {
600                 load_symset("DECGraphics", PRIMARY);
601                 switch_symbols(TRUE);
602             }
603             break;
604 #endif
605         case 'g':
606             if (argv[0][2]) {
607                 if ((i = str2gend(&argv[0][2])) >= 0)
608                     flags.initgend = i;
609             } else if (argc > 1) {
610                 argc--;
611                 argv++;
612                 if ((i = str2gend(argv[0])) >= 0)
613                     flags.initgend = i;
614             }
615             break;
616         case 'p': /* profession (role) */
617             if (argv[0][2]) {
618                 if ((i = str2role(&argv[0][2])) >= 0)
619                     flags.initrole = i;
620             } else if (argc > 1) {
621                 argc--;
622                 argv++;
623                 if ((i = str2role(argv[0])) >= 0)
624                     flags.initrole = i;
625             }
626             break;
627         case 'r': /* race */
628             if (argv[0][2]) {
629                 if ((i = str2race(&argv[0][2])) >= 0)
630                     flags.initrace = i;
631             } else if (argc > 1) {
632                 argc--;
633                 argv++;
634                 if ((i = str2race(argv[0])) >= 0)
635                     flags.initrace = i;
636             }
637             break;
638 #ifdef MFLOPPY
639 #ifndef AMIGA
640         /* Player doesn't want to use a RAM disk
641          */
642         case 'R':
643             ramdisk = FALSE;
644             break;
645 #endif
646 #endif
647 #ifdef AMIGA
648         /* interlaced and non-interlaced screens */
649         case 'L':
650             bigscreen = 1;
651             break;
652         case 'l':
653             bigscreen = -1;
654             break;
655 #endif
656         case '@':
657             flags.randomall = 1;
658             break;
659         default:
660             if ((i = str2role(&argv[0][1])) >= 0) {
661                 flags.initrole = i;
662                 break;
663             } else
664                 raw_printf("\nUnknown switch: %s", argv[0]);
665         /* FALL THROUGH */
666         case '?':
667             nhusage();
668             nethack_exit(EXIT_SUCCESS);
669         }
670     }
671 }
672
673 STATIC_OVL void
674 nhusage()
675 {
676     char buf1[BUFSZ], buf2[BUFSZ], *bufptr;
677
678     buf1[0] = '\0';
679     bufptr = buf1;
680
681 #define ADD_USAGE(s)                              \
682     if ((strlen(buf1) + strlen(s)) < (BUFSZ - 1)) \
683         Strcat(bufptr, s);
684
685     /* -role still works for those cases which aren't already taken, but
686      * is deprecated and will not be listed here.
687      */
688     (void) Sprintf(buf2, "\nUsage:\n%s [-d dir] -s [-r race] [-p profession] "
689                          "[maxrank] [name]...\n       or",
690                    hname);
691     ADD_USAGE(buf2);
692
693     (void) Sprintf(
694         buf2, "\n%s [-d dir] [-u name] [-r race] [-p profession] [-[DX]]",
695         hname);
696     ADD_USAGE(buf2);
697 #ifdef NEWS
698     ADD_USAGE(" [-n]");
699 #endif
700 #ifndef AMIGA
701     ADD_USAGE(" [-I] [-i] [-d]");
702 #endif
703 #ifdef MFLOPPY
704 #ifndef AMIGA
705     ADD_USAGE(" [-R]");
706 #endif
707 #endif
708 #ifdef AMIGA
709     ADD_USAGE(" [-[lL]]");
710 #endif
711     if (!iflags.window_inited)
712         raw_printf("%s\n", buf1);
713     else
714         (void) printf("%s\n", buf1);
715 #undef ADD_USAGE
716 }
717
718 #ifdef CHDIR
719 void
720 chdirx(dir, wr)
721 char *dir;
722 boolean wr;
723 {
724 #ifdef AMIGA
725     static char thisdir[] = "";
726 #else
727     static char thisdir[] = ".";
728 #endif
729     if (dir && chdir(dir) < 0) {
730         error("Cannot chdir to %s.", dir);
731     }
732
733 #ifndef AMIGA
734     /* Change the default drive as well.
735      */
736     chdrive(dir);
737 #endif
738
739     /* warn the player if we can't write the record file */
740     /* perhaps we should also test whether . is writable */
741     /* unfortunately the access system-call is worthless */
742     if (wr)
743         check_recordfile(dir ? dir : thisdir);
744 }
745 #endif /* CHDIR */
746
747 #ifdef PORT_HELP
748 #if defined(MSDOS)
749 void
750 port_help()
751 {
752     /* display port specific help file */
753     display_file(PORT_HELP, 1);
754 }
755 #endif /* MSDOS */
756 #endif /* PORT_HELP */
757
758 /* validate wizard mode if player has requested access to it */
759 boolean
760 authorize_wizard_mode()
761 {
762     if (!strcmp(plname, WIZARD_NAME))
763         return TRUE;
764     return FALSE;
765 }
766
767 #ifdef EXEPATH
768 #ifdef __DJGPP__
769 #define PATH_SEPARATOR '/'
770 #else
771 #define PATH_SEPARATOR '\\'
772 #endif
773
774 #define EXEPATHBUFSZ 256
775 char exepathbuf[EXEPATHBUFSZ];
776
777 char *
778 exepath(str)
779 char *str;
780 {
781     char *tmp, *tmp2;
782     int bsize;
783
784     if (!str)
785         return (char *) 0;
786     bsize = EXEPATHBUFSZ;
787     tmp = exepathbuf;
788     Strcpy(tmp, str);
789     tmp2 = strrchr(tmp, PATH_SEPARATOR);
790     if (tmp2)
791         *tmp2 = '\0';
792     return tmp;
793 }
794 #endif /* EXEPATH */
795
796 /*pcmain.c*/