/
driver3.2@242/autoconf/
driver3.2@242/doc/LPC/
driver3.2@242/hosts/
driver3.2@242/hosts/amiga/NetIncl/
driver3.2@242/hosts/amiga/NetIncl/netinet/
driver3.2@242/hosts/amiga/NetIncl/sys/
driver3.2@242/hosts/atari/
driver3.2@242/hosts/fcrypt/
driver3.2@242/mudlib/
driver3.2@242/mudlib/sys/
driver3.2@242/util/
driver3.2@242/util/indent/hosts/next/
driver3.2@242/util/make_docs/
/* 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 */

/*************************************************************************/