Annotation of coherent/g/usr/lib/uucp/tay104/contrib/xchat.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *  ***********
        !             3:  *  * XCHAT.C *
        !             4:  *  ***********
        !             5:  *
        !             6:  * Extended chat processor for Taylor UUCP. See accompanying documentation.
        !             7:  *
        !             8:  * Written by:
        !             9:  *   Bob Denny ([email protected])
        !            10:  *   Based on code in DECUS UUCP (for VAX/VMS)
        !            11:  *
        !            12:  * History:
        !            13:  *   Version 1.0 shipped with Taylor 1.03. No configuration info inside.
        !            14:  *
        !            15:  *   Bob Denny - Sun Aug 30 18:41:30 1992
        !            16:  *     V1.1 - long overdue changes for other systems. Rip out interval
        !            17:  *            timer code, use timer code from Taylor UUCP, use select()
        !            18:  *            for timed reads. Use Taylor UUCP "conf.h" file to set
        !            19:  *            configuration for this program. Add defaulting of script
        !            20:  *            and log file paths.
        !            21:  *
        !            22:  * Bugs:
        !            23:  *   Does not support BSD terminal I/O. Anyone care to add it?
        !            24:  */
        !            25: 
        !            26: #include <sys/types.h>
        !            27: #include <stdio.h>
        !            28: #include <string.h>
        !            29: #include <ctype.h>
        !            30: #include <signal.h>
        !            31: #include <time.h>
        !            32: #include <sys/ioctl.h>
        !            33: #include <sys/termio.h>
        !            34: 
        !            35: #include "xc-conf.h"
        !            36: 
        !            37: /* 
        !            38:  * Pick a timing routine to use, as done in Taylor UUCP.
        !            39:  */
        !            40: #if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS || HAVE_POLL
        !            41: #define USE_SELECT_TIMER 0
        !            42: #else
        !            43: #define USE_SELECT_TIMER HAVE_SELECT
        !            44: #if USE_SELECT_TIMER
        !            45: #include <sys/time.h>
        !            46: #endif
        !            47: #endif
        !            48: 
        !            49: #if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS
        !            50: #undef HAVE_POLL
        !            51: #define HAVE_POLL 0
        !            52: #endif
        !            53: 
        !            54: #if HAVE_USLEEP || HAVE_NAP
        !            55: #undef HAVE_NAPMS
        !            56: #define HAVE_NAPMS 0
        !            57: #endif
        !            58: 
        !            59: #if HAVE_USLEEP
        !            60: #undef HAVE_NAP
        !            61: #define HAVE_NAP 0
        !            62: #endif
        !            63: 
        !            64: static int ttblind();
        !            65: static int ttcd();
        !            66: 
        !            67: /* script entry -- "compiled" form of dial, hangup, or login script */
        !            68: 
        !            69: struct script {
        !            70:        struct  script  *next;  /* pointer to next entry, or null */
        !            71:        int              opcode;        /* numeric opcode */
        !            72:        char            *strprm;        /* pointer to string param */
        !            73:        long             intprm;        /* integer parameter */
        !            74:        char            *newstate;      /* new state name */
        !            75: };
        !            76: 
        !            77: /* opcode definition array element -- one for each possible opcode */
        !            78: 
        !            79: struct script_opdef {
        !            80:        char    *opname;
        !            81:        int      opcode;        /* numeric opcode -- same as array index */
        !            82:        int      prmtype;       /* one of SC_NONE, SC_STR, SC_XSTR, SC_INT */
        !            83:        int      newstate;      /* one of SC_NONE, SC_NWST */
        !            84: };
        !            85: 
        !            86:        /* values for opcode */
        !            87: 
        !            88: #define        SC_LABEL 0      /* "label" (state name) */
        !            89: #define        SC_CDLY 1       /* set char output delay in msec */
        !            90: #define        SC_PCHR 2       /* pause char for dial string (from P in input) */
        !            91: #define        SC_PTIM 3       /* seconds to allow for pause char */
        !            92: #define        SC_WCHR 4       /* wait char for dial string (from W in input) */
        !            93: #define        SC_WTIM 5       /* seconds to allow for wait char */
        !            94: #define        SC_ZERO 6       /* zero counter */
        !            95: #define        SC_INCR 7       /* increment counter */
        !            96: #define SC_IFGT        8       /* change state if counter > int param */
        !            97: #define        SC_WAIT 9       /* wait for int param seconds */
        !            98: #define        SC_GOTO 10      /* unconditional change to new state */
        !            99: #define        SC_SEND 11      /* send strparam (after sprintf substitutions) */
        !           100: #define        SC_BRK  12      /* send a break */
        !           101: #define        SC_HANG 13      /* drop DTR */
        !           102: #define        SC_DIAL 14      /* send telno string (after subst PCHR & WCHR) */
        !           103: #define        SC_DTIM 15      /* time in msec per digit (for timeout calculations) */
        !           104:                        /* default = 100 (one tenth second) */
        !           105: #define        SC_CTIM 16      /* additional time (in seconds) to wait for carrier */
        !           106:                        /* default = 45 seconds */
        !           107: #define        SC_EXIT 17      /* script done, success */
        !           108: #define        SC_FAIL 18      /* script done, failure */
        !           109: #define        SC_LOG  19      /* write strparam to uucp.log */
        !           110: #define        SC_LOGE 20      /* write strparam to uucp.log w/error ind */
        !           111: #define        SC_DBG  21      /* write strparam to debug log if debug lvl = LGI */
        !           112: #define        SC_DBGE 22      /* write strparam to debug log if debug lvl = LGIE */
        !           113: #define        SC_DBST 23      /* 'or' intparam into debug mask */
        !           114: #define        SC_DBCL 24      /* 'bicl' intparam into debug mask */
        !           115: #define        SC_TIMO 25      /* newstate if no match in intparam secs */
        !           116:                        /* (uses calculated dial time if intparam is 0) */
        !           117: #define        SC_XPCT 26      /* wait for strparam, goto _newstate if found */
        !           118: #define        SC_CARR 27      /* goto _newstate if carrier detected */
        !           119: #define        SC_FLSH 28      /* flush typeahead buffer */
        !           120: #define        SC_IFBL 29      /* change state if controller is blind w/o CD */
        !           121: #define        SC_IFBG 30      /* chg state if ctlr is blind and counter > intprm */
        !           122: #define        SC_SNDP 31      /* send parameter n */
        !           123: #define        SC_IF1P 32      /* if parameter n present */
        !           124: #define        SC_IF0P 33      /* if parameter n absent */
        !           125: #define SC_DBOF 34     /* open debugging file */
        !           126: #define SC_TELN 35     /* Set telno from parameter n */
        !           127: #define SC_7BIT 36     /* Set port to 7-bit stripping */
        !           128: #define SC_8BIT 37     /* Set port for 8-bit characters */
        !           129: #define SC_PNON 38     /* Set port for 8-bit, no parity */
        !           130: #define SC_PEVN 39     /* Set port for 7-bit, even parity */
        !           131: #define SC_PODD 40     /* Set port for 7-bit, odd parity */
        !           132: #define SC_HUPS 41     /* Change state on HUP signal */
        !           133: #define        SC_END  42      /* end of array */
        !           134: 
        !           135:        /* values for prmtype, prm2type */
        !           136: 
        !           137: #define        SC_NONE 0               /* no parameter */
        !           138: #define        SC_STR  1               /* simple string */
        !           139: #define        SC_INT  2               /* integer */
        !           140: #define        SC_NWST 3               /* new state name */
        !           141: #define        SC_XSTR 4               /* translated string */
        !           142: 
        !           143: /* opcode definition table for dial/login/hangup scripts */
        !           144: 
        !           145: static struct  script_opdef    sc_opdef[] =
        !           146:       {
        !           147:        {"label",       SC_LABEL,       SC_NONE,        SC_NONE},
        !           148:        {"chrdly",      SC_CDLY,        SC_INT,         SC_NONE},
        !           149:        {"pchar",       SC_PCHR,        SC_STR,         SC_NONE},
        !           150:        {"ptime",       SC_PTIM,        SC_INT,         SC_NONE},
        !           151:        {"wchar",       SC_WCHR,        SC_STR,         SC_NONE},
        !           152:        {"wtime",       SC_WTIM,        SC_INT,         SC_NONE},
        !           153:        {"zero",        SC_ZERO,        SC_NONE,        SC_NONE},
        !           154:        {"count",       SC_INCR,        SC_NONE,        SC_NONE},
        !           155:        {"ifgtr",       SC_IFGT,        SC_INT,         SC_NWST},
        !           156:        {"sleep",       SC_WAIT,        SC_INT,         SC_NONE},
        !           157:        {"goto",        SC_GOTO,        SC_NONE,        SC_NWST},
        !           158:        {"send",        SC_SEND,        SC_XSTR,        SC_NONE},
        !           159:        {"break",       SC_BRK,         SC_NONE,        SC_NONE},
        !           160:        {"hangup",      SC_HANG,        SC_NONE,        SC_NONE},
        !           161:        {"7bit",        SC_7BIT,        SC_NONE,        SC_NONE},
        !           162:        {"8bit",        SC_8BIT,        SC_NONE,        SC_NONE},
        !           163:        {"nopar",       SC_PNON,        SC_NONE,        SC_NONE},
        !           164:        {"evenpar",     SC_PEVN,        SC_NONE,        SC_NONE},
        !           165:        {"oddpar",      SC_PODD,        SC_NONE,        SC_NONE},
        !           166:        {"telno",       SC_TELN,        SC_INT,         SC_NONE},
        !           167:        {"dial",        SC_DIAL,        SC_NONE,        SC_NONE},
        !           168:        {"dgttime",     SC_DTIM,        SC_INT,         SC_NONE},
        !           169:        {"ctime",       SC_CTIM,        SC_INT,         SC_NONE},
        !           170:        {"success",     SC_EXIT,        SC_NONE,        SC_NONE},
        !           171:        {"failed",      SC_FAIL,        SC_NONE,        SC_NONE},
        !           172:        {"log",         SC_LOG,         SC_XSTR,        SC_NONE},
        !           173:        {"logerr",      SC_LOGE,        SC_XSTR,        SC_NONE},
        !           174:        {"debug",       SC_DBG,         SC_XSTR,        SC_NONE},
        !           175:        {"debuge",      SC_DBGE,        SC_XSTR,        SC_NONE},
        !           176:        {"dbgset",      SC_DBST,        SC_INT,         SC_NONE},
        !           177:        {"dbgclr",      SC_DBCL,        SC_INT,         SC_NONE},
        !           178:        {"dbgfile",     SC_DBOF,        SC_XSTR,        SC_NONE},
        !           179:        {"timeout",     SC_TIMO,        SC_INT,         SC_NWST},
        !           180:        {"expect",      SC_XPCT,        SC_XSTR,        SC_NWST},
        !           181:        {"ifcarr",      SC_CARR,        SC_NONE,        SC_NWST},
        !           182:        {"ifhang",      SC_HUPS,        SC_NONE,        SC_NWST},
        !           183:        {"flush",       SC_FLSH,        SC_NONE,        SC_NONE},
        !           184:        {"ifblind",     SC_IFBL,        SC_NONE,        SC_NWST},
        !           185:        {"ifblgtr",     SC_IFBG,        SC_INT,         SC_NWST},
        !           186:        {"sendstr",     SC_SNDP,        SC_INT,         SC_NONE},
        !           187:        {"ifstr",       SC_IF1P,        SC_INT,         SC_NWST},
        !           188:        {"ifnstr",      SC_IF0P,        SC_INT,         SC_NWST},
        !           189:        {"table end",   SC_END,         SC_NONE,        SC_NONE}
        !           190:       };
        !           191: 
        !           192: #define SUCCESS 0
        !           193: #define        FAIL    1
        !           194: #define ERROR  -1
        !           195: #define MAX_SCLINE     255     /* max length of a line in a script file */
        !           196: #define MAX_EXPCT      127     /* max length of an expect string */
        !           197: #define        CTL_DELIM       " \t\n\r" /* Delimiters for tokens */
        !           198: #define        SAME            0       /* if (strcmp(a,b) == SAME) ... */
        !           199: #define        SLOP            10      /* Slop space on arrays */
        !           200: #define        MAX_STRING      200     /* Max length string to send/expect */
        !           201: 
        !           202: #define        DEBUG_LEVEL(level) \
        !           203:           (Debug & (1 << level))
        !           204: 
        !           205: #define        DB_LOG  0       /* error messages and a copy of the LOGFILE output */
        !           206: #define        DB_LGIE 1       /* dial,login,init trace -- errors only */
        !           207: #define        DB_LGI  2       /* dial,login,init trace -- nonerrors (incl chr I/O) */
        !           208: #define        DB_LGII 3       /* script processing internals */
        !           209: 
        !           210: #define TRUE    1
        !           211: #define FALSE   0
        !           212: 
        !           213: #define NONE   0
        !           214: #define EVEN   1
        !           215: #define ODD    2
        !           216: 
        !           217: #define logit(m, p1) fprintf(stderr, "%s %s\n", m, p1)
        !           218: 
        !           219: static char **paramv;          /* Parameter vector */
        !           220: static int paramc;             /* Parameter count */
        !           221: static char telno[64];         /* Telephone number w/meta-chars */
        !           222: static int Debug;
        !           223: static int fShangup = FALSE;   /* TRUE if HUP signal received */
        !           224: static FILE  *dbf = NULL;
        !           225: static struct termio old, new;
        !           226: 
        !           227: extern int usignal();
        !           228: extern int uhup();
        !           229: 
        !           230: static struct siglist
        !           231: {
        !           232:   int signal;
        !           233:   int (*o_catcher) ();
        !           234:   int (*n_catcher) ();
        !           235: } sigtbl[] = {
        !           236:              { SIGHUP,   NULL, uhup },
        !           237:              { SIGINT,   NULL, usignal },
        !           238:             { SIGIOT,   NULL, usignal },
        !           239:              { SIGQUIT,  NULL, usignal },
        !           240:              { SIGTERM,  NULL, usignal },
        !           241:              { SIGALRM,  NULL, usignal },
        !           242:              { 0,        NULL, NULL    }    /* Table end */
        !           243:            };
        !           244: 
        !           245: extern struct script *read_script();
        !           246: extern void msleep();
        !           247: extern char xgetc();
        !           248: extern void charlog();
        !           249: extern void setup_tty();
        !           250: extern void restore_tty();
        !           251: extern void ttoslow();
        !           252: extern void ttflui();
        !           253: extern void tthang();
        !           254: extern void ttbreak();
        !           255: extern void tt7bit();
        !           256: extern void ttpar();
        !           257: extern void DEBUG();
        !           258: 
        !           259: extern void *malloc();
        !           260: 
        !           261: 
        !           262: /*
        !           263:  * **********************************
        !           264:  * * BEGIN EXECUTION - MAIN PROGRAM *
        !           265:  * **********************************
        !           266:  *
        !           267:  * This program is called by Taylor UUCP with a list of
        !           268:  * arguments in argc/argv, and stdin/stdout mapped to the
        !           269:  * tty device, and stderr mapped to the Taylor logfile, where
        !           270:  * anything written to stdout will be logged as an error.
        !           271:  * 
        !           272:  */
        !           273: int main(argc, argv)
        !           274: int argc;
        !           275: char *argv[];
        !           276: {
        !           277:   int i, stat;
        !           278:   FILE *sf;
        !           279:   char sfname[256];
        !           280:   struct script *script;
        !           281:   struct siglist *sigs;
        !           282: 
        !           283:   /*
        !           284:    * The following is needed because my cpp does not have the
        !           285:    * #error directive...
        !           286:    */
        !           287: #if ! HAVE_SELECT
        !           288:   no_select_sorry();           /* Sad way to fail make */
        !           289: #endif
        !           290: 
        !           291:   paramv = &argv[2];           /* Parameters start at 2nd arg */
        !           292:   paramc = argc - 2;           /* Number of live parameters */
        !           293: 
        !           294:   telno[0] = '\0';
        !           295: 
        !           296:   if (argc < 2)
        !           297:     {
        !           298:       fprintf(stderr, "%s: no script file supplied\n", argv[0]);
        !           299:       exit(FAIL);
        !           300:     }
        !           301: 
        !           302:   /*
        !           303:    * If the script file argument begins with '/', then we assume
        !           304:    * it is an absolute pathname, otherwise, we prepend the 
        !           305:    * SCRIPT_DIR path.
        !           306:    */
        !           307:   *sfname = '\0';              /* Empty name string */
        !           308:   if(argv[1][0] != '/')                /* If relative path */
        !           309:     strcat(sfname, SCRIPT_DIR); /* Prepend the default dir. */
        !           310:   strcat(sfname, argv[1]);     /* Add the script file name */
        !           311: 
        !           312:   /*
        !           313:    * Now open the script file.
        !           314:    */
        !           315:   if ((sf = fopen(sfname, "r")) == NULL)
        !           316:     {
        !           317:       fprintf(stderr, "%s: Failed to open script %s\n", argv[0], sfname);
        !           318:       perror(" ");
        !           319:       exit(FAIL);
        !           320:     }
        !           321: 
        !           322:   /*
        !           323:    * COMPILE SCRIPT
        !           324:    */
        !           325:   if ((script = read_script(sf)) == NULL)
        !           326:     {
        !           327:       fprintf(stderr, "%s: script error in \"%s\"\n", argv[0], argv[1]);
        !           328:       exit(FAIL);
        !           329:     }
        !           330: 
        !           331:   /*
        !           332:    * Set up a signal catcher so the line can be returned to
        !           333:    * it's current state if something nasty happens.
        !           334:    */
        !           335:   sigs = &sigtbl[0];
        !           336:   while(sigs->signal)
        !           337:     {
        !           338:       sigs->o_catcher = (int (*) ())signal(sigs->signal, sigs->n_catcher);
        !           339:       sigs += 1;
        !           340:     }
        !           341: 
        !           342:   /*
        !           343:    * Save current tty settings, then set up raw, single
        !           344:    * character input processing, with 7-bit stripping.
        !           345:    */
        !           346:   setup_tty();
        !           347: 
        !           348:   /*
        !           349:    * EXECUTE SCRIPT
        !           350:    */
        !           351:   if ((stat = do_script(script)) != SUCCESS)
        !           352:     fprintf(stderr, "%s: script %s failed.\n", argv[0], argv[1]);
        !           353: 
        !           354:   /*
        !           355:    * Clean up and exit.
        !           356:    */
        !           357:   restore_tty();
        !           358: #ifdef FIXSIGS
        !           359:   sigs = &sigtbl[0];
        !           360:   while(sigs->signal)
        !           361:     if(sigs->o_catcher != -1)
        !           362:       signal(sigs->signal, sigs->o_catcher);
        !           363: #endif
        !           364:   exit(stat);
        !           365: }
        !           366: 
        !           367: /* 
        !           368:  * deal_script - deallocate a script and all strings it points to
        !           369:  */
        !           370: int deal_script(loc)
        !           371: struct script *loc;
        !           372: {
        !           373:   /*
        !           374:    * If pointer is null, just exit
        !           375:    */
        !           376:   if (loc == (struct script *)NULL)
        !           377:     return SUCCESS;
        !           378:   
        !           379:   /*
        !           380:    * Deallocate the rest of the script
        !           381:    */
        !           382:   deal_script(loc->next);
        !           383:   
        !           384:   /*
        !           385:    * Deallocate the string parameter, if any
        !           386:    */
        !           387:   if (loc->strprm != (char *)NULL)
        !           388:     free(loc->strprm);
        !           389:   
        !           390:   /*
        !           391:    * Deallocate the new state name parameter, if any
        !           392:    */
        !           393:   if (loc->newstate != (char *)NULL)
        !           394:     free(loc->newstate);
        !           395:   
        !           396:   /*
        !           397:    * Deallocate this entry
        !           398:    */
        !           399:   free(loc);
        !           400:   
        !           401:   return SUCCESS;
        !           402: }
        !           403: 
        !           404: 
        !           405: /* 
        !           406:  * read_script
        !           407:  *
        !           408:  * Read & compile a script, return pointer to first entry, or null if bad
        !           409:  */
        !           410: struct script *read_script(fd)
        !           411:      FILE *fd;
        !           412: {
        !           413:   struct script        *this = NULL;
        !           414:   struct script        *prev = NULL;
        !           415:   struct script        *first = NULL;
        !           416:   long len, i;
        !           417:   char inpline[MAX_SCLINE];
        !           418:   char inpcopy[MAX_SCLINE];
        !           419:   char *c, *cln, *opc, *cp;
        !           420:   
        !           421:   /*
        !           422:    * MAIN COMPILATION LOOP
        !           423:    */  
        !           424:   while ((c = fgets(inpline, (sizeof inpline - 1), fd)) != (char *)NULL)
        !           425:     {
        !           426:       /*
        !           427:        * Skip comments and blank lines
        !           428:        */
        !           429:       if (*c == '#' || *c == '\n')
        !           430:        continue;
        !           431:       
        !           432:       /* 
        !           433:        * Get rid of the trailing newline, and copy the string
        !           434:        */
        !           435:       inpline[strlen(inpline)-1] = '\0';
        !           436:       strcpy(inpcopy, inpline);
        !           437:       
        !           438:       /*
        !           439:        * Look for text starting in the first col (a label)
        !           440:        */
        !           441:       if ((!isspace(inpline[0])) &&
        !           442:          (cln = strchr (inpline, ':')) != (char *)NULL) {
        !           443:        this = (struct script *)malloc (sizeof (struct script));
        !           444:        if (prev != (struct script *)NULL)
        !           445:          prev->next = this;
        !           446:        prev = this;
        !           447:        if (first == (struct script *)NULL)
        !           448:          first = this;
        !           449:        this->next = (struct script *)NULL;
        !           450:        this->opcode = SC_LABEL;
        !           451:        len = cln - c;
        !           452:        this->strprm = (char *)malloc(len+1);
        !           453:        strncpy(this->strprm, c, len);
        !           454:        (this->strprm)[len] = '\0';
        !           455:        this->intprm = 0;
        !           456:        this->newstate = (char *)NULL;
        !           457:        c = cln + 1;
        !           458:       }
        !           459:       
        !           460:       /*
        !           461:        * Now handle the opcode. Fold it to lower case.
        !           462:        */
        !           463:       opc = strtok(c, CTL_DELIM);
        !           464:       if (opc == (char *)NULL) /* If no opcode... */
        !           465:        continue;                       /* ...read the next line */
        !           466:       cp = opc;
        !           467:       while(*cp)
        !           468:        tolower(*cp++);
        !           469:       
        !           470:       /* 
        !           471:        * If we have an opcode but we haven't seen anything
        !           472:        * else (like a label) yet, i.e., this is the first
        !           473:        * entry, and there was no label.  We need to 
        !           474:        * cobble up a label so that read_script is happy
        !           475:        */
        !           476:       if (first == (struct script *)NULL) 
        !           477:        {
        !           478:          this = (struct script *)malloc (sizeof (struct script));
        !           479:          prev = this;
        !           480:          first = this;
        !           481:          this->next = (struct script *)NULL;
        !           482:          this->opcode = SC_LABEL;
        !           483:          this->strprm = (char *)malloc(2);
        !           484:          strcpy(this->strprm, ":");
        !           485:          this->intprm = 0;
        !           486:          this->newstate = (char *)NULL;
        !           487:        }
        !           488:       
        !           489:       /* 
        !           490:        * Find opcode - ndex through the opcode definition table
        !           491:        */
        !           492:       for (i=1; sc_opdef[i].opcode != SC_END; i++)
        !           493:        if (strcmp(opc, sc_opdef[i].opname) == SAME) 
        !           494:          break;
        !           495:       if ((sc_opdef[i].opcode) == SC_END)
        !           496:        {
        !           497:          logit ("Bad opcode in script", opc);
        !           498:          deal_script(first);
        !           499:          return (struct script *)NULL;
        !           500:         }
        !           501:       
        !           502:       /*
        !           503:        * Found opcode. Allocate a new command node and initialize
        !           504:        */
        !           505:       this = (struct script *)malloc(sizeof (struct script));
        !           506:       prev->next = this;
        !           507:       prev = this;
        !           508:       this->next = (struct script *)NULL;
        !           509:       this->opcode = sc_opdef[i].opcode;
        !           510:       this->strprm = (char *)NULL;
        !           511:       this->intprm = 0;
        !           512:       this->newstate = (char *)NULL;
        !           513:       
        !           514:       /* 
        !           515:        * Pick up new state parameter, if any
        !           516:        */
        !           517:       if (sc_opdef[i].newstate == SC_NWST)
        !           518:        {
        !           519:          c = strtok((char *)NULL, CTL_DELIM);
        !           520:          if (c == (char *)NULL)
        !           521:            {
        !           522:              logit("Missing new state", opc);
        !           523:              deal_script(first);
        !           524:              return (struct script *)NULL;
        !           525:            }
        !           526:          else
        !           527:            {
        !           528:              this->newstate = (char *)malloc(strlen(c)+1);
        !           529:              strcpy(this->newstate, c);
        !           530:            }
        !           531:        }
        !           532:       
        !           533:       /*
        !           534:        * Pick up the string or integer parameter. Handle missing
        !           535:        * parameter gracefully.
        !           536:        */
        !           537:       switch (sc_opdef[i].prmtype)
        !           538:        {
        !           539:        /*
        !           540:         * INT parameter - convert and store in node
        !           541:         */
        !           542:        case SC_INT:
        !           543:          c = strtok((char *)NULL, CTL_DELIM);
        !           544:          if (c == (char *)NULL)
        !           545:            {
        !           546:              logit("Missing script param", opc);
        !           547:              deal_script(first);
        !           548:              return (struct script *)NULL;
        !           549:            }
        !           550:          /*
        !           551:           * If this is the parameter to DBST or DBCL, force
        !           552:            * base-10 conversion, else convert per parameter.
        !           553:           */
        !           554:          if (sc_opdef[i].opcode == SC_DBST ||
        !           555:              sc_opdef[i].opcode == SC_DBCL)
        !           556:            this->intprm = strtol(c, (char **)NULL, 0);
        !           557:          else
        !           558:            this->intprm = strtol(c, (char **)NULL, 10);
        !           559:          break;
        !           560: 
        !           561:        /*
        !           562:         * STR/XSTR strings.
        !           563:         */
        !           564:        case SC_STR:            
        !           565:        case SC_XSTR:           
        !           566:          c = strtok((char *)NULL, CTL_DELIM);
        !           567:          if (c == (char *)NULL)
        !           568:            {
        !           569:              logit("Missing script param", opc);
        !           570:              deal_script(first);
        !           571:              return (struct script *)NULL;
        !           572:            }
        !           573:          /*
        !           574:           * For XSTR opcode, use c to find out where
        !           575:           * the string param begins in the copy of the
        !           576:           * input line, and pick up all that's left of
        !           577:           * the line (to allow imbedded blanks, etc.).
        !           578:           */
        !           579:          if (sc_opdef[i].prmtype == SC_XSTR)
        !           580:            c = &inpcopy[0] + (c - &inpline[0]);
        !           581: 
        !           582:          /*
        !           583:           * Allocate a buffer for the string parameter
        !           584:           */
        !           585:          this->strprm = (char *)malloc(strlen(c)+1);
        !           586: 
        !           587:          /*
        !           588:           * For XSTR, Translate the string and store its
        !           589:           * length. Note that, after escape sequences are 
        !           590:           * compressed, the resulting string may well be a 
        !           591:           * few bytes shorter than the input string (whose 
        !           592:           * length was the basis for the malloc above),
        !           593:           * but it will never be longer.
        !           594:           */
        !           595:          if (sc_opdef[i].prmtype == SC_XSTR)
        !           596:            {
        !           597:              this->intprm = xlat_str(this->strprm, c);
        !           598:              this->strprm[this->intprm] = '\0';
        !           599:            }
        !           600:          else
        !           601:            strcpy(this->strprm, c);
        !           602:          break;
        !           603:          
        !           604:        }
        !           605:     }
        !           606:   
        !           607:   /*
        !           608:    * EOF
        !           609:    */
        !           610:   return first;
        !           611: }
        !           612: 
        !           613: 
        !           614: /*
        !           615:  * xlat_str
        !           616:  *
        !           617:  * Translate embedded escape characters in a "send" or "expect" string.
        !           618:  *
        !           619:  * Called by read_script(), above.
        !           620:  *
        !           621:  * Returns the actual length of the resulting string.  Note that imbedded
        !           622:  * nulls (specified by \000 in the input) ARE allowed in the result.  
        !           623:  */
        !           624: xlat_str(out, in)
        !           625:      char *out, *in;
        !           626: {
        !           627:   register int i = 0, j = 0;
        !           628:   int byte, k;
        !           629:   
        !           630:   while (in[i]) 
        !           631:     {
        !           632:       if (in[i] != '\\') 
        !           633:        {
        !           634:          out[j++] = in[i++];
        !           635:        }
        !           636:       else 
        !           637:        {
        !           638:          switch (in[++i]) 
        !           639:            {
        !           640:            case 'd':           /* EOT */
        !           641:              out[j++] = 0x04;
        !           642:              break;
        !           643:            case 'N':           /* null */
        !           644:              out[j++] = 0x00;
        !           645:              break;
        !           646:            case 'n':           /* line feed */
        !           647:              out[j++] = 0x0a;
        !           648:              break;
        !           649:            case 'r':           /* carriage return */
        !           650:              out[j++] = 0x0d;
        !           651:              break;
        !           652:            case 's':           /* space */
        !           653:              out[j++] = ' ';
        !           654:              break;
        !           655:            case 't':           /* tab */
        !           656:              out[j++] = '\t';
        !           657:              break;
        !           658:            case '-':           /* hyphen */
        !           659:              out[j++] = '-';
        !           660:              break;
        !           661:            case '\\':          /* back slash */
        !           662:              out[j++] = '\\';
        !           663:              break;
        !           664:            case '0':           /* '\nnn' format */
        !           665:            case '1':
        !           666:            case '2':
        !           667:            case '3':
        !           668:            case '4':
        !           669:            case '5':
        !           670:            case '6':
        !           671:            case '7':
        !           672:              byte = in[i] - '0';
        !           673:              k = 0;
        !           674:              
        !           675:              while (3 > ++k)   
        !           676:                if ((in[i+1] < '0') || (in[i+1] > '7'))
        !           677:                  break;
        !           678:                else 
        !           679:                  {
        !           680:                    byte = (byte<<3) + in[i+1] - '0';
        !           681:                    ++i;
        !           682:                  }
        !           683:              out[j++] = byte;
        !           684:              break;
        !           685:            default:            /* don't know so skip it */
        !           686:              break;
        !           687:            }
        !           688:          ++i;
        !           689:        }
        !           690:     } 
        !           691:   return j;
        !           692: }
        !           693: 
        !           694: 
        !           695: /* find a state within a script */
        !           696: 
        !           697: struct script *
        !           698:   find_state(begin, newstate)
        !           699: struct script *begin;
        !           700: char *newstate;
        !           701: {
        !           702:   struct script *here;
        !           703:   
        !           704:   for (here=begin; here != (struct script *)NULL; here=here->next) {
        !           705:     if (here->opcode == SC_LABEL && 
        !           706:        strcmp(here->strprm, newstate) == SAME)
        !           707:       return here;
        !           708:   }
        !           709:   return (struct script *)NULL;
        !           710: }
        !           711: 
        !           712: 
        !           713: /* 
        !           714:  * do_script() - execute a script 
        !           715:  */
        !           716: int do_script(begin)
        !           717:      struct script *begin;
        !           718: {
        !           719:   struct script *curstate, *newstate, *curscr;
        !           720:   int   dbgsave;
        !           721:   char  tempstr[MAX_SCLINE];
        !           722:   char   dfname[256];
        !           723:   char *c, chr;
        !           724:   int   prmlen;
        !           725:   int    dbfd;
        !           726:   
        !           727:   time_t sc_carrtime = 45000;  /* time to wf carr after dial */
        !           728:   time_t sc_chrdly   = 100;    /* delay time for ttoslow */
        !           729:   time_t sc_ptime    = 2000;   /* time to allow for pause char */
        !           730:   time_t sc_wtime    = 10000;  /* time to allow for wait char */
        !           731:   time_t sc_dtime    = 100;    /* time to allow for each digit */
        !           732:   time_t sc_dtmo;              /* total time to dial number */
        !           733:   int    sc_counter;           /* random counter */
        !           734:   char   sc_pchar    = ',';    /* modem pause character */
        !           735:   char   sc_wchar    = 'W';    /* modem wait-for-dialtone character */
        !           736:   time_t sc_begwait;           /* time at beg of wait */
        !           737:   time_t sc_secs;              /* timeout period */
        !           738:   
        !           739:   int    expcnt;
        !           740:   int    expin;
        !           741:   static char expbuf[MAX_EXPCT];
        !           742:   
        !           743:   dbgsave = Debug;
        !           744:   curstate = begin;
        !           745:   
        !           746:   if (curstate == (struct script *)NULL) 
        !           747:     return SUCCESS;
        !           748:   
        !           749:   _newstate:
        !           750:   /* 
        !           751:    * do all of curstate's actions.  Enter with curstate pointing
        !           752:    * to a label entry
        !           753:    */
        !           754:   expin = 0;
        !           755:   
        !           756:   for (curscr = curstate->next; /* point to 1st scr after label */
        !           757:        (curscr != (struct script *)NULL) &&  /* do until end of scr */
        !           758:        (curscr->opcode != SC_LABEL);           /* or next label */
        !           759:        curscr = curscr->next) 
        !           760:     {
        !           761:       expcnt = 0;
        !           762:       switch (curscr->opcode) 
        !           763:        {
        !           764:        case SC_LABEL:
        !           765:          logit("Script proc err", curstate->strprm);
        !           766:          return FAIL;
        !           767:          
        !           768:        case SC_FLSH:
        !           769:          DEBUG(DB_LGII, "Flushing typeahead buffer\n", 0);
        !           770:          ttflui();
        !           771:          break;
        !           772:          
        !           773:        case SC_CDLY:
        !           774:          sc_chrdly = curscr->intprm;
        !           775:          DEBUG(DB_LGII, "Set chrdly to %d\n", sc_chrdly);
        !           776:          break;
        !           777:          
        !           778:        case SC_PCHR:
        !           779:          sc_pchar = *(curscr->strprm);
        !           780:          DEBUG(DB_LGII, "Set pause char to %c\n", sc_pchar);
        !           781:          break;
        !           782:          
        !           783:        case SC_PTIM:
        !           784:          sc_ptime = curscr->intprm;
        !           785:          DEBUG(DB_LGII, "Set pause time to %d\n", sc_ptime);
        !           786:          break;
        !           787:          
        !           788:        case SC_WCHR:
        !           789:          sc_wchar = *(curscr->strprm);
        !           790:          DEBUG(DB_LGII, "Set wait char to %c\n", sc_wchar);
        !           791:          break;
        !           792:          
        !           793:        case SC_WTIM:
        !           794:          sc_wtime = curscr->intprm;
        !           795:          DEBUG(DB_LGII, "Set wait time to %d\n", sc_wtime);
        !           796:          break;
        !           797:          
        !           798:        case SC_ZERO:
        !           799:          sc_counter = 0;
        !           800:          DEBUG(DB_LGII, "Set counter to %d\n", sc_counter);
        !           801:          break;
        !           802:          
        !           803:        case SC_INCR:
        !           804:          sc_counter++;
        !           805:          DEBUG(DB_LGII, "Incr counter to %d\n", sc_counter);
        !           806:          break;
        !           807:          
        !           808:        case SC_WAIT:
        !           809:          DEBUG(DB_LGII, "Sleeping %d tenth-secs\n", curscr->intprm);
        !           810:          msleep(curscr->intprm);
        !           811:          break;
        !           812:          
        !           813:        case SC_DTIM:
        !           814:          sc_dtime = curscr->intprm;
        !           815:          DEBUG(DB_LGII, "Digit time is %d\n", sc_dtime);
        !           816:          break;
        !           817:          
        !           818:        case SC_CTIM:
        !           819:          sc_carrtime = curscr->intprm;
        !           820:          DEBUG(DB_LGII, "Carrier time is %d\n", sc_carrtime);
        !           821:          break;
        !           822:          
        !           823:        case SC_EXIT:
        !           824:          Debug = dbgsave;
        !           825:          DEBUG(DB_LGI, "Script ended successfully\n", 0);
        !           826:          return SUCCESS;
        !           827:          
        !           828:        case SC_FAIL:
        !           829:          Debug = dbgsave;
        !           830:          if (DEBUG_LEVEL(DB_LGI) && dbf != NULL)
        !           831:            fprintf(dbf, "Script failed\n");
        !           832:          else if (expin)
        !           833:            charlog(expbuf, expin, DB_LOG, 
        !           834:                    "Script failed.  Last received data");
        !           835:          return FAIL;
        !           836:          
        !           837:        case SC_LOG:
        !           838:          logit(curscr->strprm, "");
        !           839:          break;
        !           840:          
        !           841:        case SC_LOGE:
        !           842:          logit("ERROR: ", curscr->strprm);
        !           843:          break;
        !           844:          
        !           845:        case SC_DBOF:
        !           846:          /*
        !           847:           * If the debug file name does not begin with "/", then
        !           848:           * we prepend the LOG_DIR to the string. Then CREATE the
        !           849:           * file. This WIPES OUT previous logs. 
        !           850:           */
        !           851:          *dfname = '\0';       /* Zero name string */
        !           852:          if(curscr->strprm[0] != '/')
        !           853:            strcat(dfname, LOG_DIR); /* Prepend default directory */
        !           854:          strcat(dfname, curscr->strprm); /* Add given string */
        !           855:          DEBUG(DB_LGII, "Open debug file %s\n", dfname);
        !           856:          if ((dbfd = creat (dfname, 0600)) <= 0)
        !           857:            {
        !           858:              logit("Failed to create debug log %s", dfname);
        !           859:              perror("");
        !           860:              return FAIL;
        !           861:            }
        !           862:          if ((dbf = fdopen(dbfd, "w")) == NULL)
        !           863:            {
        !           864:              logit("Failed to open debug log fildes.", "");
        !           865:              perror("");
        !           866:              return FAIL;
        !           867:            }
        !           868:          break;
        !           869:          
        !           870:        case SC_DBG:
        !           871:          DEBUG(DB_LGI, "<%s>\n", curscr->strprm);
        !           872:          break;
        !           873:          
        !           874:        case SC_DBGE:
        !           875:          DEBUG(DB_LGIE, "ERROR: <%s>\n", curscr->strprm);
        !           876:          break;
        !           877:          
        !           878:        case SC_DBST:
        !           879:          Debug |= curscr->intprm;
        !           880:          DEBUG(DB_LGII, "Debug mask set to %04o (octal)\n", Debug);
        !           881:          break;
        !           882:          
        !           883:        case SC_DBCL:
        !           884:          Debug &= ~(curscr->intprm);
        !           885:          DEBUG(DB_LGII, "Debug mask set to %04o (octal)\n", Debug);
        !           886:          break;
        !           887:          
        !           888:        case SC_BRK:
        !           889:          DEBUG(DB_LGI, "Sending break\n", 0);
        !           890:          ttbreak();
        !           891:          break;
        !           892:          
        !           893:        case SC_HANG:
        !           894:          DEBUG(DB_LGI, "Dropping DTR\n", 0);
        !           895:          tthang();
        !           896:          break;
        !           897:          
        !           898:        case SC_7BIT:
        !           899:          DEBUG(DB_LGI, "Enabling 7-bit stripping\n", 0);
        !           900:          tt7bit(TRUE);
        !           901:          break;
        !           902:          
        !           903:        case SC_8BIT:
        !           904:          DEBUG(DB_LGI, "Disabling 7-bit stripping\n", 0);
        !           905:          tt7bit(FALSE);
        !           906:          break;
        !           907:          
        !           908:        case SC_PNON:
        !           909:          DEBUG(DB_LGI, "Setting 8-bit, no parity\n", 0);
        !           910:          ttpar(NONE);
        !           911:          break;
        !           912:          
        !           913:        case SC_PEVN:
        !           914:          DEBUG(DB_LGI, "Setting 7-bit, even parity\n", 0);
        !           915:          ttpar(EVEN);
        !           916:          break;
        !           917:          
        !           918:        case SC_PODD:
        !           919:          DEBUG(DB_LGI, "Setting 7-bit, odd parity\n", 0);
        !           920:          ttpar(ODD);
        !           921:          break;
        !           922:          
        !           923:        case SC_IFBL:
        !           924:          if (ttblind()) 
        !           925:            {
        !           926:              DEBUG(DB_LGI, "Blind mux,\n", 0);
        !           927:              goto _chgstate;
        !           928:            }
        !           929:          break;
        !           930:          
        !           931:        case SC_IFBG:
        !           932:          if (ttblind() && sc_counter > curscr->intprm) 
        !           933:            {
        !           934:              DEBUG(DB_LGI, "Blind mux & ctr > %d\n", 
        !           935:                    curscr->intprm);
        !           936:              goto _chgstate;
        !           937:            }
        !           938:          break;
        !           939:          
        !           940:        case SC_IFGT:
        !           941:          if (sc_counter > curscr->intprm) 
        !           942:            {
        !           943:              DEBUG(DB_LGI, "Counter > %d\n", curscr->intprm);
        !           944:              goto _chgstate;
        !           945:            }
        !           946:          break;
        !           947:          
        !           948:        case SC_GOTO:
        !           949:          _chgstate:
        !           950:          DEBUG(DB_LGI, "Changing to state %s\n",
        !           951:                curscr->newstate);
        !           952:          curstate = find_state(begin, curscr->newstate);
        !           953:          if (curstate == NULL) 
        !           954:            {
        !           955:              logit("New state not found",
        !           956:                    curscr->newstate);
        !           957:              return FAIL;
        !           958:            }
        !           959:          goto _newstate;
        !           960:          
        !           961:        case SC_SEND:
        !           962:          ttoslow(curscr->strprm, curscr->intprm, sc_chrdly);
        !           963:          break;
        !           964:          
        !           965:        case SC_TELN:
        !           966:          if (curscr->intprm > paramc - 1)
        !           967:            {
        !           968:              sprintf(tempstr, "telno - param #%d", curscr->intprm);
        !           969:              logit(tempstr, " not present");
        !           970:              return FAIL;
        !           971:            }
        !           972:          strcpy(telno, paramv[curscr->intprm]);
        !           973:          DEBUG(DB_LGII, "telno set to %s\n", telno);
        !           974:          break;
        !           975:          
        !           976:        case SC_SNDP:
        !           977:          if (curscr->intprm > paramc - 1)
        !           978:            {
        !           979:              sprintf(tempstr, "sendstr - param #%d", curscr->intprm);
        !           980:              logit(tempstr, " not present");
        !           981:              return FAIL;
        !           982:            }
        !           983:          prmlen = xlat_str(tempstr, paramv[curscr->intprm]);
        !           984:          ttoslow(tempstr, prmlen, sc_chrdly);
        !           985:          break;
        !           986:          
        !           987:        case SC_IF1P:
        !           988:          if (curscr->intprm < paramc)
        !           989:            goto _chgstate;
        !           990:          break;
        !           991:          
        !           992:        case SC_IF0P:
        !           993:          if (curscr->intprm >= paramc)
        !           994:            goto _chgstate;
        !           995:          break;
        !           996:          
        !           997:        case SC_DIAL:
        !           998:          if(telno[0] == '\0')
        !           999:            {
        !          1000:              logit("telno not set", "");
        !          1001:              return(FAIL);
        !          1002:            }
        !          1003:          /*
        !          1004:           * Compute and set a default timeout for the 'timeout'
        !          1005:           * command. Some parameters in this computation may be
        !          1006:           * changed by the script. See the man page xchat(8) for
        !          1007:           * details.
        !          1008:           */
        !          1009:          sc_dtmo = (sc_dtime+sc_chrdly)*strlen(telno) 
        !          1010:            + sc_carrtime;
        !          1011:          c=strcpy(tempstr, telno);
        !          1012:          for (; *c!='\0'; c++) 
        !          1013:            {
        !          1014:              if (*c == 'W') 
        !          1015:                {
        !          1016:                  *c = sc_wchar;
        !          1017:                  sc_dtmo += sc_wtime;
        !          1018:                }
        !          1019:              else if (*c == 'P') 
        !          1020:                {
        !          1021:                  *c = sc_pchar;
        !          1022:                  sc_dtmo += sc_ptime;
        !          1023:                }
        !          1024:            }
        !          1025:          DEBUG(DB_LGI, "Dialing, default timeout is %d millisecs\n", sc_dtmo);
        !          1026:          ttoslow(tempstr, 0, sc_chrdly);
        !          1027:          break;
        !          1028:          
        !          1029:        case SC_TIMO:   /* these are "expects", don't bother */
        !          1030:        case SC_XPCT:   /* with them yet, other than noting that */
        !          1031:        case SC_CARR:   /* they exist */
        !          1032:          expcnt++;
        !          1033:          break;
        !          1034:        }
        !          1035:       
        !          1036:     }
        !          1037:   
        !          1038:   /* we've done the current state's actions, now do its expects, if any */
        !          1039:   
        !          1040:   if (expcnt == 0) 
        !          1041:     {
        !          1042:       if (curscr != (struct script *)NULL &&  
        !          1043:          (curscr->opcode == SC_LABEL)) 
        !          1044:        {
        !          1045:          curstate = curscr;
        !          1046:          DEBUG(DB_LGI, "Fell through to state %s\n",
        !          1047:                curstate->strprm);
        !          1048:          goto _newstate;
        !          1049:        }
        !          1050:       else 
        !          1051:        {
        !          1052:          logit("No way out of state", curstate->strprm);
        !          1053:          return FAIL;
        !          1054:        }
        !          1055:     }
        !          1056:   
        !          1057:   time(&sc_begwait);   /* log time at beg of expect */
        !          1058:   DEBUG(DB_LGI, "Doing expects for state %s\n", curstate->strprm);
        !          1059:   charlog((char *)NULL, 0, DB_LGI, "Received");
        !          1060:   
        !          1061:   while (1) 
        !          1062:     {
        !          1063:       chr = xgetc(1);          /* Returns upon char input or 1 sec. tmo */
        !          1064:       
        !          1065:       charlog(&chr, 1, DB_LGI, (char *)NULL);
        !          1066:       
        !          1067:       if (chr != EOF) 
        !          1068:        {
        !          1069:          if (expin < MAX_EXPCT) 
        !          1070:            {
        !          1071:              expbuf[expin++] = chr & 0x7f;
        !          1072:            }
        !          1073:          else 
        !          1074:            {
        !          1075:              strncpy(expbuf, &expbuf[1], MAX_EXPCT-1);
        !          1076:              expbuf[MAX_EXPCT-1] = chr & 0x7f;
        !          1077:            }
        !          1078:        }
        !          1079:       
        !          1080:       /* for each entry in the current state... */
        !          1081:       
        !          1082:       for (curscr = curstate->next; 
        !          1083:           (curscr != (struct script *)NULL) &&
        !          1084:           (curscr->opcode != SC_LABEL);
        !          1085:           curscr = curscr->next) 
        !          1086:        {
        !          1087:          
        !          1088:          switch (curscr->opcode) 
        !          1089:            {
        !          1090:            case SC_TIMO:
        !          1091:              sc_secs = curscr->intprm;
        !          1092:              if (sc_secs == 0)
        !          1093:                sc_secs = sc_dtmo;
        !          1094:              sc_secs /= 1000;
        !          1095:              if (time(NULL)-sc_begwait > sc_secs) 
        !          1096:                {
        !          1097:                  DEBUG(DB_LGI,
        !          1098:                        "\nTimed out (%d secs)\n", sc_secs);
        !          1099:                  goto _chgstate;
        !          1100:                }
        !          1101:              break;
        !          1102:              
        !          1103:            case SC_CARR:
        !          1104:              if (ttcd()) 
        !          1105:                {
        !          1106:                  DEBUG(DB_LGI, "\nGot carrier\n", 0);
        !          1107:                  goto _chgstate;
        !          1108:                }
        !          1109:              break;
        !          1110:              
        !          1111:            case SC_HUPS:
        !          1112:              if (fShangup) 
        !          1113:                {
        !          1114:                  DEBUG(DB_LGI, "\nGot data set hangup\n", 0);
        !          1115:                  goto _chgstate;
        !          1116:                }
        !          1117:              break;
        !          1118:              
        !          1119:            case SC_XPCT:
        !          1120:              if ((expin >= curscr->intprm) &&
        !          1121:                  (strncmp(curscr->strprm, 
        !          1122:                           &expbuf[expin - curscr->intprm],
        !          1123:                           curscr->intprm) == SAME)) 
        !          1124:                {
        !          1125:                  charlog(curscr->strprm, curscr->intprm,
        !          1126:                          DB_LGI, "Matched");
        !          1127:                  goto _chgstate;
        !          1128:                }
        !          1129:              break;
        !          1130:              
        !          1131:            }
        !          1132:        }
        !          1133:     }
        !          1134: }
        !          1135: 
        !          1136: /*
        !          1137:  * SIGNAL HANDLERS
        !          1138:  */
        !          1139: 
        !          1140: /*
        !          1141:  * usignal - generic signal catcher
        !          1142:  */
        !          1143: static int usignal(isig)
        !          1144:      int isig;
        !          1145: {
        !          1146:   DEBUG(DB_LOG, "Caught signal %d. Exiting...\n", isig);
        !          1147:   restore_tty();
        !          1148:   exit(FAIL);
        !          1149: }
        !          1150: 
        !          1151: /*
        !          1152:  * uhup - HUP catcher
        !          1153:  */
        !          1154: static int uhup(isig)
        !          1155:      int isig;
        !          1156: {
        !          1157:   DEBUG(DB_LOG, "Data set hangup.\n");
        !          1158:   fShangup = TRUE;
        !          1159: }
        !          1160: 
        !          1161: /*
        !          1162:  * TERMINAL I/O ROUTINES
        !          1163:  */
        !          1164: 
        !          1165: /*
        !          1166:  * xgetc - get a character with timeout
        !          1167:  *
        !          1168:  * Assumes that stdin is opened on a terminal or TCP socket 
        !          1169:  * with O_NONBLOCK. 
        !          1170:  */
        !          1171: static char xgetc(tmo)
        !          1172: int tmo;                       /* Timeout, seconds */
        !          1173: {
        !          1174:   char c;
        !          1175:   struct timeval s;
        !          1176:   int f = 1;                   /* Select on stdin */
        !          1177:   int result;
        !          1178: 
        !          1179:   if(read(0, &c, 1)  <= 0)     /* If no data available */
        !          1180:     {
        !          1181:       s.tv_sec = (long)tmo;
        !          1182:       s.tv_usec = 0L;
        !          1183:       if(select (1, &f, (int *) NULL, &f, &s) == 1)
        !          1184:        read(0, &c, 1);
        !          1185:       else
        !          1186:        c = '\377';
        !          1187:     }
        !          1188: 
        !          1189:   return(c);
        !          1190: }
        !          1191: 
        !          1192: /* 
        !          1193:  * Pause for an interval in milliseconds
        !          1194:  */
        !          1195: void msleep(msec)
        !          1196: long msec;
        !          1197: {
        !          1198: 
        !          1199: #if HAVE_USLEEP
        !          1200:   if(msec == 0)                        /* Skip all of this if delay = 0 */
        !          1201:     return;
        !          1202:   usleep (msec * (long)1000);
        !          1203: #endif /* HAVE_USLEEP */
        !          1204: 
        !          1205: #if HAVE_NAPMS
        !          1206:   if(msec == 0)                        /* Skip all of this if delay = 0 */
        !          1207:     return;
        !          1208:   napms (msec);
        !          1209: #endif /* HAVE_NAPMS */
        !          1210: 
        !          1211: #if HAVE_NAP
        !          1212:   if(msec == 0)                        /* Skip all of this if delay = 0 */
        !          1213:     return;
        !          1214:   nap (msec);
        !          1215: #endif /* HAVE_NAP */
        !          1216: 
        !          1217: #if HAVE_POLL
        !          1218:   struct pollfd sdummy;
        !          1219: 
        !          1220:   if(msec == 0)
        !          1221:     return;
        !          1222:   /* 
        !          1223:    * We need to pass an unused pollfd structure because poll checks
        !          1224:    * the address before checking the number of elements.
        !          1225:    */
        !          1226:   poll (&sdummy, 0, msec);
        !          1227: #endif /* HAVE_POLL */
        !          1228: 
        !          1229: #if USE_SELECT_TIMER
        !          1230:   struct timeval s;
        !          1231: 
        !          1232:   if(msec == 0)
        !          1233:     return;
        !          1234:   s.tv_sec = msec / 1000L;
        !          1235:   s.tv_usec = (msec % 1000L) * 1000L;
        !          1236:   select (0, (int *) NULL, (int *) NULL, (int *) NULL, &s);
        !          1237: #endif /* USE_SELECT_TIMER */
        !          1238: 
        !          1239: #if ! HAVE_NAPMS && ! HAVE_NAP && ! HAVE_USLEEP && \
        !          1240:     ! HAVE_POLL && ! USE_SELECT_TIMER
        !          1241:   if(msec == 0)
        !          1242:     return;
        !          1243:   sleep (1);                   /* Sleep for a whole second (UGH!) */
        !          1244: #endif /* HAVE_ and USE_ nothing */
        !          1245: }
        !          1246: 
        !          1247: /*
        !          1248:  * Debugging output
        !          1249:  */
        !          1250: static void DEBUG(level, msg1, msg2)
        !          1251: int level;
        !          1252: char *msg1, *msg2;
        !          1253: {
        !          1254:   if ((dbf != NULL) && DEBUG_LEVEL(level))
        !          1255:     fprintf(dbf, msg1, msg2);
        !          1256: }
        !          1257: 
        !          1258: /*
        !          1259:  * charlog - log a string of characters
        !          1260:  *
        !          1261:  * SPECIAL CASE: msg=NULL, len=1 and msg[0]='\377' gets logged
        !          1262:  *               when read does its 1 sec. timeout. Log "<1 sec.>"
        !          1263:  *               so user can see elapsed time 
        !          1264:  */
        !          1265: static void charlog(buf, len, mask, msg)
        !          1266: char *buf;
        !          1267: int len, mask;
        !          1268: char *msg;
        !          1269: {
        !          1270:   char tbuf[256];
        !          1271: 
        !          1272:   if (DEBUG_LEVEL(mask) && dbf != NULL)
        !          1273:     {
        !          1274:       if(msg == (char *)NULL)
        !          1275:        msg = "";
        !          1276:       strncpy(tbuf, buf, len);
        !          1277:       tbuf[len] = '\0';
        !          1278:       if(len == 1 && tbuf[0] == '\377')
        !          1279:        strcpy(tbuf, "<1 sec.>");
        !          1280:       fprintf(dbf, "%s %s\n", msg, tbuf);
        !          1281:     }
        !          1282: }
        !          1283: 
        !          1284: /*
        !          1285:  * setup_tty()
        !          1286:  *
        !          1287:  * Save current tty settings, then set up raw, single
        !          1288:  * character input processing, with 7-bit stripping.
        !          1289:  */
        !          1290: static void setup_tty()
        !          1291: {
        !          1292:   register int i;
        !          1293: 
        !          1294:   ioctl(0, TCGETA, &old);
        !          1295: 
        !          1296:   new = old;
        !          1297: 
        !          1298:   for(i = 0; i < 7; i++)
        !          1299:     new.c_cc[i] = '\0';
        !          1300:   new.c_cc[VMIN] = 0;          /* MIN = 0, use requested count */
        !          1301:   new.c_cc[VTIME] = 10;                /* TIME = 1 sec. */
        !          1302:   new.c_iflag = ISTRIP;                /* Raw mode, 7-bit stripping */
        !          1303:   new.c_lflag = 0;             /* No special line discipline */
        !          1304: 
        !          1305:   ioctl(0, TCSETA, &new);
        !          1306: }
        !          1307: 
        !          1308: /*
        !          1309:  * restore_tty() - restore signal handlers and tty modes on exit.
        !          1310:  */
        !          1311: static void restore_tty(sig)
        !          1312: int sig;
        !          1313: {
        !          1314:   ioctl(0, TCSETA, &old);
        !          1315:   return;
        !          1316: }
        !          1317: 
        !          1318: /* 
        !          1319:  * ttoslow() - Send characters with pacing delays
        !          1320:  */
        !          1321: static void ttoslow(s, len, delay)
        !          1322:      char *s; 
        !          1323:      int len;
        !          1324:      time_t delay; 
        !          1325: {
        !          1326:   int i;
        !          1327:   
        !          1328:   if (len == 0)
        !          1329:     len = strlen(s);
        !          1330:   
        !          1331:   charlog (s, len, DB_LGI, "Sending slowly");
        !          1332:   
        !          1333:   for (i = 0; i < len; i++, s++)
        !          1334:     {
        !          1335:       write(1, s, 1);
        !          1336:       msleep(delay);
        !          1337:     }
        !          1338: }
        !          1339: 
        !          1340: /*
        !          1341:  * ttflui - flush input buffer
        !          1342:  */
        !          1343: static void ttflui()
        !          1344: {
        !          1345:   if(isatty(0))
        !          1346:     (void) ioctl ( 0, TCFLSH, 0);
        !          1347: }
        !          1348: 
        !          1349: /*
        !          1350:  * ttcd - Test if carrier is present
        !          1351:  *
        !          1352:  * NOT IMPLEMENTED. I don't know how!!!
        !          1353:  */
        !          1354: static int ttcd()
        !          1355: {
        !          1356:   return TRUE;
        !          1357: }
        !          1358: 
        !          1359: /*
        !          1360:  * tthang - Force DTR low for 1-2 sec.
        !          1361:  */
        !          1362: static void tthang()
        !          1363: {
        !          1364:   if(!isatty())
        !          1365:     return;
        !          1366: 
        !          1367: #ifdef TCCLRDTR
        !          1368:   (void) ioctl (1, TCCLRDTR, 0);
        !          1369:   sleep (2);
        !          1370:   (void) ioctl (1, TCSETDTR, 0);
        !          1371: #endif
        !          1372: 
        !          1373:   return;
        !          1374: }
        !          1375: 
        !          1376: /*
        !          1377:  * ttbreak - Send a "break" on the line
        !          1378:  */
        !          1379: static void ttbreak()
        !          1380: {
        !          1381:   (void) ioctl (1, TCSBRK, 0);
        !          1382: }
        !          1383: 
        !          1384: /*
        !          1385:  * ttblind - return TRUE if tty is "blind"
        !          1386:  *
        !          1387:  * NOT IMPLEMENTED - Don't know how!!!
        !          1388:  */
        !          1389: static int ttblind()
        !          1390: {
        !          1391:   return FALSE;
        !          1392: }
        !          1393: 
        !          1394: /*
        !          1395:  * tt7bit - enable/disable 7-bit stripping on line
        !          1396:  */
        !          1397: static void tt7bit(enable)
        !          1398:      int enable;
        !          1399: {
        !          1400:   if(enable)
        !          1401:     new.c_iflag |= ISTRIP;
        !          1402:   else
        !          1403:     new.c_iflag &= ~ISTRIP;
        !          1404: 
        !          1405:   ioctl(0, TCSETA, &new);
        !          1406: }
        !          1407: 
        !          1408: /*
        !          1409:  * ttpar - Set parity mode on line. Ignore parity errors on input.
        !          1410:  */
        !          1411: static void ttpar(mode)
        !          1412:      int mode;
        !          1413: {
        !          1414:   switch(mode)
        !          1415:     {
        !          1416:     case NONE:
        !          1417:       new.c_iflag &= ~(INPCK | IGNPAR);
        !          1418:       new.c_cflag &= ~(CSIZE | PARENB | PARODD);
        !          1419:       new.c_cflag |= CS8;
        !          1420:       break;
        !          1421: 
        !          1422:     case EVEN:
        !          1423:       new.c_iflag |= (INPCK | IGNPAR);
        !          1424:       new.c_cflag &= ~(CSIZE | PARODD);
        !          1425:       new.c_cflag |= (CS7 | PARENB);
        !          1426: 
        !          1427:       break;
        !          1428: 
        !          1429:     case ODD:
        !          1430:       new.c_iflag |= (INPCK | IGNPAR);
        !          1431:       new.c_cflag &= ~(CSIZE);
        !          1432:       new.c_cflag |= (CS7 | PARENB | PARODD);
        !          1433:       break;
        !          1434:     }
        !          1435: 
        !          1436:   ioctl(0, TCSETA, &new);
        !          1437: }
        !          1438: 
        !          1439: 
        !          1440: 
        !          1441: 
        !          1442: 
        !          1443: 
        !          1444: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.