OSDN Git Service

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