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