OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / sys / amiga / amidos.c
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
49 flushout()
50 {
51     (void) fflush(stdout);
52 }
53
54 #ifndef getuid
55 getuid()
56 {
57     return 1;
58 }
59 #endif
60
61 #ifndef getlogin
62 char *
63 getlogin()
64 {
65     return ((char *) NULL);
66 }
67 #endif
68
69 #ifndef AZTEC_50
70 int
71 abs(x)
72 int x;
73 {
74     return x < 0 ? -x : x;
75 }
76 #endif
77
78 #ifdef SHELL
79 int
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
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
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 #ifdef BETA
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 */
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
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
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
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
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 *
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
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
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
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 }