/*
 * @(#)sysdep.amiga        Version Amiga 0.1     87/09/20
 *
 * (C) Copyright 1987 by John Gilmore
 * Copying and use of this program are controlled by the terms of the Free
 * Software Foundation's GNU Emacs General Public License.
 *
 * Amiga Changes Copyright 1988 by William Loftus. All rights reserved.
 *
 */

#ifndef lint
char sysdep_version[] = "@(#)sysdep.amiga gnuucp Version Amiga 0.10 BETA";
#endif

/*
 * Split out of uuslave.c by John Gilmore, 8 August 1987.
 * ported to the Amiga by William Loftus, 20 September 1987.
 */

/* FIXME -- System dependent defines (not really -- should be in a .h) */
/*
 * Timeout for raw characters -- if we don't hear a char within BYTE_TIMEOUT
 * seconds, we assume the other side has gone away.  Has nothing to do with
 * retransmission timeouts (if any!).
 */
extern int debug;

/* Amiga */
#include "uucp.h"
#include "modem.h"
#include <exec/types.h>
#include <ctype.h>
#include <fcntl.h>
#include <dos.h>
#include <exec/exec.h>
#include <devices/serial.h>
#include <devices/keymap.h>
#include <devices/timer.h>
#include <libraries/dos.h>
#include <signal.h>
#include <stdio.h>
#define NAMESIZE 128
#define FAILURE  1

/* Declarations for the serial read and write. */
unsigned char rs_in[2];
unsigned char rs_out[2];
extern struct MsgPort *CreatePort();
struct IOExtSer *Read_Request;
struct IOExtSer *Write_Request;
struct timerequest Timer;
struct MsgPort *Timer_Port = NULL;

extern char spool_dir[];
extern char path[];
extern int logfd;

void set_baud();

void destroy_lock();

int
openout(acu, baud)
  char *acu;
  int  baud;
{
        set_baud(baud);
        return SUCCESS;
}

/*
 * Basement level I/O routines
 *
 * xwrite() writes a character string to the serial port
 * xgetc() returns a character from the serial port, or an EOF for timeout.
 * sigint() restores the state of the serial port on exit.
 */
int
sigint()
{
    if (!CheckIO((char *) &Timer)) {
      AbortIO((char *) &Timer);
    }
    reset_modem();
    CloseDevice(Write_Request);
    DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
    FreeMem(Write_Request,sizeof(*Write_Request));
    CloseDevice(Read_Request);
    DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
    FreeMem(Read_Request,sizeof(*Read_Request));
    DeletePort(Timer_Port);
    if (logfd) close(logfd);
    chdir(path);
    destroy_lock();
    printf("\nAbnormal Termination.\n");
    exit(TRUE);
    return (TRUE);
}

void
cleanup()
{
    if (!CheckIO((char *) &Timer)) {
      AbortIO((char *) &Timer);
    }
    reset_modem();
    CloseDevice(Write_Request);
    DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
    FreeMem(Write_Request,sizeof(*Write_Request));
    CloseDevice(Read_Request);
    DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
    FreeMem(Read_Request,sizeof(*Read_Request));
    DeletePort(Timer_Port);
    if (logfd) close(logfd);
    chdir(path);
    destroy_lock();
    exit(TRUE);
}

