home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / com / c_kermit / sources / ckudia.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-01  |  41.6 KB  |  1,194 lines

  1. char *dialv = "Dial Command, V2.0(013) 29 Aug 89";
  2.  
  3. /*  C K U D I A  --  Dialing program for connection to remote system */
  4.  
  5. /*
  6.  Original 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.  Os9/68k and Microcom modem support by Bob Larson (Blarson@ecla.usc.edu)
  14.  
  15.  ------
  16.  
  17.  This module should work under all versions of Unix.  It calls externally
  18.  defined system-depended functions for i/o, but depends upon the existence
  19.  of various modem control functions.
  20.  
  21.  This module, and the supporting routines in the ckutio.c module, assume
  22.  that the computer and modem properly utilize the following data communi-
  23.  cations signals (that means one should prepare the modem to use, not
  24.  circumvent, these signals):
  25.  
  26.      Data Terminal Ready:  This signal is asserted by the computer
  27.      when Kermit is about to ask the modem to dial a call, and is
  28.      removed when Kermit wishes to have the modem hang up a call.
  29.      The signal is asserted both while Kermit is asking the modem
  30.      to dial a specific number, and after connection, while Kermit
  31.      is in a data exchange mode.
  32.  
  33.      Carrier detect:  This signal must be asserted by the modem when
  34.      a carrier is detected from a remote modem on a communications
  35.      circuit.  It must be removed by the modem when the circuit
  36.      disconnects or is hung up.  (Carrier detect is ignored while
  37.      Kermit is asking the modem to dial the call, because there is
  38.      no consistant usage of this signal during the dialing phase
  39.      among different modem manufacturers.)
  40.  
  41. */
  42.  
  43. /*
  44.  * Modifications:
  45.  *
  46.  *  21-Jul-85   Fixed failure returns hanging on no carrier signal
  47.  *          Requires tthang change too (ckutio.c revision)
  48.  *                          -- Herm Fischer
  49.  *
  50.  *  28-Jun-85   Fixed bug with defaulting the modem-failure message
  51.  *          in lbuf.
  52.  *                          -- Dan Schullman
  53.  *
  54.  *  27-Jun-85   Merged in code from Joe Orost at Berkeley for
  55.  *          supporting the US Robotics modem, which included
  56.  *          changing the single characters in MDMINF into
  57.  *          multi-character strings and modifying waitFor.
  58.  *                          -- Dan Schullman
  59.  *
  60.  *  26-Jun-85   Allow interrupts to be used to abort dialing,
  61.  *          and ring the bell when a connection is made.
  62.  *          Reorganized some of the failure paths to use the
  63.  *          same code, and now close the line on failures.
  64.  *          Allow use of stored numbers with the DF100 and
  65.  *          DF200 modems.  Handlers now declared after the
  66.  *          call to setjmp.
  67.  *                          -- Dan Schullman
  68.  *
  69.  *  24-May-85   DF03, DF100-series, DF200-series, and "unknown" modem
  70.  *          support added.  Also restructured the various data
  71.  *          tables, fixed some bugs related to missing data and
  72.  *          missing case labels, and modified the failure message
  73.  *          to display the "reason" given by the modem.
  74.  *                          -- Dan Schullman
  75.  *  16-Mar-87   Support for the ATT7300 UNIX PC internal modem was
  76.  *          added.
  77.  *                          -- Richard E. Hill
  78.  *
  79.  *  21-Feb-88   Os9/68k and microcom modem support.
  80.  *                          -- Bob Larson
  81.  *
  82.  *  14-Mar-88   Rewrite code for ATT7300 (here and in ckutio.c)
  83.  *          Avoids dial(3c) with it's LCK files, hangs up line
  84.  *          correctly, enables user interrupts and timeouts,
  85.  *          turns on/off the system getty() login procedure.
  86.  *          Correct Hayes command sequence at little.
  87.  *          Procedures: attdial, atthang, ongetty, offgetty.
  88.  *          Parts adapted from work of Richard E. Hill and
  89.  *          Kevin O'Gorman.
  90.  *                          -- Joe R. Doupnik
  91.  *
  92.  * 13-Jan-89 Add IBM/Siemens/Rolm CBX dialing support.  - F. da Cruz
  93.  *
  94.  *  29-Aug-89   Added support for AT&T 2212C, 2224B, 2224CEO, and
  95.  *          2296A switched-network modems in AT&T mode, and
  96.  *          for the AT&T Digital Terminal Data Module (DTDM).
  97.  *                          -- Eric F. Jones
  98.  */
  99.  
  100. /*
  101.  * To add support for another modem, do the following:
  102.  *
  103.  *  Define a modem number symbol (n_XXX) for it, keeping the list
  104.  *  in alphabetical and numerical order, and renumbering the values
  105.  *  as necessary.
  106.  *
  107.  *  Create a MDMINF structure for it, again keeping the list alphabetical
  108.  *  for sanity's sake.
  109.  *
  110.  *  Add the address of the MDMINF structure to the ptrtab array, again
  111.  *  in alphabetical and numerical order.
  112.  *
  113.  *  Add the "user visible" modem name and corresponding modem number to
  114.  *  the mdmtab array, again in alphabetical order.
  115.  *
  116.  *  Read through the code and add modem-specific sections as necessary.
  117.  */
  118.  
  119. /*
  120.  * The intent of the "unknown" modem is hopefully to allow KERMIT to support
  121.  * unknown modems by having the user type the entire autodial sequence
  122.  * (possibly including control characters, etc.) as the "phone number".
  123.  * The only reason that the CONNECT command cannot be used to do this is
  124.  * that a remote line cannot normally be opened unless carrier is present.
  125.  *
  126.  * The protocol and other characteristics of this modem are unknown, with
  127.  * some "reasonable" values being chosen for some of them.  The only way to
  128.  * detect if a connection is made is to look for carrier present.
  129.  *
  130.  * SUPPORT IS CURRENTLY ONLY PARTIALLY SKETCHED OUT FOR THIS.  ALSO, IT
  131.  * SHOULD PERHAPS BE HANDLED MUCH EARLIER, SIMPLY READING USER INPUT AND
  132.  * SENDING IT TO THE MODEM AND ECHOING MODEM RESPONSES BACK TO THE USER,
  133.  * ALL THE TIME LOOKING FOR CARRIER.  OF COURSE, THE PROBLEM THEN BECOMES
  134.  * ONE OF ALLOWING THE USER TO CANCEL THE DIALING.  WE COULD CHOOSE SOME
  135.  * PHRASE THAT WOULD PRESUMABLY NEVER BE A PART OF A VALID AUTODIAL SEQUENCE
  136.  * (E.G., "QUIT" and "quit"). -- DS
  137.  */
  138. #include <stdio.h>
  139. #include <ctype.h>
  140. #include <signal.h>
  141. #include "ckcdeb.h"
  142. #include "ckcasc.h"
  143. #include "ckcker.h"
  144. #include "ckucmd.h"
  145.  
  146. #ifndef ZILOG
  147. #include <setjmp.h>         /* Longjumps */
  148. #else
  149. #include <setret.h>
  150. #endif
  151.  
  152. #ifdef OS2
  153. #define SIGALRM SIGUSR1
  154. void alarm( unsigned );
  155. #endif
  156.  
  157. extern int flow, local, mdmtyp, quiet, speed, parity, seslog, ttyfd, network;
  158. extern char ttname[], sesfil[];
  159.  
  160. #define MDMINF  struct mdminf
  161.  
  162. MDMINF      /* structure for modem-specific information */
  163.     {
  164.     int     dial_time;  /* time modem allows for dialing (secs) */
  165.     char    *pause_chars;   /* character(s) to tell modem to pause */
  166.     int     pause_time; /* time associated with pause chars (secs) */
  167.     char    *wake_str;  /* string to wakeup modem & put in cmd mode */
  168.     int     wake_rate;  /* delay between wake_str characters (msecs) */
  169.     char    *wake_prompt;   /* string prompt after wake_str */
  170.     char    *dmode_str; /* string to put modem in dialing mode */
  171.     char    *dmode_prompt;  /* string prompt for dialing mode */
  172.     char    *dial_str;  /* dialing string, with "%s" for number */
  173.     int     dial_rate;  /* delay between dialing characters (msecs) */
  174.     };
  175.  
  176. /*
  177.  * Define symbolic modem numbers.
  178.  *
  179.  * The numbers MUST correspond to the ordering of entries
  180.  * within the ptrtab array, and start at one (1).
  181.  *
  182.  * It is assumed that there are relatively few of these
  183.  * values, and that the high(er) bytes of the value may
  184.  * be used for modem-specific mode information.
  185.  *
  186.  * REMEMBER that only the first eight characters of these
  187.  * names are guaranteed to be unique.
  188.  */
  189.  
  190. #define     n_ATTDTDM    1
  191. #define     n_ATTMODEM   2
  192. #define     n_CERMETEK   3
  193. #define     n_DF03       4
  194. #define     n_DF100      5
  195. #define     n_DF200      6
  196. #define     n_GDC        7
  197. #define     n_HAYES      8
  198. #define     n_PENRIL     9
  199. #define     n_RACAL     10
  200. #define     n_UNKNOWN   11
  201. #define     n_USROBOT   12
  202. #define     n_VENTEL    13
  203. #define     n_CONCORD   14
  204. #define     n_ATTUPC    15  /* aka Unix PC and ATT7300 */
  205. #define     n_ROLM          16      /* Rolm CBX */
  206. #define     n_MICROCOM  17
  207.  
  208. /*
  209.  * Declare modem "variant" numbers for any of the above for which it is
  210.  * necessary to note various operational modes, using the second byte
  211.  * of a modem number.
  212.  *
  213.  * It is assumed that such modem modes share the same modem-specific
  214.  * information (see MDMINF structure) but may differ in some of the actions
  215.  * that are performed.
  216.  */
  217. #define     n_HAYESNV   ( n_HAYES + ( 1<<8 ) )
  218.  
  219. /*
  220.  * Declare structures containing modem-specific information.
  221.  *
  222.  * REMEMBER that only the first SEVEN characters of these
  223.  * names are guaranteed to be unique.
  224.  */
  225.  
  226. static
  227. MDMINF ATTMODEM =   /* information for AT&T switched-network modems */
  228.             /* "Number" following "dial" can include: p's and
  229.              * t's to indicate pulse or tone (default) dialing,
  230.              * + for wait for dial tone, , for pause, r for
  231.              * last number dialed, and, except for 2224B, some
  232.              * comma-delimited options like o12=y, before number.
  233.  
  234.  * "Important" options for the modems:
  235.  *
  236.  *  All:        Except for 2224B, enable option 12 for "transparent
  237.  *          data," o12=y.  If a computer port used for both
  238.  *          incoming and outgoing calls is connected to the
  239.  *          modem, disable "enter interactive mode on carriage
  240.  *          return," EICR.  The Kermit "dial" command can
  241.  *          function with EIA leads standard, EIAS.
  242.  *
  243.  *  2212C:      Internal hardware switches at their default
  244.  *          positions (four rockers down away from numbers)
  245.  *          unless EICR is not wanted (rocker down at the 4).
  246.  *          For EIAS, rocker down at the 1.
  247.  *
  248.  *  2224B:      Front-panel switch position 1 must be up (at the 1,
  249.  *          closed).  Disable EICR with position 2 down.
  250.  *          For EIAS, position 4 down.
  251.  *          All switches on the back panel down.
  252.  *
  253.  *  2224CEO:    All front-panel switches down except either 5 or 6.
  254.  *          Enable interactive flow control with o16=y.
  255.  *          Select normal asynchronous mode with o34=0 (zero).
  256.  *          Disable EICR with position 3 up.  For EIAS, 1 up.
  257.  *          Reset the modem after changing switches.
  258.  *
  259.  *  2296A:      If option 00 (zeros) is present, use o00=0.
  260.  *          Enable interactive flow control with o16=y.
  261.  *          Select normal asynchronous mode with o34=0 (zero).
  262.  *                      (available in Microcom Networking version, but
  263.  *                      not necessarily other models of the 2296A).
  264.  *          Enable modem-port flow control (if available) with
  265.  *          o42=y.  Enable asynchronous operation with o50=y.
  266.  *          Disable EICR with o69=n.  For EIAS, o66=n, using
  267.  *          front panel.
  268.  */
  269.     {
  270.     20,         /* dial_time */
  271.     ",",        /* pause_chars */
  272.     2,          /* pause_time */
  273.     "+",        /* wake_str */
  274.     0,          /* wake_rate */
  275.     "",         /* wake_prompt */
  276.     "",         /* dmode_str */
  277.     "",         /* dmode_prompt */
  278.     "at%s\r",       /* dial_str */
  279.     0           /* dial_rate */
  280.     };
  281.  
  282. static
  283. MDMINF ATTDTDM =    /* information for AT&T Digital Terminal Data Module
  284.  *          For dialing: KYBD switch down, others usually up. */
  285.     {
  286.     20,         /* dial_time */
  287.     "",         /* pause_chars */
  288.     0,          /* pause_time */
  289.     "",         /* wake_str */
  290.     0,          /* wake_rate */
  291.     "",         /* wake_prompt */
  292.     "",         /* dmode_str */
  293.     "",         /* dmode_prompt */
  294.     "%s\r",     /* dial_str */      /* not used */
  295.     0           /* dial_rate */
  296.     };
  297.  
  298. static
  299. MDMINF CERMETEK =   /* information for "Cermetek Info-Mate 212 A" modem */
  300.     {
  301.     20,         /* dial_time */
  302.     "BbPpTt",       /* pause_chars */
  303.     0,          /* pause_time */    /** unknown -- DS **/
  304.     "  XY\016R\r",  /* wake_str */
  305.     200,        /* wake_rate */
  306.     "",         /* wake_prompt */
  307.     "",         /* dmode_str */
  308.     NULL,       /* dmode_prompt */
  309.     "\016D '%s'\r", /* dial_str */
  310.     200         /* dial_rate */
  311.     };
  312.  
  313. static
  314. MDMINF DF03 =       /* information for "DEC DF03-AC" modem */
  315.     {
  316.     27,         /* dial_time */
  317.     "=",        /* pause_chars */   /* wait for second dial tone */
  318.     15,         /* pause_time */
  319.     "\001\002",     /* wake_str */
  320.     0,          /* wake_rate */
  321.     "",         /* wake_prompt */
  322.     "",         /* dmode_str */
  323.     NULL,       /* dmode_prompt */
  324.     "%s",       /* dial_str */
  325.     0           /* dial_rate */
  326.     };
  327.  
  328. static
  329. MDMINF DF100 =      /* information for "DEC DF100-series" modem */
  330.             /*
  331.              * The telephone "number" can include "P"s and/or "T"s
  332.              * within it to indicate that subsequent digits are
  333.              * to be dialed using pulse or tone dialing.  The
  334.              * modem defaults to pulse dialing.  You may modify
  335.              * the dial string below to explicitly default all
  336.              * dialing to pulse or tone, but doing so prevents
  337.              * the use of phone numbers that you may have stored
  338.              * in the modem's memory.
  339.              */
  340.     {
  341.     30,         /* dial_time */
  342.     "=",        /* pause_chars */   /* wait for second dial tone */
  343.     15,         /* pause_time */
  344.     "\001",     /* wake_str */
  345.     0,          /* wake_rate */
  346.     "",         /* wake_prompt */
  347.     "",         /* dmode_str */
  348.     NULL,       /* dmode_prompt */
  349.     "%s#",      /* dial_str */
  350.     0           /* dial_rate */
  351.     };
  352.  
  353. static
  354. MDMINF DF200 =      /* information for "DEC DF200-series" modem */
  355.             /*
  356.              * The telephone "number" can include "P"s and/or "T"s
  357.              * within it to indicate that subsequent digits are
  358.              * to be dialed using pulse or tone dialing.  The
  359.              * modem defaults to pulse dialing.  You may modify
  360.              * the dial string below to explicitly default all
  361.              * dialing to pulse or tone, but doing so prevents
  362.              * the use of phone numbers that you may have stored
  363.              * in the modem's memory.
  364.              */
  365.     {
  366.     30,         /* dial_time */
  367.     "=W",       /* pause_chars */   /* =: second tone; W: 5 secs */
  368.     15,         /* pause_time */    /* worst case */
  369.     "\002",     /* wake_str */      /* allow stored number usage */
  370.     0,          /* wake_rate */
  371.     "",         /* wake_prompt */
  372.     "",         /* dmode_str */
  373.     NULL,       /* dmode_prompt */
  374.     "%s!",      /* dial_str */
  375.     0           /* dial_rate */
  376.     };
  377.  
  378. static
  379. MDMINF GDC =        /* information for "GeneralDataComm 212A/ED" modem */
  380.     {
  381.     32,         /* dial_time */
  382.     "%",        /* pause_chars */
  383.     3,          /* pause_time */
  384.     "\r\r",     /* wake_str */
  385.     500,        /* wake_rate */
  386.     "$",        /* wake_prompt */
  387.     "D\r",      /* dmode_str */
  388.     ":",        /* dmode_prompt */
  389.     "T%s\r",        /* dial_str */
  390.     0           /* dial_rate */
  391.     };
  392.  
  393. static
  394. MDMINF HAYES =      /* information for "Hayes" modem */
  395.     {
  396.     35,         /* dial_time */
  397.     ",",        /* pause_chars */
  398.     2,          /* pause_time */
  399.     "AT\r",     /* wake_str */
  400. /*** Note: Other wake_str's are possible here.  For Hayes 2400 that is to
  401. /*** be used for both in and out calls, AT&F&D3 might be best.  For out calls
  402. /*** only, maybe AT&F&D2.  See Hayes 2400 manual. ***/
  403.     0,          /* wake_rate */
  404.     "",         /* wake_prompt */
  405.     "",         /* dmode_str */
  406.     "",         /* dmode_prompt */
  407.     "ATD%s\r",      /* dial_str, note: user can supply D or T */
  408.     0           /* dial_rate */
  409.     };
  410.  
  411. static
  412. MDMINF PENRIL =     /* information for "Penril" modem */
  413.     {
  414.     50,         /* dial_time */
  415.     "",         /* pause_chars */   /** unknown -- HF **/
  416.     0,          /* pause_time */
  417.     "\r\r",     /* wake_str */
  418.     300,        /* wake_rate */
  419.     ">",        /* wake_prompt */
  420.     "k\r",      /* dmode_str */
  421.     ":",        /* dmode_prompt */
  422.     "%s\r",     /* dial_str */
  423.     0           /* dial_rate */
  424.     };
  425.  
  426. static
  427. MDMINF RACAL =      /* information for "Racal Vadic" modem */
  428.     {
  429.     35,         /* dial_time */
  430.     "Kk",       /* pause_chars */
  431.     5,          /* pause_time */
  432.     "\005\r",       /* wake_str */
  433.     50,         /* wake_rate */
  434.     "*",        /* wake_prompt */
  435.     "D\r",      /* dmode_str */
  436.     "?",        /* dmode_prompt */
  437.     "%s\r",     /* dial_str */
  438.     0           /* dial_rate */
  439.     };
  440.  
  441. static
  442. MDMINF UNKNOWN =    /* information for "Unknown" modem */
  443.     {
  444.     30,         /* dial_time */
  445.     "",         /* pause_chars */
  446.     0,          /* pause_time */
  447.     "",         /* wake_str */
  448.     0,          /* wake_rate */
  449.     "",         /* wake_prompt */
  450.     "",         /* dmode_str */
  451.     NULL,       /* dmode_prompt */
  452.     "%s\r",     /* dial_str */
  453.     0           /* dial_rate */
  454.     };
  455.  
  456. static
  457. MDMINF USROBOT =    /* information for "US Robotics 212A" modem */
  458.     {
  459.     30,         /* dial_time */
  460.     ",",        /* pause_chars */
  461.     2,          /* pause_time */
  462.     "ATS2=01\r",    /* wake_str */
  463.     0,          /* wake_rate */
  464.     "OK\r",     /* wake_prompt */
  465.     "",         /* dmode_str */
  466.     NULL,       /* dmode_prompt */
  467.     "ATTD%s\r",     /* dial_str */
  468.     0           /* dial_rate */
  469.     };
  470.  
  471. static
  472. MDMINF VENTEL =     /* information for "Ventel" modem */
  473.     {
  474.     20,         /* dial_time */
  475.     "%",        /* pause_chars */
  476.     5,          /* pause_time */
  477.     "\r\r\r",       /* wake_str */
  478.     300,        /* wake_rate */
  479.     "$",        /* wake_prompt */
  480.     "",         /* dmode_str */
  481.     NULL,       /* dmode_prompt */
  482.     "<K%s\r>",      /* dial_str */
  483.     0           /* dial_rate */
  484.     };
  485.  
  486. static
  487. MDMINF CONCORD =    /* Info for Condor CDS 220 2400b modem */
  488.     {
  489.     35,         /* dial_time */
  490.     ",",        /* pause_chars */
  491.     2,          /* pause_time */
  492.     "\r\r",     /* wake_str */
  493.     20,         /* wake_rate */
  494.     "CDS >",        /* wake_prompt */
  495.     "",         /* dmode_str */
  496.     NULL,       /* dmode_prompt */
  497.     "<D M%s\r>",    /* dial_str */
  498.     0           /* dial_rate */
  499.     };
  500.  
  501. static
  502. MDMINF ATTUPC = /* dummy information for "ATT7300/Unix PC" internal modem */
  503.     {
  504.     20,         /* dial_time */
  505.     "",         /* pause_chars */
  506.     0,          /* pause_time */
  507.     "",         /* wake_str */
  508.     0,          /* wake_rate */
  509.     "",         /* wake_prompt */
  510.     "",         /* dmode_str */
  511.     NULL,       /* dmode_prompt */
  512.     "%s\r",     /* dial_str */
  513.     0           /* dial_rate */
  514.     };
  515.  
  516. static
  517. MDMINF ROLM =       /* IBM / Siemens / Rolm 8000, 9000, 9751 CBX */
  518.     {
  519.     60,         /* dial_time */
  520.     "",         /* pause_chars */
  521.     0,          /* pause_time */
  522.     "\r\r",     /* wake_str */
  523.     5,          /* wake_rate */
  524.     "MODIFY?",          /* wake_prompt */
  525.     "",         /* dmode_str */
  526.     "",         /* dmode_prompt */
  527.     "CALL %s\r",    /* dial_str */
  528.     0           /* dial_rate */
  529.     };
  530.  
  531. static
  532. MDMINF MICROCOM =   /* information for "Microcom" modems in native mode */
  533.             /* (long answer only) */
  534.     {
  535.     35,         /* dial_time */
  536.     ",!@",      /* pause_chars (! and @ aren't pure pauses) */
  537.     3,          /* pause_time */
  538.     "\r",       /* wake_str */
  539.     100,        /* wake_rate */
  540.     "!",        /* wake_prompt */
  541.     "",         /* dmode_str */
  542.     NULL,       /* dmode_prompt */
  543.     "d%s\r",        /* dial_str */
  544.     0           /* dial_rate */
  545.     };
  546.  
  547. /*
  548.  * Declare table for converting modem numbers to information pointers.
  549.  *
  550.  * The entries MUST be in ascending order by modem number, without any
  551.  * "gaps" in the numbers, and starting from one (1).
  552.  *
  553.  * This table should NOT include entries for the "variant" modem numbers,
  554.  * since it is assumed that they share the same information as the normal
  555.  * value.
  556.  */
  557. static
  558. MDMINF *ptrtab[] =
  559.     {
  560.     &ATTDTDM,
  561.     &ATTMODEM,
  562.     &CERMETEK,
  563.     &DF03,
  564.     &DF100,
  565.     &DF200,
  566.     &GDC,
  567.     &HAYES,
  568.     &PENRIL,
  569.     &RACAL,
  570.     &UNKNOWN,
  571.     &USROBOT,
  572.     &VENTEL,
  573.     &CONCORD,
  574.     &ATTUPC,            /* ATT7300 internal modem, jrd*/
  575.     &ROLM,          /* Rolm CBX, fdc */
  576.     &MICROCOM,
  577.     };
  578.  
  579. /*
  580.  * Declare modem names and associated numbers for command parsing,
  581.  * and also for doing number-to-name translation.
  582.  *
  583.  * The entries MUST be in alphabetical order by modem name.
  584.  */
  585. struct keytab mdmtab[] =
  586.     {
  587.     "attdtdm",      n_ATTDTDM,  0,
  588.     "attmodem",     n_ATTMODEM, 0,
  589.     "att7300",      n_ATTUPC,   0,
  590.     "cermetek",     n_CERMETEK, 0,
  591.     "concord",      n_CONCORD,  0,
  592.     "df03-ac",      n_DF03,     0,
  593.     "df100-series", n_DF100,    0,
  594.     "df200-series", n_DF200,    0,
  595.     "direct",       0,      0,
  596.     "gendatacomm",  n_GDC,      0,
  597.     "hayes",        n_HAYES,    0,
  598.     "microcom",     n_MICROCOM, 0,
  599.     "none",             0,              0,
  600.     "penril",       n_PENRIL,   0,
  601.     "racalvadic",   n_RACAL,    0,
  602.     "rolm",     n_ROLM,     0,
  603.     "unknown",      n_UNKNOWN,  0,
  604.     "usrobotics-212a",  n_USROBOT,  0,
  605.     "ventel",       n_VENTEL,   0
  606.     };
  607.  
  608. int nmdm = (sizeof(mdmtab) / sizeof(struct keytab));    /* number of modems */
  609.  
  610. #define DIALING 4       /* for ttpkt parameter */
  611. #define CONNECT 5
  612.  
  613. #define CONNECTED 1     /* for completion status */
  614. #define FAILED    2
  615.  
  616. /*
  617.  * Failure reasons for use with the 'longjmp' exit.
  618.  */
  619. #define F_time      1   /* timeout */
  620. #define F_int       2   /* interrupt */
  621. #define F_modem     3   /* modem-detected failure */
  622. #define F_minit     4   /* cannot initialize modem */
  623.  
  624. static
  625. char *F_reason[5] = {       /* failure reasons for message */
  626.     "Unknown",  "Timeout", "Interrupt", "Modem", "Initialize" };
  627.  
  628. static int tries = 0;
  629.  
  630. #define LBUFL 100
  631. static char lbuf[LBUFL];
  632.  
  633. static jmp_buf sjbuf;
  634.  
  635. static SIGTYP (*savAlrm)(); /* for saving alarm handler */
  636. static SIGTYP (*savInt)();  /* for saving interrupt handler */
  637.  
  638. char *                  /* Copy a string of the */
  639. xcpy(to,from,len)           /* the given length. */
  640.   register char *to, *from;
  641.   register unsigned len; {
  642.     while (len--) *to++ = *from++;
  643. }
  644.  
  645. SIGTYP
  646. dialtime() {            /* timer interrupt handler */
  647. #ifdef OS2
  648.     alarmack();
  649. #endif
  650.     longjmp( sjbuf, F_time );
  651. }
  652.  
  653. SIGTYP
  654. dialint() {             /* user-interrupt handler */
  655. #ifdef OS2
  656.     alarmack();
  657. #endif
  658.     longjmp( sjbuf, F_int );
  659.     }
  660.  
  661. static
  662. ttolSlow(s,millisec) char *s; int millisec; {  /* output s-l-o-w-l-y */
  663.     for (; *s; s++) {
  664.     ttoc(*s);
  665.     msleep(millisec);
  666.     }
  667.     }
  668.  
  669. /*
  670.  * Wait for a string of characters.
  671.  *
  672.  * The characters are waited for individually, and other characters may
  673.  * be received "in between".  This merely guarantees that the characters
  674.  * ARE received, and in the order specified.
  675.  */
  676. static
  677. waitFor(s) char *s; {
  678.     CHAR c;
  679.     while ( c = *s++ )          /* while more characters remain... */
  680.     while ( ( ttinc(0) & 0177 ) != c ) /* wait for the character */
  681.         ;
  682. }
  683.  
  684. static
  685. didWeGet(s,r) char *s, *r; {    /* Looks in string s for response r */
  686.     int lr = strlen(r);     /*  0 means not found, 1 means found it */
  687.     int i;
  688.     debug(F110,"didWeGet",r,0);
  689.     debug(F110," in",s,0);
  690.     for (i = strlen(s)-lr; i >= 0; i--)
  691.     if ( s[i] == r[0] ) if ( !strncmp(s+i,r,lr) ) return( 1 );
  692.     return( 0 );
  693. }
  694.  
  695.  
  696. /* R E S E T -- Reset alarms, etc. on exit. */
  697.  
  698. static
  699. reset ()
  700.     {
  701.     alarm(0);
  702.     signal(SIGALRM,savAlrm);        /* restore alarm handler */
  703. #ifndef OS2
  704.     signal(SIGINT,savInt);      /* restore interrupt handler */
  705. #endif
  706.     }
  707.  
  708. /*  C K D I A L  --  Dial up the remote system */
  709.  
  710. /* Returns 1 if call completed, 0 otherwise */
  711.  
  712. ckdial(telnbr) char *telnbr; {
  713.  
  714.     char c;
  715.     char *i, *j;
  716.     int waitct, status;
  717.     char errmsg[50], *erp;
  718.     MDMINF *pmdminf;    /* pointer to modem-specific info */
  719.     int augmdmtyp;  /* "augmented" modem type, to handle modem modes */
  720.     int mdmEcho = 0;    /* assume modem does not echo */
  721.     int n, n1;
  722.     char *pc;       /* pointer to a character */
  723.  
  724.         if (network) {
  725.         printf("Sorry, 'dial' not available on network connection\n");
  726.         return(0);
  727.     }
  728.     if (mdmtyp < 1) {
  729.         printf("Sorry, you must 'set modem' first\n");
  730.         return(0);
  731.     }
  732.     if (!local) {
  733.         printf("Sorry, you must 'set line' first\n");
  734.         return(0);
  735.     }
  736.     if (speed < 0) {
  737.         printf("Sorry, you must 'set speed' first\n");
  738.         return(0);
  739.     }
  740.         debug(F110,"dial",telnbr,0);
  741.  
  742.     /* Carrier no-wait can be invalidated by ckutio fun and games, jrd */
  743.     if (ttopen(ttname,&local,mdmtyp) < 0) { /* Open, no carrier wait */
  744.         erp = errmsg;
  745.         sprintf(erp,"Sorry, can't open %s",ttname);
  746.         perror(errmsg);
  747.         return(0);
  748.     }
  749.     pmdminf = ptrtab[mdmtyp-1]; /* set pointer to modem info */
  750.     augmdmtyp = mdmtyp;     /* initialize "augmented" modem type */
  751.  
  752.                        /* interdigit waits for tone dial */
  753.  
  754.     waitct = 1*strlen(telnbr) ; /* compute time to dial worst case */
  755.     waitct += pmdminf->dial_time;   /* dialtone + completion wait times */
  756.     for (i=telnbr; *i; i++)     /* add in pause characters time */
  757.         for (j=pmdminf->pause_chars; *j; j++)
  758.         if (*i == *j) {
  759.             waitct += pmdminf->pause_time;
  760.             break;
  761.             }
  762.  
  763.        printf("Dialing thru %s, speed %d, number %s.\n",ttname,speed,telnbr);
  764.        printf("The timeout for completing the call is %d seconds.\n",waitct);
  765. #ifndef OS2
  766.        printf("Type the interrupt character (^C) to cancel the dialing.\n");
  767. #endif
  768.        debug(F101,ttname,"",speed);
  769.        debug(F101,"timeout","",waitct);
  770.  
  771. /* Hang up the modem (in case it wasn't "on hook") */
  772.  
  773.     if ( tthang() < 0 ) {
  774.         printf("Sorry, Can't hang up tty line\n");
  775.         return(0);
  776.     }
  777.         if (augmdmtyp == n_ROLM) sleep(1);
  778.  
  779. /* Condition console terminal and communication line */
  780.                 /* place line into "clocal" dialing state */
  781.     if ( ttpkt(speed,DIALING,parity) < 0 )  {
  782.         printf("Sorry, Can't condition communication line\n");
  783.         return(0);
  784.     }
  785.         if (augmdmtyp == n_ROLM) sleep(1);
  786. /*
  787.  * Establish jump vector, or handle "failure" jumps.
  788.  */
  789.  
  790.     if ( n = setjmp(sjbuf) )        /* if a "failure jump" was taken... */
  791.     {
  792.     alarm ( 0 );            /* disable timeouts */
  793.     if ( n1 = setjmp(sjbuf) )   /* failure while handling failure */
  794.         {
  795.         printf ( "%s failure while handling failure.\n", F_reason[n1] );
  796.         }
  797.     else                /* first (i.e., non-nested) failure */
  798.         {
  799.         signal ( SIGALRM, dialtime );   /* be sure to catch signals */
  800. #ifndef OS2
  801.         if ( signal ( SIGINT, SIG_IGN ) != SIG_IGN )
  802.         signal ( SIGINT, dialint );
  803. #endif
  804.         alarm ( 10 );       /* be sure to exit this section */
  805.         ttclos ();          /* hangup and close the line */
  806.         }
  807.     switch ( n )            /* type of failure */
  808.         {
  809.         case F_time:        /* timed out */
  810.         {
  811.         printf ( "No connection made within the allotted time.\n" );
  812.         debug(F110,"dial","timeout",0);
  813.         break;
  814.         }
  815.         case F_int:         /* dialing interrupted */
  816.         {
  817.         printf ( "Dialing interrupted.\n" );
  818.         debug(F110,"dial","interrupted",0);
  819.         break;
  820.         }
  821.         case F_modem:       /* modem detected a failure */
  822.         {
  823.         printf ( "Failed (\"" );
  824.         for ( pc=lbuf; *pc; pc++ )
  825.             if ( isprint(*pc) )
  826.             putchar(*pc);   /* display printable reason */
  827.         printf ( "\").\n" );
  828.         debug(F110,"dial",lbuf,0);
  829.         break;
  830.         }
  831.         case F_minit:       /* cannot initialize modem */
  832.         {
  833.         printf ( "Cannot initialize modem.\n" );
  834.         debug(F110,"dial","modem init",0);
  835.         break;
  836.         }
  837.         }
  838.     reset();            /* reset alarms, etc. */
  839.     return (0);         /* exit with failure code */
  840.     }
  841.  
  842. /*
  843.  * Set timer and interrupt handlers.
  844.  */
  845.  
  846. /* The following call to ttflui() commented out because ttpkt just did this */
  847. /*  ttflui();   */      /* flush input buffer if any */
  848.  
  849.     savAlrm = signal(SIGALRM,dialtime); /* set alarm handler */
  850. #ifndef OS2
  851.     if ( ( savInt = signal ( SIGINT, SIG_IGN ) ) != SIG_IGN )
  852.     signal ( SIGINT, dialint ); /* set int handler if not ignored */
  853. #endif
  854.     debug(F100,"ckdial giving modem 10 secs to wake up","",0);
  855.     alarm(10);          /* give modem 10 seconds to wake up */
  856.  
  857. /*
  858.  * Put modem in command mode.
  859.  */
  860.  
  861. #define OKAY 1          /* modem attention attempt status */
  862. #define IGNORE 2
  863. #define GOT_O -2
  864. #define GOT_A -3
  865.  
  866. switch (augmdmtyp) {
  867.  
  868. #ifdef ATT7300
  869.     case n_ATTUPC:
  870. /*
  871.   For ATT7300/Unix PC's with their special internal modem. Timeout
  872.   and user interrupts are enabled during dialing.  attdial() is in
  873.   file ckutio.c.  - jrd
  874. */
  875.     {
  876.     alarm(waitct);              /* do alarm properly */
  877.     if (attdial(ttname,speed,telnbr))   /* dial internal modem */
  878.         {
  879.         reset();            /* reset alarms, etc. */
  880.         if ( ! quiet ) printf("Call did not complete.");
  881.         ttclos();           /* close line if open */
  882.         return(0);          /* return failure */
  883.         }
  884.     reset();                /* reset alarms, etc. */
  885.     ttpkt(speed,CONNECT,parity);        /* cancel dialing ioctl */
  886.     if ( ! quiet ) printf ("Call completed.\07\r\n");
  887.     return(1);   /* no conversation with modem to complete dialing */
  888.     }
  889. #endif /* att7300 */
  890.  
  891.     case n_HAYES:
  892.     case n_HAYESNV:
  893.     while(tries++ < 4) {
  894.         ttol( HAYES.wake_str, strlen(HAYES.wake_str) ); /* wakeup */
  895.         status = 0;
  896.         while ( status <= 0 ) {
  897.         switch (ttinc(0) & 0177) {
  898.             case 'A':           /* echoing, ignore */
  899.             status = GOT_A;
  900.             break;
  901.             case 'T':
  902.             if (status == GOT_A) {
  903.                 mdmEcho = 1;    /* expect echoing later */
  904.                 status = 0;
  905.                 break;
  906.             }
  907.             status = IGNORE;
  908.             break;
  909.             case LF:
  910.             case CR:
  911.             status = 0;
  912.             break;
  913.             case '0':           /* numeric result code */
  914.             augmdmtyp = n_HAYESNV;  /* nonverbal result codes */
  915.             status = OKAY;
  916.             break;
  917.             case 'O':           /* maybe English result code*/
  918.             status = GOT_O;
  919.             break;
  920.             case 'K':
  921.             if (status == GOT_O) {
  922.                 augmdmtyp = n_HAYES;
  923.                 status = OKAY;
  924.                 break;
  925.             }           /* else its default anyway */
  926.             default:
  927.             status = IGNORE;
  928.             break;
  929.             }
  930.         }
  931.         if (status == OKAY) break;
  932.         if (status == IGNORE) ttflui();
  933.         sleep(1);       /* wait before retrying */
  934.     }
  935.     if (status != 0) break;
  936.     longjmp( sjbuf, F_minit );  /* modem-initialization failure */
  937.  
  938.     case n_MICROCOM:        /* interdigit waits for tone dial */
  939.         {
  940.         jmp_buf savejmp;
  941.         alarm(0);
  942.         xcpy((char *)savejmp, (char *)sjbuf, sizeof savejmp);
  943.         if(setjmp(sjbuf)) {
  944.             /* try the autobaud sequence */
  945.         xcpy((char *)sjbuf, (char *)savejmp, sizeof savejmp);
  946.         alarm(5);
  947.             ttolSlow("44445", MICROCOM.wake_rate);
  948.         waitFor(MICROCOM.wake_str);
  949.         } else {
  950.         alarm(2);
  951.         ttolSlow(MICROCOM.wake_str, MICROCOM.wake_rate);
  952.             waitFor(MICROCOM.wake_str);
  953.         alarm(0);
  954.         xcpy((char *)sjbuf, (char *)savejmp, sizeof savejmp);
  955.         }
  956.     }
  957.     break;
  958.     case n_ATTDTDM:     /* DTDM requires BREAK to wake up */
  959.     ttsndb();       /* Send BREAK */
  960.     break;          /* ttsndb() defined in ckutio.c */
  961.  
  962.     default:            /* place modem into command mode */
  963.     debug(F111,"ckdial default, wake string",pmdminf->wake_str,
  964.           pmdminf->wake_rate);
  965.     ttolSlow(pmdminf->wake_str, pmdminf->wake_rate);
  966.     debug(F110,"ckdial default, waiting for wake_prompt",
  967.           pmdminf->wake_prompt,0);
  968.     waitFor(pmdminf->wake_prompt);
  969.     break;
  970.     }
  971.     debug(F100,"ckdial got wake prompt","",0);
  972.     alarm(0);           /* turn off alarm */
  973.     msleep(500);        /* give things settling time */
  974.     alarm(10);          /* alarm on dialing prompts */
  975.  
  976.  
  977. /* Dial the number */
  978.                 /* put modem into dialing mode */
  979.     ttolSlow(pmdminf->dmode_str, pmdminf->dial_rate);
  980.     if (pmdminf->dmode_prompt) {    /* wait for prompt, if any expected */
  981.     waitFor(pmdminf->dmode_prompt);
  982.     msleep(300);
  983.     }
  984.  
  985.     alarm(0);           /* turn off alarm on dialing prompts */
  986.     alarm(waitct);      /* time to allow for connecting */
  987.     ttflui();           /* clear out stuff from waking modem up */
  988.  
  989.     sprintf(lbuf, pmdminf->dial_str, telnbr); /* form dialing string */
  990.     debug(F110,"dialing",lbuf,0);
  991.     ttolSlow(lbuf,pmdminf->dial_rate);  /* send dialing string */
  992.  
  993.     if (augmdmtyp == n_RACAL) { /* acknowledge printout of dialing string */
  994.     sleep(3);
  995.     ttflui();
  996.     ttoc('\r');
  997.     }
  998.  
  999. /* Check for connection */
  1000.  
  1001. /*
  1002.  * I believe we also need to look for carrier in order to determine if a
  1003.  * connection has been made.  In fact, for many we may only want to look for
  1004.  * the "failure" responses in order to short-circuit the timeout, and let
  1005.  * carrier be the determination of whether a connection has been made. -- DS
  1006.  */
  1007.  
  1008. /*
  1009.  * The following four lines added at request of Peter Mauzey, but I'm not
  1010.  * sure this is where they're really supposed to go.
  1011.  */
  1012.     if (augmdmtyp == n_ATTMODEM || augmdmtyp == n_ATTDTDM ) {
  1013.     signal(SIGALRM, dialtime);
  1014.     alarm(waitct);
  1015.     }
  1016.     status = 0;
  1017.     strcpy(lbuf,"No Connection");   /* default failure reason */
  1018.     while (status == 0) {
  1019.       switch (augmdmtyp) {
  1020.     default:
  1021.         for (n=0; n < LBUFL-1; n++) { /* accumulate response */
  1022.         lbuf[n] = (ttinc(0) & 0177);
  1023.         if ( lbuf[n] == CR || lbuf[n] == LF ) break;
  1024.         }
  1025.         lbuf[n] = '\0';     /* terminate response from modem */
  1026.         debug(F110,"dial modem response",lbuf,0);
  1027.         if (n) {            /* if one or more characters present */
  1028.         switch (augmdmtyp) {
  1029.           case n_ATTMODEM:
  1030.               if (didWeGet(lbuf,"Answered")) status = CONNECTED;
  1031.               if (didWeGet(lbuf,"Connected")) status = CONNECTED;
  1032.               if (didWeGet(lbuf,"Not connected")) status = FAILED;
  1033.               if (didWeGet(lbuf,"Not Connected")) status = FAILED;
  1034.               if (didWeGet(lbuf,"Busy")) status = FAILED;
  1035.               if (didWeGet(lbuf,"No dial tone")) status = FAILED;
  1036.               if (didWeGet(lbuf,"No Dial Tone")) status = FAILED;
  1037.               if (didWeGet(lbuf,"No answer")) status = FAILED;
  1038.               if (didWeGet(lbuf,"No Answer")) status = FAILED;
  1039.               break;
  1040.           case n_ATTDTDM:
  1041.               if (didWeGet(lbuf,"DENIED")) status = FAILED;
  1042.               if (didWeGet(lbuf,"CHECK OPTIONS")) status = FAILED;
  1043.               if (didWeGet(lbuf,"DISCONNECTED")) status = FAILED;
  1044.               if (didWeGet(lbuf,"ANSWERED")) status = CONNECTED;
  1045.               if (didWeGet(lbuf,"BUSY")) status = FAILED;
  1046. #ifdef ATT6300
  1047.               if (debug) {
  1048.             if (didWeGet(lbuf,"\177\177")) status = CONNECTED;
  1049.                       }
  1050. #endif
  1051.               break;
  1052.           case n_CERMETEK:
  1053.             if (didWeGet(lbuf,"\016A")) {
  1054.             status = CONNECTED;
  1055.             ttolSlow("\016U 1\r",200);  /* make transparent*/
  1056.             }
  1057.             break;
  1058.           case n_DF100:      /* DF100 won't generate some of these */
  1059.           case n_DF200:
  1060.             if (didWeGet(lbuf,"Attached")) status = CONNECTED;
  1061.             /*
  1062.              * The DF100 will respond with "Attached" even if DTR
  1063.              * and/or carrier are not present.  Another reason to
  1064.              * (also) wait for carrier?
  1065.              */
  1066.             if (didWeGet(lbuf,"Busy")) status = FAILED;
  1067.             if (didWeGet(lbuf,"Disconnected")) status = FAILED;
  1068.             if (didWeGet(lbuf,"Error")) status = FAILED;
  1069.             if (didWeGet(lbuf,"No answer")) status = FAILED;
  1070.             if (didWeGet(lbuf,"No dial tone")) status = FAILED;
  1071.             if (didWeGet(lbuf,"Speed:")) status = FAILED;
  1072.             /*
  1073.              * It appears that the "Speed:..." response comes after an
  1074.              * "Attached" response, so this is never seen.  HOWEVER,
  1075.              * it would be very handy to detect this and temporarily
  1076.              * reset the speed, since it's a nuisance otherwise.
  1077.              * If we wait for some more input from the modem, how do
  1078.              * we know if it's from the remote host or the modem?
  1079.              * Carrier reportedly doesn't get set until after the
  1080.              * "Speed:..." response (if any) is sent.  Another reason
  1081.              * to (also) wait for carrier.
  1082.              */
  1083.             break;
  1084.           case n_GDC:
  1085.             if (didWeGet(lbuf,"ON LINE")) status = CONNECTED;
  1086.             if (didWeGet(lbuf,"NO CONNECT")) status = FAILED;
  1087.             break;
  1088.           case n_HAYES:
  1089.           case n_USROBOT:
  1090.             if (didWeGet(lbuf,"CONNECT 1200")) {
  1091.             if (speed != 1200) {
  1092.                 if (ttpkt(1200,DIALING) < 0) {
  1093.                 printf("Can't change speed to 1200\r\n");
  1094.                 } else {
  1095.                 speed = 1200;
  1096.                 status = CONNECTED;
  1097.                 if ( !quiet )
  1098.                   printf("Speed changed to 1200\r\n");
  1099.                 }
  1100.             } /* Expand this to include more speeds */
  1101.             }
  1102.             if (didWeGet(lbuf,"CONNECT")) status = CONNECTED;
  1103.             if (didWeGet(lbuf,"NO CARRIER")) status = FAILED;
  1104.             if (didWeGet(lbuf,"NO DIALTONE")) status = FAILED;
  1105.             if (didWeGet(lbuf,"BUSY")) status = FAILED;
  1106.             if (didWeGet(lbuf,"NO ANSWER")) status = FAILED;
  1107.             if (didWeGet(lbuf,"RING")) status = FAILED;
  1108.             if (didWeGet(lbuf,"ERROR")) status = FAILED;
  1109.             break;
  1110.           case n_PENRIL:
  1111.             if (didWeGet(lbuf,"OK")) status = CONNECTED;
  1112.             if (didWeGet(lbuf,"BUSY")) status = FAILED;
  1113.             if (didWeGet(lbuf,"NO RING")) status = FAILED;
  1114.             break;
  1115.           case n_RACAL:
  1116.             if (didWeGet(lbuf,"ON LINE")) status = CONNECTED;
  1117.             if (didWeGet(lbuf,"FAILED CALL")) status = FAILED;
  1118.             break;
  1119.           case n_ROLM:
  1120.             if (didWeGet(lbuf,"CALLING")) status = 0;
  1121.             if (didWeGet(lbuf,"COMPLETE")) status = CONNECTED;
  1122.             if (didWeGet(lbuf,"FAILED")) status = FAILED;
  1123.             if (didWeGet(lbuf,"NOT AVAILABLE")) status = FAILED;
  1124.             if (didWeGet(lbuf,"LACKS PERMISSION")) status = FAILED;
  1125.             if (didWeGet(lbuf,"NOT A DATALINE")) status = FAILED;
  1126.             /*
  1127.                       Early versions of the Rolm 9751
  1128.               CBX software do not give a CALL COMPLETE indication
  1129.               when dialing an outpool number, but it does seem to
  1130.               return a long string of DELs at that point.
  1131.               (this doesn't really work...)
  1132.             if (didWeGet(lbuf,"\177\177\177")) status = CONNECTED;
  1133.             */
  1134.             break;
  1135.           case n_VENTEL:
  1136.             if (didWeGet(lbuf,"ONLINE!")) status = CONNECTED;
  1137.             if (didWeGet(lbuf,"BUSY")) status = FAILED;
  1138.             if (didWeGet(lbuf,"DEAD PHONE")) status = FAILED;
  1139.             break;
  1140.           case n_CONCORD:
  1141.             if (didWeGet(lbuf,"INITIATING")) status = CONNECTED;
  1142.             if (didWeGet(lbuf,"BUSY")) status = FAILED;
  1143.             if (didWeGet(lbuf,"CALL FAILED")) status = FAILED;
  1144.             break;
  1145.           case n_MICROCOM:
  1146.             /* "RINGBACK" means phone line ringing, continue */
  1147.             if (didWeGet(lbuf,"NO CONNECT")) status = FAILED;
  1148.                     /* trailing speed ignored */
  1149.             if (didWeGet(lbuf,"CONNECT")) status = CONNECTED;
  1150.             if (didWeGet(lbuf,"BUSY")) status = FAILED;
  1151.             if (didWeGet(lbuf,"NO DIALTONE")) status = FAILED;
  1152.             if (didWeGet(lbuf,"COMMAND ERROR")) status = FAILED;
  1153.             if (didWeGet(lbuf,"IN USE")) status = FAILED;
  1154.             break;
  1155.         }
  1156.         }
  1157.         break;
  1158.  
  1159.     case n_DF03:            /* because response lacks CR or NL */
  1160.         c = ttinc(0) & 0177;
  1161.         if ( c == 'A' ) status = CONNECTED;
  1162.         if ( c == 'B' ) status = FAILED;
  1163.         break;
  1164.  
  1165.     case n_HAYESNV:
  1166.         c = ttinc(0) & 0177;
  1167.         if (mdmEcho) {      /* sponge up dialing string */
  1168.         mdmEcho = c!='\r';  /* until return is echoed */
  1169.         break;
  1170.         }
  1171.         if (c == '1') status = CONNECTED;
  1172.         if (c == '3') status = FAILED;
  1173.         if (c == '5') status = CONNECTED;
  1174.         break;
  1175.  
  1176.     case n_UNKNOWN:
  1177.         /** SHOULD WAIT FOR CARRIER OR TIMEOUT -- DS **/
  1178.         break;
  1179.     }               /* switch (augmdmtyp) */
  1180.     }                   /* while status == 0 */
  1181.     alarm(0);               /* turn off alarm on connecting */
  1182.     if ( status != CONNECTED )      /* modem-detected failure */
  1183.     longjmp( sjbuf, F_modem );  /* exit (with reason in lbuf) */
  1184.     msleep(500);            /* allow some time...  */
  1185.     alarm(3);               /* precaution in case of trouble */
  1186.     debug(F110,"dial","succeeded",0);
  1187.     if (augmdmtyp != n_ROLM)        /* Rolm has wierd modem signaling */
  1188.       ttpkt(speed,CONNECT,parity);  /* cancel dialing state ioctl */
  1189.     reset ();               /* reset alarms, etc. */
  1190.     if ( ! quiet )
  1191.     printf ( "Call completed.\07\n" );
  1192.     return (1);             /* return, and presumably connect */
  1193. }
  1194.