Annotation of 43BSDTahoe/new/kermit/ckudia.c, revision 1.1.1.1

1.1       root        1: char *dialv = "Dial Command, V2.0(008) 26 Jul 85";
                      2: 
                      3: /*  C K U D I A  --  Dialing program for connection to remote system */
                      4: 
                      5: /*
                      6:  Author: Herm Fischer (HFISCHER@USC-ECLB)
                      7:  Contributed to Columbia University for inclusion in C-Kermit.
                      8:  Copyright (C) 1985, Herman Fischer, 16400 Ventura Blvd, Encino CA 91436
                      9:  Permission is granted to any individual or institution to use, copy, or
                     10:  redistribute this software so long as it is not sold for profit, provided this
                     11:  copyright notice is retained. 
                     12: 
                     13:  ------
                     14: 
                     15:  This module should work under all versions of Unix.  It calls externally
                     16:  defined system-depended functions for i/o, but depends upon the existence
                     17:  of various modem control functions.
                     18: 
                     19:  This module, and the supporting routines in the ckutio.c module, assume
                     20:  that the computer and modem properly utilize the following data communi-
                     21:  cations signals (that means one should prepare the modem to use, not
                     22:  circumvent, these signals):
                     23: 
                     24:      Data Terminal Ready:  This signal is asserted by the computer
                     25:      when Kermit is about to ask the modem to dial a call, and is
                     26:      removed when Kermit wishes to have the modem hang up a call.
                     27:      The signal is asserted both while Kermit is asking the modem
                     28:      to dial a specific number, and after connection, while Kermit
                     29:      is in a data exchange mode.  
                     30: 
                     31:      Carrier detect:  This signal must be asserted by the modem when
                     32:      a carrier is detected from a remote modem on a communications
                     33:      circuit.  It must be removed by the modem when the circuit
                     34:      disconnects or is hung up.  (Carrier detect is ignored while
                     35:      Kermit is asking the modem to dial the call, because there is
                     36:      no consistant usage of this signal during the dialing phase
                     37:      among different modem manufacturers.)
                     38: 
                     39: */
                     40: 
                     41: /*
                     42:  * Modifications:
                     43:  *
                     44:  *     21-Jul-85       Fixed failure returns hanging on no carrier signal
                     45:  *                     Requires tthang change too (ckutio.c revision)
                     46:  *                                                     -- Herm Fischer
                     47:  *
                     48:  *     28-Jun-85       Fixed bug with defaulting the modem-failure message
                     49:  *                     in lbuf.
                     50:  *                                                     -- Dan Schullman
                     51:  *
                     52:  *     27-Jun-85       Merged in code from Joe Orost at Berkeley for
                     53:  *                     supporting the US Robotics modem, which included
                     54:  *                     changing the single characters in MDMINF into
                     55:  *                     multi-character strings and modifying waitFor.
                     56:  *                                                     -- Dan Schullman
                     57:  *
                     58:  *     26-Jun-85       Allow interrupts to be used to abort dialing,
                     59:  *                     and ring the bell when a connection is made.
                     60:  *                     Reorganized some of the failure paths to use the
                     61:  *                     same code, and now close the line on failures.
                     62:  *                     Allow use of stored numbers with the DF100 and
                     63:  *                     DF200 modems.  Handlers now declared after the
                     64:  *                     call to setjmp.
                     65:  *                                                     -- Dan Schullman
                     66:  *
                     67:  *     24-May-85       DF03, DF100-series, DF200-series, and "unknown" modem
                     68:  *                     support added.  Also restructured the various data
                     69:  *                     tables, fixed some bugs related to missing data and
                     70:  *                     missing case labels, and modified the failure message
                     71:  *                     to display the "reason" given by the modem.
                     72:  *                                                     -- Dan Schullman
                     73:  */
                     74: 
                     75: /*
                     76:  * To add support for another modem, do the following:
                     77:  *
                     78:  *     Define a modem number symbol (n_XXX) for it, keeping the list
                     79:  *     in alphabetical and numerical order, and renumbering the values
                     80:  *     as necessary.
                     81:  *
                     82:  *     Create a MDMINF structure for it, again keeping the list alphabetical
                     83:  *     for sanity's sake.
                     84:  *
                     85:  *     Add the address of the MDMINF structure to the ptrtab array, again
                     86:  *     in alphabetical and numerical order.
                     87:  *
                     88:  *     Add the "user visible" modem name and corresponding modem number to
                     89:  *     the mdmtab array, again in alphabetical order.
                     90:  *
                     91:  *     Read through the code and add modem-specific sections as necessary.
                     92:  */
                     93: 
                     94: /*
                     95:  * The intent of the "unknown" modem is hopefully to allow KERMIT to support
                     96:  * unknown modems by having the user type the entire autodial sequence
                     97:  * (possibly including control characters, etc.) as the "phone number".
                     98:  * The only reason that the CONNECT command cannot be used to do this is
                     99:  * that a remote line cannot normally be opened unless carrier is present.
                    100:  *
                    101:  * The protocol and other characteristics of this modem are unknown, with
                    102:  * some "reasonable" values being chosen for some of them.  The only way to
                    103:  * detect if a connection is made is to look for carrier present.
                    104:  *
                    105:  * SUPPORT IS CURRENTLY ONLY PARTIALLY SKETCHED OUT FOR THIS.  ALSO, IT
                    106:  * SHOULD PERHAPS BE HANDLED MUCH EARLIER, SIMPLY READING USER INPUT AND
                    107:  * SENDING IT TO THE MODEM AND ECHOING MODEM RESPONSES BACK TO THE USER,
                    108:  * ALL THE TIME LOOKING FOR CARRIER.  OF COURSE, THE PROBLEM THEN BECOMES
                    109:  * ONE OF ALLOWING THE USER TO ABORT THE DIALING.  WE COULD CHOOSE SOME
                    110:  * PHRASE THAT WOULD PRESUMABLY NEVER BE A PART OF A VALID AUTODIAL SEQUENCE
                    111:  * (E.G., "QUIT" and "quit"). -- DS
                    112:  */
                    113: #include "ckcdeb.h"
                    114: #include <stdio.h>
                    115: #include <ctype.h>
                    116: #include <signal.h>
                    117: #include <setjmp.h>
                    118: #include "ckcker.h"
                    119: #include "ckucmd.h"
                    120: 
                    121: extern int flow, local, mdmtyp, quiet, speed;
                    122: extern char ttname[], sesfil[];
                    123: 
                    124: #define        MDMINF  struct mdminf
                    125: 
                    126: MDMINF         /* structure for modem-specific information */
                    127:     {
                    128:     int                dial_time;      /* time modem allows for dialing (secs) */
                    129:     char       *pause_chars;   /* character(s) to tell modem to pause */
                    130:     int                pause_time;     /* time associated with pause chars (secs) */
                    131:     char       *wake_str;      /* string to wakeup modem & put in cmd mode */
                    132:     int                wake_rate;      /* delay between wake_str characters (msecs) */
                    133:     char       *wake_prompt;   /* string prompt after wake_str */
                    134:     char       *dmode_str;     /* string to put modem in dialing mode */
                    135:     char       *dmode_prompt;  /* string prompt for dialing mode */
                    136:     char       *dial_str;      /* dialing string, with "%s" for number */
                    137:     int                dial_rate;      /* delay between dialing characters (msecs) */
                    138:     };
                    139: 
                    140: /*
                    141:  * Define symbolic modem numbers.
                    142:  *
                    143:  * The numbers MUST correspond to the ordering of entries
                    144:  * within the ptrtab array, and start at one (1).
                    145:  *
                    146:  * It is assumed that there are relatively few of these
                    147:  * values, and that the high(er) bytes of the value may
                    148:  * be used for modem-specific mode information.
                    149:  *
                    150:  * REMEMBER that only the first eight characters of these
                    151:  * names are guaranteed to be unique.
                    152:  */
                    153: 
                    154: #define                n_CERMETEK       1
                    155: #define                n_DF03           2
                    156: #define                n_DF100          3
                    157: #define                n_DF200          4
                    158: #define                n_GDC            5
                    159: #define                n_HAYES          6
                    160: #define                n_PENRIL         7
                    161: #define                n_RACAL          8
                    162: #define                n_UNKNOWN        9
                    163: #define                n_USROBOT       10
                    164: #define                n_VENTEL        11
                    165: 
                    166: /*
                    167:  * Declare modem "variant" numbers for any of the above for which it is
                    168:  * necessary to note various operational modes, using the second byte
                    169:  * of a modem number.
                    170:  *
                    171:  * It is assumed that such modem modes share the same modem-specific
                    172:  * information (see MDMINF structure) but may differ in some of the actions
                    173:  * that are performed.
                    174:  */
                    175: #define                n_HAYESNV       ( n_HAYES + ( 1<<8 ) )
                    176: 
                    177: /*
                    178:  * Declare structures containing modem-specific information.
                    179:  *
                    180:  * REMEMBER that only the first SEVEN characters of these
                    181:  * names are guaranteed to be unique.
                    182:  */
                    183: 
                    184: static
                    185: MDMINF CERMETEK =      /* information for "Cermetek Info-Mate 212 A" modem */
                    186:     {
                    187:     20,                        /* dial_time */
                    188:     "BbPpTt",          /* pause_chars */
                    189:     0,                 /* pause_time */        /** unknown -- DS **/
                    190:     "  XY\016R\r",     /* wake_str */
                    191:     200,               /* wake_rate */
                    192:     "",                        /* wake_prompt */
                    193:     "",                        /* dmode_str */
                    194:     "",                        /* dmode_prompt */
                    195:     "\016D '%s'\r",    /* dial_str */
                    196:     200                        /* dial_rate */
                    197:     };
                    198: 
                    199: static
                    200: MDMINF DF03 =          /* information for "DEC DF03-AC" modem */
                    201:     {
                    202:     27,                        /* dial_time */
                    203:     "=",               /* pause_chars */       /* wait for second dial tone */
                    204:     15,                        /* pause_time */
                    205:     "\001\002",                /* wake_str */
                    206:     0,                 /* wake_rate */
                    207:     "",                        /* wake_prompt */
                    208:     "",                        /* dmode_str */
                    209:     "",                        /* dmode_prompt */
                    210:     "%s",              /* dial_str */
                    211:     0                  /* dial_rate */
                    212:     };
                    213: 
                    214: static
                    215: MDMINF DF100 =         /* information for "DEC DF100-series" modem */
                    216:                        /*
                    217:                         * The telephone "number" can include "P"s and/or "T"s
                    218:                         * within it to indicate that subsequent digits are
                    219:                         * to be dialed using pulse or tone dialing.  The
                    220:                         * modem defaults to pulse dialing.  You may modify
                    221:                         * the dial string below to explicitly default all
                    222:                         * dialing to pulse or tone, but doing so prevents
                    223:                         * the use of phone numbers that you may have stored
                    224:                         * in the modem's memory.
                    225:                         */
                    226:     {
                    227:     30,                        /* dial_time */
                    228:     "=",               /* pause_chars */       /* wait for second dial tone */
                    229:     15,                        /* pause_time */
                    230:     "\001",            /* wake_str */
                    231:     0,                 /* wake_rate */
                    232:     "",                        /* wake_prompt */
                    233:     "",                        /* dmode_str */
                    234:     "",                        /* dmode_prompt */
                    235:     "%s#",             /* dial_str */
                    236:     0                  /* dial_rate */
                    237:     };
                    238: 
                    239: static
                    240: MDMINF DF200 =         /* information for "DEC DF200-series" modem */
                    241:                        /*
                    242:                         * The telephone "number" can include "P"s and/or "T"s
                    243:                         * within it to indicate that subsequent digits are
                    244:                         * to be dialed using pulse or tone dialing.  The
                    245:                         * modem defaults to pulse dialing.  You may modify
                    246:                         * the dial string below to explicitly default all
                    247:                         * dialing to pulse or tone, but doing so prevents
                    248:                         * the use of phone numbers that you may have stored
                    249:                         * in the modem's memory.
                    250:                         */
                    251:     {
                    252:     30,                        /* dial_time */
                    253:     "=W",              /* pause_chars */       /* =: second tone; W: 5 secs */
                    254:     15,                        /* pause_time */        /* worst case */
                    255:     "\002",            /* wake_str */          /* allow stored number usage */
                    256:     0,                 /* wake_rate */
                    257:     "",                        /* wake_prompt */
                    258:     "",                        /* dmode_str */
                    259:     "",                        /* dmode_prompt */
                    260:     "%s!",             /* dial_str */
                    261:     0                  /* dial_rate */
                    262:     };
                    263: 
                    264: static
                    265: MDMINF GDC =           /* information for "GeneralDataComm 212A/ED" modem */
                    266:     {
                    267:     32,                        /* dial_time */
                    268:     "%",               /* pause_chars */
                    269:     3,                 /* pause_time */
                    270:     "\r\r",            /* wake_str */
                    271:     500,               /* wake_rate */
                    272:     "$",               /* wake_prompt */
                    273:     "D\r",             /* dmode_str */
                    274:     ":",               /* dmode_prompt */
                    275:     "T%s\r",           /* dial_str */
                    276:     0                  /* dial_rate */
                    277:     };
                    278: 
                    279: static
                    280: MDMINF HAYES =         /* information for "Hayes" modem */
                    281:     {
                    282:     35,                        /* dial_time */
                    283:     ",",               /* pause_chars */
                    284:     2,                 /* pause_time */
                    285:     "AT\r",            /* wake_str */
                    286:     0,                 /* wake_rate */
                    287:     "",                        /* wake_prompt */
                    288:     "",                        /* dmode_str */
                    289:     "",                        /* dmode_prompt */
                    290:     "AT DT %s\r",      /* dial_str */
                    291:     0                  /* dial_rate */
                    292:     };
                    293: 
                    294: static
                    295: MDMINF PENRIL =                /* information for "Penril" modem */
                    296:     {
                    297:     50,                        /* dial_time */
                    298:     "",                        /* pause_chars */       /** unknown -- HF **/
                    299:     0,                 /* pause_time */
                    300:     "\r\r",            /* wake_str */
                    301:     300,               /* wake_rate */
                    302:     ">",               /* wake_prompt */
                    303:     "k\r",             /* dmode_str */
                    304:     ":",               /* dmode_prompt */
                    305:     "%s\r",            /* dial_str */
                    306:     0                  /* dial_rate */
                    307:     };
                    308: 
                    309: static
                    310: MDMINF RACAL =         /* information for "Racal Vadic" modem */
                    311:     {
                    312:     35,                        /* dial_time */
                    313:     "Kk",              /* pause_chars */
                    314:     5,                 /* pause_time */
                    315:     "\005\r",          /* wake_str */
                    316:     50,                        /* wake_rate */
                    317:     "*",               /* wake_prompt */
                    318:     "D\r",             /* dmode_str */
                    319:     "?",               /* dmode_prompt */
                    320:     "%s\r",            /* dial_str */
                    321:     0                  /* dial_rate */
                    322:     };
                    323: 
                    324: static
                    325: MDMINF UNKNOWN =       /* information for "Unknown" modem */
                    326:     {
                    327:     30,                        /* dial_time */
                    328:     "",                        /* pause_chars */
                    329:     0,                 /* pause_time */
                    330:     "",                        /* wake_str */
                    331:     0,                 /* wake_rate */
                    332:     "",                        /* wake_prompt */
                    333:     "",                        /* dmode_str */
                    334:     "",                        /* dmode_prompt */
                    335:     "%s\r",            /* dial_str */
                    336:     0                  /* dial_rate */
                    337:     };
                    338: 
                    339: static
                    340: MDMINF USROBOT =       /* information for "US Robotics 212A" modem */
                    341:     {
                    342:     30,                        /* dial_time */
                    343:     ",",               /* pause_chars */
                    344:     2,                 /* pause_time */
                    345:     "ATS2=01\r",       /* wake_str */
                    346:     0,                 /* wake_rate */
                    347:     "OK\r",            /* wake_prompt */
                    348:     "",                        /* dmode_str */
                    349:     "",                        /* dmode_prompt */
                    350:     "ATTD%s\r",                /* dial_str */
                    351:     0                  /* dial_rate */
                    352:     };
                    353: 
                    354: static
                    355: MDMINF VENTEL =                /* information for "Ventel" modem */
                    356:     {
                    357:     20,                        /* dial_time */
                    358:     "%",               /* pause_chars */
                    359:     5,                 /* pause_time */
                    360:     "\r\r\r",          /* wake_str */
                    361:     300,               /* wake_rate */
                    362:     "$",               /* wake_prompt */
                    363:     "",                        /* dmode_str */
                    364:     "",                        /* dmode_prompt */
                    365:     "<K%s'r>",         /* dial_str */
                    366:     0                  /* dial_rate */
                    367:     };
                    368: 
                    369: /*
                    370:  * Declare table for converting modem numbers to information pointers.
                    371:  *
                    372:  * The entries MUST be in ascending order by modem number, without any
                    373:  * "gaps" in the numbers, and starting from one (1).
                    374:  *
                    375:  * This table should NOT include entries for the "variant" modem numbers,
                    376:  * since it is assumed that they share the same information as the normal
                    377:  * value.
                    378:  */
                    379: static
                    380: MDMINF *ptrtab[] =
                    381:     {
                    382:     &CERMETEK,
                    383:     &DF03,
                    384:     &DF100,
                    385:     &DF200,
                    386:     &GDC,
                    387:     &HAYES,
                    388:     &PENRIL,
                    389:     &RACAL,
                    390:     &UNKNOWN,
                    391:     &USROBOT,
                    392:     &VENTEL
                    393:     };
                    394: 
                    395: /*
                    396:  * Declare modem names and associated numbers for command parsing,
                    397:  * and also for doing number-to-name translation.
                    398:  *
                    399:  * The entries MUST be in alphabetical order by modem name.
                    400:  */
                    401: struct keytab mdmtab[] =
                    402:     {
                    403:     "cermetek",                n_CERMETEK,     0,
                    404:     "df03-ac",         n_DF03,         0,
                    405:     "df100-series",    n_DF100,        0,
                    406:     "df200-series",    n_DF200,        0,
                    407:     "direct",          0,              0,
                    408:     "gendatacomm",     n_GDC,          0,
                    409:     "hayes",           n_HAYES,        0,
                    410:     "penril",          n_PENRIL,       0,
                    411:     "racalvadic",      n_RACAL,        0,
                    412:     "unknown",         n_UNKNOWN,      0,
                    413:     "usrobotics-212a", n_USROBOT,      0,
                    414:     "ventel",          n_VENTEL,       0
                    415:     };
                    416: 
                    417: int nmdm = (sizeof(mdmtab) / sizeof(struct keytab));   /* number of modems */
                    418: 
                    419: #define DIALING 4              /* for ttpkt parameter */
                    420: #define CONNECT 5
                    421: 
                    422: #define CONNECTED 1            /* for completion status */
                    423: #define FAILED   2
                    424: 
                    425: /*
                    426:  * Failure reasons for use with the 'longjmp' exit.
                    427:  */
                    428: #define        F_time          1       /* timeout */
                    429: #define F_int          2       /* interrupt */
                    430: #define        F_modem         3       /* modem-detected failure */
                    431: #define        F_minit         4       /* cannot initialize modem */
                    432: 
                    433: static
                    434: char *F_reason[5] = {          /* failure reasons for message */
                    435:     "Unknown",  "Timeout", "Interrupt", "Modem", "Initialize" };
                    436: 
                    437: static int tries = 0;
                    438: 
                    439: #define LBUFL 100
                    440: static char lbuf[LBUFL];
                    441: 
                    442: static jmp_buf sjbuf;
                    443: 
                    444: static int (*savAlrm)();       /* for saving alarm handler */
                    445: static int (*savInt)();                /* for saving interrupt handler */
                    446: 
                    447: dialtime() {                   /* timer interrupt handler */
                    448:     longjmp( sjbuf, F_time );
                    449: }
                    450: 
                    451: dialint()                      /* user-interrupt handler */
                    452:     {
                    453:     longjmp( sjbuf, F_int );
                    454:     }
                    455: 
                    456: static
                    457: ttolSlow(s,millisec) char *s; int millisec; {  /* output s-l-o-w-l-y */
                    458:     for (; *s; s++) {
                    459:        ttoc(*s);
                    460:        msleep(millisec);
                    461:        }
                    462:     }
                    463: 
                    464: /*
                    465:  * Wait for a string of characters.
                    466:  *
                    467:  * The characters are waited for individually, and other characters may
                    468:  * be received "in between".  This merely guarantees that the characters
                    469:  * ARE received, and in the order specified.
                    470:  */
                    471: static
                    472: waitFor(s) char *s;
                    473:     {
                    474:     CHAR c;
                    475:     while ( c = *s++ )                 /* while more characters remain... */
                    476:        while ( ( ttinc(0) & 0177 ) != c ) ;    /* wait for the character */
                    477:     }
                    478: 
                    479: static
                    480: didWeGet(s,r) char *s, *r; {   /* Looks in string s for response r */
                    481:     int lr = strlen(r);                /*  0 means not found, 1 means found it */
                    482:     int i;
                    483:     for (i = strlen(s)-lr; i >= 0; i--)
                    484:        if ( s[i] == r[0] ) if ( !strncmp(s+i,r,lr) ) return( 1 );
                    485:     return( 0 );           
                    486: }
                    487: 
                    488: 
                    489: /* R E S E T -- Reset alarms, etc. on exit. */
                    490: 
                    491: static
                    492: reset ()
                    493:     {
                    494:     alarm(0);
                    495:     signal(SIGALRM,savAlrm);           /* restore alarm handler */
                    496:     signal(SIGINT,savInt);             /* restore interrupt handler */
                    497:     }
                    498: 
                    499: 
                    500: 
                    501: /*  D I A L  --  Dial up the remote system */
                    502: 
                    503: dial(telnbr) char *telnbr; {
                    504: 
                    505:     char c;
                    506:     char *i, *j;
                    507:     int waitct, status;
                    508:     char errmsg[50], *erp;
                    509:     MDMINF *pmdminf;   /* pointer to modem-specific info */
                    510:     int augmdmtyp;     /* "augmented" modem type, to handle modem modes */
                    511:     int mdmEcho = 0;   /* assume modem does not echo */
                    512:     int n, n1;
                    513:     char *pc;          /* pointer to a character */
                    514: 
                    515:        if (!mdmtyp) {
                    516:            printf("Sorry, you must 'set modem' first\n");
                    517:            return(-2);
                    518:        }
                    519:        if (!local) {
                    520:            printf("Sorry, you must 'set line' first\n");
                    521:            return(-2);
                    522:        }
                    523:        if (speed < 0) {
                    524:            printf("Sorry, you must 'set speed' first\n");
                    525:            return(-2);
                    526:         }
                    527:        if (ttopen(ttname,&local,mdmtyp) < 0) {/* Open, no wait for carrier */
                    528:            erp = errmsg;
                    529:            sprintf(erp,"Sorry, can't open %s",ttname);
                    530:            perror(errmsg);
                    531:            return(-2);
                    532:        }
                    533:        pmdminf = ptrtab[mdmtyp-1];     /* set pointer to modem info */ 
                    534:        augmdmtyp = mdmtyp;             /* initialize "augmented" modem type */
                    535: /* cont'd... */
                    536: 
                    537: 
                    538:                                        /* interdigit waits for tone dial */
                    539: /* ...dial, cont'd */
                    540: 
                    541: 
                    542:        waitct = 1*strlen(telnbr) ;     /* compute time to dial worst case */
                    543:        waitct += pmdminf->dial_time;   /* dialtone + completion wait times */
                    544:        for (i=telnbr; *i; i++)         /* add in pause characters time */
                    545:            for (j=pmdminf->pause_chars; *j; j++)
                    546:                if (*i == *j) {
                    547:                    waitct += pmdminf->pause_time; 
                    548:                    break;
                    549:                    }
                    550: 
                    551:        printf("Dialing thru %s, speed %d, number %s.\r\n",ttname,speed,telnbr);
                    552:        printf("The timeout for completing the call is %d seconds.\r\n",waitct);
                    553:        printf("Type the interrupt character to cancel the dialing.\r\n");
                    554: 
                    555: /* Hang up the modem (in case it wasn't "on hook") */
                    556: 
                    557:        if ( tthang() < 0 ) {
                    558:            printf("Sorry, Can't hang up tty line\n");
                    559:            return(-2);
                    560:            }
                    561: 
                    562: /* Condition console terminal and communication line */            
                    563:                                /* place line into "clocal" dialing state */
                    564:        if ( ttpkt(speed,DIALING) < 0 )  {
                    565:            printf("Sorry, Can't condition communication line\n");
                    566:            return(-2);
                    567:        }
                    568: 
                    569: /*
                    570:  * Establish jump vector, or handle "failure" jumps.
                    571:  */
                    572: 
                    573:     if ( n = setjmp(sjbuf) )           /* if a "failure jump" was taken... */
                    574:        {
                    575:        alarm ( 0 );                    /* disable timeouts */
                    576:        if ( n1 = setjmp(sjbuf) )       /* failure while handling failure */
                    577:            {
                    578:            printf ( "%s failure while handling failure.\r\n", F_reason[n1] );
                    579:            }
                    580:        else                            /* first (i.e., non-nested) failure */
                    581:            {
                    582:            signal ( SIGALRM, dialtime );       /* be sure to catch signals */
                    583:            if ( signal ( SIGINT, SIG_IGN ) != SIG_IGN ) 
                    584:                signal ( SIGINT, dialint );
                    585:            alarm ( 5 );                /* be sure to get out of this section */
                    586:            ttclos ();                  /* hangup and close the line */
                    587:            }
                    588:        switch ( n )                    /* type of failure */
                    589:            {
                    590:            case F_time:                /* timed out */
                    591:                {
                    592:                printf ( "No connection made within the allotted time.\r\n" );
                    593:                break;
                    594:                }
                    595:            case F_int:                 /* dialing interrupted */
                    596:                {
                    597:                printf ( "Dialing interrupted.\r\n" );
                    598:                break;
                    599:                }
                    600:            case F_modem:               /* modem detected a failure */
                    601:                {
                    602:                printf ( "Failed (\"" );
                    603:                for ( pc=lbuf; *pc; pc++ )
                    604:                    if ( isprint(*pc) )
                    605:                        putchar(*pc);   /* display printable reason */ 
                    606:                printf ( "\").\r\n" );
                    607:                break;
                    608:                }
                    609:            case F_minit:               /* cannot initialize modem */
                    610:                {
                    611:                printf ( "Cannot initialize modem.\r\n" );
                    612:                break;
                    613:                }
                    614:            }
                    615:        reset ();                       /* reset alarms, etc. */
                    616:        return ( -2 );                  /* exit with failure code */
                    617:        }
                    618: 
                    619: /*
                    620:  * Set timer and interrupt handlers.
                    621:  */
                    622: 
                    623:     savAlrm = signal(SIGALRM,dialtime);        /* set alarm handler */
                    624:     if ( ( savInt = signal ( SIGINT, SIG_IGN ) ) != SIG_IGN )
                    625:        signal ( SIGINT, dialint );     /* set int handler if not ignored */
                    626:     alarm(10);                 /* give modem 10 seconds to wake up */
                    627: 
                    628:     ttflui();                  /* flush input buffer if any */
                    629: 
                    630: /*
                    631:  * Put modem in command mode.
                    632:  */
                    633: 
                    634: #define OKAY 1                 /* modem attention attempt status */
                    635: #define IGNORE 2
                    636: #define GOT_O -2
                    637: #define GOT_A -3
                    638: 
                    639: switch (augmdmtyp) {
                    640:     case n_HAYES:
                    641:     case n_HAYESNV:
                    642:        while(tries++ < 4) {
                    643:            ttol( HAYES.wake_str, strlen(HAYES.wake_str) );     /* wakeup */
                    644:            status = 0;
                    645:            while ( status <= 0 ) {
                    646:                switch (ttinc(0) & 0177) {
                    647:                    case 'A':                   /* echoing, ignore */
                    648:                        status = GOT_A;
                    649:                        break;
                    650:                    case 'T':
                    651:                        if (status == GOT_A) {
                    652:                            mdmEcho = 1;        /* expect echoing later */
                    653:                            status = 0;
                    654:                            break;
                    655:                        }
                    656:                        status = IGNORE;
                    657:                        break;
                    658:                    case '\n':
                    659:                    case '\r':
                    660:                        status = 0;
                    661:                        break;
                    662:                    case '0':                   /* numeric result code */
                    663:                        augmdmtyp = n_HAYESNV;  /* nonverbal result codes */
                    664:                        status = OKAY;
                    665:                        break;
                    666:                    case 'O':                   /* maybe English result code*/
                    667:                        status = GOT_O;
                    668:                        break;
                    669:                    case 'K':
                    670:                        if (status == GOT_O) {
                    671:                            augmdmtyp = n_HAYES;
                    672:                            status = OKAY;
                    673:                            break;
                    674:                        }                       /* else its default anyway */
                    675:                    default:
                    676:                        status = IGNORE;
                    677:                        break;
                    678:                    }
                    679:                }
                    680:            if (status == OKAY) break;
                    681:            if (status == IGNORE) ttflui();
                    682:            sleep(1);           /* wait before retrying */
                    683:        }
                    684:         if (status != 0) break;
                    685:        longjmp( sjbuf, F_minit );      /* modem-initialization failure */
                    686: 
                    687: /* cont'd... */
                    688: 
                    689:                                        /* interdigit waits for tone dial */
                    690: /* ...dial, cont'd */
                    691: 
                    692:     default:                   /* place modem into command mode */
                    693:        ttolSlow(pmdminf->wake_str, pmdminf->wake_rate);
                    694:        waitFor(pmdminf->wake_prompt);
                    695:        break;
                    696:     }
                    697:     alarm(0);                  /* turn off alarm */
                    698:     msleep(500);               /* give things settling time */
                    699:     alarm(10);                 /* alarm on dialing prompts */
                    700: 
                    701:                
                    702: /* Dial the number */
                    703: 
                    704:                                /* put modem into dialing mode */
                    705:     ttolSlow(pmdminf->dmode_str, pmdminf->dial_rate);  
                    706:     if (pmdminf->dmode_prompt) {       /* wait for prompt, if any expected */
                    707:        waitFor(pmdminf->dmode_prompt);
                    708:        msleep(300);
                    709:        }
                    710: 
                    711:     alarm(0);                  /* turn off alarm on dialing prompts */
                    712:     alarm(waitct);             /* time to allow for connecting */
                    713:     ttflui();                  /* clear out stuff from waking modem up */
                    714:     sprintf(lbuf, pmdminf->dial_str, telnbr); /* form dialing string */
                    715:     ttolSlow(lbuf,pmdminf->dial_rate); /* send dialing string */
                    716: 
                    717:     if (augmdmtyp == n_RACAL) {        /* acknowledge printout of dialing string */
                    718:        sleep(3);
                    719:        ttflui();
                    720:        ttoc('\r');
                    721:        }
                    722: 
                    723: /* cont'd... */
                    724: 
                    725: 
                    726:                                        /* interdigit waits for tone dial */
                    727: /* ...dial, cont'd */
                    728: 
                    729: 
                    730: /* Check for connection */
                    731: 
                    732: /*
                    733:  * I believe we also need to look for carrier in order to determine if a
                    734:  * connection has been made.  In fact, for many we may only want to look for
                    735:  * the "failure" responses in order to short-circuit the timeout, and let
                    736:  * carrier be the determination of whether a connection has been made. -- DS
                    737:  */
                    738: 
                    739:     status = 0;
                    740:     strcpy(lbuf,"No Connection");      /* default failure reason */
                    741:     while (status == 0) {
                    742:       switch (augmdmtyp) {
                    743:        default:
                    744:            for (n=0; n < LBUFL; n++) { /* accumulate response */
                    745:                lbuf[n] = (ttinc(0) & 0177); 
                    746:                if ( lbuf[n] == '\r' || lbuf[n] == '\n' ) break;
                    747:                }
                    748:            lbuf[n] = '\0';             /* terminate response from modem */
                    749:            if (n) {                    /* if one or more characters present */
                    750:                switch (augmdmtyp) {
                    751:                  case n_CERMETEK:
                    752:                    if (didWeGet(lbuf,"\016A")) {       
                    753:                        status = CONNECTED;
                    754:                        ttolSlow("\016U 1\r",200);      /* make transparent*/
                    755:                        }
                    756:                    break;
                    757:                  case n_DF100:      /* DF100 won't generate some of these */
                    758:                  case n_DF200:
                    759:                    if (didWeGet(lbuf,"Attached")) status = CONNECTED;
                    760:                    /*
                    761:                     * The DF100 will respond with "Attached" even if DTR
                    762:                     * and/or carrier are not present.  Another reason to
                    763:                     * (also) wait for carrier?
                    764:                     */
                    765:                    if (didWeGet(lbuf,"Busy")) status = FAILED;
                    766:                    if (didWeGet(lbuf,"Disconnected")) status = FAILED;
                    767:                    if (didWeGet(lbuf,"Error")) status = FAILED;
                    768:                    if (didWeGet(lbuf,"No answer")) status = FAILED;
                    769:                    if (didWeGet(lbuf,"No dial tone")) status = FAILED;
                    770:                    if (didWeGet(lbuf,"Speed:")) status = FAILED;
                    771:                    /*
                    772:                     * It appears that the "Speed:..." response comes after an
                    773:                     * "Attached" response, so this is never seen.  HOWEVER,
                    774:                     * it would be very handy to detect this and temporarily
                    775:                     * reset the speed, since it's a nuiscance otherwise.
                    776:                     * If we wait for some more input from the modem, how do
                    777:                     * we know if it's from the remote host or the modem?
                    778:                     * Carrier reportedly doesn't get set until after the
                    779:                     * "Speed:..." response (if any) is sent.  Another reason
                    780:                     * to (also) wait for carrier.
                    781:                     */
                    782:                    break;
                    783:                  case n_GDC:
                    784:                    if (didWeGet(lbuf,"ON LINE")) status = CONNECTED;
                    785:                    if (didWeGet(lbuf,"NO CONNECT")) status = FAILED;
                    786:                    break;
                    787:                  case n_HAYES:
                    788:                  case n_USROBOT:
                    789:                    if (didWeGet(lbuf,"CONNECT")) status = CONNECTED;
                    790:                    if (didWeGet(lbuf,"NO CARRIER")) status = FAILED;
                    791:                    break;
                    792:                  case n_PENRIL:
                    793:                    if (didWeGet(lbuf,"OK")) status = CONNECTED;
                    794:                    if (didWeGet(lbuf,"BUSY")) status = FAILED;
                    795:                    if (didWeGet(lbuf,"NO RING")) status = FAILED;
                    796:                    break;
                    797:                  case n_RACAL:
                    798:                    if (didWeGet(lbuf,"ON LINE")) status = CONNECTED;
                    799:                    if (didWeGet(lbuf,"FAILED CALL")) status = FAILED;
                    800:                    break;
                    801:                  case n_VENTEL:
                    802:                    if (didWeGet(lbuf,"ONLINE!")) status = CONNECTED;
                    803:                    if (didWeGet(lbuf,"BUSY")) status = FAILED;
                    804:                    if (didWeGet(lbuf,"DEAD PHONE")) status = FAILED;
                    805:                    break;
                    806:                }
                    807:            }
                    808:            break;
                    809: 
                    810:        case n_DF03:                    /* because response lacks CR or NL */
                    811:            c = ttinc(0) & 0177;
                    812:            if ( c == 'A' ) status = CONNECTED;
                    813:            if ( c == 'B' ) status = FAILED;
                    814:            break;
                    815: 
                    816:        case n_HAYESNV:
                    817:            c = ttinc(0) & 0177;
                    818:            if (mdmEcho) {              /* sponge up dialing string */
                    819:                mdmEcho = c!='\r';      /* until return is echoed */
                    820:                break;
                    821:                }
                    822:            if (c == '1') status = CONNECTED;
                    823:            if (c == '3') status = FAILED;
                    824:            if (c == '5') status = CONNECTED;
                    825:            break;
                    826: 
                    827:        case n_UNKNOWN:
                    828:            /** SHOULD WAIT FOR CARRIER OR TIMEOUT -- DS **/
                    829:            break;
                    830:        }                               /* switch (augmdmtyp) */
                    831:     }                                  /* while status == 0 */
                    832: 
                    833: 
                    834:     alarm(0);                          /* turn off alarm on connecting */
                    835:     if ( status != CONNECTED )         /* modem-detected failure */
                    836:        longjmp( sjbuf, F_modem );      /* exit (with reason in lbuf) */
                    837:     alarm(3);                          /* precaution in case of trouble */
                    838:     ttpkt(speed,CONNECT);              /* cancel dialing state ioctl */
                    839:     reset ();                          /* reset alarms, etc. */
                    840:     if ( ! quiet )
                    841:        printf ( "Call completed.\07\r\n" );
                    842:     return ( 0 );                      /* return, and presumably connect */
                    843: }

unix.superglobalmegacorp.com

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