home *** CD-ROM | disk | FTP | other *** search
- # include "util.h"
- # include <signal.h>
- # include "d_syscodes.h"
- # include "d_proto.h"
- # include "d_returns.h"
- # include <stdio.h>
- #if defined(SYS5) || defined(M_XENIX)
- # include <string.h>
- #else
- # include <strings.h>
- #endif
- # include "d_structs.h"
- # include "d_script.h"
-
- /* Jun 81 D. Crocker rgetc() tossed out almost all the control
- * characters. changed to toss only null & DEL
- * Sep 83 G.B. Reilly added support for script command for prompt
- * M. Laubach recognition.
- */
-
- extern char *dupfpath();
- extern char *tbldfldir;
- extern int errno;
- extern FILE *d_scfp;
- extern unsigned short d_lxill[],
- d_lrill[];
- extern int d_baudrate;
- extern int d_errno;
- extern int d_lxmax;
- extern int d_lrmax;
- extern int d_debug;
- extern int d_xretry;
- extern int d_toack;
- extern int d_todata;
- extern int d_wpack;
- #ifdef SYS5
- extern unsigned short d_prbitc, d_prbiti, d_prbito, d_prbitl;
- extern unsigned short d_scbitc, d_scbiti, d_scbito, d_scbitl;
- #else
- extern int d_pron, d_proff, d_scon, d_scoff;
- #endif /* SYS5 */
- extern int d_nbuff;
- extern int d_didial;
- extern FILE * d_prtfp;
- /*** prompt varibable ******************** reilly@udel-relay ***/
- int d_prompt = 0; /* global prompt var. =0 means disabled */
- /* <>0 is ascii value of prompt character*/
-
- #define MAXNUMS 5
- #define NOPARSE -1
- #define IGNORE -2
- #define ANYARGS -3
-
- /* structure defining the legal script file commands, their type,
- * and legal number of fields.
- */
- struct scrcmds
- {
- char *s_cmdname; /* command string */
- int s_cmdtype; /* command type number */
- int s_cmdminfields; /* min number of fields for command */
- int s_cmdmaxfields; /* max number of fields allowed */
- } d_sccmds[] =
- {
- "dial", S_DIAL, 2, 2,
- "conn", S_DIAL, 2, 2,
- "phone", S_DIAL, 2, 2,
- "xillegal", S_XILL, 2, 2,
- "rillegal", S_RILL, 2, 2,
- "xmitill", S_XILL, 2, 2,
- "recvill", S_RILL, 2, 2,
- "xmitpack", S_XPCK, 2, 2,
- "recvpack", S_RPCK, 2, 2,
- "xmitsize", S_XPCK, 2, 2,
- "recvsize", S_RPCK, 2, 2,
- "transmit", S_XMIT, 2, 2,
- "send", S_XMIT, 2, 2,
- "xmit", S_XMIT, 2, 2,
- "receive", S_RECV, 3, 3,
- "recv", S_RECV, 3, 3,
- "start", S_GO, 1, 1,
- "go", S_GO, 1, 1,
- "end", S_END, 1, 1,
- "stop", S_END, 1, 1,
- "bye", S_END, 1, 1,
- "nrexmit", S_RETR, 2, 2,
- "waitack", S_TOAK, 2, 2,
- "waitdata", S_TODA, 2, 2,
- "{", S_SELST, 1, 1,
- "}", S_SELEND, 1, 1,
- "alternate", S_ALT, 1, 1,
- "case", S_ALT, 1, 1,
- "cmnt", S_REM, IGNORE, IGNORE,
- "rem", S_REM, IGNORE, IGNORE,
- "rem:", S_REM, IGNORE, IGNORE,
- "com", S_REM, IGNORE, IGNORE,
- "com:", S_REM, IGNORE, IGNORE,
- "#", S_REM, IGNORE, IGNORE,
- "log", S_LOG, 2, 2,
- "abort", S_ABORT, 1, 1,
- "bill", S_BILL, 3, 3,
- "replay", S_REPLAY, 1, 1,
- "mark", S_MARK, 1, 1,
- #ifdef SYS5
- "stty-pr", S_PRTTY, 3, 5,
- "stty-sc", S_SCTTY, 3, 5,
- #else
- "stty-pr", S_PRTTY, 3, 3,
- "stty-sc", S_SCTTY, 3, 3,
- #endif /* SYS5 */
- "window", S_DBLBUF, 3, 3,
- "use", S_USEFILE, 2, ANYARGS,
- /*** prompt command has one format "prompt <val>" reilly@udel-relay ***/
- "prompt", S_PROMPT, 2, 2,
- 0, 0, 0, 0,
- };
-
- char d_scfile[82], /* script file path name */
- d_rawq[MATCHLEN], /* pushback queue for string matcher */
- *d_prawq; /* pointer to next available character */
- /* in 'd_rawq'. */
-
- unsigned d_scline; /* current line number in script file */
- int d_nfields = 0; /* current number of "use" fields */
- char *d_fields[MAXFIELDS]; /* current "use" fields */
-
- int d_ntries = 2, /* number of times to try to dial numbers
- */
- d_wait = 15, /* number of seconds to wait between dial
- */
- /* attempts.
- */
- d_nrawq; /* number of available characters in
- 'd_rawq' */
- int d_dodrop; /* non zero if a dial has been made */
-
- LOCVAR int d_gotxill = 0; /* non zero if xill command received */
- LOCVAR int d_gotrill = 0; /* non zero if rill command received */
-
- /*
- * D_SCRIPT
- *
- * this routine reads lines from the script file, parses them up, and
- * then initiates the requested actions.
- */
-
- d_script ()
- {
- register int nselect, result;
- char linebuf[MAXSCRLINE + 2],
- *fields[MAXFIELDS];
- int nfields;
-
- nselect = 0;
- d_dodrop = 0;
-
- for (;;)
- {
- result = d_scrblk ();
-
- switch (result)
- {
- case D_OK:
- return(D_OK);
-
- case D_FATAL:
- case D_EOF:
- case D_NFIELDS:
- case D_QUOTE:
- case D_UNKNOWN:
- return (D_FATAL);
-
- case D_NONFATAL:
- /* An error that may be recoverable. If there is
- * an alternate, use it.
- */
- if (nselect <= 0)
- /* Not within a select block; therefore, not alt */
- return (D_FATAL);
-
- /* We are within a select block; go to the alternate */
- if ((result = d_nxtalt ()) < 0)
- return (result);
- switch (result)
- {
- case S_ALT:
- continue;
-
- case S_SELEND:
- /* no more alternates; return error */
- return (D_FATAL);
-
- default:
- d_scerr ("Bad syntax scriptfile");
- return (D_FATAL);
- }
-
-
- case S_SELST:
- /* The next line had better be an alternate */
- if (d_cmdget (linebuf, &nfields, fields, d_scfp) != S_ALT)
- {
- d_scerr ("Missing 'alternate' after 'begin'");
- return (D_FATAL);
- }
- nselect++;
- continue;
-
- case S_SELEND:
- /* verify that there was a select block being
- * looked at. If so, then the last alternate
- * was the successful one. Continue normally.
- */
- if (nselect-- <= 0)
- {
- d_scerr ("Inappropriate select end");
- return (D_FATAL);
- }
- continue;
-
- case S_ALT:
- /* First, make sure the context was correct */
- if (nselect <= 0)
- {
- d_scerr ("Inappropriate alt\n");
- return (D_FATAL);
- }
- /* If we get here, then an alternate within a select
- * was completed successfully. Move on.
- */
- if ((result = d_selend ()) < 0)
- return (result);
- nselect--;
- switch (result)
- {
- case S_SELEND:
- continue;
-
- default:
- d_scerr ("error in format of script file");
- return (D_FATAL);
- }
-
- default:
- if (result < 0)
- return (result);
- d_scerr ("d_script", "Internal error: result = %d", result);
- return (D_FATAL);
- }
-
- }
- }
-
- d_scrblk ()
- {
- char linebuf[MAXSCRLINE + 2],
- *fields[MAXFIELDS];
- int command, result, nfields;
-
- for (;;)
- {
- /* read the command */
- command = d_cmdget (linebuf, &nfields, fields, d_scfp);
- if (command < 0)
- return (command);
-
-
- result = d_cmdproc(command, nfields, fields);
- if (result == D_CONTIN)
- continue;
- return (result);
- }
- }
-
- d_cmdproc (command, nfields, fields)
- int command, nfields;
- char *fields[];
- {
- register int result, word, i;
- register char *ptr;
-
- /* switch out on the command type. for most of the commands,
- * there is a routine to handle them.
- */
- switch (command)
- {
- case S_EOF:
- /* Not really a script command. This is returned to
- * indicate an unexpected EOF on the script input file.
- * Try to revert to a previous script file. If there is
- * none, then this really is an unexpected EOF. Return
- * an error to indicate so.
- */
- if (d_scclose() > 0)
- return (D_CONTIN);
- return (D_EOF);
-
- case S_DBLBUF:
- /* Can use 'd_nbuff' as a counter of the number of
- * outstanding packets to allow if we later mod the
- * code to allow more than double buffering.
- * See the file 'd_packet.c'
- */
- result = atoi (fields[1]);
- #ifdef D_LOG
- if ((result != 1) &&
- (result != 2) )
- d_log("d_cmdproc", "Illegal buffer number, %d", result);
- else
- #endif /* D_LOG */
- d_nbuff = result;
-
- /* This variable will be non-zero if the master startup
- * routine should transmit a packet telling the other
- * side about the buffering window. This packet can not
- * be transmitted to sites running the old code.
- */
- d_wpack = atoi (fields[2]);
- return (D_CONTIN);
-
- case S_USEFILE:
- /* takes additional input from another file until
- * that file is exhausted.
- */
-
- fields[1] = dupfpath(fields[1], tbldfldir);
-
- for (i = 2; i <= nfields; i ++)
- {
- if (*fields[i] == '"') fields[i]++;
- if (ptr = rindex(fields[i], '"')) *ptr = '\0';
- }
-
- if (d_scopen (fields[1], nfields, &fields[0]) < 0)
- return (D_FATAL);
- return (D_CONTIN);
-
- case S_PRTTY:
- #ifdef SYS5
- sscanf(fields[1], "%ho", &d_prbitc);
- sscanf(fields[2], "%ho", &d_prbiti);
- sscanf(fields[3], "%ho", &d_prbito);
- sscanf(fields[4], "%ho", &d_prbitl);
-
- #ifdef D_LOG
- d_log("d_cmdproc", "%s %o %o %o %o", fields[0],
- d_prbitc, d_prbiti, d_prbito, d_prbitl);
- #endif /* D_LOG */
-
- #else /* SYS5 */
- /* Could use fields[1&2], but let's check consistancy */
- sscanf(fields[1], "%o", &d_pron);
- sscanf(fields[2], "%o", &d_proff);
- #ifdef D_LOG
- d_log("d_cmdproc", "%s %o %o", fields[0], d_pron, d_proff);
- #endif /* D_LOG */
- #endif /* SYS5 */
- return (D_CONTIN);
-
- case S_SCTTY:
- #ifdef SYS5
- sscanf(fields[1], "%ho", &d_scbitc);
- sscanf(fields[2], "%ho", &d_scbiti);
- sscanf(fields[3], "%ho", &d_scbito);
- sscanf(fields[4], "%ho", &d_scbitl);
-
- #ifdef D_LOG
- d_log("d_cmdproc", "%s %o %o %o %o", fields[0],
- d_scbitc, d_scbiti, d_scbito, d_scbitl);
- #endif /* D_LOG */
-
- #else
-
- sscanf(fields[1], "%o", &d_scon);
- sscanf(fields[2], "%o", &d_scoff);
- #ifdef D_LOG
- d_log("d_cmdproc", "%s %o %o", fields[0], d_scon, d_scoff);
- #endif /* D_LOG */
- #endif /* SYS5 */
- return (D_CONTIN);
-
- case S_MARK:
- d_mark ();
- return (D_CONTIN);
-
- case S_REPLAY:
- d_replay ();
- return (D_CONTIN);
-
- case S_LOG:
- /* Force this to always log */
- d_plog (-1, "%s", fields[1]);
- return (D_CONTIN);
-
- case S_BILL:
- d_didial = 1; /* pretend we're dialport for dial_log purposes */
- d_cstart(fields[1], fields[2]);
- return (D_CONTIN);
-
- case S_REM:
- return (D_CONTIN);
-
- case S_ABORT:
- return (D_FATAL);
-
- case S_ALT:
- case S_SELST:
- case S_SELEND:
- return (command);
-
- case S_DIAL: /* get line & make raw mode for matching */
- /* Make sure any previous connections are cleaned up */
- if (d_dodrop != 0)
- {
- d_dodrop = 0;
- d_drop ();
- }
-
- /* Don't let input from last dial get in this one's queue */
- d_mark ();
-
- if (d_scdial (fields[1]) < 0)
- return (D_NONFATAL);
- d_dodrop = 1;
- return (D_CONTIN);
-
- case S_XMIT:
- if ((result = d_scxmit (fields[1])) < 0)
- return (result);
- return (D_CONTIN);
-
- case S_RECV:
- if ((result = d_screcv (fields[1], fields[2])) < 0)
- return (result);
- return (D_CONTIN);
-
- case S_GO: /* regular tty mode during session */
- /*** expanded to call and log ttscript when prompt active ***/
- /*** necessary to get raw mode for control chars ***/
- /*** 9/27/83 laubach@udel-relay ***/
- if (d_prompt == 0) {
- if (d_ttproto (d_baudrate) < 0)
- return (D_NONFATAL);
- }
- else {
- if (d_ttscript ( d_baudrate) < 0)
- return (D_NONFATAL);
- #ifdef D_DBGLOG
- d_dbglog("d_cmdproc","ttscript selected for raw prompt mode");
- #endif /* D_DBGLOG */
- }
- return (D_OK);
-
- case S_END:
- return (D_OK);
-
- case S_XPCK:
- result = atoi (fields[1]);
-
- if ((result < MINPATHSIZ) || (result > MAXPACKET))
- {
- d_scerr ("illegal max transmit packet length: %d", result);
- d_errno = D_SCRERR;
- return (D_NONFATAL);
- }
-
- #ifdef D_DBGLOG
- d_dbglog ("d_script", "setting 'd_lxmax' to %d", result);
- #endif /* D_DBGLOG */
- d_lxmax = result;
- return (D_CONTIN);
-
- case S_RPCK:
- result = atoi (fields[1]);
-
- if ((result < MINPATHSIZ) || (result > MAXPACKET))
- {
- d_scerr ("illegal max receive packet length");
- d_errno = D_SCRERR;
- return (D_NONFATAL);
- }
-
- #ifdef D_DBGLOG
- d_dbglog ("d_script", "setting 'd_lrmax' to %d", result);
- #endif /* D_DBGLOG */
- d_lrmax = result;
- return (D_CONTIN);
-
- case S_XILL:
- if (!d_gotxill) { /* zero the vector on first S_XILL command */
- d_gotxill = 1;
- #ifdef D_DBGLOG
- d_dbglog("d_script", "zeroing xill vector");
- #endif /* D_DBGLOG */
- for (word = 0; word < 8; word++)
- d_lxill[word] = 0;
- }
-
- if ((result = d_scill (fields[1], d_lxill)) < 0)
- return (result);
-
- #ifdef D_DBGLOG
- d_dbglog ("d_script", "d_lxill = %o %o %o %o %o %o %o %o",
- d_lxill[0], d_lxill[1], d_lxill[2], d_lxill[3],
- d_lxill[4], d_lxill[5], d_lxill[6], d_lxill[7]);
- #endif /* D_DBGLOG */
- return (D_CONTIN);
-
- case S_RILL:
- if (!d_gotrill) { /* zero the vector on first S_RILL command */
- d_gotrill = 1;
- #ifdef D_DBGLOG
- d_dbglog("d_script", "zeroing rill vector");
- #endif /* D_DBGLOG */
- for (word = 0; word < 8; word++)
- d_lrill[word] = 0;
- }
-
- if ((result = d_scill (fields[1], d_lrill)) < 0)
- return (result);
-
- #ifdef D_DBGLOG
- d_dbglog ("d_script", "d_lrill = %o %o %o %o %o %o %o %o",
- d_lrill[0], d_lrill[1], d_lrill[2], d_lrill[3],
- d_lrill[4], d_lrill[5], d_lrill[6], d_lrill[7]);
- #endif /* D_DBGLOG */
- return (D_CONTIN);
-
- case S_RETR:
- result = atoi (fields[1]);
- if (result <= 0)
- d_scerr("d_script", "Bad retry value: %d", result);
- else
- d_xretry = result;
- return (D_CONTIN);
-
- case S_TOAK:
- result = atoi (fields[1]);
- if (result <= 0)
- d_scerr ("d_script", "Bad ack time out value: %d", result);
- else
- d_toack = result;
- return (D_CONTIN);
-
- case S_TODA:
- result = atoi (fields[1]);
- if (result <= 0)
- d_scerr ("d_script", "Bad data time out value: %d", result);
- else
- d_todata = result;
- return (D_CONTIN);
-
- /*** prompt has one field which is the decimal ascii value of the prompt ***/
- /*** character reilly@udel-relay ***/
- case S_PROMPT:
- d_prompt = atoi (fields[1]);
- #ifdef D_DBGLOG
- d_dbglog ("d_script", "Prompt ASCII %d (decimal)", d_prompt);
- #endif /* D_DBGLOG */
- return (D_CONTIN);
-
- default:
- d_scerr ("internal error -- unknown command %d", command);
- return (D_FATAL);
- }
- }
-
- d_cmdget (linebuf, nfields, fields, channel)
- int *nfields;
- char *linebuf, *fields[];
- FILE *channel;
- {
- register int result;
- char *nstart;
- int command, nwantmin, nwantmax;
- register struct scrcmds *cmdpt;
-
- /* read a line from the script file */
- again:
- if ((result = d_scgetline (linebuf, channel)) < 0)
- return (result);
-
- if (result == 0)
- return (S_EOF);
-
- #ifdef D_DBGLOG
- d_dbglog ("d_scrproc", "line %d - '%s'", d_scline, linebuf);
- #endif /* D_DBGLOG */
-
- /* First, seperate off the first field of the input line */
- switch (d_getword(linebuf, &fields[0], &nstart))
- {
- case -1:
- /* end of line. I.e, no line. Try again */
- goto again;
-
- case -2:
- /* unterminated quote. */
- d_scerr ("quoted string missing end quote");
- return (D_QUOTE);
-
- case 0:
- /* Found a word OK */
- break;
-
- default:
- d_scerr ("unknown return from d_getword");
- return (D_FATAL);
- }
-
- /* search the command list for the string in the first field
- * of the line.
- */
- cmdpt = d_sccmds;
- for(;;)
- {
- if (cmdpt -> s_cmdname == 0)
- {
- d_scerr ("command not known");
- return (D_UNKNOWN);
- }
-
- if (strcmp (fields[0], cmdpt -> s_cmdname) != 0)
- {
- cmdpt++;
- continue;
- }
-
- command = cmdpt -> s_cmdtype;
- nwantmin = cmdpt -> s_cmdminfields;
- nwantmax = cmdpt -> s_cmdmaxfields;
- break;
- }
-
- /* if this is meant to be tossed, go get another line */
- if (nwantmin == IGNORE)
- goto again;
-
- /* if this is not meant to be parsed further, don't */
- if (nwantmin == NOPARSE)
- {
- fields[1] = nstart;
- return (command);
- }
-
- /* parse the rest of the line and make sure the right number
- * of fields are present.
- */
- *nfields = d_linparse (&fields[1], nstart, MAXFIELDS-1);
- if (*nfields < 0)
- switch (*nfields)
- {
- case -1:
- d_scerr ("too many fields");
- return (D_NFIELDS);
-
- case -2:
- d_scerr ("quoted string missing end quote");
- return (D_QUOTE);
-
- case -3:
- d_scerr ("backquote appeared at end of line");
- return (D_QUOTE);
-
- case -4:
- d_scerr ("invalid $ variable used");
- return (D_FATAL);
-
- case -5:
- d_scerr ("line too long");
- return (D_FATAL);
-
- default:
- d_scerr ("unknown error from line parser");
- return (D_FATAL);
- }
-
- if ( (nwantmin == ANYARGS || *nfields >= (nwantmin - 1)) &&
- (nwantmax == ANYARGS || *nfields <= (nwantmax - 1)) )
- return (command);
-
- /* If it gets here, then this command had wrong # of fields */
- d_scerr ("command has %d fields", (*nfields+1));
- return (D_NFIELDS);
- }
-
-
-
-
- d_selend ()
- {
- register int command;
- char linebuf[MAXSCRLINE + 2],
- *fields[MAXFIELDS];
- int nfields;
-
- for (;;)
- {
- command = d_cmdget (linebuf, &nfields, fields, d_scfp);
- if (command < 0)
- return (command);
- switch (command)
- {
- default:
- continue;
-
- case S_SELEND:
- return (S_SELEND);
-
- case S_SELST:
- d_selend ();
- continue;
-
- }
- }
- }
-
- d_nxtalt ()
- {
- register int command;
- char linebuf[MAXSCRLINE + 2],
- *fields[MAXFIELDS];
- int nfields;
-
- for (;;)
- {
- command = d_cmdget (linebuf, &nfields, fields, d_scfp);
- if (command < 0)
- return (command);
- switch (command)
- {
- default:
- continue;
-
- case S_SELEND:
- case S_ALT:
- return (command);
-
- case S_SELST:
- d_selend ();
- continue;
- }
- }
- }
-
- /*
- * D_SCRDIAL
- *
- * this routine is called to do the dial command in the script file.
- * it just calls lower level routines to parse the number string and
- * do the actual dialing.
- *
- * number -- number specification string from the script file
- */
-
- d_scdial (number)
- register char *number;
- {
- register int nnumbs,
- result;
- struct telspeed telnumbs[MAXNUMS];
-
- #ifdef D_DBGLOG
- d_dbglog ("d_scdial", "attempting to call '%s'", number);
- #endif /* D_DBGLOG */
-
- /* parse the number spec, do the dialing, and set the port to raw mode */
-
- if ((nnumbs = d_numparse (number, telnumbs, MAXNUMS, d_scfile, d_scline)) < 0)
- return (nnumbs);
-
- if ((result = d_connect (telnumbs, nnumbs, d_ntries, d_wait)) < 0)
- return (result);
-
- return (D_OK);
- }
-
- /*
- * D_SCRXMIT
- *
- * this routine is called to transmit a string given in the script file.
- * the string is converted to standard internal format and then passed
- * to a lower transmission routine.
- *
- * string -- string to be transmitted in 'C' style
- */
-
- d_scxmit (string)
- register char *string;
- {
- register int length;
- char canonstr[MAXSCRLINE];
-
- if (*string == '"')
- if ((length = d_canon (string, canonstr)) < 0)
- {
- d_scerr ("transmit string format error");
- return (D_FATAL);
- }
-
- if (d_xstring (canonstr, length) < 0)
- return (D_FATAL);
-
- return (D_OK);
- }
-
- /*
- * D_SCRRECV
- *
- * this routine is called to wait until a given string is received on
- * the port. the routine will return when the sting has been identified.
- * there is also a timer that is set to cause the routine to return with
- * an error if the string is not received within the specified interval.
- *
- * string -- the string to be watched for
- *
- * timestr -- a timeout value, in seconds, given as an ascii string
- */
-
- d_screcv (string, timestr)
- char *string,
- *timestr;
- {
- register unsigned int timeout;
- register int length,
- result;
- char canonstr[MAXSCRLINE];
-
- #ifdef D_DBGLOG
- d_dbglog ("d_screcv", "looking for '%s' in '%s' seconds", string, timestr);
- #endif /* D_DBGLOG */
-
- /* convert the transmit string, check its length, and convert the timeout */
- /* value. */
-
- if ((length = d_canon (string, canonstr)) < 0)
- {
- d_scerr ("receive string format error");
- return (D_FATAL);
- }
-
- if (length > MATCHLEN)
- {
- d_scerr ("receive string too long");
- return (D_FATAL);
- }
-
- if ((result = atoi (timestr)) < 1)
- {
- d_scerr ("illegal timeout value");
- return (D_FATAL);
- }
- timeout = result; /* convert to unsigned */
-
- /* set up the timer */
-
- if (setjmp (timerest)) {
- d_scerr ("no match for '%s' after %d seconds", string, timeout);
- d_errno = D_TIMEOUT;
- return (D_NONFATAL);
- }
- s_alarm ((unsigned) timeout);
-
- /* do the matching */
-
- while ((result = d_scmatch (canonstr)) == D_NO)
- d_rgetc ();
-
- s_alarm (0);
-
- switch (result)
- {
- case D_OK:
- return (D_OK);
-
- case D_NONFATAL:
- d_scerr ("eof on port while trying match");
- d_errno = D_PORTEOF;
- return (D_NONFATAL);
-
- case D_FATAL:
- d_scerr ("read error on port while trying match");
- d_errno = D_PORTRD;
- return (D_FATAL);
-
- case D_INTRPT:
- d_scerr ("no match for '%s' after %d seconds", string, timeout);
- d_errno = D_TIMEOUT;
- return (D_NONFATAL);
- }
-
- d_errno = D_SYSERR;
- return (D_FATAL);
- }
-
-
- /*
- * D_SCILL
- *
- * this routine is called to translate a string specifying illegal
- * characters for either transmission or recption, and set the bits
- * corresponding to those characters in the given bit vector.
- *
- * string -- pointer to character specification string in canonical
- * format
- *
- * bitvector -- pointer to bit vector
- */
-
- d_scill (string, bitvector)
- char *string;
- unsigned short bitvector[];
- {
- register int bit,
- length;
- register char *cp;
- char canonstr[MAXSCRLINE];
-
- /* translate the character string */
-
- if ((length = d_canon (string, canonstr)) < 0)
- {
- d_scerr ("error in illegal character specification");
- return (D_FATAL);
- }
-
- /* run through the bytes in the converted string and set the bit */
- /* corresponding to each one */
-
- cp = canonstr;
-
- for (bit = 0; bit < length; bit++)
- d_setbit (*cp++, bitvector);
-
- return (D_OK);
- }
-
-
- /*
- * D_SCMATCH
- *
- * this routine checks for a match between the string and the input
- * stream.
- *
- * string -- string to be matched in the input stream
- *
- *
- * return values:
- *
- * D_OK -- the string has been found
- *
- * D_NO -- the string cannot be matched with the current starting
- * character. delete the first character and try again.
- *
- * D_NONFATAL -- eof on port while reading characters
- *
- * D_FATAL -- read error on port
- *
- * D_INTRPT -- no match after the specified time
- */
-
- d_scmatch (string)
- char *string;
- {
- register int c,
- result;
-
- if (*string == '\0')
- return (D_OK);
-
- if ((c = d_rgetc ()) < D_OK)
- return (c);
-
- if (c == *string)
- {
- result = d_scmatch (++string);
-
- if (result < D_OK)
- d_unrgetc (c);
-
- return (result);
- }
- else
- {
- d_unrgetc (c);
- return (D_NO);
- }
- }
-
- /*
- * D_RGETC
- *
- * this routine is used to read characters from the port in raw mode.
- * to allow matching of strings in the input stream, this function
- * implements a look behind facility. the port is read only if the
- * push back list is empty.
- */
-
- d_rgetc ()
- {
- register int result;
- int theval;
- char c;
-
- /* if the queue isn't empty, use what it has */
-
- if (d_nrawq)
- {
- d_nrawq--;
- return (*d_prawq--);
- }
-
- /* have to read the port. watch for timeout interrupts */
-
- while ((theval = d_getc (d_prtfp)) != EOF)
- {
- c = toascii (theval); /* filter out some of the junk characters */
- if ((result = d_tscribe ((char *) &c, 1)) < 0)
- return (result);
-
- switch (c)
- { /* let controls go by, except */
- case '\000': /* skip null & DEL, because they are */
- case '\177': /* almost always just noise */
- continue;
- }
-
- return (c);
- }
-
- if (feof (d_prtfp))
- return (D_NONFATAL);
-
- if (errno == EINTR)
- return (D_INTRPT);
-
- return (D_FATAL);
- }
-
-
- /*
- * D_UNRGETC
- *
- * this routine pushes back a character onto the look behind queue
- * used by the 'd_rgetc' routine
- *
- * c -- the character to be pushed back
- */
-
- d_unrgetc (c)
- char c;
- {
-
- /* set up the queue if it isn't ready */
-
- if (d_prawq <= 0)
- {
- d_prawq = d_rawq;
- *d_prawq = c;
- d_nrawq = 1;
- return;
- }
-
- /* otherwise, stick it on the end */
-
- *++d_prawq = c;
- d_nrawq++;
- }
-
- /*
- * D_XSTRING
- *
- * this routine is called to transmit strings on the port. If the
- * string contains octal 377, then the function pauses for 1 second
- * before continuing.
- *
- * string -- pointer to string
- *
- * length -- number of characters in string to be sent.
- */
-
- d_xstring (string, length)
- register char *string;
- int length;
- {
- register int result;
-
- #ifdef D_DBGLOG
- d_dbglog ("d_xstring", "sending '%s', length %d", string, length);
- #endif /* D_DBGLOG */
-
- sleep ((unsigned) 2); /* permit any needed line-settling */
- for ( ; length--; string++)
- {
- /* NOSTRICT */
- if ((int)*string == DELAY_CH)
- sleep ((unsigned) 1);
- else if ((int)*string == BREAK_CH)
- d_brkport();
- else
- if ((result = d_wrtport (string, 1)) < 0)
- break;
- if (*string == '\r')
- sleep ((unsigned) 1); /* may nned line-settling */
- }
- sleep ((unsigned) 2); /* permit any needed line-settling */
-
- return (result);
- }
-
- /*
- * D_SCRERR
- *
- * routine which is called to log errors in the script file. the
- * purpose of this is so the name of the file and the line number
- * can be tacked on in one place.
- *
- * format -- 'd_log' type format string
- *
- * a, b, c, d, ... -- variables to be logged
- */
-
- /* VARARGS1 */
- d_scerr (format, a, b, c, d, e, f, g, h)
- char *format;
- unsigned a, b, c, d, e, f, g, h;
- {
- #ifdef D_LOG
- char tmpfmt[256];
-
- sprintf (tmpfmt, "%s%s", "Error in %s, line %d: ", format);
-
- d_log ("d_scerr", tmpfmt, d_scfile, d_scline, a, b, c, d, e, f, g, h);
- #endif /* D_LOG */
- d_errno = D_SCRERR;
- }
-