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