/* SCCS Id: @(#)amidos.c 3.2 2000/01/12 /* Copyright (c) Olaf Seibert, Nijmegen, The Netherlands, 1988,1990. */ /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1991,1992,1993,1996. */ /* NetHack may be freely redistributed. See license for details. */ /* * An assortment of imitations of cheap plastic MSDOS and Unix functions. */ #include "hack.h" #include "winami.h" /* Defined in config.h, let's undefine it here (static function below) */ #undef strcmpi #include #include #include #undef COUNT #ifdef __SASC_60 # include # include #endif #ifdef AZTEC_50 # include # undef strcmpi #endif /* Prototypes */ #include "NH:sys/amiga/winami.p" #include "NH:sys/amiga/amiwind.p" #include "NH:sys/amiga/amidos.p" extern char Initialized; extern struct window_procs amii_procs; #ifndef __SASC_60 int Enable_Abort = 0; /* for stdio package */ #endif /* Initial path, so we can find NetHack.cnf */ char PATH[PATHLEN] = "NetHack:"; static boolean record_exists(void); void flushout() { (void) fflush(stdout); } #ifndef getuid getuid() { return 1; } #endif #ifndef getlogin char * getlogin() { return ((char *) NULL); } #endif #ifndef AZTEC_50 int abs(x) int x; { return x < 0? -x: x; } #endif #ifdef SHELL int dosh() { int i; char buf[ 500 ]; extern struct ExecBase *SysBase; /* Only under 2.0 and later ROMs do we have System() */ if( SysBase->LibNode.lib_Version >= 37 && !amibbs) { getlin("Enter CLI Command...", buf ); i = System( buf, NULL ); } else { i = 0; pline("No mysterious force prevented you from using multitasking."); } return i; } #endif /* SHELL */ #ifdef MFLOPPY # include # define Sprintf (void) sprintf #define EXTENSION 72 /* * This routine uses an approximation of the free bytes on a disk. * How large a file you can actually write depends on the number of * extension blocks you need for it. * In each extenstion block there are maximum 72 pointers to blocks, * so every 73 disk blocks have only 72 available for data. * The (necessary) file header is also good for 72 data block pointers. */ /* TODO: update this for FFS */ long freediskspace(path) char *path; { register long freeBytes = 0; register struct InfoData *infoData; /* Remember... longword aligned */ char fileName[32]; /* * Find a valid path on the device of which we want the free space. * If there is a colon in the name, it is an absolute path * and all up to the colon is everything we need. * Remember slashes in a volume name are allowed! * If there is no colon, it is relative to the current directory, * so must be on the current device, so "" is enough... */ { register char *colon; strncpy(fileName, path, sizeof(fileName) - 1); fileName[31] = 0; if (colon = index(fileName, ':')) colon[1] = '\0'; else fileName[0] = '\0'; } { BPTR fileLock; infoData = (struct InfoData *) alloc(sizeof(struct InfoData)); if (fileLock = Lock(fileName, SHARED_LOCK)) { if (Info(fileLock, infoData)) { /* We got a kind of DOS volume, since we can Lock it. */ /* Calculate number of blocks available for new file */ /* Kludge for the ever-full VOID: (oops RAM:) device */ if (infoData->id_UnitNumber == -1 && infoData->id_NumBlocks == infoData->id_NumBlocksUsed) { freeBytes = AvailMem(0L) - 64 * 1024L; /* Just a stupid guess at the */ /* Ram-Handler overhead per block: */ freeBytes -= freeBytes/16; } else { /* Normal kind of DOS file system device/volume */ freeBytes = infoData->id_NumBlocks - infoData->id_NumBlocksUsed; freeBytes -= (freeBytes + EXTENSION) / (EXTENSION + 1); freeBytes *= infoData->id_BytesPerBlock; } if (freeBytes < 0) freeBytes = 0; } UnLock(fileLock); } free(infoData); return freeBytes; } } long filesize(file) char *file; { register BPTR fileLock; register struct FileInfoBlock *fileInfoBlock; register long size = 0; fileInfoBlock = (struct FileInfoBlock *)alloc(sizeof(struct FileInfoBlock)); if (fileLock = Lock(file, SHARED_LOCK)) { if (Examine(fileLock, fileInfoBlock)) { size = fileInfoBlock->fib_Size; } UnLock(fileLock); } free(fileInfoBlock); return size; } #if 0 void eraseall(path, files) const char *path, *files; { BPTR dirLock, dirLock2; struct FileInfoBlock *fibp; int chklen; #ifdef BETA if(files != alllevels)panic("eraseall"); #endif chklen=(int)index(files,'*')-(int)files; if (dirLock = Lock( (char *)path ,SHARED_LOCK)) { dirLock2=DupLock(dirLock); dirLock2= CurrentDir(dirLock2); fibp=AllocMem(sizeof(struct FileInfoBlock),0); if(fibp){ if(Examine(dirLock,fibp)){ while(ExNext(dirLock,fibp)){ if(!strncmp(fibp->fib_FileName,files,chklen)){ DeleteFile(fibp->fib_FileName); } } } FreeMem(fibp,sizeof(struct FileInfoBlock)); } UnLock(dirLock); UnLock(CurrentDir(dirLock2)); } } #endif /* This size makes that most files can be copied with two Read()/Write()s */ #define COPYSIZE 4096 char *CopyFile(from, to) const char *from, *to; { register BPTR fromFile, toFile; register char *buffer; register long size; char *error = NULL; buffer = (char *) alloc(COPYSIZE); if (fromFile = Open( (char *)from, MODE_OLDFILE)) { if (toFile = Open( (char *)to, MODE_NEWFILE)) { while (size = Read(fromFile, buffer, (long)COPYSIZE)) { if (size == -1){ error = "Read error"; break; } if (size != Write(toFile, buffer, size)) { error = "Write error"; break; } } Close(toFile); } else error = "Cannot open destination"; Close(fromFile); } else error = "Cannot open source (this should not occur)"; free(buffer); return error; } /* this should be replaced */ saveDiskPrompt(start) { char buf[BUFSIZ], *bp; BPTR fileLock; if (flags.asksavedisk) { /* Don't prompt if you can find the save file */ if (fileLock = Lock(SAVEF, SHARED_LOCK)) { UnLock(fileLock); #if defined(TTY_GRAPHICS) if(windowprocs.win_init_nhwindows!=amii_procs.win_init_nhwindows) clear_nhwindow( WIN_MAP ); #endif #if defined(AMII_GRAPHICS) if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows) clear_nhwindow( WIN_BASE ); #endif return 1; } pline( "If save file is on a SAVE disk, put that disk in now." ); if( strlen( SAVEF ) > QBUFSZ - 25 - 22 ) panic( "not enough buffer space for prompt" ); /* THIS IS A HACK */ #if defined(TTY_GRAPHICS) if(windowprocs.win_init_nhwindows!=amii_procs.win_init_nhwindows){ getlin("File name ?",buf); clear_nhwindow( WIN_MAP ); } #endif #if defined(AMII_GRAPHICS) if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows){ getlind("File name ?", buf, SAVEF); clear_nhwindow( WIN_BASE ); } #endif clear_nhwindow( WIN_MESSAGE); if (!start && *buf == '\033') return 0; /* Strip any whitespace. Also, if nothing was entered except * whitespace, do not change the value of SAVEF. */ for (bp = buf; *bp; bp++) { if (!isspace(*bp)) { strncpy(SAVEF, bp, PATHLEN); break; } } } return 1; } /* Return 1 if the record file was found */ static boolean record_exists() { FILE *file; if (file = fopenp(RECORD, "r")) { fclose(file); return TRUE; } return FALSE; } #ifdef MFLOPPY /* * Under MSDOS: Prompt for game disk, then check for record file. * For Amiga: do nothing, but called from restore.c */ void gameDiskPrompt(){} #endif /* * Add a slash to any name not ending in / or :. There must * be room for the /. */ void append_slash(name) char *name; { char *ptr; if (!*name)return; ptr = eos(name) - 1; if (*ptr != '/' && *ptr != ':') { *++ptr = '/'; *++ptr = '\0'; } } void getreturn(str) const char *str; { int ch; raw_printf("Hit %s.", str); while ((ch = nhgetch()) != '\n' && ch != '\r' ) continue; } /* Follow the PATH, trying to fopen the file. */ #define PATHSEP ';' FILE * fopenp(name, mode) register const char *name, *mode; { register char *bp, *pp, lastch; register FILE *fp; register BPTR theLock; char buf[BUFSIZ]; /* Try the default directory first. Then look along PATH. */ if (strlen(name) >= BUFSIZ) return( NULL ); strcpy(buf, name); if (theLock = Lock(buf, SHARED_LOCK)) { UnLock(theLock); if (fp = fopen(buf, mode)) return fp; } pp = PATH; while (pp && *pp) { bp = buf; while (*pp && *pp != PATHSEP){ if( bp > buf + BUFSIZ - 1 ) return( NULL ); lastch = *bp++ = *pp++; } if (lastch != ':' && lastch != '/' && bp != buf) *bp++ = '/'; if (bp + strlen(name) > buf + BUFSIZ - 1) return( NULL ); strcpy(bp, name); if (theLock = Lock(buf, SHARED_LOCK)) { UnLock(theLock); if (fp = fopen(buf, mode)) return fp; } if (*pp) pp++; } return NULL; } #endif /* MFLOPPY */ #ifdef CHDIR /* * A not general-purpose directory changing routine. * Assumes you want to return to the original directory eventually, * by chdir()ing to orgdir (which is defined in pcmain.c). * Assumes -1 is not a valid lock, since 0 is valid. */ #define NO_LOCK ((BPTR) -1) static BPTR OrgDirLock = NO_LOCK; chdir(dir) const char *dir; { extern char orgdir[]; if (dir == orgdir) { /* We want to go back to where we came from. */ if (OrgDirLock != NO_LOCK) { UnLock(CurrentDir(OrgDirLock)); OrgDirLock = NO_LOCK; } } else { /* * Go to some new place. If still at the original * directory, save the FileLock. */ BPTR newDir; if (newDir = Lock( (char *)dir, SHARED_LOCK)) { if (OrgDirLock == NO_LOCK) { OrgDirLock = CurrentDir(newDir); } else { UnLock(CurrentDir(newDir)); } } else { return -1; /* Failed */ } } /* CurrentDir always succeeds if you have a lock */ return 0; } #endif /* CHDIR */ /* Chdir back to original directory */ #undef exit void nethack_exit(code) { #ifdef CHDIR extern char orgdir[]; #endif #ifdef CHDIR chdir(orgdir); /* chdir, not chdirx */ #endif #ifdef AMII_GRAPHICS if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows) CleanUp(); #endif exit(code); } void regularize(s) /* normalize file name - we don't like :'s or /'s */ register char *s; { register char *lp; while((lp = index(s, ':')) || (lp = index(s, '/'))) *lp = '_'; }