home *** CD-ROM | disk | FTP | other *** search
- /*
- ** $Source: WB_2.1:homes/rkr/prog/sercli/src/RCS/sercli.c,v $
- ** $Author: rkr $
- ** $Revision: 1.13 $
- ** $Locker: rkr $
- ** $State: Exp $
- ** $Date: 1993/06/16 23:27:34 $
- **
- ** sercli (an Amiga .device <-> FIFO interface tool)
- ** Copyright (C) 1993 Richard Rauch
- **
- ** See /doc/sercli.doc and /COPYING for use and distribution license.
- **
- */
-
- #include <exec/types.h>
- #include <exec/io.h>
- #include <exec/lists.h>
- #include <exec/memory.h>
- #include <exec/nodes.h>
- #include <exec/ports.h>
- #include <devices/serial.h>
- #include <devices/timer.h>
- #include <intuition/intuition.h>
- #include <intuition/intuitionbase.h>
- #include <libraries/dos.h>
-
- #ifdef AZTEC_C
- #include <functions.h>
- #else
- #include <clib/alib_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #endif
-
- #include "defs.h"
- #include "ser_supp.h"
- #include "misc.h"
- #include "fifo.h"
- #include "config.h"
- #include "sercli-config.h"
- #include "rexx.h"
- #include "version.h"
-
-
- #define COPYRIGHT_NOTICE \
- "\n" \
- "$VER: " NAME " " VERSION " (" __DATE__")\n" \
- "Copyright (C) 1991, 1993 by Richard Rauch.\n" \
- "No warranty; distribute at will.\n" \
- "(see doc/sercli.doc for more info)\n" \
- "(see also the GNU General Public License)\n" \
- "\n"
-
-
- #define SER_READ_MAX 512
- #define FIFO_BUF_SIZE (SER_READ_MAX * 4)
-
- #define CTRL(x) (x ^ '@')
-
- #define dput(x) write_ser_str (x) /*** for debugging only ***/
-
- /*
- ** FIFO related globals.
- **
- */
- char *FifoSlav; /* fifo_s */
- char *FifoMast; /* fifo_m */
- char FifrIP; /* read msg pending */
- char FifwIP; /* write msg pending */
- long *FifoBase;
- Message RMsg;
- Message WMsg;
- MsgPort *FifoSink;
- void *FifoR;
- void *FifoW;
- ULONG pmask;
-
- char *nether_name; /*** who/what is on the other end... ***/
-
- int alert_ser = 0;
- int alert_loc = 1;
- char *config_file_name;
-
-
- /*
- ** Intuition/Window related globals
- **
- */
- NewWindow nw =
- {
- 0, 0, 0, 0,
- 0, 1,
-
- CLOSEWINDOW, /*** IDCMP ***/
-
- NOCAREREFRESH | SMART_REFRESH | WINDOWCLOSE | WINDOWDEPTH
- | WINDOWDRAG, /*** Flags ***/
-
- NULL, NULL,
- NULL, /*** title ***/
- NULL,
- NULL,
- 0, 0, 0, 0,
- WBENCHSCREEN
- };
- Window *win;
- char *window_title; /*** Just use nw.Title??? ***/
- WORD win_width;
- WORD win_height;
- ULONG imask;
-
-
- ULONG wake_flags; /*** Mask of bits to Wait() on. ***/
-
-
- static void clean_up (void);
- static void init (void);
-
-
- /*
- ** DICE (and maybe Lattice/SAS, dunno) uses a function, onbreak() to allow
- ** you to control what happens when a ^c occurs.
- **
- ** Aztec allows ^c checking to be turned off with a global flag variable.
- **
- ** ---rkr.
- **
- */
- #ifdef AZTEC_C
- extern long Enable_Abort;
- void onbreak (int (*brk) (void) ) {}
- #else
- long Enable_Abort;
- #endif
-
-
- void hex_dump (char *buf, size_t len)
- {
- while (len--)
- {
- char c = *buf;
- static char hex_chars [] =
- {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
- };
-
- putchar (hex_chars [(c >> 4) & 0xf]);
- putchar (hex_chars [ c & 0xf]);
-
- if (len)
- {
- putchar (' ');
- putchar (' ');
- }
-
- ++buf;
- }
- }
-
-
-
- void on_error_ser (void *ptr)
- {
- char *cmd;
- char *err;
- char err_buf [50];
- IOExtSer *ior;
- static char *serial_errors [] =
- {
- "not an error...",
- "Device in use",
- "unused",
- "Invalid bps rate",
- "Out of memory",
- "Bad parameter",
- "hardware data overrun (hmmm)",
- "unused",
- "unused",
- "`ParityErr'",
- "unused",
- "`TimeErr'",
- "BufOverflow'",
- "No DSR",
- "No CTS",
- "`DetectedBreak'",
- };
-
-
- ior = ptr;
-
- printf
- (
- "\n***\nserial error on {%s}; %s/%d\n",
- prog_id,
- ser_device_name,
- ser_device_unit
- );
-
- switch (ior->IOSer.io_Command)
- {
- case CMD_WRITE:
- cmd = "CMD_WRITE";
- break;
-
- case CMD_READ:
- cmd = "CMD_READ";
- break;
-
- case SDCMD_QUERY:
- cmd = "SDCMD_QUERY";
- break;
-
- case SDCMD_SETPARAMS:
- cmd = "SDCMD_SETPARAMS";
- break;
-
- default:
- cmd = "duh?";
- break;
- }
-
- if ( (ior->IOSer.io_Error > 0) && (ior->IOSer.io_Error < 16) )
- err = serial_errors [ior->IOSer.io_Error];
- else
- {
- err = err_buf;
- sprintf (err_buf, "Unknown error number, %d", ior->IOSer.io_Error);
- }
-
- printf
- (
- "{\n"
- "\tio_Command == %s\n"
- "\tio_Flags == 0x%08.8x\n"
- "\tio_Error == %d: %s\n"
- "\tio_Actual == %d\n"
- "\tio_Length == %d\n"
- "\tio_Data == 0x%x\n"
- "\tio_ExtFlags == 0x%08.8x\n"
- "\tio_Baud == %d\n"
- "\tio_ReadLen == %d\n"
- "\tio_WriteLen == %d\n"
- "\tio_StopBits == %d\n"
- "\tio_SerFlags == 0x%08.8x\n"
- "\tio_Status == %d\n"
- "}\n",
- cmd,
- ior->IOSer.io_Flags,
- ior->IOSer.io_Error, err,
- ior->IOSer.io_Actual,
- ior->IOSer.io_Length,
- ior->IOSer.io_Data,
- ior->io_ExtFlags,
- ior->io_Baud,
- ior->io_ReadLen,
- ior->io_WriteLen,
- ior->io_StopBits,
- ior->io_SerFlags,
- ior->io_Status
- );
-
- printf ("io_Data contents == {");
- hex_dump (ior->IOSer.io_Data, ior->IOSer.io_Length);
- printf ("}\n\n");
- }
-
-
- void open_fifo (void)
- {
- FifoSlav = malloc (strlen (prog_id) + 16);
- FifoMast = malloc (strlen (prog_id) + 16);
- if (!(FifoSlav && FifoMast) )
- {
- fprintf (stderr, "unable to allocate FIFO name-strings\n");
- exit (10);
- }
- sprintf (FifoMast, "%s_m", prog_id);
- sprintf (FifoSlav, "%s_s", prog_id);
-
- FifoSink = CreatePort (NULL, 0);
- if (!FifoSink)
- {
- fprintf (stderr, "unable to create FifoSink FIFO port\n");
- exit (10);
- }
-
- /*
- * FIFOS
- */
-
- FifoBase = OpenLibrary ("fifo.library", 0);
- if (!FifoBase)
- {
- fprintf (stderr, "unable to open %s\n", FIFONAME);
- exit (10);
- }
-
- FifoW = OpenFifo (FifoMast, FIFO_BUF_SIZE, FIFOF_WRITE | FIFOF_NORMAL | FIFOF_NBIO);
- if (FifoW == NULL)
- {
- fprintf (stderr, "unable to open fifo %s\n", FifoMast);
- exit (10);
- }
-
- FifoR = OpenFifo (FifoSlav, FIFO_BUF_SIZE, FIFOF_READ | FIFOF_NORMAL | FIFOF_NBIO);
- if (FifoR == NULL)
- {
- fprintf (stderr, "unable to open fifo %s\n", FifoSlav);
- exit (10);
- }
- RMsg.mn_ReplyPort = FifoSink;
- WMsg.mn_ReplyPort = FifoSink;
-
- pmask = 1 << FifoSink->mp_SigBit;
- }
-
- void close_fifo (void)
- {
- /*
- ** Shut down the pending FIFO reads/writes.
- **
- */
- if (FifrIP)
- {
- if (alert_loc)
- printf ("shutting down `FifrIP' (FIFO: read ? pending)\n");
- RequestFifo (FifoR, &RMsg, FREQ_ABORT);
- WaitMsg (&RMsg);
- FifrIP = 0;
- }
- if (FifwIP)
- {
- if (alert_loc)
- printf ("shutting down `FifwIP' (FIFO: write ? pending)\n");
- RequestFifo (FifoW, &WMsg, FREQ_ABORT);
- WaitMsg (&WMsg);
- FifwIP = 0;
- }
-
- /*
- ** Shut down the FIFO read/write streams.
- **
- */
- if (FifoR)
- {
- if (alert_loc)
- printf ("shutting down `FifoR' (FIFO: Read stream)\n");
- CloseFifo (FifoR, FIFOF_EOF);
- FifoR = NULL;
- }
- if (FifoW)
- {
- if (alert_loc)
- printf ("shutting down `FifoW' (FIFO: Write stream)\n");
- CloseFifo (FifoW, FIFOF_EOF);
- FifoW = NULL;
- }
-
- if (FifoBase)
- {
- if (alert_loc)
- printf ("closing FifoBase (libs:fifo.library)\n");
- CloseLibrary ( (struct Library *) FifoBase);
- FifoBase = NULL; /*** DANGEROUS; should make this auto-init! ***/
- }
-
- if (FifoSink)
- {
- if (alert_loc)
- printf ("releasing `FifoSink' (misc. FIFO: msg. rec. port)\n");
- DeletePort (FifoSink);
- FifoSink = NULL;
- RMsg.mn_ReplyPort = FifoSink;
- WMsg.mn_ReplyPort = FifoSink;
-
- }
- if (FifoSlav)
- {
- free (FifoSlav);
- FifoSlav = NULL;
- }
- if (FifoMast)
- {
- free (FifoMast);
- FifoMast = NULL;
- }
- pmask = 0;
- }
-
-
- void clean_up (void)
- {
- close_fifo ();
- if (win)
- {
- if (alert_loc)
- printf ("releasing `win' (Intuition Window)\n");
- CloseWindow (win);
- win = NULL;
- }
- close_rexx ();
- close_ser ();
- }
-
-
- void init (void)
- {
- read_sercli_config ();
- set_error_handler (error_type_serial, on_error_ser); /*** ignore old handler??? ***/
-
- onbreak (do_nothing);
- atexit (clean_up);
- Enable_Abort = 0;
-
- if (alert_loc)
- printf (COPYRIGHT_NOTICE);
-
- open_ser ();
- open_rexx ();
-
-
- {
- char
- buf [256];
- int
- len;
-
- if (!nether_name)
- nether_name = strdup ("no user");
- len = sprintf
- (
- buf,
- "%s: with {%s} id {%s}",
- PROG_NAME,
- nether_name,
- prog_id
- );
- nw.Title = window_title = strdup (buf); /*** just use nw.Title??? ***/
-
- win_width = nw.Width = GADGETS_WIDTH + (len * TEXT_WIDTH);
- win_height = nw.Height = TEXT_HEIGHT + 2;
-
- win = OpenWindow (&nw);
- }
-
- if (!win)
- exit (10);
-
- open_fifo ();
-
- imask = 1 << win->UserPort->mp_SigBit;
- }
-
-
- void SendBreak (int c)
- {
- char buf [256];
- long fh;
-
- sprintf (buf, "FIFO:%s/%c", prog_id, c);
- if (fh = Open (buf, 1005))
- Close (fh);
- }
-
- void set_wake_flags (void)
- {
- wake_flags
- = ser_read_reply_mask
- | ser_write_reply_mask
- | imask
- | pmask
- | rexx_mask;
- }
-
- void send_eof (void)
- {
- close_fifo ();
- if (alert_ser)
- write_ser_str ("\n<EOF>\n");
- open_fifo ();
- set_wake_flags ();
- }
-
- int main (int argc, char *argv [])
- {
- char *buf;
- char *o_buf;
- short notDone = 1;
- short online = 0; /*** have we told FIFO to send an EOF? ***/
- short carrier = 0; /*** connected? ***/
-
-
- buf = malloc (SER_READ_MAX);
- o_buf = malloc (SER_READ_MAX);
- if (!(buf && o_buf) )
- {
- fprintf (stderr, "Could not allocate ser<->FIFO i/o buffers.\n");
- exit (10);
- }
-
- if (argc > 1)
- config_file_name = argv [1];
- else
- config_file_name = "sercli_config";
-
- init ();
-
- /*
- ** Begin by requesting asynch i/o from our FIFO and the .device
- **
- */
- read_ser_asynch (buf, SER_READ_MAX);
- RequestFifo (FifoR, &RMsg, FREQ_RPEND);
- FifrIP = 1;
-
- set_wake_flags ();
-
- while (notDone)
- {
- ULONG mask;
- IOExtSer *ser_status;
-
- mask = Wait (wake_flags);
- top:
- ser_status = query_ser ();
- carrier = !(ser_status->io_Status & 32);
- if (carrier != online)
- {
- fprintf (stderr, "-- NOTICE (%s): Carrier just changed to %d\n", prog_id, carrier);
- // handle_error (error_type_serial, ser_status);
- if (online)
- send_eof ();
- online = carrier;
- }
-
- if (mask & imask)
- {
- IntuiMessage *im;
-
- while (im = (IntuiMessage *) GetMsg (win->UserPort) )
- {
- switch (im->Class)
- {
- case CLOSEWINDOW:
- notDone = 0;
- if (alert_ser)
- write_ser_str
- (
- "\a\nLocal window shut down!\n"
- "Closing serial.device...\n"
- );
-
- if (alert_loc)
- printf
- (
- "Use\n"
- "\tremcli %s\n"
- "to wrap up session.\n"
- "Or re-launch sercli without creating a new shell.\n"
- "(May not work as I make further changes...)\n"
- "(Also note that DTR should go down on exit..)\n",
- prog_id
- );
- break;
-
- default:
- dput ("\nhuh?\n");
- break;
- }
- }
- }
-
- if (mask & ser_read_reply_mask)
- {
- IOExtSer *ior;
-
- ior = (IOExtSer *) GetMsg (ser_read_reply_port);
- if (ior)
- {
- char c;
- ULONG count;
- ULONG n;
- ULONG read_len;
-
-
- read_len = ior->IOSer.io_Actual;
- if (read_len)
- {
- ULONG data_index;
-
- for
- (
- count = 0, data_index = 0;
- data_index < read_len;
- ++data_index, ++count
- )
- {
- c = buf [count];
- switch (c)
- {
- /*
- ** (STUPID) <CR>/<LF> conversion.
- **
- */
- case '\x0d':
- o_buf [count] = '\n';
- break;
-
- /*
- ** break detection...
- **
- */
- case CTRL ('C'):
- case CTRL ('D'):
- case CTRL ('E'):
- case CTRL ('F'):
- SendBreak (CTRL (c) );
- --count;
- break;
-
- /*
- ** EOF conversion
- **
- */
- case CTRL ('\\'):
- send_eof ();
- break;
-
- /*
- ** standard copy operation...
- **
- */
- default:
- o_buf [count] = c;
- break;
- }
- }
- }
-
- read_ser_asynch (buf, SER_READ_MAX);
- if (read_len && count)
- n = WriteFifo (FifoW, o_buf, count);
-
- /*
- ** This was borrowed from remcli.c in the fifodev2.lzh
- ** archive. I've zapped it out, as it really needs
- ** further adaption to work.
- **
- ** This shouldn't be necessary, anyway, as (hopefully)
- ** only typed input will be coming in through the serial
- ** port.
- **
- ** if (n != count)
- ** {
- ** ser_to_fif_p = 1;
- ** if (FifwIP == 0)
- ** {
- ** RequestFifo (FifoW, &WMsg, FREQ_WAVAIL);
- ** FifwIP = 1;
- ** }
- ** }
- ** else
- ** do next read, set pending flag.
- **
- */
- }
- }
-
-
- if (mask & ser_write_reply_mask)
- clear_write_replies ();
-
-
- if (mask & rexx_mask)
- handle_rexx ();
-
-
- if (mask & pmask)
- {
- Message *msg;
-
- while (msg = (Message *)GetMsg (FifoSink))
- {
- if (msg == (Message *)&RMsg)
- {
- char *ptr;
- long n;
-
- FifrIP = 0;
-
- if ( (n = ReadFifo (FifoR, &ptr, 0) ) > 0)
- {
- if (n > 256) /* limit size */
- n = 256;
- write_ser_asynch (ptr, n);
- /* clear N bytes */
- n = ReadFifo (FifoR, &ptr, n);
- }
- if (n < 0) /* EOF */
- {
- if (alert_ser)
- write_ser_str
- (
- "\a\nFIFO EOF!\n"
- "Closing .device...\n"
- );
- notDone = 0;
- }
- else
- {
- RequestFifo (FifoR, &RMsg, FREQ_RPEND);
- FifrIP = 1;
- }
- }
- else if (msg == (Message *)&WMsg)
- {
- /*
- ** remcli.c uses this; I don't, so this entire
- ** if()...else if()... construct could be removed.
- **
- ** However, if it becomes a problem, I could
- ** conceivably want to reinstate it for flow-control,
- ** so...here it is in token form.
- **
- */
- if (alert_ser)
- write_ser_str
- (
- "\nHey, a WMsg came back!\n"
- "And I didn't even send one!\n\n"
- );
- }
- goto top;
- }
- }
- }
- return (0);
- }
-
-