/* hosts/amiga/amiga.c ** ** Collects all routines needed for the Amiga which are not specific ** enough to go into one of the other files. ** ** 25-Feb-93 [lars] ** 28-Feb-93 [lars] Moved to DICE 2.07.53 ** 02-Apr-93 [lars] send_udp() dummy added. ** 09-Apr-93 [lars] Overloaded break check of the compiler. ** 17-Jun-93 [lars] Put in support for AmiTCP. ** 20-Sep-93 [lars] Fixed small but fatal bug in chmod(). */ /*-----------------------------------------------------------------------*/ #include <exec/types.h> #include <exec/libraries.h> #include <exec/execbase.h> #ifdef INCLUDE_VERSION #include <dos/dos.h> #include <clib/dos_protos.h> #else #include <libraries/dos.h> #endif #include <stdlib.h> #include <stdio.h> #include <strings.h> #include "config.h" #include "patchlevel.h" #include "nsignal.h" #if defined(_DCC) && !defined(INCLUDE_VERSION) /* for fstat() */ #include <sys/stat.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #endif extern struct Library *SysBase; /* DICE runtime will open it */ void init_rusage(void); /*-----------------------------------------------------------------------*/ #ifdef INCLUDE_VERSION # define OSVERSION "2.0" # ifndef AMIGA_TCP # define NETVERSION # define NETSTRING "" # elif defined(AMITCP) # define NETVERSION ", AmiTCP" # define NETSTRING NETVERSION # else /* AS225 */ # define NETVERSION ", AS225" # define NETSTRING NETVERSION # endif /* type of net interface */ #else /* OS 1.3 */ # define OSVERSION "1.3" # define NETVERSION # define NETSTRING "" #endif static char ver[] = "\0$VER: Amylaar-LPMud " GAME_VERSION PATCH_LEVEL " (OS " OSVERSION NETVERSION ") "; static APTR oldException = NULL; static ULONG oldExceptSig = 0L; extern ULONG sys_signal_alarm; /*----------------------------------------------------------------------- ** void amiga_init(void); ** void amiga_end(void); ** ** Perform all necessary setup/setdown operations. */ void amiga_init (void) { char *vp = ver; /* so the version string won't be optimized away */ printf ("dr %s%s (Amiga, OS %s%s)\n", GAME_VERSION, PATCH_LEVEL, OSVERSION, NETSTRING); #ifdef INCLUDE_VERSION if (SysBase->lib_Version < 36) { printf ("Fatal: Need OS 2.0 to run.\n"); exit(20); } #endif init_rusage(); #if defined(AMIGA_TCP) amiga_sockinit(); #endif oldException = ((struct Task*)FindTask(NULL))->tc_ExceptCode; oldExceptSig = SetExcept(0L, 0L); } void amiga_end (void) { static short done = 0; if (done++) return; /* May be called multiple times */ SetExcept (oldExceptSig, EXT_SIGINT | EXT_SIGHUP | sys_signal_alarm); ((struct Task*)FindTask(NULL))->tc_ExceptCode = oldException; #if defined(AMIGA_TCP) amiga_sockexit(); #endif } /*----------------------------------------------------------------------- ** int send_udp (char *to_host, int to_port, char *msg) ** ** This is normally implemented in comm1.c when UDP communications ** are used. Unfortunately, since make_func doesn't incarnate a full ** preprocessor, compiling with simulated sockets makes interpret.c access ** send_udp() even though comm1.c doesn't know about it. ** So this dummy... */ #ifndef UDP_SEND int send_udp(char *to_host, int to_port, char *msg) { return 0; } #endif /*----------------------------------------------------------------------- ** char *do_ixconvert (char *name) ** char *ixconvert (char *fname) ** char *ixconvert2 (char *fname) ** ** do_ixconvert() takes a unix filename and amigaizes by changing it. ** ** ixconvert() and ixconvert2() are the interface, each providing ** an own static buffer for the changed name, thus keeping the original ** intact. */ #define BUFLEN 1024 char *do_ixconvert (char *name) { char *s1; int flag; flag = 0; while (!flag) { /* Replace ':/' by ':' */ if ((s1 = strstr (name, ":/")) != NULL) strcpy (s1+1, s1+2); /* Replace ':./' by ':' */ else if ((s1 = strstr (name, ":./")) != NULL) strcpy (s1+1, s1+3); else flag = 1; } /* Replace ':../' by ':/' */ if ((s1 = strstr (name, ":../")) != NULL) strcpy (s1+1, s1+3); /* Remove leading '/' */ for (s1 = name; *s1 == '/'; s1++); if (s1 != name) strcpy (name, s1); /* Replace '../' by '/' */ for (s1 = name; (s1 = strstr (s1, "../")) != NULL; strcpy (s1, s1+2)); /* Replace './' by '' */ for (s1 = name; (s1 = strstr (s1, "./")) != NULL; strcpy (s1, s1+2)); /* Remove trailing '/.' */ while ((flag=strlen(name)) >= 2 && !strcmp (s1 = name+flag-2, "/.")) *s1 = '\0'; /* Replace trailing '/..' by '/' */ if (strlen(name) >= 3 && !strcmp (s1 = name+strlen(name)-3, "/..")) strcpy (s1, "/"); /* Replace '..' name by '/' */ if (!strcmp (name, "..")) strcpy (name, "/"); /* Replace '.' name by '' */ if (!strcmp (name, ".")) *name = '\0'; return name; } char *ixconvert (char *fname) { static char name[BUFLEN]; if (strlen(fname) < BUFLEN) strcpy (name, fname); else { strncpy (name, fname, BUFLEN-1); name[BUFLEN-1] = '\0'; } return do_ixconvert (name); } char *ixconvert2 (char *fname) { static char name[BUFLEN]; if (strlen(fname) < BUFLEN) strcpy (name, fname); else { strncpy (name, fname, BUFLEN-1); name[BUFLEN-1] = '\0'; } return do_ixconvert (name); } /*----------------------------------------------------------------------- ** Set the access mode of a file. ** For Amiga-OS, only the owner access can be set. ** It is not guaranteed that the mode will be checked with any OS ** older than 2.0. */ int chmod (char *file, long mode) { BPTR lock; struct FileInfoBlock *info; int rc; /* Unix mode 'rwx??????' => DOS mode 'rwxw' aka 'rwxd'. ** Well, this should be done using the FIB* constants from dos.h ** but they will hardly change and 'knowing' them keeps this a one-liner. ** Note that the Amiga-OS bits disallow the operation when set. */ mode = ~((mode & 0700) >> 5 | (mode & 0200) >> 7) & 017; info = (struct FileInfoBlock *) malloc (sizeof (struct FileInfoBlock)); if (info == NULL) return -1; rc = -1; if ((lock = Lock (file, SHARED_LOCK)) == NULL) goto chmod_exit; if (Examine (lock, info) == DOSFALSE) goto chmod_exit; UnLock (lock); if (SetProtection (file, (info->fib_Protection & (~017)) | mode) != DOSFALSE) rc = 0; chmod_exit: free (info); return rc; } /*----------------------------------------------------------------------- ** DICE-specifics. */ #if defined(_DCC) /*----------------------------------------------------------------------- ** The routine the DICE runtime lib will call for Ctrl-C checks. ** It is overloaded so it will work with LPMuds special signal handling. */ void chkabort(void) { check_signals(); } /*----------------------------------------------------------------------- ** DICE has the prototype, but not the fun... */ void *memchr (const void *buf, int c, size_t s) { while (s--) if (*(char *)buf == (char) c) return buf; else ((char *)buf)++; return NULL; } #ifndef INCLUDE_VERSION /* !OS 2.0 */ /*----------------------------------------------------------------------- ** DICE's implementation of fstat() uses dos ExamineFH() when running ** under OS 2.0. Unfortunately there's no stub for it the 1.3-amiga.lib ** so compiling for OS 1.3 can't be done. ** To circumvent this, this downstripped version of fstat() is used ** when compiling for OS 1.3. Due to that OS limitations, it doesn't ** work properly. */ typedef struct FileInfoBlock FileInfoBlock; fstat(int fd, struct stat *xstat) { int r = -1; _IOFDS *d; clrmem(xstat, sizeof(*xstat)); if (d = __getfh(fd)) { r = stat(d->fd_FileName, xstat); /* * extended size will not show up in examine if we have written * the active handle. */ { long pos = Seek(d->fd_Fh, 0L, 0); long siz; Seek(d->fd_Fh, 0L, 1); siz = Seek(d->fd_Fh, pos, -1); if (xstat->st_size < siz) xstat->st_size = siz; } } return(r); } #ifndef DICE206 /*----------------------------------------------------------------------- ** Not used with OS 1.3, but statically mentioned with the lib. */ LONG SystemTagList (UBYTE *command, /* struct TagItem * */ void *tags) { return 0; } #endif /* !DICE206 */ #endif /* !OS 2.0 */ #endif /* DICE */ /*************************************************************************/