1 /* NetHack 3.7	pcsys.c	$NHDT-Date: 1596498283 2020/08/03 23:44:43 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.42 $ */
2 /*      Copyright (c) 2012 by Michael Allison              */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /*
6  *  System related functions for MSDOS, OS/2, TOS
7  */
8 
9 #define NEED_VARARGS
10 #include "hack.h"
11 #include "wintty.h"
12 
13 #include <ctype.h>
14 #include <fcntl.h>
15 #if !defined(MSDOS) && !defined(WIN_CE) && !defined(CROSS_TO_AMIGA)
16 #include <process.h>
17 #endif
18 #if defined(__GO32__) || defined(CROSS_TO_AMIGA)
19 #define P_WAIT 0
20 #define P_NOWAIT 1
21 #endif
22 #ifdef TOS
23 #include <osbind.h>
24 #endif
25 #if defined(MSDOS) && !defined(__GO32__)
26 #define findfirst findfirst_file
27 #define findnext findnext_file
28 #define filesize filesize_nh
29 #endif
30 
31 #if defined(MICRO) || defined(OS2)
32 void nethack_exit(int) NORETURN;
33 #else
34 #define nethack_exit exit
35 #endif
36 static void msexit(void);
37 
38 #ifdef MOVERLAY
39 extern void __far __cdecl _movepause(void);
40 extern void __far __cdecl _moveresume(void);
41 extern unsigned short __far __cdecl _movefpause;
42 extern unsigned short __far __cdecl _movefpaused;
43 #define __MOVE_PAUSE_DISK 2  /* Represents the executable file */
44 #define __MOVE_PAUSE_CACHE 4 /* Represents the cache memory */
45 #endif                       /* MOVERLAY */
46 FILE * fopenp(const char *name, const char *mode);
47 
48 #if defined(MICRO)
49 
50 void
flushout(void)51 flushout(void)
52 {
53     (void) fflush(stdout);
54     return;
55 }
56 
57 static const char *COMSPEC =
58 #ifdef TOS
59     "SHELL";
60 #else
61     "COMSPEC";
62 #endif
63 
64 #define getcomspec() nh_getenv(COMSPEC)
65 
66 #ifdef SHELL
67 int
dosh(void)68 dosh(void)
69 {
70 #ifndef NOCWD_ASSUMPTIONS
71     extern char orgdir[];
72 #endif
73     char *comspec;
74 #ifndef __GO32__
75     int spawnstat;
76 #endif
77 #if defined(MSDOS) && defined(NO_TERMS)
78     int grmode = iflags.grmode;
79 #endif
80     if ((comspec = getcomspec())) {
81 #ifndef TOS /* TOS has a variety of shells */
82         suspend_nhwindows(
83             "To return to NetHack, enter \"exit\" at the system prompt.\n");
84 #else
85 #if defined(MSDOS) && defined(NO_TERMS)
86         grmode = iflags.grmode;
87 #endif
88         suspend_nhwindows((char *) 0);
89 #endif /* TOS */
90 #ifndef NOCWD_ASSUMPTIONS
91         chdirx(orgdir, 0);
92 #endif
93 #ifdef __GO32__
94         if (system(comspec) < 0) { /* wsu@eecs.umich.edu */
95 #else
96 #ifdef MOVERLAY
97         /* Free the cache memory used by overlays, close .exe */
98         _movefpause |= __MOVE_PAUSE_DISK;
99         _movefpause |= __MOVE_PAUSE_CACHE;
100         _movepause();
101 #endif
102         spawnstat = spawnl(P_WAIT, comspec, comspec, (char *) 0);
103 #ifdef MOVERLAY
104         _moveresume();
105 #endif
106 
107         if (spawnstat < 0) {
108 #endif
109             raw_printf("Can't spawn \"%s\"!", comspec);
110             getreturn("to continue");
111         }
112 #ifdef TOS
113         /* Some shells (e.g. Gulam) turn the cursor off when they exit */
114         if (iflags.BIOS)
115             (void) Cursconf(1, -1);
116 #endif
117 #ifndef NOCWD_ASSUMPTIONS
118         chdirx(hackdir, 0);
119 #endif
120         get_scr_size(); /* maybe the screen mode changed (TH) */
121 #if defined(MSDOS) && defined(NO_TERMS)
122         if (grmode)
123             gr_init();
124 #endif
125         resume_nhwindows();
126     } else
127         pline("Can't find %s.", COMSPEC);
128     return 0;
129 }
130 #endif /* SHELL */
131 #endif /* MICRO */
132 
133 /*
134  * Add a backslash to any name not ending in /, \ or :	 There must
135  * be room for the \
136  */
137 void
138 append_slash(char *name)
139 {
140     char *ptr;
141 
142     if (!*name)
143         return;
144     ptr = name + (strlen(name) - 1);
145     if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
146         *++ptr = '\\';
147         *++ptr = '\0';
148     }
149     return;
150 }
151 
152 void
153 getreturn(const char *str)
154 {
155 #ifdef TOS
156     msmsg("Hit <Return> %s.", str);
157 #else
158 #ifdef CROSS_TO_AMIGA
159     (void) printf("Hit <Enter> %s.", str);
160 #else
161     msmsg("Hit <Enter> %s.", str);
162 #endif
163 #endif
164     while (pgetchar() != '\n')
165         ;
166     return;
167 }
168 
169 void msmsg
170 VA_DECL(const char *, fmt)
171 {
172     VA_START(fmt);
173     VA_INIT(fmt, const char *);
174 #if defined(MSDOS) && defined(NO_TERMS)
175     if (iflags.grmode)
176         gr_finish();
177 #endif
178     Vprintf(fmt, VA_ARGS);
179     flushout();
180     VA_END();
181     return;
182 }
183 
184 /*
185  * Follow the PATH, trying to fopen the file.
186  */
187 #ifdef TOS
188 #ifdef __MINT__
189 #define PATHSEP ':'
190 #else
191 #define PATHSEP ','
192 #endif
193 #else
194 #define PATHSEP ';'
195 #endif
196 
197 FILE *
198 fopenp(const char *name, const char *mode)
199 {
200     char buf[BUFSIZ], *bp, *pp, lastch = 0;
201     FILE *fp;
202 
203     /* Try the default directory first.  Then look along PATH.
204      */
205     (void) strncpy(buf, name, BUFSIZ - 1);
206     buf[BUFSIZ - 1] = '\0';
207     if ((fp = fopen(buf, mode)))
208         return fp;
209     else {
210         int ccnt = 0;
211         pp = getenv("PATH");
212         while (pp && *pp) {
213             bp = buf;
214             while (*pp && *pp != PATHSEP) {
215                 lastch = *bp++ = *pp++;
216                 ccnt++;
217             }
218             if (lastch != '\\' && lastch != '/') {
219                 *bp++ = '\\';
220                 ccnt++;
221             }
222             (void) strncpy(bp, name, (BUFSIZ - ccnt) - 2);
223             bp[BUFSIZ - ccnt - 1] = '\0';
224             if ((fp = fopen(buf, mode)))
225                 return fp;
226             if (*pp)
227                 pp++;
228         }
229     }
230 #ifdef OS2_CODEVIEW /* one more try for hackdir */
231     (void) strncpy(buf, hackdir, BUFSZ);
232     buf[BUFSZ - 1] = '\0';
233     if ((strlen(name) + 1 + strlen(buf)) < BUFSZ - 1) {
234         append_slash(buf);
235         Strcat(buf, name);
236     } else
237         impossible("fopenp() buffer too small for complete filename!");
238     if (fp = fopen(buf, mode))
239         return fp;
240 #endif
241     return (FILE *) 0;
242 }
243 
244 #if defined(MICRO) || defined(OS2)
245 void
246 nethack_exit(int code)
247 {
248     msexit();
249     exit(code);
250 }
251 
252 /* Chdir back to original directory
253  */
254 #ifdef TOS
255 extern boolean run_from_desktop; /* set in pcmain.c */
256 #endif
257 
258 static void
259 msexit(void)
260 {
261 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
262     extern char orgdir[];
263 #endif
264 
265     flushout();
266 #ifndef TOS
267     enable_ctrlP(); /* in case this wasn't done */
268 #endif
269 #if defined(CHDIR) && !defined(NOCWD_ASSUMPTIONS)
270     chdir(orgdir); /* chdir, not chdirx */
271     chdrive(orgdir);
272 #endif
273 #ifdef TOS
274     if (run_from_desktop)
275         getreturn("to continue"); /* so the user can read the score list */
276 #ifdef TEXTCOLOR
277     if (colors_changed)
278         restore_colors();
279 #endif
280 #endif
281     wait_synch();
282     return;
283 }
284 #endif /* MICRO || OS2 */
285