int xgetc()
{
    int rd,ch;

         Timer.tr_time.tv_secs = BYTE_TIMEOUT;
         Timer.tr_time.tv_micro = 0;
         SendIO((char *) &Timer.tr_node);

         rd = FALSE;
         while (rd == FALSE) {
             chkabort();
             Wait((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
                  (1L << Timer_Port->mp_SigBit));
             if (CheckIO(Read_Request)) {
                 WaitIO(Read_Request);
                 ch=(int)rs_in[0];
                 rd = TRUE;
                 BeginIO(Read_Request);
             }
             if (rd == FALSE && CheckIO((char*) &Timer)) {
                 WaitIO((char*)&Timer);
                 return(EOF);
             }
         }     /* end while */

         if (!CheckIO((char *) &Timer)) {
            AbortIO((char *) &Timer);
         } else {
            WaitIO((char *) &Timer);
         }

         return((int)ch);
}

xwrite(buf,ctr)
char *buf;
int ctr;

{
    Write_Request->IOSer.io_Command = CMD_WRITE;
    Write_Request->IOSer.io_Length = ctr;
    Write_Request->IOSer.io_Data = (APTR) &buf[0];
    DoIO(Write_Request);
    return ctr;
}

void bzero(s, cnt)
 char   *s;
 int    cnt;
{
        int    i;
        for (i = 0; i < cnt; i++) {
                *s++ = '\0';
        }
}

void bcopy(from, to, cnt)
 char   *from;
 char   *to;
 int    cnt;
{
        int    i;
        for (i = 0; i < cnt; i++) {
                *to++ = *from++;
        }
}

/*
 * Create a temporary file name for receiving a file into.
 * "name" is the name we will actually eventually want to use for the file.
 * We currently ignore it, but some OS's that can't move files around
 * easily might want to e.g. put the temp file into the same directory
 * that this file is going into.
 *
 * FIXME:
 * This interface should be able to return a "possible" filename, and
 * be re-called if the name is already in use, to get another.
 * This avoids checking here whether the name is good -- saving system calls.
 */
char *
temp_filename(name)
        char *name;
{
        static char tname[NAMESIZE];

        strcpy(tname,name);
        return tname;
}


/*
 * Transform a filename from a uucp packet (in Unix format) into a local
 * filename that will work in the local file system.
 */
char *
munge_filename(name)
        char *name;
{
        return name;
}

hangup()
{
  reset_modem();
  if (system("run < NIL: > NIL: UUCP:c/uuxqt") == -1) {
     puts("UUCP: can not execute UUCP:c/uuxqt\n");
  }
  return SUCCESS;
}

static char names[3000];
static char *pointers[300];
static int file_pointer;

char *
work_scan(system_name)
  char *system_name;
{
    char name[128];
    int count;

    file_pointer = 0;

    if (strlen(system_name) > 7) {
       system_name[7] = '\0';
    }

    sprintf(name,"%s/C.%s#?", spool_dir, system_name);

    if (debug > 2) printf("Looking for %s\n",name);

    count = getfnl(name,names,sizeof(names),0);

    if (count > 0) {
      if (strbpl(pointers,300,names) != count) {
         printf("Too many command files for %s.\n",system_name);
         return (char *)NULL;
      }
    } else {
      return (char *)NULL;
    }
    if (debug > 2) printf("Found -> %s\n", pointers[file_pointer]);
    return (char *)1;
}

char *
work_next(system_name)
  char *system_name;
{
  if (debug > 2) printf("Found -> %s\n",pointers[file_pointer]);
  return pointers[file_pointer++];
}

void
amiga_setup()
{
        Read_Request =
           (struct IOExtSer *)AllocMem(sizeof(*Read_Request),
                                       MEMF_PUBLIC|MEMF_CLEAR);

        Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
        Read_Request->IOSer.io_Message.mn_ReplyPort =
                                       CreatePort("Read_RS",0);

        if(OpenDevice(SERIALNAME,NULL,Read_Request,NULL)) {
          printf("Can not open serial port for read.\n");
          DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
          FreeMem(Read_Request,sizeof(*Read_Request));
          destroy_lock();
          exit(TRUE);
        }

        Read_Request->IOSer.io_Length = 1;
        Read_Request->IOSer.io_Data = (APTR) &rs_in[0];

        Write_Request =
           (struct IOExtSer *)AllocMem(sizeof(*Write_Request),
                                       MEMF_PUBLIC|MEMF_CLEAR);

        Write_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;

        Write_Request->IOSer.io_Message.mn_ReplyPort =
                                        CreatePort("Write_RS",0);

        if(OpenDevice(SERIALNAME,NULL,Write_Request,NULL)) {
           printf("Can not open open serial port for write.\n");
           DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
           FreeMem(Write_Request,sizeof(*Write_Request));
           DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
           FreeMem(Read_Request,sizeof(*Read_Request));
           destroy_lock();
           exit(TRUE);
         }

        Write_Request->IOSer.io_Command = CMD_WRITE;
        Write_Request->IOSer.io_Length = 1;
        Write_Request->IOSer.io_Data = (APTR) &rs_out[0];

        Read_Request->io_SerFlags =  SERF_SHARED | SERF_XDISABLED;
        Read_Request->io_Baud = 2400;
        Read_Request->io_ReadLen = 8L;
        Read_Request->io_WriteLen = 8L;
        Read_Request->io_CtlChar = 0x11130000L;
        Read_Request->io_RBufLen = 4096;
        Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;

        DoIO(Read_Request);

        Read_Request->IOSer.io_Command = CMD_READ;

        Timer_Port = CreatePort("Timer Port",0L);

        if (OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &Timer, 0))  {
           printf("Can't open timer device.");
           DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
           FreeMem(Write_Request,sizeof(*Write_Request));
           DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
           FreeMem(Read_Request,sizeof(*Read_Request));
           destroy_lock();
           exit(TRUE);
        }

        Timer.tr_node.io_Message.mn_ReplyPort = Timer_Port;
        Timer.tr_node.io_Command = TR_ADDREQUEST;
        Timer.tr_node.io_Flags = 0;
        Timer.tr_node.io_Error = 0;

        BeginIO(Read_Request);

}

void set_baud(baud)
  int baud;
{
       /* if (!CheckIO(Read_Request)) */
        AbortIO(Read_Request);

        DEBUG(2, "Setting baud rate of %d\n", baud);

        Read_Request->io_Baud = baud;
        Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
        DoIO(Read_Request);

        Read_Request->IOSer.io_Command = CMD_READ;
        BeginIO(Read_Request);

        DEBUG(2, "Baud rate set\n",0);

}

