1 /*    SCCS Id: @(#)amidos.c     3.2    2000/01/12
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 #ifdef __SASC_60
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[ 500 ];
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     {
89 	getlin("Enter CLI Command...", buf );
90 	i = System( buf, NULL );
91     }
92     else
93     {
94 	i = 0;
95 	pline("No mysterious force prevented you from using multitasking.");
96     }
97     return i;
98 }
99 #endif /* SHELL */
100 
101 #ifdef MFLOPPY
102 # include <ctype.h>
103 
104 # define Sprintf (void) sprintf
105 
106 #define EXTENSION   72
107 
108 /*
109  *  This routine uses an approximation of the free bytes on a disk.
110  *  How large a file you can actually write depends on the number of
111  *  extension blocks you need for it.
112  *  In each extenstion block there are maximum 72 pointers to blocks,
113  *  so every 73 disk blocks have only 72 available for data.
114  *  The (necessary) file header is also good for 72 data block pointers.
115  */
116 /* TODO: update this for FFS */
117 long
freediskspace(path)118 freediskspace(path)
119 char *path;
120 {
121     register long freeBytes = 0;
122     register struct InfoData *infoData; /* Remember... longword aligned */
123     char fileName[32];
124 
125     /*
126      *  Find a valid path on the device of which we want the free space.
127      *  If there is a colon in the name, it is an absolute path
128      *  and all up to the colon is everything we need.
129      *  Remember slashes in a volume name are allowed!
130      *  If there is no colon, it is relative to the current directory,
131      *  so must be on the current device, so "" is enough...
132      */
133     {
134     register char *colon;
135 
136     strncpy(fileName, path, sizeof(fileName) - 1);
137     fileName[31] = 0;
138     if (colon = index(fileName, ':'))
139 	colon[1] = '\0';
140     else
141 	fileName[0] = '\0';
142     }
143     {
144     BPTR fileLock;
145     infoData = (struct InfoData *) alloc(sizeof(struct InfoData));
146     if (fileLock = Lock(fileName, SHARED_LOCK)) {
147 	if (Info(fileLock, infoData)) {
148 		/* We got a kind of DOS volume, since we can Lock it. */
149 		/* Calculate number of blocks available for new file */
150 		/* Kludge for the ever-full VOID: (oops RAM:) device */
151 	    if (infoData->id_UnitNumber == -1 &&
152 	      infoData->id_NumBlocks == infoData->id_NumBlocksUsed) {
153 		freeBytes = AvailMem(0L) - 64 * 1024L;
154 		    /* Just a stupid guess at the */
155 		    /* Ram-Handler overhead per block: */
156 		freeBytes -= freeBytes/16;
157 	    } else {
158 		/* Normal kind of DOS file system device/volume */
159 		freeBytes = infoData->id_NumBlocks - infoData->id_NumBlocksUsed;
160 		freeBytes -= (freeBytes + EXTENSION) / (EXTENSION + 1);
161 		freeBytes *= infoData->id_BytesPerBlock;
162 	    }
163 	    if (freeBytes < 0)
164 		freeBytes = 0;
165 	}
166 	UnLock(fileLock);
167     }
168     free(infoData);
169     return freeBytes;
170     }
171 }
172 
173 
174 long
filesize(file)175 filesize(file)
176 char *file;
177 {
178     register BPTR fileLock;
179     register struct FileInfoBlock *fileInfoBlock;
180     register long size = 0;
181 
182     fileInfoBlock = (struct FileInfoBlock *)alloc(sizeof(struct FileInfoBlock));
183     if (fileLock = Lock(file, SHARED_LOCK)) {
184 	if (Examine(fileLock, fileInfoBlock)) {
185 	    size = fileInfoBlock->fib_Size;
186 	}
187 	UnLock(fileLock);
188     }
189     free(fileInfoBlock);
190     return size;
191 }
192 
193 #if 0
194 void
195 eraseall(path, files)
196 const char *path, *files;
197 {
198     BPTR dirLock, dirLock2;
199     struct FileInfoBlock *fibp;
200     int chklen;
201 #ifdef BETA
202     if(files != alllevels)panic("eraseall");
203 #endif
204     chklen=(int)index(files,'*')-(int)files;
205 
206     if (dirLock = Lock( (char *)path ,SHARED_LOCK)) {
207 	dirLock2=DupLock(dirLock);
208 	dirLock2= CurrentDir(dirLock2);
209 	fibp=AllocMem(sizeof(struct FileInfoBlock),0);
210 	if(fibp){
211 	    if(Examine(dirLock,fibp)){
212 		while(ExNext(dirLock,fibp)){
213 		    if(!strncmp(fibp->fib_FileName,files,chklen)){
214 			DeleteFile(fibp->fib_FileName);
215 		    }
216 		}
217 	    }
218 	    FreeMem(fibp,sizeof(struct FileInfoBlock));
219 	}
220 	UnLock(dirLock);
221 	UnLock(CurrentDir(dirLock2));
222     }
223 }
224 #endif
225 
226 /* This size makes that most files can be copied with two Read()/Write()s */
227 
228 #define COPYSIZE    4096
229 
CopyFile(from,to)230 char *CopyFile(from, to)
231 const char *from, *to;
232 {
233     register BPTR fromFile, toFile;
234     register char *buffer;
235     register long size;
236     char *error = NULL;
237 
238     buffer = (char *) alloc(COPYSIZE);
239     if (fromFile = Open( (char *)from, MODE_OLDFILE)) {
240 	if (toFile = Open( (char *)to, MODE_NEWFILE)) {
241 	    while (size = Read(fromFile, buffer, (long)COPYSIZE)) {
242 		if (size == -1){
243 		    error = "Read error";
244 		    break;
245 		}
246 		if (size != Write(toFile, buffer, size)) {
247 		    error = "Write error";
248 		    break;
249 		}
250 	    }
251 	    Close(toFile);
252 	} else
253 	    error = "Cannot open destination";
254 	Close(fromFile);
255     } else
256 	error = "Cannot open source (this should not occur)";
257     free(buffer);
258     return error;
259 }
260 
261 
262 /* this should be replaced */
saveDiskPrompt(start)263 saveDiskPrompt(start)
264 {
265     char buf[BUFSIZ], *bp;
266     BPTR fileLock;
267 
268     if (flags.asksavedisk) {
269 	    /* Don't prompt if you can find the save file */
270 	if (fileLock = Lock(SAVEF, SHARED_LOCK)) {
271 	    UnLock(fileLock);
272 #if defined(TTY_GRAPHICS)
273 	    if(windowprocs.win_init_nhwindows!=amii_procs.win_init_nhwindows)
274 		clear_nhwindow( WIN_MAP );
275 #endif
276 #if defined(AMII_GRAPHICS)
277 	    if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows)
278 		clear_nhwindow( WIN_BASE );
279 #endif
280 	    return 1;
281 	}
282 	pline( "If save file is on a SAVE disk, put that disk in now." );
283 	if( strlen( SAVEF ) > QBUFSZ - 25 - 22 )
284 	    panic( "not enough buffer space for prompt" );
285 /* THIS IS A HACK */
286 #if defined(TTY_GRAPHICS)
287 	if(windowprocs.win_init_nhwindows!=amii_procs.win_init_nhwindows){
288 	    getlin("File name ?",buf);
289 	    clear_nhwindow( WIN_MAP );
290 	}
291 #endif
292 #if defined(AMII_GRAPHICS)
293 	if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows){
294 	    getlind("File name ?", buf, SAVEF);
295 	    clear_nhwindow( WIN_BASE );
296 	}
297 #endif
298 	clear_nhwindow( WIN_MESSAGE);
299 	if (!start && *buf == '\033')
300 	    return 0;
301 
302     /* Strip any whitespace. Also, if nothing was entered except
303      * whitespace, do not change the value of SAVEF.
304      */
305 	for (bp = buf; *bp; bp++) {
306 	    if (!isspace(*bp)) {
307 	    strncpy(SAVEF, bp, PATHLEN);
308 	    break;
309 	    }
310 	}
311     }
312     return 1;
313 }
314 
315 /* Return 1 if the record file was found */
316 static boolean
record_exists()317 record_exists()
318 {
319     FILE *file;
320 
321     if (file = fopenp(RECORD, "r")) {
322 	fclose(file);
323 	return TRUE;
324     }
325     return FALSE;
326 }
327 
328 #ifdef MFLOPPY
329 /*
330  * Under MSDOS: Prompt for game disk, then check for record file.
331  * For Amiga: do nothing, but called from restore.c
332  */
333 void
gameDiskPrompt()334 gameDiskPrompt(){}
335 #endif
336 
337 /*
338  * Add a slash to any name not ending in / or :.  There must
339  * be room for the /.
340  */
341 void
append_slash(name)342 append_slash(name)
343 char *name;
344 {
345     char *ptr;
346 
347     if (!*name)return;
348 
349     ptr = eos(name) - 1;
350     if (*ptr != '/' && *ptr != ':') {
351 	*++ptr = '/';
352 	*++ptr = '\0';
353     }
354 }
355 
356 
357 void
getreturn(str)358 getreturn(str)
359 const char *str;
360 {
361     int ch;
362 
363     raw_printf("Hit <RETURN> %s.", str);
364     while ((ch = nhgetch()) != '\n' && ch != '\r' )
365 	continue;
366 }
367 
368 /* Follow the PATH, trying to fopen the file.
369  */
370 #define PATHSEP    ';'
371 
372 FILE *
fopenp(name,mode)373 fopenp(name, mode)
374 register const char *name, *mode;
375 {
376     register char *bp, *pp, lastch;
377     register FILE *fp;
378     register BPTR theLock;
379     char buf[BUFSIZ];
380 
381     /* Try the default directory first.  Then look along PATH.
382      */
383     if (strlen(name) >= BUFSIZ) return( NULL );
384     strcpy(buf, name);
385     if (theLock = Lock(buf, SHARED_LOCK)) {
386 	UnLock(theLock);
387 	if (fp = fopen(buf, mode))
388 	    return fp;
389     }
390     pp = PATH;
391     while (pp && *pp) {
392 	bp = buf;
393 	while (*pp && *pp != PATHSEP){
394 	    if( bp > buf + BUFSIZ - 1 ) return( NULL );
395 	    lastch = *bp++ = *pp++;
396 	}
397 	if (lastch != ':' && lastch != '/' && bp != buf)
398 	    *bp++ = '/';
399 	if (bp + strlen(name) > buf + BUFSIZ - 1) return( NULL );
400 	strcpy(bp, name);
401 	if (theLock = Lock(buf, SHARED_LOCK)) {
402 	    UnLock(theLock);
403 	    if (fp = fopen(buf, mode)) return fp;
404 	}
405 	if (*pp)
406 	    pp++;
407     }
408     return NULL;
409 }
410 #endif /* MFLOPPY */
411 
412 #ifdef CHDIR
413 
414 /*
415  *  A not general-purpose directory changing routine.
416  *  Assumes you want to return to the original directory eventually,
417  *  by chdir()ing to orgdir (which is defined in pcmain.c).
418  *  Assumes -1 is not a valid lock, since 0 is valid.
419  */
420 
421 #define NO_LOCK     ((BPTR) -1)
422 
423 static BPTR OrgDirLock = NO_LOCK;
424 
chdir(dir)425 chdir(dir)
426 const char *dir;
427 {
428     extern char orgdir[];
429 
430     if (dir == orgdir) {
431 	    /* We want to go back to where we came from. */
432 	if (OrgDirLock != NO_LOCK) {
433 	    UnLock(CurrentDir(OrgDirLock));
434 	    OrgDirLock = NO_LOCK;
435 	}
436     } else {
437 	    /*
438 	     * Go to some new place. If still at the original
439 	     * directory, save the FileLock.
440 	     */
441 	BPTR newDir;
442 
443 	if (newDir = Lock( (char *)dir, SHARED_LOCK)) {
444 	    if (OrgDirLock == NO_LOCK) {
445 		OrgDirLock = CurrentDir(newDir);
446 	    } else {
447 		UnLock(CurrentDir(newDir));
448 	    }
449 	} else {
450 	    return -1;  /* Failed */
451 	}
452     }
453     /* CurrentDir always succeeds if you have a lock */
454     return 0;
455 }
456 
457 #endif /* CHDIR */
458 
459 /* Chdir back to original directory
460  */
461 #undef exit
462 void
nethack_exit(code)463 nethack_exit(code)
464 {
465 #ifdef CHDIR
466     extern char orgdir[];
467 #endif
468 
469 #ifdef CHDIR
470     chdir(orgdir);      /* chdir, not chdirx */
471 #endif
472 
473 #ifdef AMII_GRAPHICS
474     if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows)
475 	CleanUp();
476 #endif
477     exit(code);
478 }
479 
480 void
regularize(s)481 regularize(s)    /* normalize file name - we don't like :'s or /'s */
482 register char *s;
483 {
484     register char *lp;
485 
486     while((lp = index(s, ':')) || (lp = index(s, '/')))
487 	*lp = '_';
488 }
489