home *** CD-ROM | disk | FTP | other *** search
- /*
- * SYSDEP.C
- *
- * (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.
- * Additional chgs Copyright 1989 by Matthew Dillon, All Rights Reserved.
- * Additional chgs Copyright 1993 by Michael B. Smith, All Rights Reserved.
- */
-
- #include "includes.h"
- #include <hardware/cia.h>
- #include <devices/timer.h>
- #include <devices/serial.h>
- #include <pwd.h>
- #include "uucp.h"
- #include "version.h"
- #include <OwnDevUnit.h>
-
- #define Assert(x) if (!(x)) _assert_failed(__LINE__);
-
- Prototype int openout (char *, int);
- Prototype void sigint (int);
- Prototype void cleanup (void);
- Prototype int xdatardy (void);
- Prototype int xgetc (int,int);
- Prototype int xwrite (const void *, int);
- Prototype int xwritea (const void *, int);
- Prototype int xxwrite (const void *, int, int);
- Prototype void SendBreak (void);
- Prototype int CheckCarrier (void);
- Prototype void munge_filename (char *, char *);
- Prototype int hangup (void);
- Prototype void set_dir (const char *dirname);
- Prototype int work_scan (char *);
- Prototype char *work_next (void);
- Prototype void amiga_setup (void);
- Prototype void set_baud (int);
- Prototype void OpenSerial (int);
- Prototype void CloseSerial (int);
- Prototype void xexit (int);
- Prototype void printc (unsigned char);
- Prototype void NiceAbortIO (void *);
-
- Prototype char *DeviceName;
- Prototype int DeviceUnit;
-
- char
- *DeviceName = "serial.device";
- int
- DeviceUnit = 0;
- static void
- _assert_failed (int);
-
- IDENT (".03");
-
- /*
- * Split out of uuslave.c by John Gilmore, 8 August 1987.
- * ported to the Amiga by William Loftus, 20 September 1987.
- * rewritten by Matthew Dillon, October 1989
- */
-
- struct IOExtSer
- Iosr,
- Iosw,
- Ioss;
- struct timerequest
- Iot0;
- char
- *OldTaskName;
- unsigned char
- XInBuf [512]; /* for xgetc() */
- int
- XInIdx = 0,
- XInLen = 0,
- IoswIP = 0,
- IosrIP = 0,
- IotIP = 0,
- InExitRoutine = 0,
- debugRead = 0;
-
- int
- openout (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.
- */
-
- void
- sigint (int sig)
- {
- xexit (10);
- return;
- }
-
-
- void
- cleanup (void)
- {
-
- signal (SIGINT, SIG_IGN);
-
- ++InExitRoutine;
-
- if (InExitRoutine == 1 && Iosr.IOSer.io_Device && CheckCarrier ())
- reset_modem ();
-
- CloseSerial (1);
-
- if (OldTaskName) {
- struct Task
- *task = (struct Task *) FindTask (NULL);
-
- task->tc_Node.ln_Name = OldTaskName;
- }
-
- if (Iot0.tr_node.io_Device) {
- CloseDevice ((struct IORequest *) &Iot0);
- Iot0.tr_node.io_Device = NULL;
- }
- if (Iot0.tr_node.io_Message.mn_ReplyPort) {
- DeletePort (Iot0.tr_node.io_Message.mn_ReplyPort);
- Iot0.tr_node.io_Message.mn_ReplyPort = NULL;
- }
-
- mountrequest (1);
-
- UnLockFiles (); /* unlock any hanging locks */
- return;
- }
-
- int
- xdatardy (void)
- {
- if (XInIdx != XInLen)
- return 1;
- CheckCarrier ();
- return (Ioss.IOSer.io_Actual > 0);
- }
-
- int
- xgetc (int byteto, int delay_flg)
- {
- int
- ch,
- n,
- smask,
- tmask,
- bytetimeout;
-
- top:
- if (XInIdx != XInLen) {
- if (debug > 8) {
- if (debugRead == 0)
- printf("\nREAD: ");
- debugRead = 1;
- printc (XInBuf [XInIdx]);
- }
- xfer.bytes_recv++;
- return (int) XInBuf [XInIdx++];
- }
-
- XInIdx = 0;
- XInLen = 0;
-
- /* Mod by Steve Drew:
- * at high speeds and fast machines we can end up going through all
- * layers for only 1 byte. Delaying a small amount here give the serial
- * device a chance to buffer a few chars and then we will grab them all
- * saving many cpu cycles. On a 030 system with 14.4K modem have seen
- * cpu load go from %70 down to %10 with this one line change.
- */
- if (byteto && delay_flg && NoDelay == 0) {
- Delay (3L); /* .06 sec */
- }
-
- if (!CheckCarrier ()) /* carrier lost? */
- return EOF;
-
- Assert (Iosr.IOSer.io_Device);
-
- if ((n = Ioss.IOSer.io_Actual) > 0) { /* at least one.. */
- Iosr.IOSer.io_Command = CMD_READ;
- Iosr.IOSer.io_Data = (APTR) XInBuf;
- if (n > sizeof (XInBuf))
- n = sizeof (XInBuf);
- Iosr.IOSer.io_Length = n;
- DoIO ((struct IORequest *) &Iosr);
- if (Iosr.IOSer.io_Actual > 0) {
- if (debug > 8)
- printf ("(r%d/%d)\n", n, Iosr.IOSer.io_Actual);
- XInIdx = 0;
- XInLen = Iosr.IOSer.io_Actual;
- goto top;
- }
- }
-
- /*
- * no bytes ready, byteto is 0 (no wait)
- */
-
- if (byteto == 0)
- return EOF;
-
- /*
- * no bytes ready, wait for one.
- *
- * once every 3 seconds check carrier detect.
- */
-
- bytetimeout = byteto;
- Iot0.tr_time.tv_secs = 3;
- Iot0.tr_time.tv_micro= 0;
- SendIO ((struct IORequest *) &Iot0);
- IotIP = 1;
-
- Iosr.IOSer.io_Command = CMD_READ;
- Iosr.IOSer.io_Data = (APTR) XInBuf;
- Iosr.IOSer.io_Length = 1;
- Iosr.IOSer.io_Actual = 0; /* trying to find a bug... */
- SendIO ((struct IORequest *) &Iosr);
- IosrIP = 1;
-
- smask = 1L << Iosr.IOSer.io_Message.mn_ReplyPort->mp_SigBit;
- tmask = 1L << Iot0.tr_node.io_Message.mn_ReplyPort->mp_SigBit;
-
- for (;;) {
- long
- mask = Wait (tmask | smask | SIGBREAKF_CTRL_C);
-
- if (debug > 8) {
- printf ("** wakeup **");
- if (mask & tmask)
- printf ("timeout ");
- if (mask & smask)
- printf ("rcv ");
- if (mask & SIGBREAKF_CTRL_C)
- printf ("^C");
- printf ("\n");
- fflush (stdout);
- }
-
- if (mask & SIGBREAKF_CTRL_C) {
- NiceAbortIO (&Iosr);
- WaitIO ((struct IORequest *) &Iosr);
- IosrIP = 0;
- AbortIO ((struct IORequest *) &Iot0);
- WaitIO ((struct IORequest *) &Iot0);
- IotIP = 0;
- xexit (10);
- }
-
- if (CheckIO ((struct IORequest *) &Iosr)) {
- WaitIO ((struct IORequest *) &Iosr);
- IosrIP = 0;
- AbortIO ((struct IORequest *) &Iot0);
- WaitIO ((struct IORequest *) &Iot0);
- IotIP = 0;
-
- ch = (int) XInBuf [0];
-
- if (debug > 8) {
- if (debugRead == 0)
- printf ("\nREAD ");
- debugRead = 1;
- if (debug > 9)
- printf ("(waitc%d)", Iosr.IOSer.io_Actual);
- printc ((unsigned char) ch);
- }
- xfer.bytes_recv++;
- return ch;
- }
-
- if (CheckIO ((struct IORequest *) &Iot0)) {
- WaitIO ((struct IORequest *) &Iot0);
- IotIP = 0;
-
- Iot0.tr_time.tv_secs = 3;
- Iot0.tr_time.tv_micro= 0;
-
- bytetimeout -= Iot0.tr_time.tv_secs;
- if (bytetimeout > 0) {
- if (CheckCarrier () == 0) {
- NiceAbortIO (&Iosr);
- WaitIO ((struct IORequest *) &Iosr);
- IosrIP = 0;
- break;
- }
- SendIO ((struct IORequest *) &Iot0);
- IotIP = 1;
- }
- else {
- NiceAbortIO (&Iosr);
- WaitIO ((struct IORequest *) &Iosr);
- IosrIP = 0;
- if (Iosr.IOSer.io_Actual == 1) {
- xfer.bytes_recv++;
- return (int) XInBuf [0];
- }
- break;
- }
- }
- }
-
- if (debug > 8)
- printf ("\nRecv-EOF\n");
-
- return EOF;
- }
-
- int
- xwrite (const void *buf, int ctr)
- {
- return xxwrite (buf, ctr, 0);
- }
-
- int
- xwritea (const void *buf, int ctr)
- {
- xxwrite (buf, ctr, 1);
- return ctr;
- }
-
- int
- xxwrite (const void *buf, int ctr, int async)
- {
- Assert (Iosr.IOSer.io_Device);
-
- if (debug > 9) {
- int
- i;
-
- if (debugRead)
- printf ("\nWRITE ");
- debugRead = 0;
- for (i = 0; i < ctr; ++i) {
- printc (((unsigned char *) buf) [i]);
- }
- printf ("\n");
- }
-
- if (IoswIP) {
- WaitIO ((struct IORequest *) &Iosw);
- IoswIP = 0;
- }
-
- Iosw.IOSer.io_Command = CMD_WRITE;
- Iosw.IOSer.io_Length = ctr;
- Iosw.IOSer.io_Data = (APTR) buf;
- if (async) {
- SendIO ((struct IORequest *) &Iosw);
- IoswIP = 1;
- }
- else {
- DoIO ((struct IORequest *) &Iosw);
- }
- xfer.bytes_send += ctr;
- return ctr;
- }
-
- void
- SendBreak (void)
- {
- Assert (Iosr.IOSer.io_Device);
- Ioss.IOSer.io_Command = SDCMD_BREAK;
- DoIO ((struct IORequest *) &Ioss);
-
- return;
- }
-
- int
- CheckCarrier (void)
- {
- Assert (Iosr.IOSer.io_Device);
- Ioss.IOSer.io_Command = SDCMD_QUERY;
- DoIO ((struct IORequest *) &Ioss);
-
- if (debug > 8 && Ioss.IOSer.io_Actual) {
- printf ("*** carrier data len %ld\n", Ioss.IOSer.io_Actual);
- fflush (stdout);
- }
-
- if (IgnoreCD)
- return 1;
-
- if (Ioss.io_Status & CIAF_COMCD) /* non-zero == no carrier */
- return 0;
-
- return 1;
- }
-
- /*
- * Transform a filename from a uucp packet (in Unix format) into a local
- * filename that will work in the local file system.
- */
-
- void
- munge_filename (char *s, char *d)
- {
- if (*s != '~') {
- if (s != d)
- strcpy (d, s);
- return;
- }
-
- /*
- * ~/ ... convert to UUPUB:
- * ~user/... convert to <homedir>/...
- */
-
- {
- int
- i,
- c;
- char
- *t;
- struct passwd
- *pw;
-
- for (i = 1; s [i] && s [i] != '/'; ++i)
- ;
- c = s [i];
-
- s [i] = 0;
- if (i == 1)
- pw = NULL;
- else
- pw = getpwnam (s + 1);
- s [i] = c;
-
- if (c == '/')
- ++i;
-
- if (pw) {
- t = malloc (strlen (pw->pw_dir) + strlen (s + i) + 1);
- strcpy (t, pw->pw_dir);
- }
- else {
- t = malloc (strlen (s + i) + 32);
- strcpy (t, GetConfigDir (UUPUB));
- }
- strcat (t, s + i);
- strcpy (d, t);
- free (t);
- }
-
- return;
- }
-
- int
- hangup (void)
- {
- char
- buf [128];
-
- reset_modem ();
-
- sprintf (buf, "run >nil: <nil: %s", GetConfigProgram (UUXQT));
-
- if (PriMode)
- SetTaskPri (FindTask (NULL), OldPri - 1);
-
- if (Execute (buf, 0, 0) == 0)
- fprintf (stderr, "Unable to run UUXQT\n");
-
- if (PriMode)
- SetTaskPri (FindTask (NULL), OldPri + 1);
-
- return SUCCESS;
- }
-
- void
- set_dir (const char *dirname)
- {
- /*
- ** set_dir
- **
- ** Change our directory to the appropriate subdirectory
- ** of UUSpool:, or to the UUSpool: main directory if
- ** UseSubDirs is not set.
- */
-
- static char
- *p = NULL;
- int
- i;
-
- if (debug > 1) {
- printf ("set_dir (%s)\n", dirname);
- }
-
- if (!uuspool)
- uuspool = "UUSpool:";
-
- if (UseSubDirs == 0) {
- if (safe_chdir (uuspool)) {
- ulog (-1, "safe_chdir (%s) failure %ld", uuspool, IoErr ());
- }
- return;
- }
-
- if (!p) {
-
- i = strlen (uuspool) + 35;
- p = malloc (i);
- if (!p) {
- ulog (-1, "No memory in set_dir()!");
- exit (30);
- }
- }
-
- /* our own AddPart ... */
- i = strlen (uuspool);
- if (uuspool [i - 1] != ':' && uuspool [i - 1] != '/') {
- sprintf (p, "%s/%s", uuspool, dirname);
- }
- else {
- sprintf (p, "%s%s", uuspool, dirname);
- }
-
- if (safe_chdir (p)) {
- ulog (-1, "safe_chdir (%s) failure %ld", p, IoErr ());
- }
-
- return;
- }
-
- static char
- names [MAXFILES * 16],
- *pointers [MAXFILES];
- static int
- file_pointer = 0;
-
- int
- bp_strcmp (const void *s1, const void *s2)
- {
- return strcmp (* ((char **) s1), * ((char **) s2));
- }
-
- int
- search_dir (const char *system_name)
- {
- static char
- name [128];
-
- sprintf (name, "C.%.7s#?", system_name);
- if (debug > 2)
- printf ("Looking for %s\n", name);
-
- return getfnl (name, names, sizeof (names), 0);
- }
-
- int
- work_scan (char *system_name)
- {
- int
- count;
-
- file_pointer = 0;
-
- set_dir (system_name);
-
- #if 0
- if (strlen (system_name) > 7) /* FIXME - why? */
- system_name [7] = '\0';
- #endif
-
- count = search_dir (system_name);
- if (debug > 1) {
- printf ("count from search_dir (%s) is %ld\n", system_name, count);
- }
-
- if (count == 0 && UseSubDirs) {
- /* try looking in UUSpool: main directory too */
- safe_chdir (uuspool);
- count = search_dir (system_name);
- if (debug > 1) {
- printf ("count from uuspool search_dir (%s) is %ld\n", system_name, count);
- }
- }
-
- if (count > 0) {
- if (strbpl (pointers, MAXFILES, names) != count) {
- ulog (-1, "Too many command files for %s.", system_name);
- return 0;
- }
- }
- else {
- return 0;
- }
-
- qsort (pointers, count, sizeof (char *), bp_strcmp);
- if (debug > 2)
- printf ("Found -> %s\n", pointers [file_pointer]);
-
- return 1;
- }
-
- char *
- work_next (void)
- {
- char
- *ptr;
-
- if (ptr = pointers [file_pointer]) {
- if (debug > 2)
- printf ("Found -> %s\n", ptr);
- ++file_pointer;
- }
-
- return ptr;
- }
-
- void
- amiga_setup (void)
- {
- int
- err;
- struct Task
- *task = (struct Task *) FindTask (NULL);
-
- mountrequest (0); /* disallow requesters */
-
- OpenSerial (1);
-
- if (err = OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *) &Iot0, 0)) {
- Iot0.tr_node.io_Device = NULL;
- ulog (-1, "Can't open timer device (error %ld).", err);
- xexit (10);
- }
-
- Iot0.tr_node.io_Message.mn_ReplyPort = (struct MsgPort *) CreatePort ("UUCICO-Timer", 0L);
- Iot0.tr_node.io_Command = TR_ADDREQUEST;
- Iot0.tr_node.io_Error = 0;
-
- OldTaskName = task->tc_Node.ln_Name;
- task->tc_Node.ln_Name = "uucico";
-
- return;
- }
-
- void
- set_baud (int baud)
- {
- Assert (Iosr.IOSer.io_Device);
-
- /*
- * only modify serial parameters if not run from a Getty. This is
- * to get around a bug in the A2232 serial.device (possibly also
- * the normal serial.device) having to do with hanging semaphores.
- *
- * it is also possible that this might be desirable for operation.
- */
-
- if ((Getty == 0) && (Overide == 0)) {
- Iosr.IOSer.io_Command = SDCMD_SETPARAMS;
- Iosr.io_SerFlags = SERF_SHARED | SERF_XDISABLED;
- Iosr.io_Baud = baud;
- Iosr.io_ReadLen = 8L;
- Iosr.io_WriteLen = 8L;
- Iosr.io_CtlChar = 0x11130000L;
- Iosr.io_RBufLen = 4096;
- Iosr.io_StopBits= 1;
- Iosr.io_BrkTime = 500000;
-
- if (SevenWire)
- Iosr.io_SerFlags |= SERF_7WIRE;
-
- DoIO ((struct IORequest *) &Iosr);
- }
-
- return;
- }
-
- void
- OpenSerial (int lock)
- {
- unsigned char
- *error;
- int
- err;
-
- if (Iosr.IOSer.io_Device) {
- ulog (-1, "ERROR: softerror, OpenSerial: Serial Port already open!");
- return;
- }
-
- Iosr.io_SerFlags = SERF_SHARED | SERF_XDISABLED;
- Iosr.IOSer.io_Message.mn_ReplyPort = (struct MsgPort *) CreatePort ("Read_RS", 0);
-
- if (SevenWire)
- Iosr.io_SerFlags |= SERF_7WIRE;
-
- if (lock && Getty == 0) {
- if (DoAttempt)
- error = AttemptDevUnit (DeviceName, DeviceUnit, "UUcico", 0);
- else
- error = LockDevUnit (DeviceName, DeviceUnit, "UUcico", 0);
-
- if (error) {
- if (error [0] == ODUERR_LEADCHAR [0])
- ulog (-1, "ERROR: Unable to lock serial port: %s", &error[1]);
- else
- ulog (-1, "ERROR: %s unit %ld already owned by %s",
- DeviceName, DeviceUnit, error);
-
- xexit (10);
- }
- }
-
- if (err = OpenDevice (DeviceName, DeviceUnit, (struct IORequest *) &Iosr, 0)) {
- Iosr.IOSer.io_Device = NULL;
- DeletePort (Iosr.IOSer.io_Message.mn_ReplyPort);
- Iosr.IOSer.io_Message.mn_ReplyPort = NULL;
- ulog (-1, "ERROR: Cannot open serial port for read (error %ld, for '%s' unit %ld).",
- err, DeviceName, DeviceUnit);
- xexit (TRUE);
- }
-
- Iosw = Iosr;
- Iosw.IOSer.io_Message.mn_ReplyPort = (struct MsgPort *) CreatePort ("Write_RS", 0);
- Ioss = Iosw;
-
- Iosr.IOSer.io_Command = SDCMD_QUERY;
- DoIO ((struct IORequest *) &Iosr);
-
- set_baud (Iosr.io_Baud);
-
- return;
- }
-
- void
- CloseSerial (int lock)
- {
- if (IosrIP) {
- /* I/O Serial Read In-Process */
- NiceAbortIO (&Iosr);
- WaitIO ((struct IORequest *) &Iosr);
- IosrIP = 0;
- }
-
- if (IotIP) {
- /* I/O Timer In-Process */
- AbortIO ((struct IORequest *) &Iot0);
- WaitIO ((struct IORequest *) &Iot0);
- IotIP = 0;
- }
-
- if (IoswIP) {
- /* I/O Serial Write In-Process */
- WaitIO ((struct IORequest *) &Iosw);
- IoswIP = 0;
- }
-
- if (Iosr.IOSer.io_Device) {
- CloseDevice ((struct IORequest *) &Iosr);
- Iosr.IOSer.io_Device = NULL;
- Iosw.IOSer.io_Device = NULL;
- Ioss.IOSer.io_Device = NULL;
- }
- else {
- fprintf (stderr, "softerr, CloseSerial: Serial Port already closed!\n");
- }
-
- if (Iosr.IOSer.io_Message.mn_ReplyPort) {
- DeletePort (Iosr.IOSer.io_Message.mn_ReplyPort);
- Iosr.IOSer.io_Message.mn_ReplyPort = NULL;
- }
-
- if (Iosw.IOSer.io_Message.mn_ReplyPort) {
- DeletePort (Iosw.IOSer.io_Message.mn_ReplyPort);
- Iosw.IOSer.io_Message.mn_ReplyPort = NULL;
- }
-
- if (lock && Getty == 0)
- FreeDevUnit (DeviceName, DeviceUnit);
-
- return;
- }
-
- void
- xexit (int code)
- {
- cleanup ();
-
- if (code)
- ulog (-1, "Abnormal Termination, code %ld", code);
-
- exit (code);
- }
-
- void
- printc (unsigned char c)
- {
- c &= 0x7F;
-
- if (c == '\n')
- printf ("\\n");
- else
- if (c == '\r')
- printf ("\\r");
- else
- if (c < 32)
- printf ("^%c", c | 0x40);
- else
- if (c == 32)
- printf ("_");
- else
- if (c < 128)
- printf ("%c", c);
- else
- printf ("(%02x)", c);
-
- return;
- }
-
- void
- _assert_failed (int line)
- {
- static int
- reent = 0;
-
- if (reent == 0) {
- ++reent;
- ulog (-1, "Software Error line %d sysdep.c (uucico)", line);
- xexit (20);
- }
- }
-
- /*
- * bug fix for older A2232 serial.device's
- */
-
- void
- NiceAbortIO (void *ior)
- {
- Disable ();
- if (((struct Message *) ior)->mn_Node.ln_Type != NT_REPLYMSG)
- AbortIO ((struct IORequest *) ior);
- Enable ();
-
- return;
- }
-