home *** CD-ROM | disk | FTP | other *** search
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* |_o_o|\\ Copyright (c) 1990 The Software Distillery. All Rights Reserved */
- /* |. o.| || This program may not be distributed without the permission of */
- /* | . | || the authors: BBS: (919) 382-8265 */
- /* | o | || Dave Baker Alan Beale Jim Cooper */
- /* | . |// Jay Denebeim Bruce Drake Gordon Keener */
- /* ====== John Mainwaring Andy Mercier Jack Rouse */
- /* John Toebes Mary Ellen Toebes Doug Walker Mike Whitcher */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- #include "quickb.h"
- #include <exec/memory.h>
-
- static void miniterm(struct XPR_DATA *xd, char *startup);
- static long setup_xd(struct XPR_IO *xio);
- static void edit_opts(struct XPR_DATA *xd, char *buf);
- static void set_optstr(struct XPR_DATA *xd, char *str);
-
- /* protocol termination */
- long __saveds __asm XProtocolCleanup(register __a0 struct XPR_IO *xio)
- {
- if (xio->xpr_data)
- FreeMem(xio->xpr_data, (long)sizeof(struct XPR_DATA));
- xio->xpr_data = 0;
- return 1L;
- }
-
- /* protocol setup */
- long __saveds __asm XProtocolSetup(register __a0 struct XPR_IO *xio)
- {
- struct XPR_DATA *xd;
- char buf[256];
-
- if (!setup_xd(xio)) return XPRS_FAILURE;
- xd = (struct XPR_DATA *)xio->xpr_data;
- if (xio->xpr_filename)
- {
- strcpy(buf, xio->xpr_filename);
- set_optstr(xd, buf);
- }
- else
- edit_opts(xd, buf);
- return (xd->optAuto=='Y') ? XPRS_SUCCESS|XPRS_HOSTMON : XPRS_SUCCESS;
- }
-
- /* protocol send request */
- long __saveds __asm XProtocolSend(register __a0 struct XPR_IO *xio)
- {
- if (!setup_xd(xio)) return 0L;
- miniterm((struct XPR_DATA *)xio->xpr_data, "upl/proto:qb");
- return 1L;
- }
-
- /* protocol receive request */
- long __saveds __asm XProtocolReceive(register __a0 struct XPR_IO *xio)
- {
- if (!setup_xd(xio)) return 0L;
- miniterm((struct XPR_DATA *)xio->xpr_data, "dow/proto:qb");
- return 1L;
- }
-
- /* look for protocol initiation */
- long __saveds __asm XProtocolHostMon(
- register __a0 struct XPR_IO *xio,
- register __a1 char *serbuff,
- register __d0 long actual,
- register __d1 long maxsize)
- {
- struct XPR_DATA *xd;
- int c, lastc;
-
- xd = (struct XPR_DATA *)xio->xpr_data;
- if (!xd) return actual;
- xd->nserbuf = actual;
- xd->serbufp = serbuff;
- while (--xd->nserbuf >= 0)
- {
- lastc = xd->cchar;
- xd->cchar = c = *(xd->serbufp++) & 0x7F;
- if (c == ENQ)
- {
- bp_ENQ(xd);
- actual = 0;
- }
- else if (c == DLE)
- {
- bp_DLE(xd);
- actual = 0;
- }
- else if (c == 'I' && lastc == 0x1B)
- {
- bp_ESC_I(xd);
- actual = 0;
- }
- }
-
- return actual;
- }
-
- long __saveds __asm XProtocolUserMon(
- register __a0 struct XPR_IO *xio,
- register __a1 char *serbuff,
- register __d0 long actual,
- register __d1 long maxsize)
- {
- return actual;
- }
-
- /* return failure */
- static long Fail()
- {
- return 0L;
- }
-
- /* write an error message */
- void errormsg(struct XPR_DATA *xd, char *msg)
- {
- xd->xpru.xpru_updatemask = XPRU_ERRORMSG;
- xd->xpru.xpru_errormsg = msg;
- (*xd->xpr_update)(&xd->xpru);
- }
-
- /* set up our data structures */
- static long setup_xd(struct XPR_IO *xio)
- {
- struct XPR_UPDATE xpru;
- register struct XPR_DATA *xd;
-
- if (!xio->xpr_data)
- {
- if ((xio->xpr_data = AllocMem((long)sizeof(struct XPR_DATA),
- MEMF_CLEAR)) == NULL)
- { /* no memory */
- xpru.xpru_updatemask = XPRU_ERRORMSG;
- xpru.xpru_errormsg = "Out of memory";
- if (xio->xpr_update)
- (*xio->xpr_update)(&xpru);
- return 0L;
- }
- memset(xio->xpr_data, 0, sizeof(struct XPR_DATA));
- xd = (struct XPR_DATA *)xio->xpr_data;
- xd->xio = xio;
-
- /* default options */
- xd->maxiobuf = 16384; /* 16K buffer */
- xd->optText = 'H'; /* use CompuServe suggestion */
- xd->optOwrt = 'N'; /* use new file name */
- xd->optAuto = 'Y'; /* activate automatically */
- xd->optDelt = 'N'; /* don't delete after send */
- xd->optKeep = (xio->xpr_extension >= 2L && xio->xpr_unlink)
- ? 'N'
- : 'Y'; /* keep partial files */
- }
- else
- xd = (struct XPR_DATA *)xio->xpr_data;
-
- /* do some initialization */
- xd->Done = xd->Aborting = FALSE;
- xd->nserbuf = 0;
- xd->iobuf = NULL;
- xd->iobufn = 0;
-
- /* following are optional */
- xd->xpr_update = xio->xpr_update ? xio->xpr_update : Fail;
- xd->xpr_chkabort = xio->xpr_chkabort ? xio->xpr_chkabort : Fail;
- xd->xpr_chkmisc = xio->xpr_chkmisc ? xio->xpr_chkmisc : Fail;
- xd->xpr_gets = xio->xpr_gets ? xio->xpr_gets : Fail;
- xd->xpr_setserial = xio->xpr_setserial; /* NOTE! no default to fail */
- xd->xpr_finfo = xio->xpr_finfo ? xio->xpr_finfo : Fail;
- xd->xpr_options = (xio->xpr_extension >= 1L)
- ? xio->xpr_options : NULL;
- xd->xpr_unlink = (xio->xpr_extension >= 2L)
- ? xio->xpr_unlink : NULL;
-
- /* following are required */
- if ((xd->xpr_fopen = xio->xpr_fopen) == NULL) goto lose;
- if ((xd->xpr_fclose = xio->xpr_fclose) == NULL) goto lose;
- if ((xd->xpr_fread = xio->xpr_fread) == NULL) goto lose;
- if ((xd->xpr_fwrite = xio->xpr_fwrite) == NULL) goto lose;
- if ((xd->xpr_sread = xio->xpr_sread) == NULL) goto lose;
- if ((xd->xpr_swrite = xio->xpr_swrite) == NULL) goto lose;
-
- return 1L;
-
- lose:
- errormsg(xd, "Insufficient XPR protocol support");
- return 0L;
- }
-
- /* validate a boolean return value */
- static int check_bool(struct XPR_DATA *xd, char *buf, char *which)
- {
- if (strcmp(buf, "ON") == 0)
- buf[0] = 'Y';
- else if (strcmp(buf, "OFF") == 0)
- buf[0] = 'N';
- return TRUE;
- }
-
- /* allow user to edit option string */
- static void edit_opts(struct XPR_DATA *xd, char *buf)
- {
- char *p;
- struct xpr_option *optptr[7];
- struct xpr_option opt[7];
- struct {
- char Text[4];
- char Owrt[4];
- char Buff[8];
- char Auto[4];
- char Delt[4];
- char Keep[4];
- } optbuf;
- register int i;
- long status;
- long l;
-
- if (!xd->xpr_options)
- { /* format the current options */
- p = buf;
- *p++ = 'T'; *p++ = xd->optText; *p++ = ',';
- *p++ = 'O'; *p++ = xd->optOwrt; *p++ = ',';
- *p++ = 'B'; p += stcl_d(p, xd->maxiobuf >> 10); *p++ = ',';
- *p++ = 'A'; *p++ = xd->optAuto; *p++ = ',';
- *p++ = 'D'; *p++ = xd->optDelt; *p++ = ',';
- *p++ = 'K'; *p++ = xd->optKeep; *p++ = '\0';
-
- /* let the user edit it */
- if ((*xd->xpr_gets)("Quick B options:", buf))
- { /* set the option string */
- set_optstr(xd, buf);
- }
- return;
- }
-
- /* use the requester interface */
- memset((char *)&optbuf, 0, sizeof(optbuf));
- opt[0].xpro_description = "Quick B options:";
- opt[0].xpro_type = XPRO_HEADER;
- opt[0].xpro_value = NULL;
- opt[0].xpro_length = 0;
-
- optbuf.Text[0] = xd->optText;
- opt[1].xpro_description = "Text mode (Y,N,H,C):";
- opt[1].xpro_type = XPRO_STRING;
- opt[1].xpro_value = optbuf.Text;
- opt[1].xpro_length = sizeof(optbuf.Text);
-
- optbuf.Owrt[0] = xd->optOwrt;
- opt[2].xpro_description = "Overwrite mode (Y,N,S):";
- opt[2].xpro_type = XPRO_STRING;
- opt[2].xpro_value = optbuf.Owrt;
- opt[2].xpro_length = sizeof(optbuf.Owrt);
-
- stcl_d(optbuf.Buff, xd->maxiobuf >> 10);
- opt[3].xpro_description = "I/O buffer size (KB):";
- opt[3].xpro_type = XPRO_LONG;
- opt[3].xpro_value = optbuf.Buff;
- opt[3].xpro_length = sizeof(optbuf.Buff);
-
- strcpy(optbuf.Auto, (xd->optAuto == 'Y') ? "yes" : "no");
- opt[4].xpro_description = "Auto-activate transfers:";
- opt[4].xpro_type = XPRO_BOOLEAN;
- opt[4].xpro_value = optbuf.Auto;
- opt[4].xpro_length = sizeof(optbuf.Auto);
-
- strcpy(optbuf.Delt, (xd->optDelt == 'Y') ? "yes" : "no");
- opt[5].xpro_description = "Delete after sending:";
- opt[5].xpro_type = XPRO_BOOLEAN;
- opt[5].xpro_value = optbuf.Delt;
- opt[5].xpro_length = sizeof(optbuf.Delt);
-
- strcpy(optbuf.Keep, (xd->optKeep == 'Y') ? "yes" : "no");
- opt[6].xpro_description = "Keep partial files:";
- opt[6].xpro_type = XPRO_BOOLEAN;
- opt[6].xpro_value = optbuf.Keep;
- opt[6].xpro_length = sizeof(optbuf.Keep);
-
- /* prompt for options */
- for (i = 0; i < 7; ++i)
- optptr[i] = &opt[i];
- status = (*xd->xpr_options)(7L, optptr);
- if (status <= 0) return;
-
- /* process options */
- for (i = 1; i < 7; ++i)
- {
- if (!(status & (1 << i))) continue;
- strupr(opt[i].xpro_value);
- switch (i)
- {
- case 1: /* Text */
- if (strchr("YNCH", optbuf.Text[0]))
- xd->optText = optbuf.Text[0];
- else
- errormsg(xd, "Text option ignored");
- break;
- case 2: /* Overwrite */
- if (strchr("YNS", optbuf.Owrt[0]))
- xd->optOwrt = optbuf.Owrt[0];
- else
- errormsg(xd, "Overwrite option ignored");
- break;
- case 3: /* Buffer size */
- stcd_l(optbuf.Buff, &l);
- if (l < 0 || l > 0x7FFFFFFF >> 10)
- errormsg(xd, "Buffer size ignored; out of range");
- else
- xd->maxiobuf = l << 10;
- break;
- case 4: /* Auto-Activate */
- if (check_bool(xd, optbuf.Auto, "Auto-activate"))
- xd->optAuto = optbuf.Auto[0];
- break;
- case 5: /* Delete after send */
- if (check_bool(xd, optbuf.Delt, "Delete"))
- {
- if (optbuf.Delt[0] != 'Y' || xd->xpr_unlink)
- xd->optDelt = optbuf.Delt[0];
- else
- errormsg(xd, "Delete option ignored; file deletion not available");
- }
- break;
- case 6: /* Keep partial files */
- if (check_bool(xd, optbuf.Keep, "Keep"))
- {
- if (optbuf.Keep[0] == 'Y' || xd->xpr_unlink)
- xd->optKeep = optbuf.Keep[0];
- else
- errormsg(xd, "Keep option ignored; file deletion not available");
- }
- break;
- }
- }
-
- return;
- }
-
- /* parse and merge option string with current settings */
- static void set_optstr(struct XPR_DATA *xd, char *str)
- {
- long l;
-
- /* convert to upper case for simpler parsing */
- strupr(str);
- for (;;)
- {
- str += strspn(str, " ,");
- switch (*str++)
- {
- case 'T': /* text mode */
- if (strchr("YNCH", *str))
- xd->optText = *str;
- else
- errormsg(xd, "T option ignored; use TY, TN, TH, or TC");
- break;
- case 'O': /* overwrite */
- if (strchr("YNS", *str))
- xd->optOwrt = *str;
- else
- errormsg(xd, "O option ignored; use OY, ON, or OS");
- break;
- case 'B': /* buffer size */
- str += stcd_l(str, &l);
- if (l < 0 || l > 0x7FFFFFFF >> 10)
- errormsg(xd, "Buffer size ignored; out of range");
- else
- xd->maxiobuf = l << 10;
- break;
- case 'A': /* auto-activate */
- if (strchr("YN", *str))
- xd->optAuto = *str;
- else
- errormsg(xd, "A option ignored; use AY or AN");
- break;
- case 'D': /* delete after send */
- if (!strchr("YN", *str))
- errormsg(xd, "D option ignored; use DY or DN");
- else if (*str == 'Y' && !xd->xpr_unlink)
- errormsg(xd, "DY option ignored; file deletion not available");
- else
- xd->optDelt = *str;
- break;
- case 'K': /* keep partial receives */
- if (strchr("YN", *str))
- xd->optKeep = *str;
- else
- errormsg(xd, "K option ignored; use KY or KN");
- break;
- default:
- return;
- }
-
- /* skip rest of option */
- str += strcspn(str, " ,");
- }
- }
-
- void cputc(struct XPR_DATA *xd, int c)
- {
- char ch = c;
- (*xd->xpr_swrite)(&ch, 1L);
- }
-
- /* called by cgetc macro to refill the buffer */
- int cfilbuf(struct XPR_DATA *xd, long timeout)
- {
- long n;
- n = (*xd->xpr_sread)(xd->serbuf, (long)MAX_SERBUF, 0L);
- if (n <= 0)
- n = (*xd->xpr_sread)(xd->serbuf, 1L, timeout);
- if (n <= 0)
- return -1;
- xd->nserbuf = n-1;
- xd->serbufp = &xd->serbuf[1];
- return (int)xd->serbuf[0];
- }
-
- static void miniterm(struct XPR_DATA *xd, char *startup)
- {
- int c = -1;
- int lastc;
- char buf[256];
- char prompt[1024];
- char *p;
- int i;
- int to;
-
- /* get the startup line */
- strcpy(buf, startup);
- if ((*xd->xpr_gets)("Startup line", buf))
- {
- for (p = buf; *p; ++p)
- cputc(xd, *p);
- cputc(xd, '\r');
- }
-
- xd->xpru.xpru_updatemask = XPRU_MSG;
- xd->xpru.xpru_msg = "Entering protocol";
- (*xd->xpr_update)(&xd->xpru);
-
- i = 0;
- to = 0;
- do {
- lastc = c;
- c = cgetc(xd, 1000000L);
- if (c < 0)
- { /* timed out */
- if (++to == 10)
- break;
- if (to == 1 && i > 0)
- {
- prompt[i] = 0;
- buf[0] = 0;
- strcpy(buf, xd->xio->xpr_filename);
- if ((*xd->xpr_gets)(prompt, buf))
- {
- for (p = buf; *p; ++p)
- cputc(xd, *p);
- cputc(xd, '\r');
- }
- i = 0;
- }
- }
- else
- {
- to = 0;
-
- if (c == ENQ)
- bp_ENQ(xd);
- else if (c == DLE)
- bp_DLE(xd);
- else if (c == 'I' && lastc == 0x1B)
- bp_ESC_I(xd);
- else if (c == '\n')
- {
- prompt[i] = 0;
- xd->xpru.xpru_updatemask = XPRU_MSG;
- xd->xpru.xpru_msg = prompt;
- (*xd->xpr_update)(&xd->xpru);
- i = 0;
- }
- else if (c != '\r' && i < sizeof(prompt)-1)
- prompt[i++] = c;
- }
- if ((*xd->xpr_chkabort)())
- xd->Aborting = TRUE;
- } while (!xd->Done && !xd->Aborting);
-
- xd->xpru.xpru_updatemask = XPRU_MSG;
- xd->xpru.xpru_msg = "Timed out";
- if (!xd->Done && !xd->Aborting)
- (*xd->xpr_update)(&xd->xpru);
-
- /* reset last character so HostMon isn't confused */
- xd->cchar = -1;
- }
-
- /* open buffered file */
- long bfopen(struct XPR_DATA *xd, char *filename, char *mode)
- {
- long file;
- file = (*xd->xpr_fopen)(filename, mode);
- if (!file) return file;
- if (xd->maxiobuf)
- {
- xd->iobuf = AllocMem(xd->maxiobuf, 0L);
- if (xd->iobuf == NULL)
- errormsg(xd, "Not enough memory to buffer I/O");
- }
- if (!xd->iobuf || mode[0] == 'r')
- {
- xd->iobufn = 0; /* bytes available */
- xd->writing = FALSE;
- }
- else
- {
- xd->iobufn = 0; /* bytes used */
- xd->writing = TRUE;
- }
- xd->iobufp = xd->iobuf;
- return file;
- }
-
- /* buffered file close */
- long bfclose(struct XPR_DATA *xd, long file)
- {
- if (xd->writing && xd->iobufn)
- (*xd->xpr_fwrite)(xd->iobuf, xd->iobufn, 1L, file);
- if (xd->iobuf)
- FreeMem(xd->iobuf, xd->maxiobuf);
- xd->iobuf = NULL;
- return (*xd->xpr_fclose)(file);
- }
-
- /* buffered file read */
- long bfread(struct XPR_DATA *xd, char *buf, long len, long file)
- {
- register long n;
- register long remain;
- if (xd->iobuf == NULL)
- return (*xd->xpr_fread)(buf, 1L, 1*len, file);
- remain = len;
- while (remain > 0)
- {
- if (xd->iobufn <= 0)
- { /* refill buffer */
- xd->iobufn = (*xd->xpr_fread)(xd->iobuf, 1L,
- xd->maxiobuf, file);
- if (xd->iobufn <= 0)
- return len - remain;
- xd->iobufp = xd->iobuf;
- }
- n = min(xd->iobufn, remain);
- memcpy(buf, xd->iobufp, (unsigned)n);
- xd->iobufp += n;
- xd->iobufn -= n;
- buf += n;
- remain -= n;
- }
- return len;
- }
-
- /* buffered file read, with optional text processing */
- long xbfread(struct XPR_DATA *xd, char *buf, long len, long file)
- {
- unsigned char c;
- long n;
- if (!xd->TextMode)
- return bfread(xd, buf, len, file);
- for (n = 0; n < len; ++n)
- {
- if (xd->TextC >= 0)
- {
- buf[n] = xd->TextC;
- xd->TextC = -1;
- }
- else if (bfread(xd, (char *)&c, 1L, file) != 1)
- break;
- else if (c == LF)
- {
- buf[n] = CR;
- xd->TextC = LF;
- }
- else
- buf[n] = c;
- }
-
- return n;
- }
-
- /* buffered file write */
- long bfwrite(struct XPR_DATA *xd, char *buf, long len, long file)
- {
- register long n;
- register long remain;
- if (xd->iobuf == NULL)
- return (*xd->xpr_fwrite)(buf, 1L, 1*len, file);
- remain = len;
- for (;;)
- {
- if (xd->iobufn >= xd->maxiobuf)
- { /* flush buffer */
- n = (*xd->xpr_fwrite)(xd->iobuf, xd->iobufn, 1L, file);
- if (n != 1)
- return -1;
- xd->iobufn = 0;
- xd->iobufp = xd->iobuf;
- }
-
- if (remain <= 0) break;
-
- n = xd->maxiobuf - xd->iobufn;
- if (n > remain) n = remain;
- memcpy(xd->iobufp, buf, (unsigned)n);
- xd->iobufp += n;
- xd->iobufn += n;
- buf += n;
- remain -= n;
- }
- return len;
- }
-
- /* buffered file write with optional text processing */
- long xbfwrite(struct XPR_DATA *xd, char *buf, long len, long file)
- {
- register int i;
- if (!xd->TextMode)
- return bfwrite(xd, buf, len, file);
- if (xd->TextC == CPMEOF)
- return len;
- for (i = 0; i < len; ++i)
- {
- if (xd->TextC == CR && buf[i] != LF)
- { /* carriage return not part of CR-LF */
- if (bfwrite(xd, "\n", 1, file) != 1)
- return i;
- }
- xd->TextC = buf[i];
- if (buf[i] == CPMEOF)
- break;
- if (buf[i] != CR && bfwrite(xd, &buf[i], 1, file) != 1)
- return i;
- }
- return len;
- }
-