diff options
Diffstat (limited to 'gnu/uucp/contrib/xchat.c')
-rw-r--r-- | gnu/uucp/contrib/xchat.c | 1444 |
1 files changed, 0 insertions, 1444 deletions
diff --git a/gnu/uucp/contrib/xchat.c b/gnu/uucp/contrib/xchat.c deleted file mode 100644 index cfb4d359662f..000000000000 --- a/gnu/uucp/contrib/xchat.c +++ /dev/null @@ -1,1444 +0,0 @@ -/* - * *********** - * * XCHAT.C * - * *********** - * - * Extended chat processor for Taylor UUCP. See accompanying documentation. - * - * Written by: - * Bob Denny (denny@alisa.com) - * Based on code in DECUS UUCP (for VAX/VMS) - * - * History: - * Version 1.0 shipped with Taylor 1.03. No configuration info inside. - * - * Bob Denny - Sun Aug 30 18:41:30 1992 - * V1.1 - long overdue changes for other systems. Rip out interval - * timer code, use timer code from Taylor UUCP, use select() - * for timed reads. Use Taylor UUCP "conf.h" file to set - * configuration for this program. Add defaulting of script - * and log file paths. - * - * Bugs: - * Does not support BSD terminal I/O. Anyone care to add it? - */ - -#include <sys/types.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <signal.h> -#include <time.h> -#include <sys/ioctl.h> -#include <sys/termio.h> - -#include "xc-conf.h" - -/* - * Pick a timing routine to use, as done in Taylor UUCP. - */ -#if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS || HAVE_POLL -#define USE_SELECT_TIMER 0 -#else -#define USE_SELECT_TIMER HAVE_SELECT -#if USE_SELECT_TIMER -#include <sys/time.h> -#endif -#endif - -#if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS -#undef HAVE_POLL -#define HAVE_POLL 0 -#endif - -#if HAVE_USLEEP || HAVE_NAP -#undef HAVE_NAPMS -#define HAVE_NAPMS 0 -#endif - -#if HAVE_USLEEP -#undef HAVE_NAP -#define HAVE_NAP 0 -#endif - -static int ttblind(); -static int ttcd(); - -/* script entry -- "compiled" form of dial, hangup, or login script */ - -struct script { - struct script *next; /* pointer to next entry, or null */ - int opcode; /* numeric opcode */ - char *strprm; /* pointer to string param */ - long intprm; /* integer parameter */ - char *newstate; /* new state name */ -}; - -/* opcode definition array element -- one for each possible opcode */ - -struct script_opdef { - char *opname; - int opcode; /* numeric opcode -- same as array index */ - int prmtype; /* one of SC_NONE, SC_STR, SC_XSTR, SC_INT */ - int newstate; /* one of SC_NONE, SC_NWST */ -}; - - /* values for opcode */ - -#define SC_LABEL 0 /* "label" (state name) */ -#define SC_CDLY 1 /* set char output delay in msec */ -#define SC_PCHR 2 /* pause char for dial string (from P in input) */ -#define SC_PTIM 3 /* seconds to allow for pause char */ -#define SC_WCHR 4 /* wait char for dial string (from W in input) */ -#define SC_WTIM 5 /* seconds to allow for wait char */ -#define SC_ZERO 6 /* zero counter */ -#define SC_INCR 7 /* increment counter */ -#define SC_IFGT 8 /* change state if counter > int param */ -#define SC_WAIT 9 /* wait for int param seconds */ -#define SC_GOTO 10 /* unconditional change to new state */ -#define SC_SEND 11 /* send strparam (after sprintf substitutions) */ -#define SC_BRK 12 /* send a break */ -#define SC_HANG 13 /* drop DTR */ -#define SC_DIAL 14 /* send telno string (after subst PCHR & WCHR) */ -#define SC_DTIM 15 /* time in msec per digit (for timeout calculations) */ - /* default = 100 (one tenth second) */ -#define SC_CTIM 16 /* additional time (in seconds) to wait for carrier */ - /* default = 45 seconds */ -#define SC_EXIT 17 /* script done, success */ -#define SC_FAIL 18 /* script done, failure */ -#define SC_LOG 19 /* write strparam to uucp.log */ -#define SC_LOGE 20 /* write strparam to uucp.log w/error ind */ -#define SC_DBG 21 /* write strparam to debug log if debug lvl = LGI */ -#define SC_DBGE 22 /* write strparam to debug log if debug lvl = LGIE */ -#define SC_DBST 23 /* 'or' intparam into debug mask */ -#define SC_DBCL 24 /* 'bicl' intparam into debug mask */ -#define SC_TIMO 25 /* newstate if no match in intparam secs */ - /* (uses calculated dial time if intparam is 0) */ -#define SC_XPCT 26 /* wait for strparam, goto _newstate if found */ -#define SC_CARR 27 /* goto _newstate if carrier detected */ -#define SC_FLSH 28 /* flush typeahead buffer */ -#define SC_IFBL 29 /* change state if controller is blind w/o CD */ -#define SC_IFBG 30 /* chg state if ctlr is blind and counter > intprm */ -#define SC_SNDP 31 /* send parameter n */ -#define SC_IF1P 32 /* if parameter n present */ -#define SC_IF0P 33 /* if parameter n absent */ -#define SC_DBOF 34 /* open debugging file */ -#define SC_TELN 35 /* Set telno from parameter n */ -#define SC_7BIT 36 /* Set port to 7-bit stripping */ -#define SC_8BIT 37 /* Set port for 8-bit characters */ -#define SC_PNON 38 /* Set port for 8-bit, no parity */ -#define SC_PEVN 39 /* Set port for 7-bit, even parity */ -#define SC_PODD 40 /* Set port for 7-bit, odd parity */ -#define SC_HUPS 41 /* Change state on HUP signal */ -#define SC_END 42 /* end of array */ - - /* values for prmtype, prm2type */ - -#define SC_NONE 0 /* no parameter */ -#define SC_STR 1 /* simple string */ -#define SC_INT 2 /* integer */ -#define SC_NWST 3 /* new state name */ -#define SC_XSTR 4 /* translated string */ - -/* opcode definition table for dial/login/hangup scripts */ - -static struct script_opdef sc_opdef[] = - { - {"label", SC_LABEL, SC_NONE, SC_NONE}, - {"chrdly", SC_CDLY, SC_INT, SC_NONE}, - {"pchar", SC_PCHR, SC_STR, SC_NONE}, - {"ptime", SC_PTIM, SC_INT, SC_NONE}, - {"wchar", SC_WCHR, SC_STR, SC_NONE}, - {"wtime", SC_WTIM, SC_INT, SC_NONE}, - {"zero", SC_ZERO, SC_NONE, SC_NONE}, - {"count", SC_INCR, SC_NONE, SC_NONE}, - {"ifgtr", SC_IFGT, SC_INT, SC_NWST}, - {"sleep", SC_WAIT, SC_INT, SC_NONE}, - {"goto", SC_GOTO, SC_NONE, SC_NWST}, - {"send", SC_SEND, SC_XSTR, SC_NONE}, - {"break", SC_BRK, SC_NONE, SC_NONE}, - {"hangup", SC_HANG, SC_NONE, SC_NONE}, - {"7bit", SC_7BIT, SC_NONE, SC_NONE}, - {"8bit", SC_8BIT, SC_NONE, SC_NONE}, - {"nopar", SC_PNON, SC_NONE, SC_NONE}, - {"evenpar", SC_PEVN, SC_NONE, SC_NONE}, - {"oddpar", SC_PODD, SC_NONE, SC_NONE}, - {"telno", SC_TELN, SC_INT, SC_NONE}, - {"dial", SC_DIAL, SC_NONE, SC_NONE}, - {"dgttime", SC_DTIM, SC_INT, SC_NONE}, - {"ctime", SC_CTIM, SC_INT, SC_NONE}, - {"success", SC_EXIT, SC_NONE, SC_NONE}, - {"failed", SC_FAIL, SC_NONE, SC_NONE}, - {"log", SC_LOG, SC_XSTR, SC_NONE}, - {"logerr", SC_LOGE, SC_XSTR, SC_NONE}, - {"debug", SC_DBG, SC_XSTR, SC_NONE}, - {"debuge", SC_DBGE, SC_XSTR, SC_NONE}, - {"dbgset", SC_DBST, SC_INT, SC_NONE}, - {"dbgclr", SC_DBCL, SC_INT, SC_NONE}, - {"dbgfile", SC_DBOF, SC_XSTR, SC_NONE}, - {"timeout", SC_TIMO, SC_INT, SC_NWST}, - {"expect", SC_XPCT, SC_XSTR, SC_NWST}, - {"ifcarr", SC_CARR, SC_NONE, SC_NWST}, - {"ifhang", SC_HUPS, SC_NONE, SC_NWST}, - {"flush", SC_FLSH, SC_NONE, SC_NONE}, - {"ifblind", SC_IFBL, SC_NONE, SC_NWST}, - {"ifblgtr", SC_IFBG, SC_INT, SC_NWST}, - {"sendstr", SC_SNDP, SC_INT, SC_NONE}, - {"ifstr", SC_IF1P, SC_INT, SC_NWST}, - {"ifnstr", SC_IF0P, SC_INT, SC_NWST}, - {"table end", SC_END, SC_NONE, SC_NONE} - }; - -#define SUCCESS 0 -#define FAIL 1 -#define ERROR -1 -#define MAX_SCLINE 255 /* max length of a line in a script file */ -#define MAX_EXPCT 127 /* max length of an expect string */ -#define CTL_DELIM " \t\n\r" /* Delimiters for tokens */ -#define SAME 0 /* if (strcmp(a,b) == SAME) ... */ -#define SLOP 10 /* Slop space on arrays */ -#define MAX_STRING 200 /* Max length string to send/expect */ - -#define DEBUG_LEVEL(level) \ - (Debug & (1 << level)) - -#define DB_LOG 0 /* error messages and a copy of the LOGFILE output */ -#define DB_LGIE 1 /* dial,login,init trace -- errors only */ -#define DB_LGI 2 /* dial,login,init trace -- nonerrors (incl chr I/O) */ -#define DB_LGII 3 /* script processing internals */ - -#define TRUE 1 -#define FALSE 0 - -#define NONE 0 -#define EVEN 1 -#define ODD 2 - -#define logit(m, p1) fprintf(stderr, "%s %s\n", m, p1) - -static char **paramv; /* Parameter vector */ -static int paramc; /* Parameter count */ -static char telno[64]; /* Telephone number w/meta-chars */ -static int Debug; -static int fShangup = FALSE; /* TRUE if HUP signal received */ -static FILE *dbf = NULL; -static struct termio old, new; - -extern int usignal(); -extern int uhup(); - -static struct siglist -{ - int signal; - int (*o_catcher) (); - int (*n_catcher) (); -} sigtbl[] = { - { SIGHUP, NULL, uhup }, - { SIGINT, NULL, usignal }, - { SIGIOT, NULL, usignal }, - { SIGQUIT, NULL, usignal }, - { SIGTERM, NULL, usignal }, - { SIGALRM, NULL, usignal }, - { 0, NULL, NULL } /* Table end */ - }; - -extern struct script *read_script(); -extern void msleep(); -extern char xgetc(); -extern void charlog(); -extern void setup_tty(); -extern void restore_tty(); -extern void ttoslow(); -extern void ttflui(); -extern void tthang(); -extern void ttbreak(); -extern void tt7bit(); -extern void ttpar(); -extern void DEBUG(); - -extern void *malloc(); - - -/* - * ********************************** - * * BEGIN EXECUTION - MAIN PROGRAM * - * ********************************** - * - * This program is called by Taylor UUCP with a list of - * arguments in argc/argv, and stdin/stdout mapped to the - * tty device, and stderr mapped to the Taylor logfile, where - * anything written to stdout will be logged as an error. - * - */ -int main(argc, argv) -int argc; -char *argv[]; -{ - int i, stat; - FILE *sf; - char sfname[256]; - struct script *script; - struct siglist *sigs; - - /* - * The following is needed because my cpp does not have the - * #error directive... - */ -#if ! HAVE_SELECT - no_select_sorry(); /* Sad way to fail make */ -#endif - - paramv = &argv[2]; /* Parameters start at 2nd arg */ - paramc = argc - 2; /* Number of live parameters */ - - telno[0] = '\0'; - - if (argc < 2) - { - fprintf(stderr, "%s: no script file supplied\n", argv[0]); - exit(FAIL); - } - - /* - * If the script file argument begins with '/', then we assume - * it is an absolute pathname, otherwise, we prepend the - * SCRIPT_DIR path. - */ - *sfname = '\0'; /* Empty name string */ - if(argv[1][0] != '/') /* If relative path */ - strcat(sfname, SCRIPT_DIR); /* Prepend the default dir. */ - strcat(sfname, argv[1]); /* Add the script file name */ - - /* - * Now open the script file. - */ - if ((sf = fopen(sfname, "r")) == NULL) - { - fprintf(stderr, "%s: Failed to open script %s\n", argv[0], sfname); - perror(" "); - exit(FAIL); - } - - /* - * COMPILE SCRIPT - */ - if ((script = read_script(sf)) == NULL) - { - fprintf(stderr, "%s: script error in \"%s\"\n", argv[0], argv[1]); - exit(FAIL); - } - - /* - * Set up a signal catcher so the line can be returned to - * it's current state if something nasty happens. - */ - sigs = &sigtbl[0]; - while(sigs->signal) - { - sigs->o_catcher = (int (*) ())signal(sigs->signal, sigs->n_catcher); - sigs += 1; - } - - /* - * Save current tty settings, then set up raw, single - * character input processing, with 7-bit stripping. - */ - setup_tty(); - - /* - * EXECUTE SCRIPT - */ - if ((stat = do_script(script)) != SUCCESS) - fprintf(stderr, "%s: script %s failed.\n", argv[0], argv[1]); - - /* - * Clean up and exit. - */ - restore_tty(); -#ifdef FIXSIGS - sigs = &sigtbl[0]; - while(sigs->signal) - if(sigs->o_catcher != -1) - signal(sigs->signal, sigs->o_catcher); -#endif - exit(stat); -} - -/* - * deal_script - deallocate a script and all strings it points to - */ -int deal_script(loc) -struct script *loc; -{ - /* - * If pointer is null, just exit - */ - if (loc == (struct script *)NULL) - return SUCCESS; - - /* - * Deallocate the rest of the script - */ - deal_script(loc->next); - - /* - * Deallocate the string parameter, if any - */ - if (loc->strprm != (char *)NULL) - free(loc->strprm); - - /* - * Deallocate the new state name parameter, if any - */ - if (loc->newstate != (char *)NULL) - free(loc->newstate); - - /* - * Deallocate this entry - */ - free(loc); - - return SUCCESS; -} - - -/* - * read_script - * - * Read & compile a script, return pointer to first entry, or null if bad - */ -struct script *read_script(fd) - FILE *fd; -{ - struct script *this = NULL; - struct script *prev = NULL; - struct script *first = NULL; - long len, i; - char inpline[MAX_SCLINE]; - char inpcopy[MAX_SCLINE]; - char *c, *cln, *opc, *cp; - - /* - * MAIN COMPILATION LOOP - */ - while ((c = fgets(inpline, (sizeof inpline - 1), fd)) != (char *)NULL) - { - /* - * Skip comments and blank lines - */ - if (*c == '#' || *c == '\n') - continue; - - /* - * Get rid of the trailing newline, and copy the string - */ - inpline[strlen(inpline)-1] = '\0'; - strcpy(inpcopy, inpline); - - /* - * Look for text starting in the first col (a label) - */ - if ((!isspace(inpline[0])) && - (cln = strchr (inpline, ':')) != (char *)NULL) { - this = (struct script *)malloc (sizeof (struct script)); - if (prev != (struct script *)NULL) - prev->next = this; - prev = this; - if (first == (struct script *)NULL) - first = this; - this->next = (struct script *)NULL; - this->opcode = SC_LABEL; - len = cln - c; - this->strprm = (char *)malloc(len+1); - strncpy(this->strprm, c, len); - (this->strprm)[len] = '\0'; - this->intprm = 0; - this->newstate = (char *)NULL; - c = cln + 1; - } - - /* - * Now handle the opcode. Fold it to lower case. - */ - opc = strtok(c, CTL_DELIM); - if (opc == (char *)NULL) /* If no opcode... */ - continue; /* ...read the next line */ - cp = opc; - while(*cp) - tolower(*cp++); - - /* - * If we have an opcode but we haven't seen anything - * else (like a label) yet, i.e., this is the first - * entry, and there was no label. We need to - * cobble up a label so that read_script is happy - */ - if (first == (struct script *)NULL) - { - this = (struct script *)malloc (sizeof (struct script)); - prev = this; - first = this; - this->next = (struct script *)NULL; - this->opcode = SC_LABEL; - this->strprm = (char *)malloc(2); - strcpy(this->strprm, ":"); - this->intprm = 0; - this->newstate = (char *)NULL; - } - - /* - * Find opcode - ndex through the opcode definition table - */ - for (i=1; sc_opdef[i].opcode != SC_END; i++) - if (strcmp(opc, sc_opdef[i].opname) == SAME) - break; - if ((sc_opdef[i].opcode) == SC_END) - { - logit ("Bad opcode in script", opc); - deal_script(first); - return (struct script *)NULL; - } - - /* - * Found opcode. Allocate a new command node and initialize - */ - this = (struct script *)malloc(sizeof (struct script)); - prev->next = this; - prev = this; - this->next = (struct script *)NULL; - this->opcode = sc_opdef[i].opcode; - this->strprm = (char *)NULL; - this->intprm = 0; - this->newstate = (char *)NULL; - - /* - * Pick up new state parameter, if any - */ - if (sc_opdef[i].newstate == SC_NWST) - { - c = strtok((char *)NULL, CTL_DELIM); - if (c == (char *)NULL) - { - logit("Missing new state", opc); - deal_script(first); - return (struct script *)NULL; - } - else - { - this->newstate = (char *)malloc(strlen(c)+1); - strcpy(this->newstate, c); - } - } - - /* - * Pick up the string or integer parameter. Handle missing - * parameter gracefully. - */ - switch (sc_opdef[i].prmtype) - { - /* - * INT parameter - convert and store in node - */ - case SC_INT: - c = strtok((char *)NULL, CTL_DELIM); - if (c == (char *)NULL) - { - logit("Missing script param", opc); - deal_script(first); - return (struct script *)NULL; - } - /* - * If this is the parameter to DBST or DBCL, force - * base-10 conversion, else convert per parameter. - */ - if (sc_opdef[i].opcode == SC_DBST || - sc_opdef[i].opcode == SC_DBCL) - this->intprm = strtol(c, (char **)NULL, 0); - else - this->intprm = strtol(c, (char **)NULL, 10); - break; - - /* - * STR/XSTR strings. - */ - case SC_STR: - case SC_XSTR: - c = strtok((char *)NULL, CTL_DELIM); - if (c == (char *)NULL) - { - logit("Missing script param", opc); - deal_script(first); - return (struct script *)NULL; - } - /* - * For XSTR opcode, use c to find out where - * the string param begins in the copy of the - * input line, and pick up all that's left of - * the line (to allow imbedded blanks, etc.). - */ - if (sc_opdef[i].prmtype == SC_XSTR) - c = &inpcopy[0] + (c - &inpline[0]); - - /* - * Allocate a buffer for the string parameter - */ - this->strprm = (char *)malloc(strlen(c)+1); - - /* - * For XSTR, Translate the string and store its - * length. Note that, after escape sequences are - * compressed, the resulting string may well be a - * few bytes shorter than the input string (whose - * length was the basis for the malloc above), - * but it will never be longer. - */ - if (sc_opdef[i].prmtype == SC_XSTR) - { - this->intprm = xlat_str(this->strprm, c); - this->strprm[this->intprm] = '\0'; - } - else - strcpy(this->strprm, c); - break; - - } - } - - /* - * EOF - */ - return first; -} - - -/* - * xlat_str - * - * Translate embedded escape characters in a "send" or "expect" string. - * - * Called by read_script(), above. - * - * Returns the actual length of the resulting string. Note that imbedded - * nulls (specified by \000 in the input) ARE allowed in the result. - */ -xlat_str(out, in) - char *out, *in; -{ - register int i = 0, j = 0; - int byte, k; - - while (in[i]) - { - if (in[i] != '\\') - { - out[j++] = in[i++]; - } - else - { - switch (in[++i]) - { - case 'd': /* EOT */ - out[j++] = 0x04; - break; - case 'N': /* null */ - out[j++] = 0x00; - break; - case 'n': /* line feed */ - out[j++] = 0x0a; - break; - case 'r': /* carriage return */ - out[j++] = 0x0d; - break; - case 's': /* space */ - out[j++] = ' '; - break; - case 't': /* tab */ - out[j++] = '\t'; - break; - case '-': /* hyphen */ - out[j++] = '-'; - break; - case '\\': /* back slash */ - out[j++] = '\\'; - break; - case '0': /* '\nnn' format */ - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - byte = in[i] - '0'; - k = 0; - - while (3 > ++k) - if ((in[i+1] < '0') || (in[i+1] > '7')) - break; - else - { - byte = (byte<<3) + in[i+1] - '0'; - ++i; - } - out[j++] = byte; - break; - default: /* don't know so skip it */ - break; - } - ++i; - } - } - return j; -} - - -/* find a state within a script */ - -struct script * - find_state(begin, newstate) -struct script *begin; -char *newstate; -{ - struct script *here; - - for (here=begin; here != (struct script *)NULL; here=here->next) { - if (here->opcode == SC_LABEL && - strcmp(here->strprm, newstate) == SAME) - return here; - } - return (struct script *)NULL; -} - - -/* - * do_script() - execute a script - */ -int do_script(begin) - struct script *begin; -{ - struct script *curstate, *newstate, *curscr; - int dbgsave; - char tempstr[MAX_SCLINE]; - char dfname[256]; - char *c, chr; - int prmlen; - int dbfd; - - time_t sc_carrtime = 45000; /* time to wf carr after dial */ - time_t sc_chrdly = 100; /* delay time for ttoslow */ - time_t sc_ptime = 2000; /* time to allow for pause char */ - time_t sc_wtime = 10000; /* time to allow for wait char */ - time_t sc_dtime = 100; /* time to allow for each digit */ - time_t sc_dtmo; /* total time to dial number */ - int sc_counter; /* random counter */ - char sc_pchar = ','; /* modem pause character */ - char sc_wchar = 'W'; /* modem wait-for-dialtone character */ - time_t sc_begwait; /* time at beg of wait */ - time_t sc_secs; /* timeout period */ - - int expcnt; - int expin; - static char expbuf[MAX_EXPCT]; - - dbgsave = Debug; - curstate = begin; - - if (curstate == (struct script *)NULL) - return SUCCESS; - - _newstate: - /* - * do all of curstate's actions. Enter with curstate pointing - * to a label entry - */ - expin = 0; - - for (curscr = curstate->next; /* point to 1st scr after label */ - (curscr != (struct script *)NULL) && /* do until end of scr */ - (curscr->opcode != SC_LABEL); /* or next label */ - curscr = curscr->next) - { - expcnt = 0; - switch (curscr->opcode) - { - case SC_LABEL: - logit("Script proc err", curstate->strprm); - return FAIL; - - case SC_FLSH: - DEBUG(DB_LGII, "Flushing typeahead buffer\n", 0); - ttflui(); - break; - - case SC_CDLY: - sc_chrdly = curscr->intprm; - DEBUG(DB_LGII, "Set chrdly to %d\n", sc_chrdly); - break; - - case SC_PCHR: - sc_pchar = *(curscr->strprm); - DEBUG(DB_LGII, "Set pause char to %c\n", sc_pchar); - break; - - case SC_PTIM: - sc_ptime = curscr->intprm; - DEBUG(DB_LGII, "Set pause time to %d\n", sc_ptime); - break; - - case SC_WCHR: - sc_wchar = *(curscr->strprm); - DEBUG(DB_LGII, "Set wait char to %c\n", sc_wchar); - break; - - case SC_WTIM: - sc_wtime = curscr->intprm; - DEBUG(DB_LGII, "Set wait time to %d\n", sc_wtime); - break; - - case SC_ZERO: - sc_counter = 0; - DEBUG(DB_LGII, "Set counter to %d\n", sc_counter); - break; - - case SC_INCR: - sc_counter++; - DEBUG(DB_LGII, "Incr counter to %d\n", sc_counter); - break; - - case SC_WAIT: - DEBUG(DB_LGII, "Sleeping %d tenth-secs\n", curscr->intprm); - msleep(curscr->intprm); - break; - - case SC_DTIM: - sc_dtime = curscr->intprm; - DEBUG(DB_LGII, "Digit time is %d\n", sc_dtime); - break; - - case SC_CTIM: - sc_carrtime = curscr->intprm; - DEBUG(DB_LGII, "Carrier time is %d\n", sc_carrtime); - break; - - case SC_EXIT: - Debug = dbgsave; - DEBUG(DB_LGI, "Script ended successfully\n", 0); - return SUCCESS; - - case SC_FAIL: - Debug = dbgsave; - if (DEBUG_LEVEL(DB_LGI) && dbf != NULL) - fprintf(dbf, "Script failed\n"); - else if (expin) - charlog(expbuf, expin, DB_LOG, - "Script failed. Last received data"); - return FAIL; - - case SC_LOG: - logit(curscr->strprm, ""); - break; - - case SC_LOGE: - logit("ERROR: ", curscr->strprm); - break; - - case SC_DBOF: - /* - * If the debug file name does not begin with "/", then - * we prepend the LOG_DIR to the string. Then CREATE the - * file. This WIPES OUT previous logs. - */ - *dfname = '\0'; /* Zero name string */ - if(curscr->strprm[0] != '/') - strcat(dfname, LOG_DIR); /* Prepend default directory */ - strcat(dfname, curscr->strprm); /* Add given string */ - DEBUG(DB_LGII, "Open debug file %s\n", dfname); - if ((dbfd = creat (dfname, 0600)) <= 0) - { - logit("Failed to create debug log %s", dfname); - perror(""); - return FAIL; - } - if ((dbf = fdopen(dbfd, "w")) == NULL) - { - logit("Failed to open debug log fildes.", ""); - perror(""); - return FAIL; - } - break; - - case SC_DBG: - DEBUG(DB_LGI, "<%s>\n", curscr->strprm); - break; - - case SC_DBGE: - DEBUG(DB_LGIE, "ERROR: <%s>\n", curscr->strprm); - break; - - case SC_DBST: - Debug |= curscr->intprm; - DEBUG(DB_LGII, "Debug mask set to %04o (octal)\n", Debug); - break; - - case SC_DBCL: - Debug &= ~(curscr->intprm); - DEBUG(DB_LGII, "Debug mask set to %04o (octal)\n", Debug); - break; - - case SC_BRK: - DEBUG(DB_LGI, "Sending break\n", 0); - ttbreak(); - break; - - case SC_HANG: - DEBUG(DB_LGI, "Dropping DTR\n", 0); - tthang(); - break; - - case SC_7BIT: - DEBUG(DB_LGI, "Enabling 7-bit stripping\n", 0); - tt7bit(TRUE); - break; - - case SC_8BIT: - DEBUG(DB_LGI, "Disabling 7-bit stripping\n", 0); - tt7bit(FALSE); - break; - - case SC_PNON: - DEBUG(DB_LGI, "Setting 8-bit, no parity\n", 0); - ttpar(NONE); - break; - - case SC_PEVN: - DEBUG(DB_LGI, "Setting 7-bit, even parity\n", 0); - ttpar(EVEN); - break; - - case SC_PODD: - DEBUG(DB_LGI, "Setting 7-bit, odd parity\n", 0); - ttpar(ODD); - break; - - case SC_IFBL: - if (ttblind()) - { - DEBUG(DB_LGI, "Blind mux,\n", 0); - goto _chgstate; - } - break; - - case SC_IFBG: - if (ttblind() && sc_counter > curscr->intprm) - { - DEBUG(DB_LGI, "Blind mux & ctr > %d\n", - curscr->intprm); - goto _chgstate; - } - break; - - case SC_IFGT: - if (sc_counter > curscr->intprm) - { - DEBUG(DB_LGI, "Counter > %d\n", curscr->intprm); - goto _chgstate; - } - break; - - case SC_GOTO: - _chgstate: - DEBUG(DB_LGI, "Changing to state %s\n", - curscr->newstate); - curstate = find_state(begin, curscr->newstate); - if (curstate == NULL) - { - logit("New state not found", - curscr->newstate); - return FAIL; - } - goto _newstate; - - case SC_SEND: - ttoslow(curscr->strprm, curscr->intprm, sc_chrdly); - break; - - case SC_TELN: - if (curscr->intprm > paramc - 1) - { - sprintf(tempstr, "telno - param #%d", curscr->intprm); - logit(tempstr, " not present"); - return FAIL; - } - strcpy(telno, paramv[curscr->intprm]); - DEBUG(DB_LGII, "telno set to %s\n", telno); - break; - - case SC_SNDP: - if (curscr->intprm > paramc - 1) - { - sprintf(tempstr, "sendstr - param #%d", curscr->intprm); - logit(tempstr, " not present"); - return FAIL; - } - prmlen = xlat_str(tempstr, paramv[curscr->intprm]); - ttoslow(tempstr, prmlen, sc_chrdly); - break; - - case SC_IF1P: - if (curscr->intprm < paramc) - goto _chgstate; - break; - - case SC_IF0P: - if (curscr->intprm >= paramc) - goto _chgstate; - break; - - case SC_DIAL: - if(telno[0] == '\0') - { - logit("telno not set", ""); - return(FAIL); - } - /* - * Compute and set a default timeout for the 'timeout' - * command. Some parameters in this computation may be - * changed by the script. See the man page xchat(8) for - * details. - */ - sc_dtmo = (sc_dtime+sc_chrdly)*strlen(telno) - + sc_carrtime; - c=strcpy(tempstr, telno); - for (; *c!='\0'; c++) - { - if (*c == 'W') - { - *c = sc_wchar; - sc_dtmo += sc_wtime; - } - else if (*c == 'P') - { - *c = sc_pchar; - sc_dtmo += sc_ptime; - } - } - DEBUG(DB_LGI, "Dialing, default timeout is %d millisecs\n", sc_dtmo); - ttoslow(tempstr, 0, sc_chrdly); - break; - - case SC_TIMO: /* these are "expects", don't bother */ - case SC_XPCT: /* with them yet, other than noting that */ - case SC_CARR: /* they exist */ - expcnt++; - break; - } - - } - - /* we've done the current state's actions, now do its expects, if any */ - - if (expcnt == 0) - { - if (curscr != (struct script *)NULL && - (curscr->opcode == SC_LABEL)) - { - curstate = curscr; - DEBUG(DB_LGI, "Fell through to state %s\n", - curstate->strprm); - goto _newstate; - } - else - { - logit("No way out of state", curstate->strprm); - return FAIL; - } - } - - time(&sc_begwait); /* log time at beg of expect */ - DEBUG(DB_LGI, "Doing expects for state %s\n", curstate->strprm); - charlog((char *)NULL, 0, DB_LGI, "Received"); - - while (1) - { - chr = xgetc(1); /* Returns upon char input or 1 sec. tmo */ - - charlog(&chr, 1, DB_LGI, (char *)NULL); - - if (chr != EOF) - { - if (expin < MAX_EXPCT) - { - expbuf[expin++] = chr & 0x7f; - } - else - { - strncpy(expbuf, &expbuf[1], MAX_EXPCT-1); - expbuf[MAX_EXPCT-1] = chr & 0x7f; - } - } - - /* for each entry in the current state... */ - - for (curscr = curstate->next; - (curscr != (struct script *)NULL) && - (curscr->opcode != SC_LABEL); - curscr = curscr->next) - { - - switch (curscr->opcode) - { - case SC_TIMO: - sc_secs = curscr->intprm; - if (sc_secs == 0) - sc_secs = sc_dtmo; - sc_secs /= 1000; - if (time(NULL)-sc_begwait > sc_secs) - { - DEBUG(DB_LGI, - "\nTimed out (%d secs)\n", sc_secs); - goto _chgstate; - } - break; - - case SC_CARR: - if (ttcd()) - { - DEBUG(DB_LGI, "\nGot carrier\n", 0); - goto _chgstate; - } - break; - - case SC_HUPS: - if (fShangup) - { - DEBUG(DB_LGI, "\nGot data set hangup\n", 0); - goto _chgstate; - } - break; - - case SC_XPCT: - if ((expin >= curscr->intprm) && - (strncmp(curscr->strprm, - &expbuf[expin - curscr->intprm], - curscr->intprm) == SAME)) - { - charlog(curscr->strprm, curscr->intprm, - DB_LGI, "Matched"); - goto _chgstate; - } - break; - - } - } - } -} - -/* - * SIGNAL HANDLERS - */ - -/* - * usignal - generic signal catcher - */ -static int usignal(isig) - int isig; -{ - DEBUG(DB_LOG, "Caught signal %d. Exiting...\n", isig); - restore_tty(); - exit(FAIL); -} - -/* - * uhup - HUP catcher - */ -static int uhup(isig) - int isig; -{ - DEBUG(DB_LOG, "Data set hangup.\n"); - fShangup = TRUE; -} - -/* - * TERMINAL I/O ROUTINES - */ - -/* - * xgetc - get a character with timeout - * - * Assumes that stdin is opened on a terminal or TCP socket - * with O_NONBLOCK. - */ -static char xgetc(tmo) -int tmo; /* Timeout, seconds */ -{ - char c; - struct timeval s; - int f = 1; /* Select on stdin */ - int result; - - if(read(0, &c, 1) <= 0) /* If no data available */ - { - s.tv_sec = (long)tmo; - s.tv_usec = 0L; - if(select (1, &f, (int *) NULL, &f, &s) == 1) - read(0, &c, 1); - else - c = '\377'; - } - - return(c); -} - -/* - * Pause for an interval in milliseconds - */ -void msleep(msec) -long msec; -{ - -#if HAVE_USLEEP - if(msec == 0) /* Skip all of this if delay = 0 */ - return; - usleep (msec * (long)1000); -#endif /* HAVE_USLEEP */ - -#if HAVE_NAPMS - if(msec == 0) /* Skip all of this if delay = 0 */ - return; - napms (msec); -#endif /* HAVE_NAPMS */ - -#if HAVE_NAP - if(msec == 0) /* Skip all of this if delay = 0 */ - return; - nap (msec); -#endif /* HAVE_NAP */ - -#if HAVE_POLL - struct pollfd sdummy; - - if(msec == 0) - return; - /* - * We need to pass an unused pollfd structure because poll checks - * the address before checking the number of elements. - */ - poll (&sdummy, 0, msec); -#endif /* HAVE_POLL */ - -#if USE_SELECT_TIMER - struct timeval s; - - if(msec == 0) - return; - s.tv_sec = msec / 1000L; - s.tv_usec = (msec % 1000L) * 1000L; - select (0, (int *) NULL, (int *) NULL, (int *) NULL, &s); -#endif /* USE_SELECT_TIMER */ - -#if ! HAVE_NAPMS && ! HAVE_NAP && ! HAVE_USLEEP && \ - ! HAVE_POLL && ! USE_SELECT_TIMER - if(msec == 0) - return; - sleep (1); /* Sleep for a whole second (UGH!) */ -#endif /* HAVE_ and USE_ nothing */ -} - -/* - * Debugging output - */ -static void DEBUG(level, msg1, msg2) -int level; -char *msg1, *msg2; -{ - if ((dbf != NULL) && DEBUG_LEVEL(level)) - fprintf(dbf, msg1, msg2); -} - -/* - * charlog - log a string of characters - * - * SPECIAL CASE: msg=NULL, len=1 and msg[0]='\377' gets logged - * when read does its 1 sec. timeout. Log "<1 sec.>" - * so user can see elapsed time - */ -static void charlog(buf, len, mask, msg) -char *buf; -int len, mask; -char *msg; -{ - char tbuf[256]; - - if (DEBUG_LEVEL(mask) && dbf != NULL) - { - if(msg == (char *)NULL) - msg = ""; - strncpy(tbuf, buf, len); - tbuf[len] = '\0'; - if(len == 1 && tbuf[0] == '\377') - strcpy(tbuf, "<1 sec.>"); - fprintf(dbf, "%s %s\n", msg, tbuf); - } -} - -/* - * setup_tty() - * - * Save current tty settings, then set up raw, single - * character input processing, with 7-bit stripping. - */ -static void setup_tty() -{ - register int i; - - ioctl(0, TCGETA, &old); - - new = old; - - for(i = 0; i < 7; i++) - new.c_cc[i] = '\0'; - new.c_cc[VMIN] = 0; /* MIN = 0, use requested count */ - new.c_cc[VTIME] = 10; /* TIME = 1 sec. */ - new.c_iflag = ISTRIP; /* Raw mode, 7-bit stripping */ - new.c_lflag = 0; /* No special line discipline */ - - ioctl(0, TCSETA, &new); -} - -/* - * restore_tty() - restore signal handlers and tty modes on exit. - */ -static void restore_tty(sig) -int sig; -{ - ioctl(0, TCSETA, &old); - return; -} - -/* - * ttoslow() - Send characters with pacing delays - */ -static void ttoslow(s, len, delay) - char *s; - int len; - time_t delay; -{ - int i; - - if (len == 0) - len = strlen(s); - - charlog (s, len, DB_LGI, "Sending slowly"); - - for (i = 0; i < len; i++, s++) - { - write(1, s, 1); - msleep(delay); - } -} - -/* - * ttflui - flush input buffer - */ -static void ttflui() -{ - if(isatty(0)) - (void) ioctl ( 0, TCFLSH, 0); -} - -/* - * ttcd - Test if carrier is present - * - * NOT IMPLEMENTED. I don't know how!!! - */ -static int ttcd() -{ - return TRUE; -} - -/* - * tthang - Force DTR low for 1-2 sec. - */ -static void tthang() -{ - if(!isatty()) - return; - -#ifdef TCCLRDTR - (void) ioctl (1, TCCLRDTR, 0); - sleep (2); - (void) ioctl (1, TCSETDTR, 0); -#endif - - return; -} - -/* - * ttbreak - Send a "break" on the line - */ -static void ttbreak() -{ - (void) ioctl (1, TCSBRK, 0); -} - -/* - * ttblind - return TRUE if tty is "blind" - * - * NOT IMPLEMENTED - Don't know how!!! - */ -static int ttblind() -{ - return FALSE; -} - -/* - * tt7bit - enable/disable 7-bit stripping on line - */ -static void tt7bit(enable) - int enable; -{ - if(enable) - new.c_iflag |= ISTRIP; - else - new.c_iflag &= ~ISTRIP; - - ioctl(0, TCSETA, &new); -} - -/* - * ttpar - Set parity mode on line. Ignore parity errors on input. - */ -static void ttpar(mode) - int mode; -{ - switch(mode) - { - case NONE: - new.c_iflag &= ~(INPCK | IGNPAR); - new.c_cflag &= ~(CSIZE | PARENB | PARODD); - new.c_cflag |= CS8; - break; - - case EVEN: - new.c_iflag |= (INPCK | IGNPAR); - new.c_cflag &= ~(CSIZE | PARODD); - new.c_cflag |= (CS7 | PARENB); - - break; - - case ODD: - new.c_iflag |= (INPCK | IGNPAR); - new.c_cflag &= ~(CSIZE); - new.c_cflag |= (CS7 | PARENB | PARODD); - break; - } - - ioctl(0, TCSETA, &new); -} - - - - - - - |