Move generic usernames to sysconf
[aNetHack.git] / sys / share / pcmain.c
blobdf756234a2662575b4bf19312862e501c10fa584
1 /* NetHack 3.6 pcmain.c $NHDT-Date: 1457207045 2016/03/05 19:44:05 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.69 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* main.c - MSDOS, OS/2, ST, Amiga, and Windows NetHack */
7 #include "hack.h"
8 #include "dlb.h"
10 #ifndef NO_SIGNAL
11 #include <signal.h>
12 #endif
14 #include <ctype.h>
16 #if !defined(AMIGA) && !defined(GNUDOS)
17 #include <sys\stat.h>
18 #else
19 #ifdef GNUDOS
20 #include <sys/stat.h>
21 #endif
22 #endif
24 #ifdef WIN32
25 #include "win32api.h" /* for GetModuleFileName */
26 #endif
28 #ifdef __DJGPP__
29 #include <unistd.h> /* for getcwd() prototype */
30 #endif
32 char orgdir[PATHLEN]; /* also used in pcsys.c, amidos.c */
34 #ifdef TOS
35 boolean run_from_desktop = TRUE; /* should we pause before exiting?? */
36 #ifdef __GNUC__
37 long _stksize = 16 * 1024;
38 #endif
39 #endif
41 #ifdef AMIGA
42 extern int bigscreen;
43 void NDECL(preserve_icon);
44 #endif
46 STATIC_DCL void FDECL(process_options, (int argc, char **argv));
47 STATIC_DCL void NDECL(nhusage);
49 #if defined(MICRO) || defined(WIN32) || defined(OS2)
50 extern void FDECL(nethack_exit, (int));
51 #else
52 #define nethack_exit exit
53 #endif
55 #ifdef WIN32
56 extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
57 extern int redirect_stdout; /* from sys/share/pcsys.c */
58 extern int GUILaunched;
59 HANDLE hStdOut;
60 char *NDECL(exename);
61 char default_window_sys[] = "mswin";
62 boolean NDECL(fakeconsole);
63 void NDECL(freefakeconsole);
64 #endif
66 #if defined(MSWIN_GRAPHICS)
67 extern void NDECL(mswin_destroy_reg);
68 #endif
70 #ifdef EXEPATH
71 STATIC_DCL char *FDECL(exepath, (char *));
72 #endif
74 int FDECL(main, (int, char **));
76 extern boolean FDECL(pcmain, (int, char **));
78 #if defined(__BORLANDC__) && !defined(_WIN32)
79 void NDECL(startup);
80 unsigned _stklen = STKSIZ;
81 #endif
83 /* If the graphics version is built, we don't need a main; it is skipped
84 * to help MinGW decide which entry point to choose. If both main and
85 * WinMain exist, the resulting executable won't work correctly.
87 #ifndef __MINGW32__
88 int
89 main(argc, argv)
90 int argc;
91 char *argv[];
93 boolean resuming;
95 sys_early_init();
96 #ifdef WIN32
97 Strcpy(default_window_sys, "tty");
98 #endif
100 resuming = pcmain(argc, argv);
101 #ifdef LAN_FEATURES
102 init_lan_features();
103 #endif
104 moveloop(resuming);
105 nethack_exit(EXIT_SUCCESS);
106 /*NOTREACHED*/
107 return 0;
109 #endif
111 boolean
112 pcmain(argc, argv)
113 int argc;
114 char *argv[];
116 register int fd;
117 register char *dir;
118 #if defined(WIN32) || defined(MSDOS)
119 char *envp = NULL;
120 char *sptr = NULL;
121 #endif
122 #if defined(WIN32)
123 char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
124 boolean save_getreturn_status = getreturn_enabled;
125 #endif
126 #ifdef NOCWD_ASSUMPTIONS
127 char failbuf[BUFSZ];
128 #endif
129 boolean resuming = FALSE; /* assume new game */
131 #ifdef _MSC_VER
132 # ifdef DEBUG
133 /* set these appropriately for VS debugging */
134 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
135 _CrtSetReportMode(_CRT_ERROR,
136 _CRTDBG_MODE_DEBUG); /* | _CRTDBG_MODE_FILE);*/
137 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
138 /*| _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW);*/
139 /* use STDERR by default
140 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
141 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
142 # endif
143 #endif
145 #if defined(__BORLANDC__) && !defined(_WIN32)
146 startup();
147 #endif
149 #ifdef TOS
150 long clock_time;
151 if (*argv[0]) { /* only a CLI can give us argv[0] */
152 hname = argv[0];
153 run_from_desktop = FALSE;
154 } else
155 #endif
156 hname = "NetHack"; /* used for syntax messages */
158 #ifndef WIN32
159 choose_windows(DEFAULT_WINDOW_SYS);
160 #else
161 choose_windows(default_window_sys);
162 #endif
164 #if !defined(AMIGA) && !defined(GNUDOS)
165 /* Save current directory and make sure it gets restored when
166 * the game is exited.
168 if (getcwd(orgdir, sizeof orgdir) == (char *) 0)
169 error("NetHack: current directory path too long");
170 #ifndef NO_SIGNAL
171 signal(SIGINT,
172 (SIG_RET_TYPE) nethack_exit); /* restore original directory */
173 #endif
174 #endif /* !AMIGA && !GNUDOS */
176 dir = nh_getenv("NETHACKDIR");
177 if (dir == (char *) 0)
178 dir = nh_getenv("HACKDIR");
179 #ifdef EXEPATH
180 if (dir == (char *) 0)
181 dir = exepath(argv[0]);
182 #endif
183 #ifdef _MSC_VER
184 if (IsDebuggerPresent()) {
185 static char exepath[_MAX_PATH];
186 /* check if we're running under the debugger so we can get to the right folder anyway */
187 if (dir != (char *)0) {
188 char *top = (char *)0;
190 if (strlen(dir) < (_MAX_PATH - 1))
191 strcpy(exepath, dir);
192 top = strstr(exepath, "\\build\\.\\Debug");
193 if (!top) top = strstr(exepath, "\\build\\.\\Release");
194 if (top) {
195 *top = '\0';
196 if (strlen(exepath) < (_MAX_PATH - (strlen("\\binary\\") + 1))) {
197 Strcat(exepath, "\\binary\\");
198 if (strlen(exepath) < (PATHLEN - 1)) {
199 dir = exepath;
205 #endif
206 if (dir != (char *)0) {
207 int fd;
208 boolean have_syscf = FALSE;
210 (void) strncpy(hackdir, dir, PATHLEN - 1);
211 hackdir[PATHLEN - 1] = '\0';
212 #ifdef NOCWD_ASSUMPTIONS
214 int prefcnt;
216 fqn_prefix[0] = (char *) alloc(strlen(hackdir) + 2);
217 Strcpy(fqn_prefix[0], hackdir);
218 append_slash(fqn_prefix[0]);
219 for (prefcnt = 1; prefcnt < PREFIX_COUNT; prefcnt++)
220 fqn_prefix[prefcnt] = fqn_prefix[0];
222 #if defined(WIN32) || defined(MSDOS)
223 /* sysconf should be searched for in this location */
224 envp = nh_getenv("COMMONPROGRAMFILES");
225 if (envp) {
226 if ((sptr = index(envp, ';')) != 0)
227 *sptr = '\0';
228 if (strlen(envp) > 0) {
229 fqn_prefix[SYSCONFPREFIX] =
230 (char *) alloc(strlen(envp) + 10);
231 Strcpy(fqn_prefix[SYSCONFPREFIX], envp);
232 append_slash(fqn_prefix[SYSCONFPREFIX]);
233 Strcat(fqn_prefix[SYSCONFPREFIX], "NetHack\\");
237 /* okay so we have the overriding and definitive locaton
238 for sysconf, but only in the event that there is not a
239 sysconf file there (for whatever reason), check a secondary
240 location rather than abort. */
242 /* Is there a SYSCF_FILE there? */
243 fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
244 if (fd >= 0) {
245 /* readable */
246 close(fd);
247 have_syscf = TRUE;
250 if (!have_syscf) {
251 /* No SYSCF_FILE where there should be one, and
252 without an installer, a user may not be able
253 to place one there. So, let's try somewhere else... */
254 fqn_prefix[SYSCONFPREFIX] = fqn_prefix[0];
256 /* Is there a SYSCF_FILE there? */
257 fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
258 if (fd >= 0) {
259 /* readable */
260 close(fd);
261 have_syscf = TRUE;
265 /* user's home directory should default to this - unless
266 * overridden */
267 envp = nh_getenv("USERPROFILE");
268 if (envp) {
269 if ((sptr = index(envp, ';')) != 0)
270 *sptr = '\0';
271 if (strlen(envp) > 0) {
272 fqn_prefix[CONFIGPREFIX] =
273 (char *) alloc(strlen(envp) + 2);
274 Strcpy(fqn_prefix[CONFIGPREFIX], envp);
275 append_slash(fqn_prefix[CONFIGPREFIX]);
278 #endif
280 #endif
281 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
282 chdirx(dir, 1);
283 #endif
285 #ifdef AMIGA
286 #ifdef CHDIR
288 * If we're dealing with workbench, change the directory. Otherwise
289 * we could get "Insert disk in drive 0" messages. (Must be done
290 * before initoptions())....
292 if (argc == 0)
293 chdirx(HACKDIR, 1);
294 #endif
295 ami_wininit_data();
296 #endif
297 #ifdef WIN32
298 save_getreturn_status = getreturn_enabled;
299 raw_clear_screen();
300 getreturn_enabled = TRUE;
301 #endif
302 initoptions();
304 #ifdef NOCWD_ASSUMPTIONS
305 if (!validate_prefix_locations(failbuf)) {
306 raw_printf("Some invalid directory locations were specified:\n\t%s\n",
307 failbuf);
308 nethack_exit(EXIT_FAILURE);
310 #endif
312 #if defined(TOS) && defined(TEXTCOLOR)
313 if (iflags.BIOS && iflags.use_color)
314 set_colors();
315 #endif
316 if (!hackdir[0])
317 #if !defined(LATTICE) && !defined(AMIGA)
318 Strcpy(hackdir, orgdir);
319 #else
320 Strcpy(hackdir, HACKDIR);
321 #endif
322 if (argc > 1) {
323 if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
324 /* avoid matching "-dec" for DECgraphics; since the man page
325 * says -d directory, hope nobody's using -desomething_else
327 argc--;
328 argv++;
329 dir = argv[0] + 2;
330 if (*dir == '=' || *dir == ':')
331 dir++;
332 if (!*dir && argc > 1) {
333 argc--;
334 argv++;
335 dir = argv[0];
337 if (!*dir)
338 error("Flag -d must be followed by a directory name.");
339 Strcpy(hackdir, dir);
341 if (argc > 1) {
342 #if defined(WIN32)
343 int sfd = 0;
344 boolean tmpconsole = FALSE;
345 hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
346 #endif
348 * Now we know the directory containing 'record' and
349 * may do a prscore().
351 if (!strncmp(argv[1], "-s", 2)) {
352 #if defined(WIN32)
354 #if 0
355 if (!hStdOut) {
356 tmpconsole = fakeconsole();
358 #endif
360 * Check to see if we're redirecting to a file.
362 sfd = (int) _fileno(stdout);
363 redirect_stdout = (sfd >= 0) ? !isatty(sfd) : 0;
365 if (!redirect_stdout && !hStdOut) {
366 raw_printf(
367 "-s is not supported for the Graphical Interface\n");
368 nethack_exit(EXIT_SUCCESS);
370 #endif
372 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
373 chdirx(hackdir, 0);
374 #endif
375 #ifdef SYSCF
376 initoptions();
377 #endif
378 prscore(argc, argv);
379 #ifdef WIN32
380 if (tmpconsole) {
381 getreturn("to exit");
382 freefakeconsole();
383 tmpconsole = FALSE;
385 #endif
386 nethack_exit(EXIT_SUCCESS);
389 #ifdef MSWIN_GRAPHICS
390 if (!strncmpi(argv[1], "-clearreg", 6)) { /* clear registry */
391 mswin_destroy_reg();
392 nethack_exit(EXIT_SUCCESS);
394 #endif
395 /* Don't initialize the window system just to print usage */
396 if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) {
397 #if 0
398 if (!hStdOut) {
399 GUILaunched = 0;
400 tmpconsole = fakeconsole();
402 #endif
403 nhusage();
405 #ifdef WIN32
406 if (tmpconsole) {
407 getreturn("to exit");
408 freefakeconsole();
409 tmpconsole = FALSE;
411 #endif
412 nethack_exit(EXIT_SUCCESS);
417 #ifdef WIN32
418 getreturn_enabled = save_getreturn_status;
419 #endif
421 * It seems you really want to play.
423 #ifdef TOS
424 if (comp_times((long) time(&clock_time)))
425 error("Your clock is incorrectly set!");
426 #endif
427 if (!dlb_init()) {
428 pline(
429 "%s\n%s\n%s\n%s\n\nNetHack was unable to open the required file "
430 "\"%s\".%s",
431 copyright_banner_line(1), copyright_banner_line(2),
432 copyright_banner_line(3), copyright_banner_line(4), DLBFILE,
433 #ifdef WIN32
434 "\nAre you perhaps trying to run NetHack within a zip utility?");
435 #else
436 "");
437 #endif
438 error("dlb_init failure.");
441 u.uhp = 1; /* prevent RIP on early quits */
442 u.ux = 0; /* prevent flush_screen() */
444 /* chdir shouldn't be called before this point to keep the
445 * code parallel to other ports.
447 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
448 chdirx(hackdir, 1);
449 #endif
451 #if defined(MSDOS) || defined(WIN32)
452 /* In 3.6.0, several ports process options before they init
453 * the window port. This allows settings that impact window
454 * ports to be specified or read from the sys or user config files.
456 process_options(argc, argv);
458 #ifdef WIN32
460 if (!strncmpi(windowprocs.name, "mswin", 5))
461 NHWinMainInit();
462 else
464 if (!strncmpi(windowprocs.name, "tty", 3)) {
465 iflags.use_background_glyph = FALSE;
466 nttty_open(1);
467 } else {
468 iflags.use_background_glyph = TRUE;
470 #endif
471 #endif
473 #if defined(MSDOS) || defined(WIN32)
474 /* Player didn't specify any symbol set so use IBM defaults */
475 if (!symset[PRIMARY].name) {
476 load_symset("IBMGraphics_2", PRIMARY);
478 if (!symset[ROGUESET].name) {
479 load_symset("RogueEpyx", ROGUESET);
481 #endif
483 #if defined(MSDOS) || defined(WIN32)
484 init_nhwindows(&argc, argv);
485 #else
486 init_nhwindows(&argc, argv);
487 process_options(argc, argv);
488 #endif
490 #ifdef WIN32
491 toggle_mouse_support(); /* must come after process_options */
492 #endif
494 #ifdef MFLOPPY
495 set_lock_and_bones();
496 #ifndef AMIGA
497 copybones(FROMPERM);
498 #endif
499 #endif
501 /* strip role,race,&c suffix; calls askname() if plname[] is empty
502 or holds a generic user name like "player" or "games" */
503 plnamesuffix();
504 set_playmode(); /* sets plname to "wizard" for wizard mode */
505 #if 0
506 /* unlike Unix where the game might be invoked with a script
507 which forces a particular character name for each player
508 using a shared account, we always allow player to rename
509 the character during role/race/&c selection */
510 iflags.renameallowed = TRUE;
511 #else
512 /* until the getlock code is resolved, override askname()'s
513 setting of renameallowed; when False, player_selection()
514 won't resent renaming as an option */
515 iflags.renameallowed = FALSE;
516 #endif
518 #if defined(PC_LOCKING)
519 /* 3.3.0 added this to support detection of multiple games
520 * under the same plname on the same machine in a windowed
521 * or multitasking environment.
523 * That allows user confirmation prior to overwriting the
524 * level files of a game in progress.
526 * Also prevents an aborted game's level files from being
527 * overwritten without confirmation when a user starts up
528 * another game with the same player name.
530 #if defined(WIN32)
531 /* Obtain the name of the logged on user and incorporate
532 * it into the name. */
533 Sprintf(fnamebuf, "%s-%s", get_username(0), plname);
534 (void) fname_encode(
535 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.", '%',
536 fnamebuf, encodedfnamebuf, BUFSZ);
537 Sprintf(lock, "%s", encodedfnamebuf);
538 /* regularize(lock); */ /* we encode now, rather than substitute */
539 #else
540 Strcpy(lock, plname);
541 regularize(lock);
542 #endif
543 getlock();
544 #else /* What follows is !PC_LOCKING */
545 #ifdef AMIGA /* We'll put the bones & levels in the user specified directory \
546 -jhsa */
547 Strcat(lock, plname);
548 Strcat(lock, ".99");
549 #else
550 #ifndef MFLOPPY
551 /* I'm not sure what, if anything, is left here, but MFLOPPY has
552 * conflicts with set_lock_and_bones() in files.c.
554 Strcpy(lock, plname);
555 Strcat(lock, ".99");
556 regularize(lock); /* is this necessary? */
557 /* not compatible with full path a la AMIGA */
558 #endif
559 #endif
560 #endif /* PC_LOCKING */
562 /* Set up level 0 file to keep the game state.
564 fd = create_levelfile(0, (char *) 0);
565 if (fd < 0) {
566 raw_print("Cannot create lock file");
567 } else {
568 #ifdef WIN32
569 hackpid = GetCurrentProcessId();
570 #else
571 hackpid = 1;
572 #endif
573 write(fd, (genericptr_t) &hackpid, sizeof(hackpid));
574 nhclose(fd);
576 #ifdef MFLOPPY
577 level_info[0].where = ACTIVE;
578 #endif
581 * Initialize the vision system. This must be before mklev() on a
582 * new game or before a level restore on a saved game.
584 vision_init();
586 display_gamewindows();
587 #ifdef WIN32
588 getreturn_enabled = TRUE;
589 #endif
592 * First, try to find and restore a save file for specified character.
593 * We'll return here if new game player_selection() renames the hero.
595 attempt_restore:
596 if ((fd = restore_saved_game()) >= 0) {
597 #ifndef NO_SIGNAL
598 (void) signal(SIGINT, (SIG_RET_TYPE) done1);
599 #endif
600 #ifdef NEWS
601 if (iflags.news) {
602 display_file(NEWS, FALSE);
603 iflags.news = FALSE;
605 #endif
606 pline("Restoring save file...");
607 mark_synch(); /* flush output */
609 if (dorecover(fd)) {
610 resuming = TRUE; /* not starting new game */
611 if (discover)
612 You("are in non-scoring discovery mode.");
613 if (discover || wizard) {
614 if (yn("Do you want to keep the save file?") == 'n')
615 (void) delete_savefile();
616 else {
617 nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
623 if (!resuming) {
624 /* new game: start by choosing role, race, etc;
625 player might change the hero's name while doing that,
626 in which case we try to restore under the new name
627 and skip selection this time if that didn't succeed */
628 if (!iflags.renameinprogress) {
629 player_selection();
630 if (iflags.renameinprogress) {
631 /* player has renamed the hero while selecting role;
632 discard current lock file and create another for
633 the new character name */
634 #if 0 /* this needs to be reconciled with the getlock mess above... */
635 delete_levelfile(0); /* remove empty lock file */
636 getlock();
637 #endif
638 goto attempt_restore;
641 newgame();
642 if (discover)
643 You("are in non-scoring discovery mode.");
646 #ifndef NO_SIGNAL
647 (void) signal(SIGINT, SIG_IGN);
648 #endif
649 #ifdef OS2
650 gettty(); /* somehow ctrl-P gets turned back on during startup ... */
651 #endif
652 return resuming;
655 STATIC_OVL void
656 process_options(argc, argv)
657 int argc;
658 char *argv[];
660 int i;
663 * Process options.
665 while (argc > 1 && argv[1][0] == '-') {
666 argv++;
667 argc--;
668 switch (argv[0][1]) {
669 case 'a':
670 if (argv[0][2]) {
671 if ((i = str2align(&argv[0][2])) >= 0)
672 flags.initalign = i;
673 } else if (argc > 1) {
674 argc--;
675 argv++;
676 if ((i = str2align(argv[0])) >= 0)
677 flags.initalign = i;
679 break;
680 case 'D':
681 wizard = TRUE, discover = FALSE;
682 break;
683 case 'X':
684 discover = TRUE, wizard = FALSE;
685 break;
686 #ifdef NEWS
687 case 'n':
688 iflags.news = FALSE;
689 break;
690 #endif
691 case 'u':
692 if (argv[0][2])
693 (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
694 else if (argc > 1) {
695 argc--;
696 argv++;
697 (void) strncpy(plname, argv[0], sizeof(plname) - 1);
698 } else
699 raw_print("Player name expected after -u");
700 break;
701 #ifndef AMIGA
702 case 'I':
703 case 'i':
704 if (!strncmpi(argv[0] + 1, "IBM", 3)) {
705 load_symset("IBMGraphics", PRIMARY);
706 load_symset("RogueIBM", ROGUESET);
707 switch_symbols(TRUE);
709 break;
710 /* case 'D': */
711 case 'd':
712 if (!strncmpi(argv[0] + 1, "DEC", 3)) {
713 load_symset("DECGraphics", PRIMARY);
714 switch_symbols(TRUE);
716 break;
717 #endif
718 case 'g':
719 if (argv[0][2]) {
720 if ((i = str2gend(&argv[0][2])) >= 0)
721 flags.initgend = i;
722 } else if (argc > 1) {
723 argc--;
724 argv++;
725 if ((i = str2gend(argv[0])) >= 0)
726 flags.initgend = i;
728 break;
729 case 'p': /* profession (role) */
730 if (argv[0][2]) {
731 if ((i = str2role(&argv[0][2])) >= 0)
732 flags.initrole = i;
733 } else if (argc > 1) {
734 argc--;
735 argv++;
736 if ((i = str2role(argv[0])) >= 0)
737 flags.initrole = i;
739 break;
740 case 'r': /* race */
741 if (argv[0][2]) {
742 if ((i = str2race(&argv[0][2])) >= 0)
743 flags.initrace = i;
744 } else if (argc > 1) {
745 argc--;
746 argv++;
747 if ((i = str2race(argv[0])) >= 0)
748 flags.initrace = i;
750 break;
751 #ifdef MFLOPPY
752 #ifndef AMIGA
753 /* Player doesn't want to use a RAM disk
755 case 'R':
756 ramdisk = FALSE;
757 break;
758 #endif
759 #endif
760 #ifdef AMIGA
761 /* interlaced and non-interlaced screens */
762 case 'L':
763 bigscreen = 1;
764 break;
765 case 'l':
766 bigscreen = -1;
767 break;
768 #endif
769 #ifdef WIN32
770 case 'w': /* windowtype */
771 if (strncmpi(&argv[0][2], "tty", 3)) {
772 nttty_open(1);
775 else {
776 NHWinMainInit();
779 choose_windows(&argv[0][2]);
780 break;
781 #endif
782 case '@':
783 flags.randomall = 1;
784 break;
785 default:
786 if ((i = str2role(&argv[0][1])) >= 0) {
787 flags.initrole = i;
788 break;
789 } else
790 raw_printf("\nUnknown switch: %s", argv[0]);
791 /* FALL THROUGH */
792 case '?':
793 nhusage();
794 nethack_exit(EXIT_SUCCESS);
799 STATIC_OVL void
800 nhusage()
802 char buf1[BUFSZ], buf2[BUFSZ], *bufptr;
804 buf1[0] = '\0';
805 bufptr = buf1;
807 #define ADD_USAGE(s) \
808 if ((strlen(buf1) + strlen(s)) < (BUFSZ - 1)) \
809 Strcat(bufptr, s);
811 /* -role still works for those cases which aren't already taken, but
812 * is deprecated and will not be listed here.
814 (void) Sprintf(buf2, "\nUsage:\n%s [-d dir] -s [-r race] [-p profession] "
815 "[maxrank] [name]...\n or",
816 hname);
817 ADD_USAGE(buf2);
819 (void) Sprintf(
820 buf2, "\n%s [-d dir] [-u name] [-r race] [-p profession] [-[DX]]",
821 hname);
822 ADD_USAGE(buf2);
823 #ifdef NEWS
824 ADD_USAGE(" [-n]");
825 #endif
826 #ifndef AMIGA
827 ADD_USAGE(" [-I] [-i] [-d]");
828 #endif
829 #ifdef MFLOPPY
830 #ifndef AMIGA
831 ADD_USAGE(" [-R]");
832 #endif
833 #endif
834 #ifdef AMIGA
835 ADD_USAGE(" [-[lL]]");
836 #endif
837 if (!iflags.window_inited)
838 raw_printf("%s\n", buf1);
839 else
840 (void) printf("%s\n", buf1);
841 #undef ADD_USAGE
844 #ifdef CHDIR
845 void
846 chdirx(dir, wr)
847 char *dir;
848 boolean wr;
850 #ifdef AMIGA
851 static char thisdir[] = "";
852 #else
853 static char thisdir[] = ".";
854 #endif
855 if (dir && chdir(dir) < 0) {
856 error("Cannot chdir to %s.", dir);
859 #ifndef AMIGA
860 /* Change the default drive as well.
862 chdrive(dir);
863 #endif
865 /* warn the player if we can't write the record file */
866 /* perhaps we should also test whether . is writable */
867 /* unfortunately the access system-call is worthless */
868 if (wr)
869 check_recordfile(dir ? dir : thisdir);
871 #endif /* CHDIR */
873 #ifdef PORT_HELP
874 #if defined(MSDOS) || defined(WIN32)
875 void
876 port_help()
878 /* display port specific help file */
879 display_file(PORT_HELP, 1);
881 #endif /* MSDOS || WIN32 */
882 #endif /* PORT_HELP */
884 /* validate wizard mode if player has requested access to it */
885 boolean
886 authorize_wizard_mode()
888 if (!strcmp(plname, WIZARD_NAME))
889 return TRUE;
890 return FALSE;
893 #ifdef EXEPATH
894 #ifdef __DJGPP__
895 #define PATH_SEPARATOR '/'
896 #else
897 #define PATH_SEPARATOR '\\'
898 #endif
900 #ifdef WIN32
901 static char exenamebuf[PATHLEN];
902 extern HANDLE hConIn;
903 extern HANDLE hConOut;
904 boolean has_fakeconsole;
906 char *
907 exename()
909 int bsize = PATHLEN;
910 char *tmp = exenamebuf, *tmp2;
912 #ifdef UNICODE
914 TCHAR wbuf[PATHLEN * 4];
915 GetModuleFileName((HANDLE) 0, wbuf, PATHLEN * 4);
916 WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL);
918 #else
919 *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0';
920 #endif
921 tmp2 = strrchr(tmp, PATH_SEPARATOR);
922 if (tmp2)
923 *tmp2 = '\0';
924 tmp2++;
925 return tmp2;
928 boolean
929 fakeconsole(void)
931 if (!hStdOut) {
932 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
933 HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
935 if (!hStdOut && !hStdIn) {
936 /* Bool rval; */
937 AllocConsole();
938 AttachConsole(GetCurrentProcessId());
939 /* rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */
940 freopen("CON", "w", stdout);
941 freopen("CON", "r", stdin);
943 has_fakeconsole = TRUE;
946 /* Obtain handles for the standard Console I/O devices */
947 hConIn = GetStdHandle(STD_INPUT_HANDLE);
948 hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
949 #if 0
950 if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
951 /* Unable to set control handler */
952 cmode = 0; /* just to have a statement to break on for debugger */
954 #endif
955 return has_fakeconsole;
957 void freefakeconsole()
959 if (has_fakeconsole) {
960 FreeConsole();
963 #endif
965 #define EXEPATHBUFSZ 256
966 char exepathbuf[EXEPATHBUFSZ];
968 char *
969 exepath(str)
970 char *str;
972 char *tmp, *tmp2;
973 int bsize;
975 if (!str)
976 return (char *) 0;
977 bsize = EXEPATHBUFSZ;
978 tmp = exepathbuf;
979 #ifndef WIN32
980 Strcpy(tmp, str);
981 #else
982 #ifdef UNICODE
984 TCHAR wbuf[BUFSZ];
985 GetModuleFileName((HANDLE) 0, wbuf, BUFSZ);
986 WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL);
988 #else
989 *(tmp + GetModuleFileName((HANDLE) 0, tmp, bsize)) = '\0';
990 #endif
991 #endif
992 tmp2 = strrchr(tmp, PATH_SEPARATOR);
993 if (tmp2)
994 *tmp2 = '\0';
995 return tmp;
997 #endif /* EXEPATH */
999 /*pcmain.c*/