1 /* NetHack 3.6 amidos.c $NHDT-Date: 1432512796 2015/05/25 00:13:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
2 /* Copyright (c) Olaf Seibert, Nijmegen, The Netherlands, 1988,1990. */
3 /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1991,1992,1993,1996. */
4 /* NetHack may be freely redistributed. See license for details. */
5
6 /*
7 * An assortment of imitations of cheap plastic MSDOS and Unix functions.
8 */
9
10 #include "hack.h"
11 #include "winami.h"
12
13 /* Defined in config.h, let's undefine it here (static function below) */
14 #undef strcmpi
15
16 #include <libraries/dos.h>
17 #include <exec/execbase.h>
18 #include <intuition/intuition.h>
19
20 #undef COUNT
21 #if defined(__SASC_60) || defined(__GNUC__)
22 #include <proto/exec.h>
23 #include <proto/dos.h>
24 #endif
25
26 #ifdef AZTEC_50
27 #include <functions.h>
28 #undef strcmpi
29 #endif
30
31 /* Prototypes */
32 #include "NH:sys/amiga/winami.p"
33 #include "NH:sys/amiga/amiwind.p"
34 #include "NH:sys/amiga/amidos.p"
35
36 extern char Initialized;
37 extern struct window_procs amii_procs;
38
39 #ifndef __SASC_60
40 int Enable_Abort = 0; /* for stdio package */
41 #endif
42
43 /* Initial path, so we can find NetHack.cnf */
44 char PATH[PATHLEN] = "NetHack:";
45
46 static boolean record_exists(void);
47
48 void
flushout()49 flushout()
50 {
51 (void) fflush(stdout);
52 }
53
54 #ifndef getuid
getuid()55 getuid()
56 {
57 return 1;
58 }
59 #endif
60
61 #ifndef getlogin
62 char *
getlogin()63 getlogin()
64 {
65 return ((char *) NULL);
66 }
67 #endif
68
69 #ifndef AZTEC_50
70 int
abs(x)71 abs(x)
72 int x;
73 {
74 return x < 0 ? -x : x;
75 }
76 #endif
77
78 #ifdef SHELL
79 int
dosh()80 dosh()
81 {
82 int i;
83 char buf[BUFSZ];
84 extern struct ExecBase *SysBase;
85
86 /* Only under 2.0 and later ROMs do we have System() */
87 if (SysBase->LibNode.lib_Version >= 37 && !amibbs) {
88 getlin("Enter CLI Command...", buf);
89 if (buf[0] != '\033')
90 i = System(buf, NULL);
91 } else {
92 i = 0;
93 pline("No mysterious force prevented you from using multitasking.");
94 }
95 return i;
96 }
97 #endif /* SHELL */
98
99 #ifdef MFLOPPY
100 #include <ctype.h>
101
102 #define Sprintf (void) sprintf
103
104 #define EXTENSION 72
105
106 /*
107 * This routine uses an approximation of the free bytes on a disk.
108 * How large a file you can actually write depends on the number of
109 * extension blocks you need for it.
110 * In each extenstion block there are maximum 72 pointers to blocks,
111 * so every 73 disk blocks have only 72 available for data.
112 * The (necessary) file header is also good for 72 data block pointers.
113 */
114 /* TODO: update this for FFS */
115 long
freediskspace(path)116 freediskspace(path)
117 char *path;
118 {
119 #ifdef UNTESTED
120 /* these changes from Patric Mueller <bhaak@gmx.net> for AROS to
121 * handle larger disks. Also needs limits.h and aros/oldprograms.h
122 * for AROS. (keni)
123 */
124 unsigned long long freeBytes = 0;
125 #else
126 register long freeBytes = 0;
127 #endif
128 register struct InfoData *infoData; /* Remember... longword aligned */
129 char fileName[32];
130
131 /*
132 * Find a valid path on the device of which we want the free space.
133 * If there is a colon in the name, it is an absolute path
134 * and all up to the colon is everything we need.
135 * Remember slashes in a volume name are allowed!
136 * If there is no colon, it is relative to the current directory,
137 * so must be on the current device, so "" is enough...
138 */
139 {
140 register char *colon;
141
142 strncpy(fileName, path, sizeof(fileName) - 1);
143 fileName[31] = 0;
144 if (colon = index(fileName, ':'))
145 colon[1] = '\0';
146 else
147 fileName[0] = '\0';
148 }
149 {
150 BPTR fileLock;
151 infoData = (struct InfoData *) alloc(sizeof(struct InfoData));
152 if (fileLock = Lock(fileName, SHARED_LOCK)) {
153 if (Info(fileLock, infoData)) {
154 /* We got a kind of DOS volume, since we can Lock it. */
155 /* Calculate number of blocks available for new file */
156 /* Kludge for the ever-full VOID: (oops RAM:) device */
157 if (infoData->id_UnitNumber == -1
158 && infoData->id_NumBlocks == infoData->id_NumBlocksUsed) {
159 freeBytes = AvailMem(0L) - 64 * 1024L;
160 /* Just a stupid guess at the */
161 /* Ram-Handler overhead per block: */
162 freeBytes -= freeBytes / 16;
163 } else {
164 /* Normal kind of DOS file system device/volume */
165 freeBytes =
166 infoData->id_NumBlocks - infoData->id_NumBlocksUsed;
167 freeBytes -= (freeBytes + EXTENSION) / (EXTENSION + 1);
168 freeBytes *= infoData->id_BytesPerBlock;
169 #ifdef UNTESTED
170 if (freeBytes > LONG_MAX) {
171 freeBytes = LONG_MAX;
172 }
173 #endif
174 }
175 if (freeBytes < 0)
176 freeBytes = 0;
177 }
178 UnLock(fileLock);
179 }
180 free(infoData);
181 return freeBytes;
182 }
183 }
184
185 long
filesize(file)186 filesize(file)
187 char *file;
188 {
189 register BPTR fileLock;
190 register struct FileInfoBlock *fileInfoBlock;
191 register long size = 0;
192
193 fileInfoBlock =
194 (struct FileInfoBlock *) alloc(sizeof(struct FileInfoBlock));
195 if (fileLock = Lock(file, SHARED_LOCK)) {
196 if (Examine(fileLock, fileInfoBlock)) {
197 size = fileInfoBlock->fib_Size;
198 }
199 UnLock(fileLock);
200 }
201 free(fileInfoBlock);
202 return size;
203 }
204
205 #if 0
206 void
207 eraseall(path, files)
208 const char *path, *files;
209 {
210 BPTR dirLock, dirLock2;
211 struct FileInfoBlock *fibp;
212 int chklen;
213 #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
214 if(files != alllevels)panic("eraseall");
215 #endif
216 chklen=(int)index(files,'*')-(int)files;
217
218 if (dirLock = Lock( (char *)path ,SHARED_LOCK)) {
219 dirLock2=DupLock(dirLock);
220 dirLock2= CurrentDir(dirLock2);
221 fibp=AllocMem(sizeof(struct FileInfoBlock),0);
222 if(fibp){
223 if(Examine(dirLock,fibp)){
224 while(ExNext(dirLock,fibp)){
225 if(!strncmp(fibp->fib_FileName,files,chklen)){
226 DeleteFile(fibp->fib_FileName);
227 }
228 }
229 }
230 FreeMem(fibp,sizeof(struct FileInfoBlock));
231 }
232 UnLock(dirLock);
233 UnLock(CurrentDir(dirLock2));
234 }
235 }
236 #endif
237
238 /* This size makes that most files can be copied with two Read()/Write()s */
239
240 #if 0 /* Unused */
241 #define COPYSIZE 4096
242
243 char *CopyFile(from, to)
244 const char *from, *to;
245 {
246 register BPTR fromFile, toFile;
247 register char *buffer;
248 register long size;
249 char *error = NULL;
250
251 buffer = (char *) alloc(COPYSIZE);
252 if (fromFile = Open( (char *)from, MODE_OLDFILE)) {
253 if (toFile = Open( (char *)to, MODE_NEWFILE)) {
254 while (size = Read(fromFile, buffer, (long)COPYSIZE)) {
255 if (size == -1){
256 error = "Read error";
257 break;
258 }
259 if (size != Write(toFile, buffer, size)) {
260 error = "Write error";
261 break;
262 }
263 }
264 Close(toFile);
265 } else
266 error = "Cannot open destination";
267 Close(fromFile);
268 } else
269 error = "Cannot open source (this should not occur)";
270 free(buffer);
271 return error;
272 }
273 #endif
274
275 /* this should be replaced */
saveDiskPrompt(start)276 saveDiskPrompt(start)
277 {
278 char buf[BUFSIZ], *bp;
279 BPTR fileLock;
280 if (sysflags.asksavedisk) {
281 /* Don't prompt if you can find the save file */
282 if (fileLock = Lock(SAVEF, SHARED_LOCK)) {
283 UnLock(fileLock);
284 #if defined(TTY_GRAPHICS)
285 if (windowprocs.win_init_nhwindows
286 != amii_procs.win_init_nhwindows)
287 clear_nhwindow(WIN_MAP);
288 #endif
289 #if defined(AMII_GRAPHICS)
290 if (windowprocs.win_init_nhwindows
291 == amii_procs.win_init_nhwindows)
292 clear_nhwindow(WIN_BASE);
293 #endif
294 return 1;
295 }
296 pline("If save file is on a SAVE disk, put that disk in now.");
297 if (strlen(SAVEF) > QBUFSZ - 25 - 22)
298 panic("not enough buffer space for prompt");
299 /* THIS IS A HACK */
300 #if defined(TTY_GRAPHICS)
301 if (windowprocs.win_init_nhwindows != amii_procs.win_init_nhwindows) {
302 getlin("File name ?", buf);
303 clear_nhwindow(WIN_MAP);
304 }
305 #endif
306 #if defined(AMII_GRAPHICS)
307 if (windowprocs.win_init_nhwindows == amii_procs.win_init_nhwindows) {
308 getlind("File name ?", buf, SAVEF);
309 clear_nhwindow(WIN_BASE);
310 }
311 #endif
312 clear_nhwindow(WIN_MESSAGE);
313 if (!start && *buf == '\033')
314 return 0;
315
316 /* Strip any whitespace. Also, if nothing was entered except
317 * whitespace, do not change the value of SAVEF.
318 */
319 for (bp = buf; *bp; bp++) {
320 if (!isspace(*bp)) {
321 strncpy(SAVEF, bp, PATHLEN);
322 break;
323 }
324 }
325 }
326 return 1;
327 }
328
329 /* Return 1 if the record file was found */
330 static boolean
record_exists()331 record_exists()
332 {
333 FILE *file;
334
335 if (file = fopenp(RECORD, "r")) {
336 fclose(file);
337 return TRUE;
338 }
339 return FALSE;
340 }
341
342 #ifdef MFLOPPY
343 /*
344 * Under MSDOS: Prompt for game disk, then check for record file.
345 * For Amiga: do nothing, but called from restore.c
346 */
347 void
gameDiskPrompt()348 gameDiskPrompt()
349 {
350 }
351 #endif
352
353 /*
354 * Add a slash to any name not ending in / or :. There must
355 * be room for the /.
356 */
357 void
append_slash(name)358 append_slash(name)
359 char *name;
360 {
361 char *ptr;
362
363 if (!*name)
364 return;
365
366 ptr = eos(name) - 1;
367 if (*ptr != '/' && *ptr != ':') {
368 *++ptr = '/';
369 *++ptr = '\0';
370 }
371 }
372
373 void
getreturn(str)374 getreturn(str)
375 const char *str;
376 {
377 int ch;
378
379 raw_printf("Hit <RETURN> %s.", str);
380 while ((ch = nhgetch()) != '\n' && ch != '\r')
381 continue;
382 }
383
384 /* Follow the PATH, trying to fopen the file.
385 */
386 #define PATHSEP ';'
387
388 FILE *
fopenp(name,mode)389 fopenp(name, mode)
390 register const char *name, *mode;
391 {
392 register char *bp, *pp, lastch;
393 register FILE *fp;
394 register BPTR theLock;
395 char buf[BUFSIZ];
396
397 /* Try the default directory first. Then look along PATH.
398 */
399 if (strlen(name) >= BUFSIZ)
400 return (NULL);
401 strcpy(buf, name);
402 if (theLock = Lock(buf, SHARED_LOCK)) {
403 UnLock(theLock);
404 if (fp = fopen(buf, mode))
405 return fp;
406 }
407 pp = PATH;
408 while (pp && *pp) {
409 bp = buf;
410 while (*pp && *pp != PATHSEP) {
411 if (bp > buf + BUFSIZ - 1)
412 return (NULL);
413 lastch = *bp++ = *pp++;
414 }
415 if (lastch != ':' && lastch != '/' && bp != buf)
416 *bp++ = '/';
417 if (bp + strlen(name) > buf + BUFSIZ - 1)
418 return (NULL);
419 strcpy(bp, name);
420 if (theLock = Lock(buf, SHARED_LOCK)) {
421 UnLock(theLock);
422 if (fp = fopen(buf, mode))
423 return fp;
424 }
425 if (*pp)
426 pp++;
427 }
428 return NULL;
429 }
430 #endif /* MFLOPPY */
431
432 #ifdef CHDIR
433
434 /*
435 * A not general-purpose directory changing routine.
436 * Assumes you want to return to the original directory eventually,
437 * by chdir()ing to orgdir (which is defined in pcmain.c).
438 * Assumes -1 is not a valid lock, since 0 is valid.
439 */
440
441 #define NO_LOCK ((BPTR) -1)
442
443 static BPTR OrgDirLock = NO_LOCK;
444
chdir(dir)445 chdir(dir) char *dir;
446 {
447 extern char orgdir[];
448
449 if (dir == orgdir) {
450 /* We want to go back to where we came from. */
451 if (OrgDirLock != NO_LOCK) {
452 UnLock(CurrentDir(OrgDirLock));
453 OrgDirLock = NO_LOCK;
454 }
455 } else {
456 /*
457 * Go to some new place. If still at the original
458 * directory, save the FileLock.
459 */
460 BPTR newDir;
461
462 if (newDir = Lock((char *) dir, SHARED_LOCK)) {
463 if (OrgDirLock == NO_LOCK) {
464 OrgDirLock = CurrentDir(newDir);
465 } else {
466 UnLock(CurrentDir(newDir));
467 }
468 } else {
469 return -1; /* Failed */
470 }
471 }
472 /* CurrentDir always succeeds if you have a lock */
473 return 0;
474 }
475
476 #endif /* CHDIR */
477
478 /* Chdir back to original directory
479 */
480 #undef exit
481 void
nethack_exit(code)482 nethack_exit(code)
483 {
484 #ifdef CHDIR
485 extern char orgdir[];
486 #endif
487
488 #ifdef CHDIR
489 chdir(orgdir); /* chdir, not chdirx */
490 #endif
491
492 #ifdef AMII_GRAPHICS
493 if (windowprocs.win_init_nhwindows == amii_procs.win_init_nhwindows)
494 CleanUp();
495 #endif
496 exit(code);
497 }
498
regularize(s)499 void regularize(s) /* normalize file name - we don't like :'s or /'s */
500 register char *s;
501 {
502 register char *lp;
503
504 while ((lp = index(s, ':')) || (lp = index(s, '/')))
505 *lp = '_';
506 }
507