Annotation of researchv10dc/lbin/kermit/ckudia.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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