home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc190.zip / ckudia.c < prev    next >
C/C++ Source or Header  |  1994-12-16  |  108KB  |  3,395 lines

  1. #include "ckcsym.h"
  2. #ifndef NOLOCAL
  3. #ifndef NODIAL
  4. char *dialv = "Dial Command, 5A(063) 4 Oct 94";
  5.  
  6. /*  C K U D I A     --  Module for automatic modem dialing. */
  7.  
  8. /*
  9.   Copyright (C) 1985, 1994, Trustees of Columbia University in the City of New
  10.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  11.   sold for profit as a software product itself, nor may it be included in or
  12.   distributed with commercial products or otherwise distributed by commercial
  13.   concerns to their clients or customers without written permission of the
  14.   Office of Kermit Development and Distribution, Columbia University.  This
  15.   copyright notice must not be removed, altered, or obscured.
  16.  
  17.   Original (version 1, 1985) author: Herm Fischer, Encino, CA.
  18.   Contributed to Columbia University in 1985 for inclusion in C-Kermit 4.0.
  19.   Author and maintainer since 1985: Frank da Cruz, Columbia University,
  20.   fdc@columbia.edu.
  21.  
  22.   Contributions by many others throughout the years, including: Mark Berryman,
  23.   Fernando Cabral, John Chmielewski, Joe Doupnik, Richard Hill, Larry Jacobs,
  24.   Eric Jones, Tom Kloos, Bob Larson, Peter Mauzey, Joe Orost, Kevin O'Gorman,
  25.   Kai Uwe Rommel, Dan Schullman, Warren Tucker, and others too numerous to
  26.   list here (but see acknowledgements in ckcmai.c).
  27.  
  28.   This module calls externally defined system-dependent functions for
  29.   communications i/o, as defined in CKCPLM.DOC, the C-Kermit Program Logic
  30.   Manual, and thus should be portable to all systems that implement those
  31.   functions, and where alarm() and signal() work as they do in UNIX. */
  32.  
  33. /*
  34.   To add support for another modem, do the following, all in this module:
  35.  
  36.   1. Define a modem-type number symbol (n_XXX) for it.
  37.  
  38.   2. Adjust MAX_MDM to the new number of modem types.
  39.  
  40.   3. Create a MDMINF structure for it.
  41.  
  42.   4. Add the address of the MDMINF structure to the ptrtab[] array,
  43.      according to the numerical value of the modem-type number.
  44.  
  45.   5. Add the user-visible (SET MODEM) name and corresponding modem
  46.      number to the mdmtab[] array, in alphabetical order by modem-name string.
  47.  
  48.   6. Read through the code and add modem-specific sections as necessary.
  49.  
  50.   NOTE: The MINIDIAL symbol is used to build this module to include support
  51.   for only a minimum number of standard and/or generally useful modem types,
  52.   namely Hayes, CCITT V.25bis, "Unknown", and None.  When adding support for
  53.   a new modem type, keep it outside of the MINIDIAL sections.
  54. */
  55.  
  56. #include "ckcdeb.h"
  57. #ifndef MAC
  58. #include <signal.h>
  59. #endif /* MAC */
  60. #include "ckcasc.h"
  61. #include "ckcker.h"
  62. #include "ckucmd.h"
  63. #include "ckcnet.h"
  64.  
  65. #ifndef ZILOG
  66. #include <setjmp.h>            /* Longjumps */
  67. #else
  68. #include <setret.h>
  69. #endif /* ZILOG */
  70.  
  71. #ifdef MAC
  72. #define signal msignal
  73. #define SIGTYP long
  74. #define alarm malarm
  75. #define SIG_IGN 0
  76. #define SIGALRM 1
  77. #define SIGINT 2
  78. SIGTYP (*msignal(int type, SIGTYP (*func)(int)))(int);
  79. #endif /* MAC */
  80.  
  81. #ifdef AMIGA
  82. #define signal asignal
  83. #define alarm aalarm
  84. #define SIGALRM (_NUMSIG+1)
  85. #define SIGTYP void
  86. SIGTYP (*asignal(int type, SIGTYP (*func)(int)))(int);
  87. unsigned aalarm(unsigned);
  88. #endif /* AMIGA */
  89.  
  90. #ifdef STRATUS
  91. /* VOS doesn't have alarm(), but it does have some things we can work with. */
  92. /* However, we have to catch all the signals in one place to do this, so    */
  93. /* we intercept the signal() routine and call it from our own replacement.  */
  94. #define signal vsignal
  95. #define alarm valarm
  96. SIGTYP (*vsignal(int type, SIGTYP (*func)(int)))(int);
  97. int valarm(int interval);
  98. #ifdef putchar
  99. #undef putchar
  100. #endif /* putchar */
  101. #define putchar(x) conoc(x)
  102. #ifdef getchar
  103. #undef getchar
  104. #endif /* getchar */
  105. #define getchar(x) coninc(0)
  106. #endif /* STRATUS */
  107.  
  108. int                    /* SET DIAL parameters */
  109.   dialhng = 1,                /* DIAL HANGUP, default is ON */
  110.   dialdpy = 0,                /* DIAL DISPLAY, default is OFF */
  111.   mdmspd  = 1,                /* DIAL SPEED-MATCHING (1 = ON) */
  112.   dialtmo = 0,                /* DIAL TIMEOUT */
  113.   dialksp = 0,                /* DIAL KERMIT-SPOOF, 0 = OFF */
  114.   dialmnp = 0,                /* DIAL MNP-ENABLE, 0 = OFF */
  115. #ifdef NOMDMHUP
  116.   dialmhu = 0;                /* DIAL MODEM-HANGUP, 0 = OFF */
  117. #else
  118.   dialmhu = 1;                /* DIAL MODEM-HANGUP */
  119. #endif /* NOMDMHUP */
  120.  
  121. int dialsta = DIA_UNK;            /* Detailed return code (ckuusr.h) */
  122.  
  123. char *dialdir = NULL;            /* DIAL DIRECTORY, default none */
  124. char *dialini = NULL;            /* DIAL INIT-STRING, default none */
  125. char *dialcmd = NULL;            /* DIAL DIAL-COMMAND, default none */
  126. char *dialnpr = NULL;            /* DIAL NUMBER-PREFIX, ditto */
  127. /* char *hupcmd  = NULL; */        /* Modem hangup command */
  128. FILE * dialfd = NULL;            /* File descriptor of dial directory */
  129.  
  130. #ifndef MINIDIAL
  131. /*
  132.   Telebit model codes:
  133.  
  134.   ATI  Model Numbers           Examples
  135.   ---  -------------           --------
  136.   123                          Telebit in "total Hayes-1200" emulation mode
  137.   960                          Telebit in Conventional Command (Hayes) mode
  138.   961  RA12C                   IBM PC internal original Trailblazer
  139.   962  RA12E                   External original Trailblazer
  140.   963  RM12C                   Rackmount original Trailblazer
  141.   964  T18PC                   IBM PC internal Trailblazer-Plus (TB+)
  142.   965  T18SA, T2SAA, T2SAS     External TB+, T1600, T2000, T3000, WB, and later
  143.   966  T18RMM                  Rackmount TB+
  144.   967  T2MC                    IBM PS/2 internal TB+
  145.   968  T1000                   External T1000
  146.   969  ?                       Qblazer
  147.   970                          Qblazer Plus
  148.   971  T2500                   External T2500
  149.   972  T2500                   Rackmount T2500
  150. */
  151.  
  152. /* Telebit model codes */
  153.  
  154. #define TB_UNK  0            /* Unknown Telebit model */
  155. #define TB_BLAZ 1            /* Original TrailBlazer */
  156. #define TB_PLUS    2            /* TrailBlazer Plus */
  157. #define TB_1000 3            /* T1000 */
  158. #define TB_1500 4            /* T1500 */
  159. #define TB_1600 5            /* T1600 */
  160. #define TB_2000 6            /* T2000 */
  161. #define TB_2500 7            /* T2500 */
  162. #define TB_3000 8            /* T3000 */
  163. #define TB_QBLA 9            /* Qblazer */
  164. #define TB_WBLA 10            /* WorldBlazer */
  165. #define TB__MAX 10            /* Highest number */
  166.  
  167. char *tb_name[] = {            /* Array of model names */
  168.     "Unknown",                /* TB_UNK  */
  169.     "TrailBlazer",            /* TB_BLAZ */
  170.     "TrailBlazer-Plus",            /* TB_PLUS */
  171.     "T1000",                /* TB_1000 */
  172.     "T1500",                /* TB_1500 */
  173.     "T1600",                /* TB_1600 */
  174.     "T2000",                /* TB_2000 */
  175.     "T2500",                /* TB_2500 */
  176.     "T3000",                /* TB_3000 */
  177.     "Qblazer",                /* TB_QBLA */
  178.     "WorldBlazer",            /* TB_WBLA */
  179.     ""
  180. };
  181. #endif /* MINIDIAL */
  182.  
  183. extern int flow, local, mdmtyp, quiet, backgrd, parity, seslog, network;
  184. extern int carrier, duplex;
  185. #ifdef NETCONN
  186. extern int ttnproto;
  187. #endif /* NETCONN */
  188. extern CHAR stchr;
  189. extern long speed;
  190. extern char ttname[], sesfil[];
  191.  
  192. /*  Failure codes  */
  193.  
  194. #define F_TIME        1        /* timeout */
  195. #define F_INT        2        /* interrupt */
  196. #define F_MODEM        3        /* modem-detected failure */
  197. #define F_MINIT        4        /* cannot initialize modem */
  198.  
  199. static int fail_code =  0;        /* Default failure reason. */
  200.  
  201. #define DW_NOTHING      0        /* What we are doing */
  202. #define DW_INIT         1
  203. #define DW_DIAL         2
  204.  
  205. static int dial_what = DW_NOTHING;    /* Nothing at first. */
  206.  
  207. static int mymdmtyp;            /* Local copy of modem type. */
  208.  
  209. _PROTOTYP (static int ddinc, (int) );
  210. _PROTOTYP (int dialhup, (void) );
  211. _PROTOTYP (static int getok, (int,int) );
  212. _PROTOTYP (char * getdws, (int) );
  213. _PROTOTYP (char * ck_time, (void) );
  214. _PROTOTYP (static VOID ttslow, (char *, int) );
  215. #ifdef COMMENT
  216. _PROTOTYP (static VOID xcpy, (char *, char *, unsigned int) );
  217. #endif /* COMMENT */
  218. _PROTOTYP (static VOID waitfor, (char *) );
  219. _PROTOTYP (static VOID dialoc, (char) );
  220. _PROTOTYP (static int didweget, (char *, char *) );
  221. _PROTOTYP (static VOID spdchg, (long) );
  222. _PROTOTYP (static VOID tbati3, (int) );
  223. _PROTOTYP (static int dialfail, (int) );
  224.  
  225. #define MDMINF    struct mdminf
  226.  
  227. MDMINF        /* structure for modem-specific information */
  228.     {
  229.     int        dial_time;    /* time modem allows for dialing (secs) */
  230.     char    *pause_chars;    /* character(s) to tell modem to pause */
  231.     int        pause_time;    /* time associated with pause chars (secs) */
  232.     char    *wake_str;    /* string to wakeup modem & put in cmd mode */
  233.     int        wake_rate;    /* delay between wake_str characters (msecs) */
  234.     char    *wake_prompt;    /* string prompt after wake_str */
  235.     char    *dmode_str;    /* string to put modem in dialing mode */
  236.     char    *dmode_prompt;    /* string prompt for dialing mode */
  237.     char    *dial_str;    /* dialing string, with "%s" for number */
  238.     int        dial_rate;    /* delay between dialing characters (msecs) */
  239.     int        esc_time;    /* guard time on escape sequence (msecs) */
  240.     char    *esc_str;    /* escape sequence */
  241.     char    *hup_str;    /* hangup string */
  242.     _PROTOTYP( int (*ok_fn), (int,int) ); /* func to read response string */
  243.     };
  244.  
  245. /*
  246.  * Define symbolic modem numbers.
  247.  *
  248.  * The numbers MUST correspond to the ordering of entries
  249.  * within the ptrtab array, and start at one (1).
  250.  *
  251.  * It is assumed that there are relatively few of these
  252.  * values, and that the high(er) bytes of the value may
  253.  * be used for modem-specific mode information.
  254.  *
  255.  * REMEMBER that only the first eight characters of these
  256.  * names are guaranteed to be unique.
  257.  */
  258.  
  259. #ifdef MINIDIAL                /* Minimum dialer support */
  260.                     /* Only for CCITT, HAYES, and UNK */
  261. #define        n_CCITT         1
  262. #define        n_HAYES         2
  263. #define        n_UNKNOWN     3
  264. #define        MAX_MDM         3    /* Number of modem types */
  265.  
  266. #else                    /* Full-blown dialer support */
  267.  
  268. #define        n_ATTDTDM     1
  269. #define         n_ATTISN         2
  270. #define        n_ATTMODEM     3
  271. #define        n_CCITT         4
  272. #define        n_CERMETEK     5
  273. #define        n_DF03         6
  274. #define        n_DF100         7
  275. #define        n_DF200         8
  276. #define        n_GDC         9
  277. #define        n_HAYES        10
  278. #define        n_PENRIL    11
  279. #define        n_RACAL        12
  280. #define        n_UNKNOWN    13
  281. #define        n_USROBOT    14
  282. #define        n_VENTEL    15
  283. #define        n_CONCORD    16
  284. #define        n_ATTUPC    17    /* aka UNIX PC and ATT7300 */
  285. #define        n_ROLM          18      /* Rolm CBX DCM */
  286. #define        n_MICROCOM    19
  287. #define         n_HST           20
  288. #define         n_TELEBIT       21      /* Telebits of all kinds */
  289. #define         n_DIGITEL       22    /* Digitel DT-22 (CCITT variant) */
  290. #define        MAX_MDM        22    /* Number of modem types */
  291.  
  292. #endif /* MINIDIAL */
  293.  
  294. /*
  295.  * Declare modem "variant" numbers for any of the above for which it is
  296.  * necessary to note various operational modes, using the second byte
  297.  * of a modem number.
  298.  *
  299.  * It is assumed that such modem modes share the same modem-specific
  300.  * information (see MDMINF structure) but may differ in some of the actions
  301.  * that are performed.
  302.  */
  303.  
  304. /*  Warning - this is starting to get kind of hokey... */
  305.  
  306. #define DIAL_NV 256
  307. #define n_HAYESNV ( n_HAYES   | DIAL_NV )
  308.  
  309. #ifndef MINIDIAL
  310. #define DIAL_PEP 512
  311. #define DIAL_V32 1024
  312. #define DIAL_V42 2048
  313. #define DIAL_SLO 4096
  314. #define n_TBPEP   ( n_TELEBIT | DIAL_PEP )
  315. #define n_TB3     ( n_TELEBIT | DIAL_V32 )
  316. #define n_TBNV    ( n_TELEBIT | DIAL_NV )
  317. #define n_TBPNV   ( n_TELEBIT | DIAL_NV | DIAL_PEP )
  318. #define n_TB3NV   ( n_TELEBIT | DIAL_NV | DIAL_V32 )
  319. #define n_TB4     ( n_TELEBIT | DIAL_V42 )
  320. #define n_TBS     ( n_TELEBIT | DIAL_SLO )
  321. #define n_TB4NV   ( n_TELEBIT | DIAL_NV | DIAL_V42 )
  322. #define n_TBSNV   ( n_TELEBIT | DIAL_NV | DIAL_SLO )
  323. #endif /* MINIDIAL */
  324.  
  325. /*
  326.  * Declare structures containing modem-specific information.
  327.  *
  328.  * REMEMBER that only the first SEVEN characters of these
  329.  * names are guaranteed to be unique.
  330.  */
  331.  
  332. #ifndef MINIDIAL
  333. static
  334. MDMINF ATTISN =                /* AT&T ISN Network */
  335.     {
  336.     30,                    /* Dial time */
  337.     "",                    /* Pause characters */
  338.     0,                    /* Pause time */
  339.     "\015\015\015\015",            /* Wake string */
  340.     900,                /* Wake rate */
  341.     "DIAL",                /* Wake prompt */
  342.     "",                    /* dmode_str */
  343.     "",                    /* dmode_prompt */
  344.     "%s\015",                /* dial_str */
  345.     0,                    /* dial_rate */
  346.     0,                    /* esc_time */
  347.     "",                    /* esc_str */
  348.     "",                    /* hup_str */
  349.     NULL                /* ok_fn */
  350.     };
  351.  
  352. static
  353. MDMINF ATTMODEM =    /* information for AT&T switched-network modems */
  354.             /* "Number" following "dial" can include: p's and
  355.              * t's to indicate pulse or tone (default) dialing,
  356.              * + for wait for dial tone, , for pause, r for
  357.              * last number dialed, and, except for 2224B, some
  358.              * comma-delimited options like o12=y, before number.
  359.  
  360.  * "Important" options for the modems:
  361.  *
  362.  *    All:        Except for 2224B, enable option 12 for "transparent
  363.  *            data," o12=y.  If a computer port used for both
  364.  *            incoming and outgoing calls is connected to the
  365.  *            modem, disable "enter interactive mode on carriage
  366.  *            return," EICR.  The Kermit "dial" command can
  367.  *            function with EIA leads standard, EIAS.
  368.  *
  369.  *    2212C:        Internal hardware switches at their default
  370.  *            positions (four rockers down away from numbers)
  371.  *            unless EICR is not wanted (rocker down at the 4).
  372.  *            For EIAS, rocker down at the 1.
  373.  *
  374.  *    2224B:        Front-panel switch position 1 must be up (at the 1,
  375.  *            closed).  Disable EICR with position 2 down.
  376.  *            For EIAS, position 4 down.
  377.  *            All switches on the back panel down.
  378.  *
  379.  *    2224CEO:    All front-panel switches down except either 5 or 6.
  380.  *            Enable interactive flow control with o16=y.
  381.  *            Select normal asynchronous mode with o34=0 (zero).
  382.  *            Disable EICR with position 3 up.  For EIAS, 1 up.
  383.  *            Reset the modem after changing switches.
  384.  *
  385.  *    2296A:        If option 00 (zeros) is present, use o00=0.
  386.  *            Enable interactive flow control with o16=y.
  387.  *            Select normal asynchronous mode with o34=0 (zero).
  388.  *                      (available in Microcom Networking version, but
  389.  *                      not necessarily other models of the 2296A).
  390.  *            Enable modem-port flow control (if available) with
  391.  *             o42=y.  Enable asynchronous operation with o50=y.
  392.  *             Disable EICR with o69=n.  For EIAS, o66=n, using
  393.  *             front panel.
  394.  */
  395.     {
  396.     20,            /* dial_time */
  397.     ",",        /* pause_chars */
  398.     2,            /* pause_time */
  399.     "+",        /* wake_str */
  400.     0,            /* wake_rate */
  401.     "",            /* wake_prompt */
  402.     "",            /* dmode_str */
  403.     "",            /* dmode_prompt */
  404.     "at%s\015",        /* dial_str */
  405.     0,            /* dial_rate */
  406.     0,            /* esc_time */
  407.     "",            /* esc_str */
  408.     "",            /* hup_str */
  409.     NULL            /* ok_fn */
  410.     };
  411.  
  412. static
  413. MDMINF ATTDTDM =    /* information for AT&T Digital Terminal Data Module
  414.  *            For dialing: KYBD switch down, others usually up. */
  415.     {
  416.     20,            /* dial_time */
  417.     "",            /* pause_chars */
  418.     0,            /* pause_time */
  419.     "",            /* wake_str */
  420.     0,            /* wake_rate */
  421.     "",            /* wake_prompt */
  422.     "",            /* dmode_str */
  423.     "",            /* dmode_prompt */
  424.     "%s\015",        /* dial_str */        /* not used */
  425.     0,            /* dial_rate */
  426.     0,            /* esc_time */
  427.     "",            /* esc_str */
  428.     "",            /* hup_str */
  429.     NULL        /* ok_fn */
  430.     };
  431. #endif /* MINIDIAL */
  432.  
  433. static
  434. MDMINF CCITT =                /* CCITT V.25bis autodialer */
  435. /*
  436.   According to V.25bis:
  437.   . Even parity is required for giving commands to the modem.
  438.   . Commands might or might not echo.
  439.   . Responses ("Indications") from the modem are terminated by CR and LF.
  440.   . Call setup is accomplished by:
  441.     - DTE raises DTR (V.24 circuit 108)              [ttopen() does this]
  442.     - Modem raises CTS (V.24 circuit 106)            [C-Kermit ignores this]
  443.     - DTE issues a call request command ("CRN")
  444.     - Modem responds with "VAL" ("command accepted")
  445.     - If the call is completed:
  446.         modem responds with "CNX" ("call connected");
  447.         modem turns CTS (106) OFF;
  448.         modem turns DSR (107) ON;
  449.       else:
  450.         modem responds with "CFI <parameter>" ("call failure indication").
  451.   . To clear a call, the DTE turns DTR (108) OFF.
  452.   . There is no mention of the Carrier Detect circuit (109) in the standard.
  453.   . There is no provision for "escaping back" to the modem's command mode.
  454.  
  455.   It is not known whether there exists in real life a pure V.25bis modem.
  456.   If there is, this code has never been tested on it.  See the Digitel entry.
  457. */
  458.     {
  459.     40,            /* dial_time -- programmable -- */
  460.     ",:",        /* pause_chars -- "," waits for programmable time */
  461.                         /* ":" waits for dial tone */
  462.     10,            /* pause_time (seconds, just a guess) */
  463.     "",            /* wake_str (none) */
  464.     200,        /* wake_rate (msec) */
  465.     "VAL",        /* wake_prompt */
  466.     "",            /* dmode_str (none) */
  467.     "",            /* dmode_prompt (none) */
  468.     "CRN%s\015",        /* dial_str */
  469.     200,        /* dial_rate (msec) */
  470.     0,            /* No esc_time */
  471.     "",            /* No esc_str  */
  472.     "",            /* No hup_str  */
  473.     NULL        /* No ok_fn    */
  474.     };
  475.  
  476. #ifndef MINIDIAL    /* Don't include the following if -DMINIDIAL ... */
  477.  
  478. static
  479. MDMINF CERMETEK =    /* Information for "Cermetek Info-Mate 212 A" modem */
  480.     {
  481.     20,            /* dial_time */
  482.     "BbPpTt",        /* pause_chars */
  483.     0,            /* pause_time */    /** unknown -- DS **/
  484.     "  XY\016R\015",    /* wake_str */
  485.     200,        /* wake_rate */
  486.     "",            /* wake_prompt */
  487.     "",            /* dmode_str */
  488.     NULL,        /* dmode_prompt */
  489.     "\016D '%s'\015",    /* dial_str */
  490.     200,        /* dial_rate */
  491.     0,            /* esc_time */
  492.     "",            /* esc_str */
  493.     "",            /* hup_str */
  494.     NULL        /* ok_fn */
  495.     };
  496.  
  497. static
  498. MDMINF DF03 =        /* information for "DEC DF03-AC" modem */
  499.     {
  500.     27,            /* dial_time */
  501.     "=",        /* pause_chars */    /* wait for second dial tone */
  502.     15,            /* pause_time */
  503.     "\001\002",        /* wake_str */
  504.     0,            /* wake_rate */
  505.     "",            /* wake_prompt */
  506.     "",            /* dmode_str */
  507.     NULL,        /* dmode_prompt */
  508.     "%s",        /* dial_str */
  509.     0,            /* dial_rate */
  510.     0,            /* esc_time */
  511.     "",            /* esc_str */
  512.     "",            /* hup_str */
  513.     NULL        /* ok_fn */
  514.     };
  515.  
  516. static
  517. MDMINF DF100 =        /* information for "DEC DF100-series" modem */
  518.             /*
  519.              * The telephone "number" can include "P"s and/or "T"s
  520.              * within it to indicate that subsequent digits are
  521.              * to be dialed using pulse or tone dialing.  The
  522.              * modem defaults to pulse dialing.  You may modify
  523.              * the dial string below to explicitly default all
  524.              * dialing to pulse or tone, but doing so prevents
  525.              * the use of phone numbers that you may have stored
  526.              * in the modem's memory.
  527.              */
  528.     {
  529.     30,            /* dial_time */
  530.     "=",        /* pause_chars */    /* wait for second dial tone */
  531.     15,            /* pause_time */
  532.     "\001",        /* wake_str */
  533.     0,            /* wake_rate */
  534.     "",            /* wake_prompt */
  535.     "",            /* dmode_str */
  536.     NULL,        /* dmode_prompt */
  537.     "%s#",        /* dial_str */
  538.     0,            /* dial_rate */
  539.     0,            /* esc_time */
  540.     "",            /* esc_str */
  541.     "",            /* hup_str */
  542.     NULL        /* ok_fn */
  543.     };
  544.  
  545. static
  546. MDMINF DF200 =        /* information for "DEC DF200-series" modem */
  547.             /*
  548.              * The telephone "number" can include "P"s and/or "T"s
  549.              * within it to indicate that subsequent digits are
  550.              * to be dialed using pulse or tone dialing.  The
  551.              * modem defaults to pulse dialing.  You may modify
  552.              * the dial string below to explicitly default all
  553.              * dialing to pulse or tone, but doing so prevents
  554.              * the use of phone numbers that you may have stored
  555.              * in the modem's memory.
  556.              */
  557.     {
  558.     30,            /* dial_time */
  559.     "=W",        /* pause_chars */    /* =: second tone; W: 5 secs */
  560.     15,            /* pause_time */    /* worst case */
  561.     "\002",        /* wake_str */        /* allow stored number usage */
  562.     0,            /* wake_rate */
  563.     "",            /* wake_prompt */
  564.     "",            /* dmode_str */
  565.     NULL,        /* dmode_prompt */
  566. #ifdef COMMENT
  567.     "%s!",        /* dial_str */
  568. #else
  569.     "   d %s\015",
  570. #endif /* COMMENT */
  571.     0,            /* dial_rate */
  572.     0,            /* esc_time */
  573.     "",            /* esc_str */
  574.     "",            /* hup_str */
  575.     NULL        /* ok_fn */
  576.     };
  577.  
  578. static
  579. MDMINF DIGITEL =        /* Digitel DT-22 CCITT variant used in Brazil */
  580. /*
  581.   Attempts to adhere strictly to the V.25bis specification do not produce good
  582.   results in real life.  The modem for which this code was developed: (a)
  583.   ignores parity; (b) sometimes terminates responses with LF CR instead of CR
  584.   LF; (c) has a Hayes-like escape sequence; (d) supports a hangup ("HUP")
  585.   command.  Information from Fernando Cabral in Brasilia.
  586. */
  587.     {
  588.     40,            /* dial_time -- programmable -- */
  589.     ",:",        /* pause_chars -- "," waits for programmable time */
  590.                         /* ":" waits for dial tone */
  591.     10,            /* pause_time (seconds, just a guess) */
  592.     "HUP\015",          /* wake_str (Not Standard CCITT) */
  593.     200,        /* wake_rate (msec) */
  594.     "VAL",        /* wake_prompt */
  595.     "",            /* dmode_str (none) */
  596.     "",            /* dmode_prompt (none) */
  597.     "CRN%s\015",        /* dial_str */
  598.     200,        /* dial_rate (msec) */
  599.     1100,        /* esc_time (Not Standard CCITT) */
  600.     "+++",        /* esc_str  (Not Standard CCITT) */
  601.     "HUP\015",        /* hup_str  (Not Standard CCITT) */
  602.     getok        /* ok_fn */
  603.     };
  604.  
  605. static
  606. MDMINF GDC =        /* information for "GeneralDataComm 212A/ED" modem */
  607.     {
  608.     32,            /* dial_time */
  609.     "%",        /* pause_chars */
  610.     3,            /* pause_time */
  611.     "\015\015",        /* wake_str */
  612.     500,        /* wake_rate */
  613.     "$",        /* wake_prompt */
  614.     "D\015",        /* dmode_str */
  615.     ":",        /* dmode_prompt */
  616.     "T%s\015",        /* dial_str */
  617.     0,            /* dial_rate */
  618.     0,            /* esc_time */
  619.     "",            /* esc_str */
  620.     "",            /* hup_str */
  621.     NULL        /* ok_fn */
  622.     };
  623. #endif /* MINIDIAL */
  624.  
  625. static
  626. MDMINF HAYES =        /* Information for Hayes and Hayes-like modems */
  627.     {
  628.     35,            /* dial_time */
  629.     ",",        /* pause_chars */
  630.     2,            /* pause_time */
  631.     "ATQ0S2=43\015",    /* wake_str */
  632. /*
  633.   Note: Other wake_str's are possible here.  For a Hayes 2400 that is to
  634.   be used for both in and out calls, AT&F&D3 might be best.  For out calls
  635.   only, maybe AT&F&D2.  See Hayes 2400 manual.
  636. */
  637.     0,            /* wake_rate */
  638.     "",            /* wake_prompt */
  639.     "",            /* dmode_str */
  640.     "",            /* dmode_prompt */
  641.     "ATD%s\015",    /* dial_str, note: user can supply D or T */
  642.     0,            /* dial_rate */
  643.     1100,        /* esc_time */
  644.     "+++",        /* esc_str */
  645.     "ATQ0H0\015",    /* hup_str */
  646.     getok        /* ok_fn */
  647.     };
  648.  
  649. #ifndef MINIDIAL
  650.  
  651. static
  652. MDMINF PENRIL =        /* information for "Penril" modem */
  653.     {
  654.     50,            /* dial_time */
  655.     "",            /* pause_chars */    /** unknown -- HF **/
  656.     0,            /* pause_time */
  657.     "\015\015",        /* wake_str */
  658.     300,        /* wake_rate */
  659.     ">",        /* wake_prompt */
  660.     "k\015",        /* dmode_str */
  661.     ":",        /* dmode_prompt */
  662.     "%s\015",        /* dial_str */
  663.     0,            /* dial_rate */
  664.     0,            /* esc_time */
  665.     "",            /* esc_str */
  666.     "",            /* hup_str */
  667.     NULL        /* ok_fn */
  668.     };
  669.  
  670. static
  671. MDMINF RACAL =        /* information for "Racal Vadic" modem, e.g. VA4492E */
  672.     {
  673.     35,            /* dial_time (manual says modem is hardwired to 60) */
  674.     "Kk",        /* pause_chars */
  675.     5,            /* pause_time */
  676.     "\005\015",        /* wake_str, ^E^M */
  677.     50,            /* wake_rate */
  678.     "*",        /* wake_prompt */
  679.     "D\015",        /* dmode_str */
  680.     "?",        /* dmode_prompt */
  681.     "%s\015",        /* dial_str */
  682.     0,            /* dial_rate */
  683.     1100,        /* esc_time */
  684.     "\003\004",        /* esc_str, ^C^D (this actually hangs up) */
  685.     "\005",        /* hup_str, ^E (this goes back to command mode) */
  686.     NULL        /* ok_fn */
  687.     };
  688. #endif /* MINIDIAL */
  689.  
  690. /*
  691.   The intent of the "unknown" modem is to allow KERMIT to support
  692.   unknown modems by having the user type the entire autodial sequence
  693.   (possibly including control characters, etc.) as the "phone number".
  694.   The protocol and other characteristics of this modem are unknown, with
  695.   some "reasonable" values being chosen for some of them.  The only way to
  696.   detect if a connection is made is to look for carrier.
  697. */
  698. static
  699. MDMINF UNKNOWN =    /* information for "Unknown" modem */
  700.     {
  701.     30,            /* dial_time */
  702.     "",            /* pause_chars */
  703.     0,            /* pause_time */
  704.     "",            /* wake_str */
  705.     0,            /* wake_rate */
  706.     "",            /* wake_prompt */
  707.     "",            /* dmode_str */
  708.     NULL,        /* dmode_prompt */
  709.     "%s\015",        /* dial_str */
  710.     0,            /* dial_rate */
  711.     0,            /* esc_time */
  712.     "",            /* esc_str */
  713.     "",            /* hup_str */
  714.     NULL        /* ok_fn */
  715.     };
  716.  
  717. #ifndef MINIDIAL
  718.  
  719. static
  720. MDMINF USROBOT =    /* information for "US Robotics 212A" modem */
  721.     {
  722.     30,            /* dial_time */
  723.     ",",        /* pause_chars */
  724.     2,            /* pause_time */
  725.     "ATQ0S2=43\015",    /* wake_str */
  726.     0,            /* wake_rate */
  727.     "OK\015",        /* wake_prompt */
  728.     "",            /* dmode_str */
  729.     NULL,        /* dmode_prompt */
  730.     "ATD%s\015",    /* dial_str */
  731.     0,            /* dial_rate */
  732.     1100,        /* esc_time */
  733.     "+++",        /* esc_str */
  734.     "ATQ0H0\015",    /* hup_str */
  735.     getok        /* ok_fn */
  736.     };
  737.  
  738. #ifdef COMMENT
  739. /* Reportedly this does not work at all. */
  740. static
  741. MDMINF VENTEL =        /* information for "Ventel" modem */
  742.     {
  743.     20,            /* dial_time */
  744.     "%",        /* pause_chars */
  745.     5,            /* pause_time */
  746.     "\015\015\015",    /* wake_str */
  747.     300,        /* wake_rate */
  748.     "$",        /* wake_prompt */
  749.     "",            /* dmode_str */
  750.     NULL,        /* dmode_prompt */
  751.     "<K\015%s\015>",    /* dial_str (was "<K%s\r>") */
  752.     0,            /* dial_rate */
  753.     0,            /* esc_time */
  754.     "",            /* esc_str */
  755.     "",            /* hup_str */
  756.     NULL        /* ok_fn */
  757.     };
  758. #else
  759. /* and this does. */
  760. static
  761. MDMINF VENTEL =        /* information for "Ventel" modem */
  762.     {
  763.     20,            /* dial_time */
  764.     "%",        /* pause_chars */
  765.     5,            /* pause_time */
  766.     "\015\015\015",    /* wake_str */
  767.     300,        /* wake_rate */
  768.     "$",        /* wake_prompt */
  769.     "K\015",        /* dmode_str (was "") */
  770.     "Number to call: ",    /* dmode_prompt (was NULL) */
  771.     "%s\015",            /* dial_str (was "<K%s\r>") */
  772.     0,            /* dial_rate */
  773.     0,            /* esc_time */
  774.     "",            /* esc_str */
  775.     "",            /* hup_str */
  776.     NULL        /* ok_fn */
  777.     };
  778. #endif /* COMMENT */
  779.  
  780. static
  781. MDMINF CONCORD =    /* Info for Condor CDS 220 2400b modem */
  782.     {
  783.     35,            /* dial_time */
  784.     ",",        /* pause_chars */
  785.     2,            /* pause_time */
  786.     "\015\015",        /* wake_str */
  787.     20,            /* wake_rate */
  788.     "CDS >",        /* wake_prompt */
  789.     "",            /* dmode_str */
  790.     NULL,        /* dmode_prompt */
  791.     "<D M%s\015>",    /* dial_str */
  792.     0,            /* dial_rate */
  793.     0,            /* esc_time */
  794.     "",            /* esc_str */
  795.     "",            /* hup_str */
  796.     NULL        /* ok_fn */
  797.     };
  798.  
  799. static
  800. MDMINF ATTUPC = /* dummy information for "ATT7300/Unix PC" internal modem */
  801.     {
  802.     30,            /* dial_time */
  803.     "",            /* pause_chars */
  804.     0,            /* pause_time */
  805.     "",            /* wake_str */
  806.     0,            /* wake_rate */
  807.     "",            /* wake_prompt */
  808.     "",            /* dmode_str */
  809.     NULL,        /* dmode_prompt */
  810.     "%s\015",        /* dial_str */
  811.     0,            /* dial_rate */
  812.     0,            /* esc_time */
  813.     "",            /* esc_str */
  814.     "",            /* hup_str */
  815.     NULL        /* ok_fn */
  816.     };
  817.  
  818. static
  819. MDMINF ROLM =        /* IBM / Siemens / Rolm 8000, 9000, 9751 CBX */
  820.     {
  821.     60,            /* dial_time */
  822.     "",            /* pause_chars */
  823.     0,            /* pause_time */
  824.     "\015\015",        /* wake_str */
  825.     5,            /* wake_rate */
  826.     "MODIFY?",            /* wake_prompt */
  827.     "",            /* dmode_str */
  828.     "",            /* dmode_prompt */
  829.     "CALL %s\015",    /* dial_str */
  830.     0,            /* dial_rate */
  831.     0,            /* esc_time */
  832.     "",            /* esc_str */
  833.     "",            /* hup_str */
  834.     NULL        /* ok_fn */
  835.     };
  836.  
  837. static
  838. MDMINF MICROCOM =    /* information for "Microcom" modems in native mode */
  839.             /* (long answer only) */
  840.     {
  841.     35,            /* dial_time */
  842.     ",!@",        /* pause_chars (! and @ aren't pure pauses) */
  843.     3,            /* pause_time */
  844.     "\015",        /* wake_str */
  845.     100,        /* wake_rate */
  846.     "!",        /* wake_prompt */
  847.     "",            /* dmode_str */
  848.     NULL,        /* dmode_prompt */
  849.     "d%s\015",        /* dial_str */
  850.     0,            /* dial_rate */
  851.     0,            /* esc_time */
  852.     "",            /* esc_str */
  853.     "",            /* hup_str */
  854.     NULL        /* ok_fn */
  855.     };
  856.  
  857. static
  858. MDMINF HST =        /* information for USR Courier and Sportster modems */
  859.     {
  860.     35,            /* dial_time */
  861.     ",",        /* pause_chars */
  862.     2,            /* pause_time */
  863.     "ATQ0S2=43X4&M4\015", /* wake_str (X7 not supported on Sportster) */
  864.     0,                /* wake_rate */
  865.     "OK\015",        /* wake_prompt */
  866.     "",                /* dmode_str */
  867.     "",                /* dmode_prompt */
  868.     "ATD%s\015",    /* dial_str */
  869.     0,            /* dial_rate */
  870.     1100,        /* esc_time */
  871.     "+++",        /* esc_str */
  872.     "ATQ0H0\015",    /* hup_str */
  873.     getok        /* ok_fn */
  874.     };
  875.  
  876. static
  877. MDMINF TELEBIT =    /* information for Telebits */
  878.     {
  879.     60,            /* dial_time */
  880.     ",",        /* pause_chars */
  881.     2,            /* pause_time */
  882. /*
  883.   NOTE: The wake_string MUST contain the I command (model query), and otherwise
  884.   must contain commands that work on ALL Telebit models.  Here we ensure that
  885.   result codes are returned (Q0), and ask for extended result codes (X1), and
  886.   ensure that the escape sequence is +++ and it is enabled.  And also, make
  887.   sure the final character is not a digit (whose echo might be mistaken for a
  888.   result code).  The Ctrl-Q and multiple A's are recommended by Telebit.
  889. */
  890.     "\021AAAAATQ0X1S12=50 S2=43 I\015", /* wake_str. */
  891.     100,        /* wake_rate = 100 msec */
  892.     "OK\015",        /* wake_prompt */
  893.     "",                /* dmode_str */
  894.     "",                /* dmode_prompt */
  895.     "ATD%s\015",    /* dial_str, Note: no T or P */
  896.     80,            /* dial_rate */
  897.     1100,        /* esc_time (guard time) */
  898.     "+++",        /* esc_str */
  899.     "ATQ0H0\015",    /* hup_str */
  900.     getok        /* ok_fn */
  901.     };
  902. #endif /* MINIDIAL */
  903.  
  904.  
  905. /*
  906.  * Declare table for converting modem numbers to information pointers.
  907.  *
  908.  * The entries MUST be in ascending order by modem number, without any
  909.  * "gaps" in the numbers, and starting from one (1).
  910.  *
  911.  * This table should NOT include entries for the "variant" modem numbers,
  912.  * since they share the same information as the normal value.
  913.  */
  914. static
  915. MDMINF *ptrtab[] = {
  916. #ifdef MINIDIAL
  917.     &CCITT,
  918.     &HAYES,
  919.     &UNKNOWN
  920. #else
  921.     &ATTDTDM,
  922.     &ATTISN,
  923.     &ATTMODEM,
  924.     &CCITT,
  925.     &CERMETEK,
  926.     &DF03,
  927.     &DF100,
  928.     &DF200,
  929.     &GDC,
  930.     &HAYES,
  931.     &PENRIL,
  932.     &RACAL,
  933.     &UNKNOWN,
  934.     &USROBOT,
  935.     &VENTEL,
  936.     &CONCORD,
  937.     &ATTUPC,
  938.     &ROLM,
  939.     &MICROCOM,
  940.     &HST,
  941.     &TELEBIT,
  942.     &DIGITEL
  943. #endif /* MINIDIAL */
  944. };
  945. /*
  946.  * Declare modem names and associated numbers for command parsing,
  947.  * and also for doing number-to-name translation.
  948.  *
  949.  * The entries must be in alphabetical order by modem name.
  950.  */
  951. struct keytab mdmtab[] = {
  952. #ifndef MINIDIAL
  953.     "attdtdm",        n_ATTDTDM,    0,
  954.     "attisn",           n_ATTISN,       0,
  955.     "attmodem",        n_ATTMODEM,    0,
  956.     "att7300",        n_ATTUPC,    0,
  957. #endif /* MINIDIAL */
  958.     "ccitt-v25bis",    n_CCITT,    0,
  959. #ifndef MINIDIAL
  960.     "cermetek",        n_CERMETEK,    0,
  961.     "concord",        n_CONCORD,    0,
  962.     "courier",          n_HST,          0,
  963.     "df03-ac",        n_DF03,        0,
  964.     "df100-series",    n_DF100,    0,
  965.     "df200-series",    n_DF200,    0,
  966.     "digitel-dt22",    n_DIGITEL,    0,
  967. #endif /* MINIDIAL */
  968.     "direct",        0,        CM_INV,    /* Synonym for NONE */
  969. #ifndef MINIDIAL
  970.     "gdc-212a/ed",    n_GDC,        0,
  971.     "gendatacomm",    n_GDC,        CM_INV,    /* Synonym for GDC */
  972. #endif /* MINIDIAL */
  973.     "hayes",        n_HAYES,    0,
  974. #ifndef MINIDIAL
  975.     "hst-courier",      n_HST,          CM_INV,    /* Synonym for COURIER */
  976.     "microcom",        n_MICROCOM,    0,
  977. #endif /* MINIDIAL */
  978.     "none",             0,              0,
  979. #ifndef MINIDIAL
  980.     "penril",        n_PENRIL,    0,
  981.     "pep-telebit",      n_TBPEP,        0,
  982.     "racalvadic",    n_RACAL,    0,
  983.     "rolm",        n_ROLM,        0,
  984.     "slow-telebit",     n_TBS,        0,
  985.     "sportster",        n_HST,          0,
  986.     "telebit",          n_TELEBIT,      0,
  987. #endif /* MINIDIAL */
  988.     "unknown",        n_UNKNOWN,    0,
  989. #ifndef MINIDIAL
  990.     "usrobotics-212a",    n_USROBOT,    0,
  991.     "v32-telebit",      n_TB3,        0,
  992.     "v42-telebit",      n_TB4,        0,
  993.     "ventel",        n_VENTEL,    0
  994. #endif /* MINIDIAL */
  995. };
  996. int nmdm = (sizeof(mdmtab) / sizeof(struct keytab)); /* Number of modems */
  997.  
  998. #define CONNECTED 1            /* For completion status */
  999. #define FAILED      2
  1000.  
  1001. static int tries = 0;
  1002. static int mdmecho = 0;    /* assume modem does not echo */
  1003. static int augmdmtyp;    /* "augmented" modem type, to handle modem modes */
  1004.  
  1005. static char *p;        /* For command strings & messages */
  1006.  
  1007. #ifdef DYNAMIC
  1008. #define LBUFL 256
  1009. static char *lbuf = NULL;
  1010. #else
  1011. #define LBUFL 100
  1012. static char lbuf[LBUFL];
  1013. #endif /* DYNAMIC */
  1014.  
  1015. #ifdef DYNAMIC
  1016. #define RBUFL 256
  1017. static char *rbuf = NULL;
  1018. #else
  1019. #define RBUFL 63
  1020. static char rbuf[RBUFL+1];
  1021. #endif /* DYNAMIC */
  1022.  
  1023. #ifdef DYNAMIC
  1024. #define FULLNUML 256
  1025. char *fbuf = NULL;            /* For full (prefixed) phone number */
  1026. #else
  1027. #define FULLNUML 100
  1028. char fbuf[FULLNUML];
  1029. #endif /* DYNAMIC */
  1030.  
  1031. #ifdef CK_POSIX_SIG
  1032. static sigjmp_buf sjbuf;
  1033. #else
  1034. static jmp_buf sjbuf;
  1035. #endif /* CK_POSIX_SIG */
  1036.  
  1037. static SIGTYP (*savalrm)();    /* For saving alarm handler */
  1038. static SIGTYP (*savint)();    /* For saving interrupt handler */
  1039.  
  1040. #ifndef MINIDIAL
  1041. int tbmodel = 0;        /* Telebit modem model */
  1042.  
  1043. char *
  1044. gtbmodel() {            /* Function to return name of Telebit model */
  1045.     if (tbmodel < 0 || tbmodel > TB__MAX) tbmodel = TB_UNK;
  1046.     return(tb_name[tbmodel]);
  1047. }
  1048.  
  1049. #ifdef COMMENT
  1050. static VOID
  1051. xcpy(to,from,len)        /* Copy the given number of bytes */
  1052.     register char *to, *from;
  1053.     register unsigned int len; {
  1054.     while (len--) *to++ = *from++;
  1055. }
  1056. #endif /* COMMENT */
  1057. #endif /* MINIDIAL */
  1058.  
  1059. static SIGTYP
  1060. dialtime(foo) int foo; {        /* Timer interrupt handler */
  1061.     fail_code = F_TIME;            /* Failure reason = timeout */
  1062.     debug(F100,"dialtime caught SIGALRM","",0);
  1063. #ifdef __EMX__
  1064.     signal(SIGALRM, SIG_ACK);        /* Needed for OS/2 */
  1065. #endif /* __EMX__ */
  1066.  
  1067. #ifdef OSK                /* OS-9 */
  1068. /*
  1069.   We are in an intercept routine but do not perform a F$RTE (done implicitly
  1070.   by RTS), so we have to decrement the sigmask as F$RTE does.  Warning:
  1071.   longjump only restores the CPU registers, NOT the FPU registers.  So, don't
  1072.   use FPU at all or at least don't use common FPU (double or float) register
  1073.   variables.
  1074. */
  1075.     sigmask(-1);
  1076. #endif /* OSK */
  1077. #ifdef CK_POSIX_SIG
  1078.     siglongjmp(sjbuf,1);
  1079. #else
  1080.     longjmp(sjbuf,1);
  1081. #endif /* CK_POSIX_SIG */
  1082. }
  1083.  
  1084. static SIGTYP
  1085. dialint(foo) int foo; {            /* Keyboard interrupt handler */
  1086.     fail_code = F_INT;
  1087.     debug(F100,"dialint caught SIGINT","",0);
  1088. #ifdef __EMX__
  1089.     signal(SIGINT, SIG_ACK);        /* Needed for OS/2 */
  1090. #endif /* __EMX__ */
  1091. #ifdef OSK                /* OS-9, see comment in dialtime() */
  1092.     sigmask(-1);
  1093. #endif /* OSK */
  1094. #ifdef CK_POSIX_SIG
  1095.     siglongjmp(sjbuf,1);
  1096. #else
  1097.     longjmp(sjbuf,1);
  1098. #endif /* CK_POSIX_SIG */
  1099. }
  1100.  
  1101. /*
  1102.   Routine to read a character from communication device, handling TELNET
  1103.   protocol negotiations in case we're connected to the modem through a
  1104.   TCP/IP TELNET modem server.
  1105. */
  1106. static int
  1107. ddinc(n) int n; {
  1108.     int c;
  1109.  
  1110. #ifdef TNCODE
  1111.     int done = 0;
  1112.     debug(F101,"ddinc entry n","",n);
  1113.     while (!done) {
  1114.     c = ttinc(n);
  1115.     debug(F000,"ddinc","",c);
  1116.     if (c < 0) return(c);
  1117.     if (c == IAC && network && ttnproto == NP_TELNET) {
  1118.         switch (tn_doop((CHAR)(c & 0xff),duplex,ttinc)) {
  1119.           case 2: duplex = 0; continue;
  1120.           case 1: duplex = 1;
  1121.           default: continue;
  1122.         }
  1123.     } else done = 1;
  1124.     }
  1125.     return(c & 0xff);
  1126. #else
  1127.     debug(F101,"ddinc entry n","",n);
  1128.     return(ttinc(n));
  1129. #endif /* TNCODE */
  1130. }
  1131.  
  1132. static VOID
  1133. ttslow(s,millisec) char *s; int millisec; { /* Output s-l-o-w-l-y */
  1134. #ifdef TCPSOCKET
  1135.     extern int tn_nlm;
  1136. #endif /* TCPSOCKET */
  1137.     if (dialdpy && duplex)        /* Echo the command in case modem */
  1138.       printf("%s\n",s);            /* isn't echoing commands. */
  1139.     for (; *s; s++) {
  1140.     ttoc(*s);
  1141. #ifdef TCPSOCKET
  1142.     if (*s == CR && network && ttnproto == NP_TELNET && tn_nlm != TNL_CR)
  1143.       ttoc((char)((tn_nlm == TNL_CRLF) ? LF : NUL));
  1144. #endif /* TCPSOCKET */
  1145.     msleep(millisec);
  1146.     }
  1147. }
  1148.  
  1149. /*
  1150.  * Wait for a string of characters.
  1151.  *
  1152.  * The characters are waited for individually, and other characters may
  1153.  * be received "in between".  This merely guarantees that the characters
  1154.  * ARE received, and in the order specified.
  1155.  */
  1156. static VOID
  1157. waitfor(s) char *s; {
  1158.     CHAR c, x;
  1159.     while ( c = *s++ ) {        /* while more characters remain... */
  1160.     do {                /* wait for the character */
  1161.         x = ddinc(0) & 0177;
  1162.         debug(F000,"dial waitfor got","",x);
  1163.         if (dialdpy) {
  1164.         if (x != LF) conoc(x);
  1165.         if (x == CR) conoc(LF);
  1166.         }
  1167.     } while ( x != c);
  1168.     }
  1169. }
  1170.  
  1171. static int
  1172. didweget(s,r) char *s, *r; {    /* Looks in string s for response r */
  1173.     int lr = (int)strlen(r);    /*  0 means not found, 1 means found it */
  1174.     int i;
  1175.     debug(F110,"didweget",r,0);
  1176.     debug(F110," in",s,0);
  1177.     for (i = (int)strlen(s)-lr; i >= 0; i--)
  1178.     if ( s[i] == r[0] ) if ( !strncmp(s+i,r,lr) ) return( 1 );
  1179.     return( 0 );
  1180. }
  1181.  
  1182.  
  1183. /* R E S E T -- Reset alarms, etc. on exit. */
  1184.  
  1185. static VOID
  1186. dreset() {
  1187.     alarm(0);
  1188.     signal(SIGALRM,savalrm);        /* restore alarm handler */
  1189.     signal(SIGINT,savint);        /* restore interrupt handler */
  1190. }
  1191.  
  1192. /*
  1193.   Call this routine when the modem reports that it has connected at a certain
  1194.   speed, giving that speed as the argument.  If the connection speed is not
  1195.   the same as Kermit's current communication speed, AND the modem interface
  1196.   speed is not locked (i.e. DIAL SPEED-MATCHING is not ON), then change the
  1197.   device speed to the one given.
  1198. */
  1199. static VOID
  1200. #ifdef CK_ANSIC
  1201. spdchg(long s)
  1202. #else
  1203. spdchg(s) long s;
  1204. #endif /* CK_ANSIC */
  1205. /* spdchg */ {
  1206.     int s2;
  1207.     if (!mdmspd)            /* If modem interface speed locked, */
  1208.       return;                /*  don't do this. */
  1209.     if (speed != s) {            /* Speeds differ? */
  1210.     s2 = s / 10L;            /* Convert to cps expressed as int */
  1211.     if (ttsspd(s2) < 0) {        /* Change speed. */
  1212.         printf(" Warning: speed change to %ld failed.\r\n",s);
  1213.     } else {
  1214.         printf(" Speed changed to %ld.\r\n",s);
  1215.         speed = s;            /* Update global speed variable */
  1216.     }
  1217.     }
  1218. }
  1219.  
  1220. /*
  1221.   Display all characters received from modem dialer through this routine,
  1222.   for consistent handling of carriage returns and linefeeds.
  1223. */
  1224. static VOID
  1225. #ifdef CK_ANSIC
  1226. dialoc(char c)
  1227. #else
  1228. dialoc(c) char c;
  1229. #endif /* CK_ANSIC */
  1230. { /* dialoc */                /* Dial Output Character */
  1231.     if (dialdpy) {
  1232.     if (c != LF) conoc(c);        /* Don't echo LF */
  1233.     if (c == CR) conoc(LF);        /* Echo CR as CRLF */
  1234.     }
  1235. }
  1236.  
  1237. #ifndef MINIDIAL
  1238. /*
  1239.   tbati3() -- Routine to find out Telebit model when ATI reports "965"
  1240.   or "971". This routine sends another query, ATI3, to get further info
  1241.   to narrow down the model number.  Argument is ATI response as integer.
  1242.   Result: sets tbmodel variable to Telebit model.
  1243. */
  1244. static VOID
  1245. tbati3(n) int n; {
  1246.     int status;
  1247.     ttflui();                /* Flush input buffer */
  1248.     ttslow("ATI3\015",100);        /* Send ATI3<CR> */
  1249.     status = getok(5,0);        /* Get OK response, nonstrict */
  1250.     if (status < 1) {            /* ERROR or timeout */
  1251.     tbmodel = TB_UNK;
  1252.     debug(F111,"tbati3 fails",rbuf,status);
  1253.     return;
  1254.     }
  1255.     debug(F110,"tbati3 rbuf",rbuf,0);
  1256.  
  1257. /* Got a good response, check the model info */
  1258.  
  1259.     if (n == 965) {            /* "965" - various models. */
  1260.     if (didweget(rbuf,"T1600")) {
  1261.         tbmodel = TB_1600;            /* T1600 */
  1262.     } else if (didweget(rbuf,"T3000")) {
  1263.         tbmodel = TB_3000;            /* T3000 */
  1264.     } else if (didweget(rbuf,"World")) {
  1265.         tbmodel = TB_WBLA;            /* WorldBlazer */
  1266.     } else if (didweget(rbuf,"Version B") || /* TrailBlazer-Plus models */
  1267.            didweget(rbuf,"TBSA") ||
  1268.            didweget(rbuf,"TBRM") ||
  1269.            didweget(rbuf,"DC")) {     /* Ven-Tel EC18K */
  1270.         tbmodel = TB_PLUS;
  1271.     } else tbmodel = TB_UNK;        /* Others: Unknown */
  1272.  
  1273.     } else if (n == 971) {        /* "971" could be T1500 or T1600. */
  1274.     if (didweget(rbuf,"T1500"))
  1275.       tbmodel = TB_1500;
  1276.     else tbmodel = TB_2500;
  1277.     }                    /* Other, don't change tbmodel. */
  1278. }
  1279. #endif /* MINIDIAL */
  1280.  
  1281. static int
  1282. dialfail(x) int x; {
  1283.     char * s;
  1284.  
  1285.     fail_code = x;
  1286.     debug(F101,"ckudial dialfail","",x);
  1287.     alarm(0);                /* Disable timeouts */
  1288.     dreset();                /* Reset alarm signals */
  1289.  
  1290.     printf("DIAL Failure: ");
  1291.     if (dialdpy) {            /* If showing progress */
  1292.     p = ck_time();            /* get current time; */
  1293.     if (*p) printf("%s: ",p);
  1294.     }
  1295.     switch (fail_code) {        /* Type of failure */
  1296.       case F_TIME:             /* Timeout */
  1297.     if (dial_what == DW_INIT)
  1298.       printf ("Timed out while trying to initialize modem.\n");
  1299.     else if (dial_what == DW_DIAL)
  1300.       printf ("DIAL TIMEOUT interval expired.\n");
  1301.     else printf("Timeout.\n");
  1302.     if (mymdmtyp == n_HAYES
  1303. #ifndef MINIDIAL
  1304.         || mymdmtyp == n_TELEBIT || mymdmtyp == n_HST
  1305. #endif /* MINIDIAL */
  1306.         )
  1307.       ttoc('\015');        /* Send CR to interrupt dialing */
  1308.     /* Some Hayes modems don't fail with BUSY on busy lines */
  1309.     dialsta = DIA_TIMO;
  1310.     debug(F110,"dial","timeout",0);
  1311.     break;
  1312.  
  1313.       case F_INT:            /* Dialing interrupted */
  1314.     printf ("Interrupted.\n");
  1315.     debug(F110,"dial","interrupted",0);
  1316.     if (mymdmtyp == n_HAYES
  1317. #ifndef MINIDIAL
  1318.         || mymdmtyp == n_TELEBIT || mymdmtyp == n_HST
  1319. #endif /* MINIDIAL */
  1320.         )
  1321.       ttoc('\015');            /* Send CR to interrupt dialing */
  1322.     dialsta = DIA_INTR;
  1323.     break;
  1324.  
  1325.       case F_MODEM:            /* Modem detected a failure */
  1326.     printf ("Call not completed.");
  1327.     if (*lbuf) {
  1328.         printf("  Modem message: \"");
  1329.         for (s = lbuf; *s; s++)
  1330.           if (isprint(*s))
  1331.         putchar(*s);        /* Display printable reason */
  1332.         printf ("\"");
  1333.     }
  1334.     printf("\n");
  1335.     debug(F110,"dial",lbuf,0);
  1336.     if (dialsta < 0) dialsta = DIA_UNSP;
  1337.     break;
  1338.  
  1339.       case F_MINIT:            /* Failure to initialize modem */
  1340.     printf ("Error initializing modem.\n");
  1341.     debug(F110,"dial","modem init",0);
  1342.     dialsta = DIA_NOIN;
  1343.     break;
  1344.     }
  1345.  
  1346. #ifdef DYNAMIC
  1347.     if (lbuf) free(lbuf); lbuf = NULL;
  1348.     if (rbuf) free(rbuf); rbuf = NULL;
  1349.     if (fbuf) free(fbuf); fbuf = NULL;
  1350. #endif /* DYNAMIC */
  1351.  
  1352.     if (dialsta < 0) dialsta = DIA_UERR; /* Set failure code */
  1353.     return(0);                /* Return zero (important) */
  1354. }
  1355.  
  1356. /*  C K D I A L     --  Dial up the remote system */
  1357.  
  1358. /* Returns 1 if call completed, 0 otherwise */
  1359.  
  1360. static int waitct, mdmwait, mdmstat = 0;
  1361.  
  1362. int
  1363. ckdial(telnbr) char *telnbr; {
  1364.  
  1365.     char c, c2;
  1366. #define ERMSGL 50
  1367.     char errmsg[ERMSGL], *erp;        /* for error messages */
  1368.     MDMINF *pmdminf;            /* pointer to modem-specific info */
  1369.     int x, m, n = F_TIME;
  1370.     char *s, *ws;
  1371.  
  1372.     char *mmsg = "Sorry, DIAL memory buffer can't be allocated\n";
  1373.  
  1374.     long conspd;
  1375.     char *cptr;
  1376.  
  1377.     mymdmtyp = mdmtyp;            /* Make local copy of modem type */
  1378.     dialsta = DIA_UNK;            /* Start with return code = unknown */
  1379.     dial_what = DW_NOTHING;        /* Doing nothing at first. */
  1380.  
  1381. #ifndef MINIDIAL
  1382.     tbmodel = TB_UNK;            /* Initialize Telebit model */
  1383. #endif /* MINIDIAL */
  1384.  
  1385.     if (mymdmtyp < 1) {
  1386.     if (network)
  1387.       printf("Please SET HOST first, and then SET MODEM\n");
  1388.     else
  1389.       printf("Sorry, you must SET MODEM first\n");
  1390.     dialsta = DIA_NOMO;
  1391.     return(0);
  1392.     }
  1393.     if (!local) {
  1394.     printf("Sorry, you must SET LINE or SET HOST first\n");
  1395.     dialsta = DIA_NOLI;
  1396.     return(0);
  1397.     }
  1398.     if (!network &&
  1399.     (speed < 0L)
  1400. #ifdef UNIX
  1401.     && (strcmp(ttname,"/dev/null"))
  1402. #endif /* UNIX */
  1403.     ) {
  1404.     printf("Sorry, you must SET SPEED first\n");
  1405.     dialsta = DIA_NOSP;
  1406.     return(0);
  1407.     }
  1408.     debug(F110,"dial number",telnbr,0);
  1409.     debug(F110,"dial prefix",(dialnpr ? dialnpr : ""), 0);
  1410.  
  1411. #ifdef DYNAMIC
  1412.     if (!(lbuf = malloc(LBUFL+1))) {    /* Allocate input line buffer */
  1413.     printf("%s", mmsg);
  1414.     dialsta = DIA_IE;
  1415.     return(0);
  1416.     }
  1417.     *lbuf = NUL;
  1418.     debug(F101,"DIAL lbuf malloc ok","",LBUFL+1);
  1419.  
  1420.     if (!rbuf) {    /* This one might already have been allocated by getok() */
  1421.     if (!(rbuf = malloc(RBUFL+1))) {    /* Allocate input line buffer */
  1422.         printf("%s", mmsg);
  1423.         dialsta = DIA_IE;
  1424.         if (lbuf) free(lbuf); lbuf = NULL;
  1425.         return(0);
  1426.     } else
  1427.       debug(F101,"DIAL rbuf malloc ok","",RBUFL+1);
  1428.     }
  1429.     if (!(fbuf = malloc(FULLNUML+1))) {    /* Allocate input line buffer */
  1430.     printf("%s", mmsg);
  1431.     dialsta = DIA_IE;
  1432.     if (lbuf) free(lbuf); lbuf = NULL;
  1433.     if (rbuf) free(rbuf); rbuf = NULL;
  1434.     return(0);
  1435.     }
  1436.     debug(F101,"DIAL fbuf malloc ok","",FULLNUML+1);
  1437. #endif /* DYNAMIC */
  1438.  
  1439. /* Add prefix to phone number */
  1440.  
  1441.     if (dialnpr && *dialnpr) {
  1442.     if (((int)strlen(dialnpr) + (int)strlen(dialnpr)) > FULLNUML) {
  1443.         printf("DIAL prefix + phone number too long!\n");
  1444. #ifdef DYNAMIC
  1445.         if (lbuf) free(lbuf); lbuf = NULL;
  1446.         if (rbuf) free(rbuf); rbuf = NULL;
  1447.         if (fbuf) free(fbuf); fbuf = NULL;
  1448. #endif /* DYNAMIC */
  1449.         return(0);
  1450.     }
  1451.     sprintf(fbuf,"%s%s",(dialnpr ? dialnpr : ""),telnbr);
  1452.     telnbr = fbuf;
  1453.     }
  1454.     debug(F110,"prefixed number", telnbr, 0);
  1455.  
  1456.     if (ttopen(ttname,&local,mymdmtyp,0) < 0) { /* Open, no carrier wait */
  1457.     erp = errmsg;
  1458.     if ((int)strlen(ttname) < (ERMSGL - 18))
  1459.       sprintf(erp,"Sorry, can't open %s",ttname);
  1460.     else
  1461.       sprintf(erp,"Sorry, can't open device");
  1462.     perror(errmsg);
  1463.     dialsta = DIA_OPEN;
  1464. #ifdef DYNAMIC
  1465.     if (lbuf) free(lbuf); lbuf = NULL;
  1466.     if (rbuf) free(rbuf); rbuf = NULL;
  1467.     if (fbuf) free(fbuf); fbuf = NULL;
  1468. #endif /* DYNAMIC */
  1469.     return(0);
  1470.     }
  1471.  
  1472. /* Condition console terminal and communication line */
  1473.  
  1474.     /* Place line into "clocal" dialing state, */
  1475.     /* important mainly for System V UNIX.     */
  1476.  
  1477.     if (ttpkt(speed,FLO_DIAL,parity) < 0) {
  1478.     ttclos(0);            /* If ttpkt fails do all this... */
  1479.     if (ttopen(ttname,&local,mymdmtyp,0) < 0) {
  1480.         erp = errmsg;
  1481.         if ((int)strlen(ttname) < (ERMSGL - 18))
  1482.           sprintf(erp,"Sorry, can't reopen %s",ttname);
  1483.         else
  1484.           sprintf(erp,"Sorry, can't reopen device");
  1485.         perror(errmsg);
  1486.         dialsta = DIA_OPEN;
  1487. #ifdef DYNAMIC
  1488.         if (lbuf) free(lbuf); lbuf = NULL;
  1489.         if (rbuf) free(rbuf); rbuf = NULL;
  1490.         if (fbuf) free(fbuf); fbuf = NULL;
  1491. #endif /* DYNAMIC */
  1492.         return(0);
  1493.     }                /* And try again. */
  1494.     if ((ttpkt(speed,FLO_DIAL,parity) < 0)
  1495. #ifdef UNIX
  1496.     && (strcmp(ttname,"/dev/null"))
  1497. #endif /* UNIX */
  1498.         ) {
  1499.         printf("Sorry, Can't condition communication line\n");
  1500.         printf("Try 'set line %s' again\n",ttname);
  1501.         dialsta = DIA_OPEN;
  1502. #ifdef DYNAMIC
  1503.         if (lbuf) free(lbuf); lbuf = NULL;
  1504.         if (rbuf) free(rbuf); rbuf = NULL;
  1505.         if (fbuf) free(fbuf); fbuf = NULL;
  1506. #endif /* DYNAMIC */
  1507.         return(0);
  1508.     }
  1509.     }
  1510.     msleep(500);
  1511.  
  1512.     pmdminf = ptrtab[ (mymdmtyp & 0xff) -1 ]; /* set pointer to modem info */
  1513.     augmdmtyp = mymdmtyp;        /* initialize "augmented" modem type */
  1514.     mymdmtyp &= 0xff;            /* major modem type */
  1515.  
  1516.     /* Interdigit waits for tone dial */
  1517.  
  1518.     if (dialtmo < 1) {            /* Automatic computation. */
  1519.     waitct = 1 * (int)strlen(telnbr) ; /* Compute worst case dial time */
  1520.     waitct += pmdminf->dial_time;    /* dialtone + completion wait times */
  1521.     for (s = telnbr; *s; s++) {    /* add in pause characters time */
  1522.         for (p=pmdminf->pause_chars; *p; p++)
  1523.           if (*s == *p) {
  1524.           waitct += pmdminf->pause_time;
  1525.           break;
  1526.           }
  1527.     }
  1528. #ifndef MINIDIAL
  1529.     if (augmdmtyp == n_TBPEP || augmdmtyp == n_TBPNV) {
  1530.         waitct += 30;    /* Longer connect wait for PEP call */
  1531.     }
  1532. #endif /* MINIDIAL */
  1533.     } else {                /* User-specified timeout */
  1534.     waitct = dialtmo;
  1535.     }
  1536. /*
  1537.   waitct is our alarm() timer.
  1538.   mdmwait is how long we tell the modem to wait for carrier.
  1539.   We set mdmwait to be 1 second less than waitct, to increase the
  1540.   chance that we get a response from the modem before timing out.
  1541. */
  1542.     if (waitct < 0) waitct = 0;
  1543.     mdmwait = (waitct > 5) ? waitct - 5 : waitct;
  1544.  
  1545.     for (m = 0; m < nmdm; m++) {    /* Look up modem type. */
  1546.     if (mdmtab[m].kwval == mymdmtyp) {
  1547.         break;
  1548.     }
  1549.     }
  1550.     if (!quiet && !backgrd) {        /* Print information messages. */
  1551.     printf(" Number: %s\n", telnbr);
  1552.     if (network) {
  1553.         printf(" Via modem server: %s, modem-dialer: %s\n",
  1554.            ttname, (m >= nmdm ? "(unknown)" : mdmtab[m].kwd) );
  1555.     } else {
  1556.         printf(" Device: %s, modem-dialer: %s",
  1557.            ttname, (m >= nmdm ? "(unknown)" : mdmtab[m].kwd) );
  1558.         if (speed > -1L)
  1559.           printf(", speed: %ld\n", speed);
  1560.         else
  1561.           printf(", speed: (unknown)\n");
  1562.     }
  1563.     printf(" Dial timeout: %d seconds\n",waitct);
  1564.     printf(
  1565. #ifdef MAC
  1566.            " Type Command-. to cancel dialing.\n"
  1567. #else
  1568. #ifdef UNIX
  1569.            " To cancel: type your interrupt character (normally Ctrl-C).\n"
  1570. #else
  1571.            " To cancel: type Ctrl-C.\n"
  1572. #endif /* UNIX */
  1573. #endif /* MAC */
  1574.            );
  1575.     }
  1576.     debug(F111,"ckdial",ttname,(int) (speed / 10L));
  1577.     debug(F101,"ckdial timeout","",waitct);
  1578.  
  1579. /* Set timer and interrupt handlers. */
  1580.  
  1581.     if (
  1582. #ifdef CK_POSIX_SIG
  1583.     sigsetjmp(sjbuf,1)
  1584. #else
  1585.     setjmp(sjbuf)
  1586. #endif /* CK_POSIX_SIG */
  1587.     ) {        /* Handle failures */
  1588.     return(dialfail(fail_code));
  1589.     } else {
  1590.     alarm(0);            /* No alarms yet. */
  1591.     savalrm = signal(SIGALRM,dialtime); /* Enable alarm() handler */
  1592. #ifdef MAC
  1593.     savint = signal(SIGINT, dialint); /* And terminal interrupt handler. */
  1594. #else /* MAC */
  1595. #ifdef OSK
  1596.     if ((savint = signal(SIGINT,SIG_IGN)) != (SIGTYP (*)()) SIG_IGN)
  1597.       signal(SIGINT,dialint);
  1598. #else
  1599.     if ((savint = signal(SIGINT,SIG_IGN)) != SIG_IGN )
  1600.       signal(SIGINT,dialint);
  1601. #endif /* OS-9 */
  1602. #endif /* MAC */
  1603.     }
  1604.  
  1605.     /* Hang up the modem (in case it wasn't "on hook") */
  1606.     /* But only if SET DIAL HANGUP ON... */
  1607.  
  1608.     if (dialhup() < 0) {
  1609.     debug(F100,"ckdial dialhup failed","",0);
  1610. #ifndef MINIDIAL
  1611.     if (mymdmtyp == n_TELEBIT)    /* Telebit might need a BREAK */
  1612.       ttsndb();            /*  first. */
  1613. #endif /* MINIDIAL */
  1614.     if (dialhng) {            /* If it failed, */
  1615.         ttclos(0);            /* close and reopen the device. */
  1616.         if (ttopen(ttname,&local,mymdmtyp,0) < 0) {
  1617.         printf("Sorry, Can't hang up communication device\n");
  1618.         printf("Try 'set line %s' again\n",ttname);
  1619.         dialsta = DIA_HANG;
  1620. #ifdef DYNAMIC
  1621.         if (lbuf) free(lbuf); lbuf = NULL;
  1622.         if (rbuf) free(rbuf); rbuf = NULL;
  1623.         if (fbuf) free(fbuf); fbuf = NULL;
  1624. #endif /* DYNAMIC */
  1625.         dreset();
  1626.         return(0);
  1627.         }
  1628.     }
  1629.     }
  1630. #ifndef MINIDIAL
  1631.     if (augmdmtyp == n_ROLM)        /* Don't start talking to Rolm */
  1632.       msleep(500);            /* too soon... */
  1633. #endif /* MINIDIAL */
  1634.  
  1635. /* Put modem in command mode. */
  1636.  
  1637.     if (
  1638. #ifdef MINIDIAL
  1639.     1
  1640. #else
  1641.     augmdmtyp != n_ATTUPC
  1642. #endif /* MINIDIAL */
  1643.     ) {
  1644.     fail_code = F_MINIT;        /* Default failure code */
  1645.     dial_what = DW_INIT;        /* What I'm Doing Now   */
  1646.     if (dialdpy) {            /* If showing progress, */
  1647.         p = ck_time();        /* display timestamp.   */
  1648.         if (*p) printf(" Initializing: %s...\n",p);
  1649.     }
  1650.     }
  1651.     switch (augmdmtyp) {        /* Send wakeup string, if any. */
  1652.  
  1653. #ifndef MINIDIAL
  1654. #ifdef ATT7300
  1655.       case n_ATTUPC: {
  1656. /*
  1657.   For ATT7300/Unix PC's with their special internal modem.  Whole dialing
  1658.   process is handled right here, an exception to the normal structure.
  1659.   Timeout and user interrupts are enabled during dialing.  attdial() is in
  1660.   file ckutio.c.  - jrd
  1661. */
  1662.         _PROTOTYP( int attdial, (char *, long, char *) );
  1663.     fail_code = F_MODEM;        /* Default failure code */
  1664.     dial_what = DW_DIAL;
  1665.     if (dialdpy) {            /* If showing progress */
  1666.         p = ck_time();        /* get current time; */
  1667.         if (*p) printf(" Dialing: %s...\n",p);
  1668.     }
  1669.     alarm(waitct);            /* do alarm properly */
  1670.     if (attdial(ttname,speed,telnbr)) { /* dial internal modem */
  1671.         dreset();            /* reset alarms, etc. */
  1672.         printf(" Call failed.\r\n");
  1673.         dialhup();                /* Hangup the call */
  1674. #ifdef DYNAMIC
  1675.         if (lbuf) free(lbuf); lbuf = NULL;
  1676.         if (rbuf) free(rbuf); rbuf = NULL;
  1677.         if (fbuf) free(fbuf); fbuf = NULL;
  1678. #endif /* DYNAMIC */
  1679.         dialsta = DIA_UERR;
  1680.         return(0);            /* return failure */
  1681.     }
  1682.     dreset();            /* reset alarms, etc. */
  1683.     ttpkt(speed,FLO_DIAX,parity);    /* cancel dialing ioctl */
  1684.     if (!quiet && !backgrd) {
  1685.         if (dialdpy) printf("\n");
  1686.         printf(" Call complete.\07\r\n");
  1687.     }
  1688.     dialsta = DIA_OK;
  1689. #ifdef DYNAMIC
  1690.     if (lbuf) free(lbuf); lbuf = NULL;
  1691.     if (rbuf) free(rbuf); rbuf = NULL;
  1692.     if (fbuf) free(fbuf); fbuf = NULL;
  1693. #endif /* DYNAMIC */
  1694.     return(1);     /* no conversation with modem to complete dialing */
  1695.     }
  1696. #endif /* ATT7300 */
  1697. #endif /* MINIDIAL */
  1698.  
  1699. /*
  1700.   For Hayes modem command language, figure out if modem is giving verbose
  1701.   or digit result codes.
  1702. */
  1703.       case n_HAYES:
  1704.       case n_HAYESNV:
  1705. #ifndef MINIDIAL
  1706.       case n_HST:
  1707.     if (augmdmtyp == n_HST)
  1708.       m = 255;
  1709.     else
  1710. #endif /* MINIDIAL */
  1711.       m = 60;            /* Maximum value for S7 */
  1712.       
  1713.     if (dialini)            /* Get wakeup string */
  1714.       ws = dialini;
  1715.     else
  1716.           ws =
  1717. #ifndef MINIDIAL
  1718.         (augmdmtyp == n_HST) ? HST.wake_str :
  1719. #endif /* MINIDIAL */
  1720.           HAYES.wake_str;
  1721.  
  1722.     for (tries = 4; tries > 0; tries--) {
  1723.         ttslow(ws,pmdminf->wake_rate);
  1724.         mdmstat = getok(4,1);
  1725.         if (mdmstat > 0) break;
  1726.         if (dialdpy && tries > 1)
  1727.           printf(" No response from modem, retrying%s...\n",
  1728.              (tries < 4) ? " again" : "");
  1729.         /* sleep(1); */        /* Wait before retrying */
  1730.     }
  1731.     debug(F101,"ckdial wake_str mdmstat","",mdmstat);
  1732.  
  1733.     if (mdmstat < 1) {         /* Initialized OK? */
  1734.         return(dialfail(F_MINIT));    /* No, fail. */
  1735.     } else {            /* Yes. */
  1736.         char hbuf[16];
  1737. /*
  1738.   Now tell the modem about our dial timeout.  For Hayes 1200, the maximum
  1739.   is 60 seconds.  For Hayes 2400 (the manual says) it is 30 seconds, but I'm
  1740.   not sure I believe this (I don't have one handy to see for myself).
  1741.   If you give the modem a value larger than its maximum, it sets the timeout
  1742.   to its maximum.  The manual does not say what happens when the value is 0,
  1743.   but experimentation shows that it allows the modem to wait forever, in
  1744.   which case Kermit will time out at the desired time.
  1745. */
  1746. /*
  1747.   Note by Kai Uwe Rommel:
  1748.   This is not acceptable for general use of the hayes modem type with other
  1749.   compatible modems. Most other modems allow a range of 1..255 while 0 is
  1750.   invalid on several modems. Let it be the user's responsibility to make
  1751.   sure a valid value is used. Higher values are desirable for users with
  1752.   rotary dialing and with high speed modems, where protocol negotiation takes
  1753.   quite a long time.
  1754. */
  1755. #ifdef COMMENT
  1756.         if (mdmwait > m)        /* If larger than maximum, */
  1757.           mdmwait = 0;        /* make it infinite. */
  1758. #else
  1759.         if (mdmwait > 255)        /* If larger than maximum, */
  1760.           mdmwait = 255;        /* make it maximum. */
  1761. #endif /* COMMENT */
  1762.         sprintf(hbuf,"ATS7=%d%c",mdmwait,13); /* S7 = Carrier wait time */
  1763.         ttslow(hbuf,pmdminf->wake_rate); /* Set it. */
  1764.         mdmstat = getok(4,1);    /* Get response from modem */
  1765.         debug(F101,"ckdial S7 mdmstat","",mdmstat);
  1766.         break;            /* Errors here are not fatal. */
  1767.     }
  1768.  
  1769. #ifndef MINIDIAL
  1770. /*
  1771.   Telebit modems fall into two basic groups: old and new.  The functions and
  1772.   command sets are different between the two groups, and also vary by specific
  1773.   models within each group, and even by firmware ROM revision number.  Read
  1774.   ckcker.bwr for details.
  1775.  
  1776.   Commands used by C-Kermit include:
  1777.  
  1778.     Old       New            Meaning
  1779.     -------   --------       ----------------------------------------
  1780.     Q0        Q0             Enable result codes.
  1781.     X1        X1             Extended result codes.
  1782.     X1        X1             Extended result codes + BUSY, NO DIALTONE, etc.
  1783.     I         I              Model number inquiry.
  1784.     I3        I3             Additional model information inquiry.
  1785.     S12=50    S12=50         Escape sequence guard time (1 sec).
  1786.     S2=43     S2=43          Escape character is '+'.
  1787.     S7=xx     S7=xx          DIAL TIMEOUT, calculated or SET by user.
  1788.     S48=0     S48=0          7-bit data (Kermit's PARITY is not NONE).
  1789.     S48=1     S48=1          8-bit data (Kermit's PARITY is NONE).
  1790.     S50=0     S50=0          Automatic speed & protocol determination.
  1791.     S50=3     S50=3          2400/1200/300 bps.
  1792.     S50=6     S50=6          V.32 (9600 bps).
  1793.     S50=255   S50=255        PEP mode.
  1794.     S110=1    S190=1 S191=7  Allow compression in PEP mode.
  1795.     S51=?     S51=?          DTE interface speed (left alone by Kermit).
  1796.     S54=3     S61=0 S63=0    Pass BREAK signal (always).
  1797.     S58=2     S58=2          RTS/CTS flow control if Kermit's FLOW is RTS/CTS.
  1798.     S58=?     S58=?          S58 unchanged if Kermit's FLOW is not RTS/CTS.
  1799.     S68=255   S68=255        Use flow control specified by S58 (always).
  1800.     S95=0     S180=0         MNP disabled (SET DIAL MNP-ENABLE OFF)
  1801.     S95=2     S180=3         MNP, fallback to direct (also as V.42 fallback)
  1802.     S97=1     S180=2         Enable V.42 (LAPM) error correction
  1803.     S98=3                    Enable compression in both directions
  1804.     S106=1                   V.42bis compression enable
  1805.  
  1806. For Kermit Spoof (same commands for all models that support it):
  1807.  
  1808.     S111=0                   No Kermit spoofing
  1809.     S111=10                  Kermit with no parity
  1810.     S111=11                  Kermit with odd parity
  1811.     S111=12                  Kermit with even parity
  1812.     S111=13                  Kermit with mark parity
  1813.     S111=14                  Kermit with space parity
  1814.     S112=??                  Kermit's start-of-packet character (stchr).
  1815. */
  1816.     case n_TELEBIT:            /* Telebits... */
  1817.     case n_TBPEP:
  1818.     case n_TB3:
  1819.     case n_TB4:
  1820.     case n_TBS:
  1821.     case n_TBNV:
  1822.     case n_TBPNV:
  1823.     case n_TB3NV:
  1824.     case n_TB4NV:
  1825.     case n_TBSNV: {
  1826.     int S111;            /* Telebit Kermit spoof register */
  1827.     char tbcmdbuf[64];        /* Telebit modem command buffer */
  1828.     char *mnpstr = "";        /* Pointer to MNP-enable string */
  1829.     char *dprstr = "";        /* Pointer to dial protocol string */
  1830. /*
  1831.   If user defined a DIAL INIT-STRING, send that now, otherwise send built-in
  1832.   Telebit string.  Try up to 4 times to get OK or 0 response from modem.
  1833.   NOTE: The default init string *must* be independent of Telebit model.
  1834. */
  1835.     ws = dialini ? dialini : TELEBIT.wake_str;
  1836.     debug(F110,"ckdial telebit init string",ws,0);
  1837.     for (tries = 4; tries > 0; tries--) {
  1838.         ttsndb();            /* Begin by sending BREAK */
  1839.         ttslow(ws,pmdminf->wake_rate); /* Send wakeup string */
  1840.         mdmstat = getok(5,0);    /* Get modem's response */
  1841.         if (mdmstat) break;        /* If response OK, done */
  1842.         if (dialdpy && tries > 1)
  1843.           printf(" No response from modem, retrying%s...\n",
  1844.              (tries < 4) ? " again" : "");
  1845.         msleep(300);        /* Otherwise, sleep 1/3 second */
  1846.         dialhup();            /* Hang up */
  1847.         ttflui();            /* Flush input buffer and try again */
  1848.     }
  1849.     if (mdmstat < 1)        /* If we didn't get a response, */
  1850.       return(dialfail(F_MINIT));    /* fail. */
  1851.  
  1852.     if (!dialini) {            /* If using built-in init strings... */
  1853. /*
  1854.   Try to get the model number.  It should be in the getok() response buffer,
  1855.   rbuf[], because the Telebit init string asks for it with the "I" command.
  1856.   If the model number is 965, we have to make another query to narrow it down.
  1857. */
  1858.         if (didweget(rbuf,"962") ||    /* Check model number */
  1859.         didweget(rbuf,"961") ||
  1860.         didweget(rbuf,"963")) {
  1861.         tbmodel = TB_BLAZ;    /* Trailblazer */
  1862.         } else if (didweget(rbuf,"972")) {
  1863.         tbmodel = TB_2500;    /* T2500 */
  1864.         } else if (didweget(rbuf,"968")) {
  1865.         tbmodel = TB_1000;    /* T1000 */
  1866.         } else if (didweget(rbuf,"966") ||
  1867.                didweget(rbuf,"967") ||
  1868.                didweget(rbuf,"964")) {
  1869.         tbmodel = TB_PLUS;    /* Trailblazer-Plus */
  1870.         } else if (didweget(rbuf,"969")) {
  1871.         tbmodel = TB_QBLA;    /* Qblazer */
  1872.         } else if (didweget(rbuf,"970")) {
  1873.         tbmodel = TB_QBLA;    /* Qblazer Plus */
  1874.         } else if (didweget(rbuf,"965")) { /* Most new models */
  1875.         tbati3(965);        /* Go find out */
  1876.         } else if (didweget(rbuf,"971")) { /* T1500 or T2500 */
  1877.         tbati3(971);        /* Go find out */
  1878.         } else if (didweget(rbuf,"123") || didweget(rbuf,"960")) {
  1879.         tbmodel = TB_UNK;    /* Telebit in Hayes mode */
  1880.         }
  1881.         debug(F111,"Telebit model",tb_name[tbmodel],tbmodel);
  1882.         if (dialdpy)
  1883.           printf("Telebit model: %s\n",tb_name[tbmodel]);
  1884.         ttflui();
  1885. /*
  1886.   Dial timeout.  S7 is set to the DIAL TIMEOUT value, or else to 255 if the
  1887.   dial timeout is greater than 255, which is the maximum value for Telebits.
  1888.   S7 can't be set to 0 on Telebits -- it gives an error.
  1889. */
  1890.         if (mdmwait > 255)        /* If dial timeout too big */
  1891.           mdmwait = 255;        /* make it as big as possible. */
  1892. /*
  1893.   Flow control.  If C-Kermit's FLOW-CONTROL is RTS/CTS, then we set this on
  1894.   the modem too.  Unfortunately, many versions of UNIX only allow RTS/CTS
  1895.   to be set outside of Kermit (e.g. by selecting a special device name).
  1896.   In that case, Kermit doesn't know that it should set RTS/CTS on the modem,
  1897.   in which case the user can add the appropriate Telebit command with
  1898.   SET DIAL DIAL-COMMAND.
  1899. */
  1900.         if (flow == FLO_RTSC) {    /* RTS/CTS active in Kermit */
  1901.         sprintf(tbcmdbuf,
  1902.             "ATS7=%d S48=%d S50=0 S58=2 S68=255\015",
  1903.             mdmwait, parity ? 0 : 1);
  1904.         } else
  1905.           sprintf(tbcmdbuf,        /* Otherwise, don't touch modem's */
  1906.               "ATS7=%d S48=%d S50=0 S68=255\015", /* flow control */
  1907.               mdmwait, parity ? 0 : 1);          /* setting. */
  1908.         s = tbcmdbuf;
  1909.         debug(F110,"ckdial Telebit init step 2",s,0);
  1910.         for (tries = 4; tries > 0; tries--) {
  1911.         ttslow(s,pmdminf->wake_rate);
  1912.         mdmstat = getok(5,1);
  1913.         if (mdmstat) break;
  1914.         if (dialdpy && tries > 1)
  1915.           printf(" No response from modem, retrying%s...\n",
  1916.              (tries < 4) ? " again" : "");
  1917.         msleep(500);
  1918.         ttflui();
  1919.         }
  1920.         if (mdmstat < 1)
  1921.           return(dialfail(F_MINIT));
  1922. /*
  1923.   Model-dependent items, but constant per model.
  1924. */
  1925.         switch(tbmodel) {
  1926.           case TB_BLAZ:
  1927.           case TB_PLUS:         /* TrailBlazer-Plus */
  1928.           case TB_1000:        /* T1000 */
  1929.           case TB_2000:        /* T2000 */
  1930.           case TB_2500:        /* T2500 */
  1931. #ifdef COMMENT
  1932. /* Code from edit 183 told modem to follow RS-232 wrt CD and DTR */
  1933.         /* DTR, CD, follow RS-232, pass BREAK */
  1934.         sprintf(tbcmdbuf,"ATS52=1 S53=4 S54=3\015");
  1935. #else
  1936. /* But everybody agreed we should not touch modem's CD and DTR settings. */
  1937.         /* Just pass BREAK */
  1938.         sprintf(tbcmdbuf,"ATS54=3\015");
  1939. #endif /* COMMENT */
  1940.         break;
  1941.           case TB_1600:        /* T1600 */
  1942.           case TB_3000:        /* T3000 */
  1943.           case TB_WBLA:        /* WorldBlazer */
  1944.           case TB_QBLA:        /* Qblazer */
  1945. #ifdef COMMENT
  1946. /* Code from edit 183 */
  1947.         /* Follow RS-232, No CONNECT suffix, pass BREAK */
  1948.         sprintf(tbcmdbuf,"AT&C1&D2&Q0 S59=0 S61=0 S63=0\015");
  1949. #else
  1950. /* Everybody agrees we should not touch modem's CD and DTR settings. */
  1951. /* Also no more &Q0, no more S59=0 (doesn't matter, so don't touch). */
  1952. /* So this section now deals only with treatment of BREAK. */
  1953. /* Here we also raise the result code from X1 to X2, which allows */
  1954. /* the T1600, T3000, and WB to supply NO DIALTONE, BUSY, RRING, and DIALING. */
  1955. /* X2 means something else on the other models. */
  1956.         /* Transmit BREAK in sequence, raise result code. */
  1957.         sprintf(tbcmdbuf,"ATX2 S61=0 S63=0\015");
  1958. #endif /* COMMENT */
  1959.         break;
  1960.           default:            /* Others, do nothing */
  1961.         tbcmdbuf[0] = NUL;
  1962.         break;
  1963.         }
  1964.         s = tbcmdbuf;
  1965.         if (*s) {
  1966.         debug(F110,"ckdial Telebit init step 3",s,0);
  1967.         for (tries = 4; tries > 0; tries--) {
  1968.             ttslow(s,pmdminf->wake_rate);
  1969.             mdmstat = getok(5,1);
  1970.             if (mdmstat) break;
  1971.             if (dialdpy && tries > 1)
  1972.               printf(" No response from modem, retrying%s...\n",
  1973.                  (tries < 4) ? " again" : "");
  1974.             msleep(500);
  1975.             ttflui();
  1976.         }
  1977.         if (mdmstat < 1)
  1978.           dialfail(F_MINIT);
  1979.         } else debug(F100,"ckdial Telebit init step 3 skipped","",0);
  1980.  
  1981. /* Error correction, MNP or V.42 */
  1982.  
  1983.         if (augmdmtyp & DIAL_V42) { /* User wants V.42 */
  1984.         switch (tbmodel) {    /* which implies fallback to MNP. */
  1985.           case TB_PLUS:        /* BC7.00 and up firmware */
  1986.           case TB_2000:        /* now really the same as TB+ ? */
  1987.           case TB_2500:        /* LAPM+compress->MNP->direct */
  1988.             mnpstr = "S50=0 S95=2 S97=1 S98=3 S106=1";
  1989.             break;
  1990.           case TB_1600:
  1991.           case TB_3000:
  1992.           case TB_WBLA:
  1993.           case TB_QBLA:
  1994. #ifdef COMMENT
  1995.             mnpstr = "S180=2 S181=0"; /* V.42, fallback = lock speed */
  1996. #else
  1997. /* Better not to mess with S181, let it be used however user has it set. */
  1998. /* S180=2 allows fallback to MNP, S180=1 disallows fallback to MNP. */
  1999.             mnpstr = "S180=2";    /* V.42 */
  2000. #endif /* COMMENT */
  2001.             break;
  2002.           default:
  2003.             if (dialdpy)
  2004.               printf("V.42 not supported by this Telebit model\n");
  2005.         }
  2006.         } else {            /* Handle DIAL MNP-ENABLE setting */
  2007.         switch (tbmodel) {
  2008.           case TB_BLAZ:        /* TrailBlazer */
  2009.           case TB_PLUS:        /* TrailBlazer-Plus */
  2010.           case TB_1000:        /* T1000 */
  2011.           case TB_2000:        /* T2000 */
  2012.           case TB_2500:        /* T2500 */
  2013.             mnpstr = dialmnp ? "S95=2" : "S95=0"; /* ON, OFF */
  2014.             break;
  2015.           case TB_1600:        /* T1600 */
  2016.           case TB_3000:        /* T3000 */
  2017.           case TB_WBLA:        /* WorldBlazer */
  2018.           case TB_QBLA:        /* Qblazer */
  2019.             mnpstr = dialmnp ? "S180=3" : "S180=0"; /* ON, OFF */
  2020.             /* (Leave S181 fallback method alone) */
  2021.             break;
  2022.           default:
  2023.             mnpstr = "";
  2024.         }
  2025.         }
  2026.  
  2027. /* Dialing protocol */
  2028.  
  2029.         dprstr = "";    /* Initialize dialing protocol string */
  2030.         p = "";        /* and message string */
  2031.         switch (augmdmtyp) {
  2032.           case n_TELEBIT:        /* Start at highest and work down */
  2033.               case n_TBNV:
  2034.                p = "standard";
  2035.         switch (tbmodel) {    /* First group starts with PEP */
  2036.           case TB_BLAZ:        /* TrailBlazer */
  2037.           case TB_PLUS:        /* TrailBlazer-Plus */
  2038.           case TB_1000:        /* T1000 */
  2039.           case TB_2000:        /* T2000 */
  2040.           case TB_2500:        /* T2500 */
  2041.             dprstr = "S50=0 S110=1"; /* PEP, compression allowed. */
  2042.             break;
  2043.           case TB_WBLA:        /* WorldBlazer has PEP */
  2044.             dprstr = "S50=0 S190=1 S191=7"; /* PEP, */
  2045.             break;                /* compression allowed. */
  2046.           case TB_1600:        /* T1600 doesn't have PEP */
  2047.           case TB_3000:        /* T3000 doesn't */
  2048.           case TB_QBLA:        /* Qblazer doesn't*/
  2049.           default:
  2050.             dprstr = "S50=0";    /* No PEP available */
  2051.             break;
  2052.         }
  2053.         break;
  2054.  
  2055.           case n_TBS:        /* Telebit up to 2400 Baud */
  2056.           case n_TBSNV:        /* i.e. "Slow mode". */
  2057.         p = "300/1200/2400 Baud"; /* Leave S90 alone assuming it is */
  2058.         dprstr = "S50=3";      /* already set for V.22 vs 212A */
  2059.         break;
  2060.           case n_TB3:        /* Telebit V.32 */
  2061.           case n_TB3NV:
  2062.         if (tbmodel == TB_3000 || tbmodel == TB_1600 ||
  2063.             tbmodel == TB_2500 || tbmodel == TB_WBLA) {
  2064.             p = "V.32";
  2065.             /* Note: we don't touch S51 (interface speed) here. */
  2066.             /* We're already talking to the modem, and the modem */
  2067.             /* SHOULD be able to make a V.32 call no matter what */
  2068.             /* its interface speed is.  (In practice, however, */
  2069.             /* that is not always true.) */
  2070.             dprstr = "S50=6";
  2071.         } else if (dialdpy)
  2072.           printf("V.32 not supported by this Telebit model.\n");
  2073.         break;
  2074.           case n_TBPEP:        /* Force PEP Protocol */
  2075.               case n_TBPNV:
  2076.         if (tbmodel != TB_1600 && /* Models that don't support PEP */
  2077.             tbmodel != TB_3000 &&
  2078.             tbmodel != TB_QBLA) {
  2079.             p = "PEP";
  2080.             if (tbmodel == TB_WBLA) /* WorldBlazer */
  2081.               dprstr = "S50=255 S190=1 S191=7";
  2082.             else if (tbmodel != TB_1000)
  2083.               dprstr = "S50=255 S110=1"; /* TrailBlazer, etc. */
  2084.             else dprstr = "S50=255"; /* T1000, no compression */
  2085.         } else if (dialdpy)
  2086.           printf("PEP not supported by this Telebit model.\n");
  2087.         break;
  2088.         }
  2089.  
  2090. /* Kermit Spoof */
  2091.  
  2092.         if (dialksp) {
  2093.         p = "Kermit Spoof";
  2094.         switch (parity) {    /* S111 value depends on parity */
  2095.           case 'e': S111 = 12; break;
  2096.           case 'm': S111 = 13; break;
  2097.           case 'o': S111 = 11; break;
  2098.           case 's': S111 = 14; break;
  2099.           case 0:
  2100.           default:  S111 = 10; break;
  2101.  
  2102.         }
  2103.         if (tbmodel != TB_QBLA)
  2104.           sprintf(tbcmdbuf,"AT%s %s S111=%d S112=%d\015",
  2105.                 mnpstr,dprstr,S111,stchr);
  2106.         else {            /* Qblazer has no Kermit spoof */
  2107.             sprintf(tbcmdbuf,"AT%s %s\015", mnpstr,dprstr);
  2108.             p = "No Kermit Spoof";
  2109.             if (dialdpy)
  2110.               printf("Kermit Spoof not supported by Qblazer\n");
  2111.         }
  2112.         } else {            /* KERMIT-SPOOF OFF */
  2113.         p = "No Kermit Spoof";
  2114.         sprintf(tbcmdbuf,"AT%s %s %s\015",
  2115.             mnpstr, dprstr,
  2116.             (tbmodel == TB_QBLA) ? "" : "S111=0");
  2117.         }
  2118.         s = tbcmdbuf;
  2119.         debug(F111,"ckdial Telebit config",p,speed);
  2120.         debug(F110,"ckdial Telebit init step 4",s,0);
  2121.         if (*s) {
  2122.         for (tries = 4; tries > 0; tries--) {
  2123.             ttslow(s,pmdminf->wake_rate);
  2124.             mdmstat = getok(5,1);
  2125.             if (mdmstat) break;
  2126.             if (dialdpy && tries > 1)
  2127.               printf(" No response from modem, retrying%s...\n",
  2128.                  (tries < 4) ? " again" : "");
  2129.             msleep(500);
  2130.             ttflui();
  2131.         }
  2132.         debug(F101,"ckdial telebit init mdmstat","",mdmstat);
  2133.         if (mdmstat < 1)
  2134.           dialfail(F_MINIT);
  2135.         }
  2136.     }
  2137.     /* Done with Telebit protocols, remove bits from modem type */
  2138.     /* Except nonverbal bit */
  2139.     augmdmtyp &= ~(DIAL_PEP|DIAL_V32|DIAL_V42|DIAL_SLO);
  2140.     debug(F101,"ckdial Telebit augmdmtyp","",augmdmtyp);
  2141.     break;
  2142.     }
  2143.  
  2144.     case n_MICROCOM:            /* Interdigit waits for tone dial */
  2145. #ifdef COMMENT
  2146.       {
  2147.         jmp_buf savejmp;
  2148.         alarm(0);
  2149.         savalrm = signal(SIGALRM,dialtime); /* Set alarm handler. */
  2150.         xcpy((char *)savejmp, (char *)sjbuf, sizeof savejmp);
  2151.         if (setjmp(sjbuf)) {
  2152.             /* try the autobaud sequence */
  2153.         xcpy((char *)sjbuf, (char *)savejmp, sizeof savejmp);
  2154.         alarm(5);
  2155.             ttslow("44445", MICROCOM.wake_rate);
  2156.         waitfor(MICROCOM.wake_str);
  2157.         } else {
  2158.         alarm(2);
  2159.         ws = dialini ? dialini : MICROCOM.wake_str;
  2160.         ttslow(ws, MICROCOM.wake_rate);
  2161.             waitfor(ws);
  2162. /*
  2163.   Kermit spoof for Microcom modems.  Untested.
  2164.   This is reportedly the way to do it for QX/3296c, QX/4232hs, QX/4232bis,
  2165.   and QX/9624c.  The effect on other models is unknown.
  2166. */
  2167.         ws = dialksp ? "APM1\015" : "APM0\015";    /* Kermit spoof */
  2168.         ttslow(ws, MICROCOM.wake_rate);
  2169.             waitfor(ws);
  2170.         alarm(0);
  2171.         signal(SIGALRM,savalrm); /* Set alarm handler. */
  2172.         xcpy((char *)sjbuf, (char *)savejmp, sizeof savejmp);
  2173.         }
  2174.     }
  2175. #else
  2176.     ws = dialini ? dialini : MICROCOM.wake_str;
  2177.     debug(F110,"ckdial microcom ttslow",ws,0);
  2178.     ttslow(ws, MICROCOM.wake_rate);
  2179.     alarm(3);
  2180.     debug(F110,"ckdial microcom waitfor",MICROCOM.wake_prompt,0);
  2181.     waitfor(MICROCOM.wake_prompt);
  2182.     debug(F110,"ckdial microcom waitfor done","",0);
  2183.     alarm(0);
  2184. /*
  2185.   Kermit spoof for Microcom modems.  Untested.
  2186.   This is reportedly the way to do it for QX/3296c, QX/4232hs, QX/4232bis,
  2187.   and QX/9624c.  The effect on other models is unknown.
  2188. */
  2189.     ws = dialksp ? "APM1\015" : "APM0\015";    /* Kermit spoof */
  2190.     ttslow(ws, MICROCOM.wake_rate);
  2191.     alarm(3);
  2192.     waitfor(ws);
  2193.     alarm(0);
  2194. #endif /* COMMENT */
  2195.     break;
  2196.  
  2197.     case n_ATTDTDM:        /* DTDM requires BREAK to wake up */
  2198.     ttsndb();        /* Send BREAK */
  2199.     break;            /* ttsndb() defined in ckutio.c */
  2200.  
  2201. #endif /* MINIDIAL */
  2202.  
  2203.     default:            /* Place modem into command mode */
  2204.     ws = dialini ? dialini : pmdminf->wake_str;
  2205.     if (ws && (int)strlen(ws) > 0) {
  2206.         debug(F111,"ckdial default, wake string", ws, pmdminf->wake_rate);
  2207.         ttslow(ws, pmdminf->wake_rate);
  2208.     } else debug(F100,"ckdial no wake_str","",0);
  2209.     if (pmdminf->wake_prompt && (int)strlen(pmdminf->wake_prompt) > 0) {
  2210.         debug(F110,"ckdial default, waiting for wake_prompt",
  2211.           pmdminf->wake_prompt,0);
  2212.         alarm(10);
  2213.         waitfor(pmdminf->wake_prompt);
  2214.     } else debug(F100,"ckdial no wake_prompt","",0);
  2215.     break;
  2216.     }
  2217.     alarm(0);                /* Turn off alarm */
  2218.     debug(F100,"ckdial got wake prompt","",0);
  2219.     msleep(500);            /* Allow settling time */
  2220.  
  2221. #ifndef MINIDIAL
  2222.  
  2223. /* Enable/disable MNP (Telebit already done above) */
  2224.  
  2225.     switch (augmdmtyp) {
  2226.       case n_HST:
  2227.     if (dialmnp)            /* EC & compression enabled */
  2228.       ttslow("AT&M4&K1\015",pmdminf->wake_rate);
  2229.     else                /* EC & compression disabled */
  2230.       ttslow("AT&M0&K0\015",pmdminf->wake_rate);
  2231.     getok(5,1);            /* Get response */
  2232.     break;
  2233.  
  2234.      /* Add others here ... */
  2235.  
  2236.       default:
  2237.     break;
  2238.     }
  2239. #endif /* MINIDIAL */
  2240.  
  2241. /* Put modem into dialing mode, if the modem requires it. */
  2242.  
  2243.     if (pmdminf->dmode_str && *(pmdminf->dmode_str)) {
  2244.     ttslow(pmdminf->dmode_str, pmdminf->dial_rate);
  2245.     savalrm = signal(SIGALRM,dialtime);
  2246.     alarm(10);
  2247.     /* Wait for prompt, if any expected */
  2248.     if (pmdminf->dmode_prompt && *(pmdminf->dmode_prompt)) {
  2249.         waitfor(pmdminf->dmode_prompt);
  2250.         msleep(300);
  2251.     }
  2252.     alarm(0);         /* Turn off alarm on dialing prompts */
  2253.     signal(SIGALRM,savalrm); /* Restore alarm */
  2254.     ttflui();         /* Clear out stuff from waking modem up */
  2255.     }
  2256.  
  2257. /* Dial the number.  First form the dialing string. */
  2258.  
  2259. #ifdef DYNAMIC
  2260.     if (!lbuf) {            /* If, for some reason, this is NULL */
  2261.     if (!(lbuf = malloc(LBUFL+1))) { /* allocate it... */
  2262.         dialsta = DIA_IE;
  2263.         return(0);
  2264.     }
  2265.     }
  2266. #endif /* DYNAMIC */
  2267.     sprintf(lbuf, dialcmd ? dialcmd : pmdminf->dial_str, telnbr);
  2268.     if ((int)strlen(lbuf) > LBUFL) {
  2269.     printf("DIAL command + phone number too long!\n");
  2270.     dreset();
  2271. #ifdef DYNAMIC
  2272.     if (lbuf) free(lbuf); lbuf = NULL;
  2273.     if (rbuf) free(rbuf); rbuf = NULL;
  2274.     if (fbuf) free(fbuf); fbuf = NULL;
  2275. #endif /* DYNAMIC */
  2276.     return(1);     /* No conversation with modem to complete dialing */
  2277.     }
  2278.     debug(F110,"dialing",lbuf,0);
  2279.     ttslow(lbuf,pmdminf->dial_rate);    /* Send the dialing string */
  2280.  
  2281.     fail_code = F_MODEM;        /* New default failure code changes */
  2282.     dial_what = DW_DIAL;        /* and our state, too. */
  2283.     if (dialdpy) {            /* If showing progress */
  2284.     p = ck_time();            /* get current time; */
  2285.     if (*p) printf(" Dialing: %s...\n",p);
  2286.     }
  2287.     x = alarm(waitct);            /* This much time allowed. */
  2288.     debug(F101,"ckdial old alarm","",x);
  2289.     debug(F101,"ckdial waitct","",waitct);
  2290.  
  2291. #ifndef MINIDIAL
  2292.     switch (augmdmtyp) {
  2293.       case n_RACAL:            /* Acknowledge dialing string */
  2294.     sleep(3);
  2295.     ttflui();
  2296.     ttoc('\015');
  2297.     break;
  2298.       case n_VENTEL:
  2299.     waitfor("\012\012");        /* Ignore the first two strings */
  2300.     break;
  2301.       default:
  2302.     break;
  2303.     }
  2304. #endif /* MINIDIAL */
  2305.  
  2306. /* Check for connection */
  2307.  
  2308.     mdmstat = 0;            /* No status yet */
  2309.     strcpy(lbuf,"No Connection");    /* Default reason for failure */
  2310.     debug(F101,"dial awaiting response, augmdmtyp","",augmdmtyp);
  2311.     while (mdmstat == 0) {
  2312.     switch (augmdmtyp) {
  2313.       default:
  2314.         for (n = -1; n < LBUFL-1; ) { /* Accumulate response */
  2315.         c2 = ddinc(0);        /* Read a character, blocking */
  2316.         if (c2 == 0 || c2 == -1) /* Ignore NULs and errors */
  2317.           continue;        /* (Timeout will handle errors) */
  2318.         else            /* Real character, keep it */
  2319.           lbuf[++n] = c2 & 0177;
  2320.         dialoc(lbuf[n]);    /* Maybe echo it  */
  2321.                 if (augmdmtyp == n_CCITT) { /* V.25 bis dialing... */
  2322. /*
  2323.   This assumes that V.25bis indications are all at least 3 characters long
  2324.   and are terminated by either CRLF or LFCR.
  2325. */
  2326.             if (n < 3) continue;
  2327.             if ((lbuf[n] == CR) && (lbuf[n-1] == LF)) break;
  2328.             if ((lbuf[n] == LF) && (lbuf[n-1] == CR)) break;
  2329.         }
  2330. #ifndef MINIDIAL
  2331.           else if (augmdmtyp == n_DIGITEL) {
  2332.             if (((lbuf[n] == CR) && (lbuf[n-1] == LF)) ||
  2333.             ((lbuf[n] == LF) && (lbuf[n-1] == CR)))
  2334.               break;
  2335.             else
  2336.               continue;
  2337.         }
  2338. #endif /* MINIDIAL */
  2339.           else {        /* All others, break on CR or LF */
  2340.             if ( lbuf[n] == CR || lbuf[n] == LF ) break;
  2341.         }
  2342.         }
  2343.         lbuf[++n] = '\0';        /* Terminate response from modem */
  2344.         debug(F111,"ckdial modem response",lbuf,n);
  2345.         if (n) {            /* If one or more characters present */
  2346.         switch (augmdmtyp) {    /* check for modem response message. */
  2347. #ifndef MINIDIAL
  2348.           case n_ATTMODEM:
  2349.             /* Careful - "Connected" / "Not Connected" */
  2350.             if (didweget(lbuf,"Busy")) { 
  2351.             mdmstat = FAILED;
  2352.             dialsta = DIA_BUSY;
  2353.             } else if (didweget(lbuf,"Not connected") ||
  2354.                    didweget(lbuf,"Not Connected")) { 
  2355.             mdmstat = FAILED;
  2356.             dialsta = DIA_NOCA;
  2357.             } else if (didweget(lbuf,"No dial tone") ||
  2358.                    didweget(lbuf,"No Dial Tone")) { 
  2359.             mdmstat = FAILED;
  2360.             dialsta = DIA_NODT;
  2361.             } else if (didweget(lbuf,"No answer") ||
  2362.                    didweget(lbuf,"No Answer")) {
  2363.             mdmstat = FAILED;
  2364.             dialsta = DIA_NOAN;
  2365.             } else if (didweget(lbuf,"Answered") ||
  2366.                    didweget(lbuf,"Connected")) {
  2367.             mdmstat = CONNECTED;
  2368.             dialsta = DIA_OK;
  2369.             }
  2370.             break;
  2371.  
  2372.           case n_ATTISN:
  2373.             if (didweget(lbuf,"ANSWERED")) {
  2374.             mdmstat = CONNECTED;
  2375.             dialsta = DIA_OK;
  2376.             } else if (didweget(lbuf,"BUSY")) { 
  2377.             mdmstat = FAILED;
  2378.             dialsta = DIA_BUSY;
  2379.             } else if (didweget(lbuf,"DISCONNECT")) { 
  2380.             mdmstat = FAILED;
  2381.             dialsta = DIA_DISC;
  2382.             } else if (didweget(lbuf,"NO ANSWER")) { 
  2383.             mdmstat = FAILED;
  2384.             dialsta = DIA_NOAN;
  2385.             } else if (didweget(lbuf,"WRONG ADDRESS")) {
  2386.             mdmstat = FAILED;
  2387.             dialsta = DIA_NOAC;
  2388.             }
  2389.             break;
  2390.  
  2391.           case n_ATTDTDM:
  2392.             if (didweget(lbuf,"ANSWERED")) {
  2393.             mdmstat = CONNECTED;
  2394.             } else if (didweget(lbuf,"BUSY")) { 
  2395.             mdmstat = FAILED;
  2396.             dialsta = DIA_BUSY;
  2397.             } else if (didweget(lbuf,"CHECK OPTIONS")) { 
  2398.             mdmstat = FAILED;
  2399.             dialsta = DIA_ERR;
  2400.             } else if (didweget(lbuf,"DISCONNECTED")) { 
  2401.             mdmstat = FAILED;
  2402.             dialsta = DIA_DISC;
  2403.             } else if (didweget(lbuf,"DENIED")) {
  2404.             mdmstat = FAILED;
  2405.             dialsta = DIA_NOAC;
  2406.             }
  2407. #ifdef DEBUG
  2408. #ifdef ATT6300
  2409.             else if (deblog && didweget(lbuf,"~~"))
  2410.               mdmstat = CONNECTED;
  2411. #endif /* ATT6300 */
  2412. #endif /* DEBUG */
  2413.             break;
  2414. #endif /* MINIDIAL */
  2415.  
  2416.           case n_CCITT:            /* CCITT V.25bis */
  2417. #ifndef MINIDIAL
  2418.           case n_DIGITEL:        /* or Digitel variant */
  2419. #endif /* MINIDIAL */
  2420.             if (didweget(lbuf,"VAL")) {    /* Dial command confirmation */
  2421. #ifndef MINIDIAL
  2422.             if (augmdmtyp == n_CCITT)
  2423. #endif /* MINIDIAL */
  2424.               continue;        /* Go back and read more */
  2425. #ifndef MINIDIAL
  2426. /* Digitel doesn't give an explicit connect confirmation message */
  2427.             else {
  2428.                 int n;
  2429.                 for (n = -1; n < LBUFL-1; ) {
  2430.                 lbuf[++n] = c2 = ddinc(0) & 0177;
  2431.                 dialoc(lbuf[n]);
  2432.                 if (((lbuf[n] == CR) && (lbuf[n-1] == LF)) ||
  2433.                     ((lbuf[n] == LF) && (lbuf[n-1] == CR)))
  2434.                   break;
  2435.                 }
  2436.                 mdmstat = CONNECTED; /* Assume we're connected */
  2437.                 if (dialdpy && carrier != CAR_OFF) {
  2438.                 sleep(1);     /* Wait a second */
  2439.                 n = ttgmdm();    /* Try to read modem signals */
  2440.                 if ((n > -1) && ((n & BM_DCD) == 0))
  2441.                   printf("Warning: No Carrier\n");
  2442.                 }
  2443.               }
  2444. #endif /* MINIDIAL */
  2445.             } else if (didweget(lbuf,"CNX")) { /* Connected */
  2446.             mdmstat = CONNECTED;
  2447.                     } else if (didweget(lbuf, "INV")) {
  2448.             mdmstat = FAILED;    /* Command error */
  2449.             dialsta = DIA_ERR;
  2450.             strcpy(lbuf,"INV");
  2451.             } else if (didweget(lbuf,"CFI")) { /* Call Failure */
  2452. #ifdef COMMENT
  2453. /*
  2454.   V.25 bis says that the failure reason comes on the same line, so
  2455.   we don't need to read any more characters here.
  2456. */
  2457.             for (n = 0; n < LBUFL-1; n++) { /* Read reason */
  2458.                 lbuf[n] = c2 = (ddinc(0) & 0177);
  2459.                             if (c2 == LF) /* Modem answers LF CR */
  2460.                   continue;
  2461.                 dialoc(lbuf[n]);
  2462.                 if (lbuf[n] == CR || lbuf[n] == LF) break;
  2463.             }
  2464. #endif /* COMMENT */
  2465.             if (didweget(lbuf,"AB")) { /* Interpret reason code */
  2466.                 strcpy(lbuf,"AB: Timed out");
  2467.                 dialsta = DIA_TIMO;
  2468.             } else if (didweget(lbuf,"CB")) {
  2469.                 strcpy(lbuf,"CB: Local DCE Busy");
  2470.                 dialsta = DIA_NRDY;
  2471.             } else if (didweget(lbuf,"ET")) {
  2472.                 strcpy(lbuf,"ET: Busy");
  2473.                 dialsta = DIA_BUSY;
  2474.             } else if (didweget(lbuf, "NS")) {
  2475.                 strcpy(lbuf,"NS: Number not stored");
  2476.                 dialsta = DIA_ERR;
  2477.             } else if (didweget(lbuf,"NT")) {
  2478.                 strcpy(lbuf,"NT: No answer");
  2479.                 dialsta = DIA_NOAN;
  2480.             } else if (didweget(lbuf,"RT")) {
  2481.                 strcpy(lbuf,"RT: Ring tone");
  2482.                 dialsta = DIA_RING;
  2483.             } else if (didweget(lbuf,"PV")) {
  2484.                 strcpy(lbuf,"PV: Parameter value error");
  2485.                 dialsta = DIA_ERR;
  2486.             } else if (didweget(lbuf,"PS")) {
  2487.                 strcpy(lbuf,"PS: Parameter syntax error");
  2488.                 dialsta = DIA_ERR;
  2489.             } else if (didweget(lbuf,"MS")) {
  2490.                 strcpy(lbuf,"MS: Message syntax error");
  2491.                 dialsta = DIA_ERR;
  2492.             } else if (didweget(lbuf,"CU")) {
  2493.                 strcpy(lbuf,"CU: Command unknown");
  2494.                 dialsta = DIA_ERR;
  2495.             } else if (didweget(lbuf,"FC")) {
  2496.                 strcpy(lbuf,"FC: Forbidden call");
  2497.                 dialsta = DIA_NOAC;
  2498.             }
  2499.             mdmstat = FAILED;
  2500.             } else if (didweget(lbuf,"INC")) { /* Incoming Call */
  2501.             strcpy(lbuf,"INC: Incoming call");
  2502.             dialsta = DIA_RING;
  2503.             mdmstat = FAILED;
  2504.             } else if (didweget(lbuf,"DLC")) { /* Delayed Call */
  2505.             strcpy(lbuf,"DLC: Delayed call");
  2506.             dialsta = DIA_NOAN;
  2507.             mdmstat = FAILED;
  2508.             } else        /* Response was probably an echo. */
  2509. #ifndef MINIDIAL
  2510.               if (augmdmtyp == n_CCITT)
  2511. #endif /* MINIDIAL */
  2512.             continue;
  2513. #ifndef MINIDIAL
  2514.               else    /* Digitel: If no error, then connect. */
  2515.             mdmstat = CONNECTED;
  2516. #endif /* MINIDIAL */
  2517.             break;
  2518.  
  2519. #ifndef MINIDIAL
  2520.           case n_CERMETEK:
  2521.             if (didweget(lbuf,"\016A")) {
  2522.             mdmstat = CONNECTED;
  2523.             ttslow("\016U 1\015",200); /* Make transparent*/
  2524.             }
  2525.             break;
  2526.  
  2527.           case n_DF100:         /* DF100 has short response codes */
  2528.             if (strcmp(lbuf,"A") == 0) {
  2529.             mdmstat = CONNECTED; /* Attached */
  2530.             dialsta = DIA_OK;
  2531.             } else if (strcmp(lbuf,"N") == 0) {
  2532.             mdmstat = FAILED;
  2533.             dialsta = DIA_NOAN; /* No answer or no dialtone */
  2534.             } else if (strcmp(lbuf,"E") == 0 ||    /* Error */
  2535.                    strcmp(lbuf,"R") == 0) { /* "Ready" (?) */
  2536.             mdmstat = FAILED;
  2537.             dialsta = DIA_ERR; /* Command error */
  2538.             }
  2539.             /* otherwise fall thru... */
  2540.  
  2541.           case n_DF200:
  2542.             if (didweget(lbuf,"Attached")) {
  2543.             mdmstat = CONNECTED;
  2544.             dialsta = DIA_OK;
  2545.             /*
  2546.              * The DF100 will respond with "Attached" even if DTR
  2547.              * and/or carrier are not present.    Another reason to
  2548.              * (also) wait for carrier?
  2549.              */
  2550.             } else if (didweget(lbuf,"Busy")) {
  2551.             mdmstat = FAILED;
  2552.             dialsta = DIA_BUSY;
  2553.             } else if (didweget(lbuf,"Disconnected")) {
  2554.             mdmstat = FAILED;
  2555.             dialsta = DIA_DISC;
  2556.             } else if (didweget(lbuf,"Error")) {
  2557.             mdmstat = FAILED;
  2558.             dialsta = DIA_ERR;
  2559.             } else if (didweget(lbuf,"No answer")) {
  2560.             mdmstat = FAILED;
  2561.             dialsta = DIA_NOAN;
  2562.             } else if (didweget(lbuf,"No dial tone")) {
  2563.             mdmstat = FAILED;
  2564.             dialsta = DIA_NODT;
  2565.             } else if (didweget(lbuf,"Speed:)")) {
  2566.             mdmstat = FAILED;
  2567.             dialsta = DIA_ERR;
  2568.             }
  2569.             /*
  2570.              * It appears that the "Speed:..." response comes after an
  2571.              * "Attached" response, so this is never seen.  HOWEVER,
  2572.              * it would be very handy to detect this and temporarily
  2573.              * reset the speed, since it's a nuisance otherwise.
  2574.              * If we wait for some more input from the modem, how do
  2575.              * we know if it's from the remote host or the modem?
  2576.              * Carrier reportedly doesn't get set until after the
  2577.              * "Speed:..." response (if any) is sent.  Another reason
  2578.              * to (also) wait for carrier.
  2579.              */
  2580.             break;
  2581.  
  2582.           case n_GDC:
  2583.             if (didweget(lbuf,"ON LINE"))
  2584.             mdmstat = CONNECTED;
  2585.             else if (didweget(lbuf,"NO CONNECT"))
  2586.             mdmstat = FAILED;
  2587.             break;
  2588.  
  2589.           case n_USROBOT:
  2590.           case n_HST:
  2591.           case n_TELEBIT:
  2592. #endif /* MINIDIAL */
  2593.           case n_HAYES:
  2594.             if (mdmspd && !network) {
  2595.             s = lbuf;
  2596.             while (*s != '\0' && *s != 'C') s++;
  2597.             cptr = (*s == 'C') ? s : NULL;
  2598.             conspd = 0L;
  2599.             if ((cptr != NULL) && !strncmp(cptr,"CONNECT ",8)) {
  2600.                 if ((int)strlen(cptr) < 9)   /* Just CONNECT, */
  2601.                   conspd = 300L;         /* use 300 bps */
  2602.                 else if (isdigit(*(cptr+8))) /* not CONNECT FAST */
  2603.                   conspd = atol(cptr + 8);   /* CONNECT nnnn */
  2604.                 if (conspd != speed) {
  2605.                 if ((conspd / 10L) > 0) {
  2606.                     if (ttsspd((int) (conspd / 10L)) < 0) {
  2607.                        printf(" Can't change speed to %ld\r\n",
  2608.                            conspd);
  2609.                     } else {
  2610.                     speed = conspd;
  2611.                     mdmstat = CONNECTED;
  2612.                     if ( !quiet && !backgrd )
  2613.                       printf(" Speed changed to %ld\r\n",
  2614.                          conspd);
  2615.                     }
  2616.                 }
  2617.                 } /* Expanded to handle any conceivable speed */
  2618.             }
  2619.             }
  2620. #ifndef MINIDIAL
  2621.             if (mymdmtyp == n_TELEBIT) {
  2622.             if (didweget(lbuf,"CONNECT FAST/KERM")) {
  2623.                 mdmstat = CONNECTED;
  2624.                 if (!quiet && !backgrd) printf("FAST/KERM ");
  2625.                 break;
  2626.             }
  2627.              }
  2628. #endif /* MINIDIAL */
  2629.               if (didweget(lbuf,"RRING") ||
  2630.             didweget(lbuf,"RINGING") ||
  2631.             didweget(lbuf,"DIALING")) {
  2632.             mdmstat = 0;
  2633.             } else if (didweget(lbuf,"CONNECT")) {
  2634.             mdmstat = CONNECTED;
  2635.             } else if (didweget(lbuf,"NO CARRIER")) {
  2636.             mdmstat = FAILED;
  2637.             dialsta = DIA_NOCA;
  2638.             } else if (didweget(lbuf,"NO DIALTONE")) {
  2639.             mdmstat = FAILED;
  2640.             dialsta = DIA_NODT;
  2641.             } else if (didweget(lbuf,"NO DIAL TONE")) {
  2642.             mdmstat = FAILED;
  2643.             dialsta = DIA_NODT;
  2644.             } else if (didweget(lbuf,"BUSY")) {
  2645.             mdmstat = FAILED;
  2646.             dialsta = DIA_BUSY;
  2647.             } else if (didweget(lbuf,"NO ANSWER")) {
  2648.             mdmstat = FAILED;
  2649.             dialsta = DIA_NOAN;
  2650.             } else if (didweget(lbuf,"VOICE")) {
  2651.             mdmstat = FAILED;
  2652.             dialsta = DIA_VOIC;
  2653.             } else if (didweget(lbuf,"RING")) {
  2654.             mdmstat = FAILED;
  2655.             dialsta = DIA_RING;            
  2656.             } else if (didweget(lbuf,"ERROR")) {
  2657.             mdmstat = FAILED;
  2658.             dialsta = DIA_ERR;
  2659.             }
  2660.             break;
  2661. #ifndef MINIDIAL
  2662.           case n_PENRIL:
  2663.             if (didweget(lbuf,"OK")) {
  2664.             mdmstat = CONNECTED;
  2665.             } else if (didweget(lbuf,"BUSY")) { 
  2666.             mdmstat = FAILED;
  2667.             dialsta = DIA_BUSY;
  2668.             } else if (didweget(lbuf,"NO RING")) {
  2669.             mdmstat = FAILED;
  2670.             dialsta = DIA_NOCA;
  2671.             }
  2672.             break;
  2673.           case n_RACAL:
  2674.             if (didweget(lbuf,"ON LINE"))
  2675.               mdmstat = CONNECTED;
  2676.             else if (didweget(lbuf,"FAILED CALL"))
  2677.               mdmstat = FAILED;
  2678.             break;
  2679.           case n_ROLM:
  2680.             if (didweget(lbuf,"CALLING"))
  2681.             mdmstat = 0;
  2682.             else if (didweget(lbuf,"COMPLETE"))
  2683.             mdmstat = CONNECTED;
  2684.             else if (didweget(lbuf,"FAILED") ||
  2685.                  didweget(lbuf,"ABANDONDED")) {
  2686.             mdmstat = FAILED;
  2687.             dialsta = DIA_NOCA;
  2688.             } else if (didweget(lbuf,"NOT AVAILABLE") ||
  2689.                    didweget(lbuf,"LACKS PERMISSION") ||
  2690.                    didweget(lbuf,"NOT A DATALINE") ||
  2691.                    didweget(lbuf,"INVALID DATA LINE NUMBER") ||
  2692.                    didweget(lbuf,"INVALID GROUP NAME")) {
  2693.             mdmstat = FAILED;
  2694.             dialsta = DIA_NOAC;
  2695.             } else if (didweget(lbuf,"BUSY")) {
  2696.             mdmstat = FAILED;
  2697.             dialsta = DIA_BUSY;
  2698.             } else if (didweget(lbuf,"DOES NOT ANSWER")) { 
  2699.             mdmstat = FAILED;
  2700.             dialsta = DIA_NOAN;
  2701.             }
  2702.             break;
  2703.           case n_VENTEL:
  2704.             if (didweget(lbuf,"ONLINE!") ||
  2705.             didweget(lbuf,"Online!")) {
  2706.             mdmstat = CONNECTED;
  2707.             } else if (didweget(lbuf,"BUSY") ||
  2708.                    didweget(lbuf,"Busy")) {
  2709.             mdmstat = FAILED;
  2710.             dialsta = DIA_BUSY;
  2711.             } else if (didweget(lbuf,"DEAD PHONE")) {
  2712.             mdmstat = FAILED;
  2713.             dialsta = DIA_DISC;
  2714.             }
  2715.             break;
  2716.           case n_CONCORD:
  2717.             if (didweget(lbuf,"INITIATING"))
  2718.             mdmstat = CONNECTED;
  2719.             else if (didweget(lbuf,"BUSY")) { 
  2720.             mdmstat = FAILED;            
  2721.             dialsta = DIA_BUSY;
  2722.             } else if (didweget(lbuf,"CALL FAILED")) {
  2723.             mdmstat = FAILED;
  2724.             dialsta = DIA_NOCA;
  2725.             }
  2726.             break;
  2727.           case n_MICROCOM:
  2728.             /* "RINGBACK" means phone line ringing, continue */
  2729.             if (didweget(lbuf,"NO CONNECT")) { 
  2730.             mdmstat = FAILED;
  2731.             dialsta = DIA_NOCA;
  2732.             } else if (didweget(lbuf,"BUSY")) { 
  2733.             mdmstat = FAILED;
  2734.             dialsta = DIA_BUSY;
  2735.             } else if (didweget(lbuf,"NO DIALTONE")) { 
  2736.             mdmstat = FAILED;
  2737.             dialsta = DIA_NODT;
  2738.             } else if (didweget(lbuf,"COMMAND ERROR")) { 
  2739.             mdmstat = FAILED;
  2740.             dialsta = DIA_ERR;
  2741.             } else if (didweget(lbuf,"IN USE")) {
  2742.             mdmstat = FAILED;
  2743.             dialsta = DIA_NOAC;
  2744.             } else if (didweget(lbuf,"CONNECT")) {
  2745.             mdmstat = CONNECTED;
  2746.             /* trailing speed ignored */
  2747.             }
  2748.             break;
  2749. #endif /* MINIDIAL */
  2750.         }
  2751.         }
  2752.         break;
  2753.  
  2754. #ifndef MINIDIAL
  2755.     case n_DF03:            /* because response lacks CR or NL */
  2756.         c = ddinc(0) & 0177;
  2757.         dialoc(c);
  2758.         debug(F000,"dial df03 got","",c);
  2759.         if ( c == 'A' ) mdmstat = CONNECTED;
  2760.         if ( c == 'B' ) mdmstat = FAILED;
  2761.         break;
  2762.  
  2763.     case n_TBNV:            /* Hayeslike modems in digit */
  2764.     case n_TB3NV            /* response mode... */:
  2765.     case n_TBPNV:
  2766.     case n_TB4NV:
  2767.     case n_TBSNV:
  2768. #endif /* MINIDIAL */
  2769.     case n_HAYESNV:
  2770.  
  2771. /*
  2772.   The method for reading Hayes numeric result codes has been totally
  2773.   redone as of 5A(174) to account for all of the following.  Not all have
  2774.   been tested, and others probably need to be added.
  2775.  
  2776.   Hayes numeric result codes (Hayes 1200 and higher):
  2777.      0 = OK
  2778.      1 = CONNECT at 300 bps (or 1200 bps on Hayes 1200 with basic code set)
  2779.      2 = RING
  2780.      3 = NO CARRIER
  2781.      4 = ERROR (in command line)
  2782.      5 = CONNECT 1200 (extended code set)
  2783.   Hayes 2400 and higher:
  2784.      6 = NO DIALTONE
  2785.      7 = BUSY
  2786.      8 = NO ANSWER
  2787.      9 = (there is no 9)
  2788.     10 = CONNECT 2400
  2789.   Reportedly, the codes for Hayes V.32 modems are:
  2790.     1x = CONNECT <suffix>
  2791.     5x = CONNECT 1200 <suffix>
  2792.     9x = CONNECT 2400 <suffix>
  2793.    11x = CONNECT 4800 <suffix>
  2794.    12x = CONNECT 9600 <suffix>
  2795.   Where:
  2796.     x:   suffix:
  2797.     R  = RELIABLE
  2798.     RC = RELIABLE COMPRESSED
  2799.     L  = LAPM
  2800.     LC = LAPM COMPRESSED
  2801.   And for Telebits, all the above, except no suffix in numeric mode, plus:
  2802.     11 = CONNECT 4800
  2803.     12 = CONNECT 9600
  2804.     13 = CONNECT 14400
  2805.     14 = CONNECT 19200
  2806.     15 = CONNECT 38400
  2807.     16 = CONNECT 57600
  2808.     20 = CONNECT 300/REL  (= MNP)
  2809.     22 = CONNECT 1200/REL (= MNP)
  2810.     23 = CONNECT 2400/REL (= MNP)
  2811.     46 = CONNECT 7512  (i.e. 75/1200)
  2812.     47 = CONNECT 1275  (i.e. 1200/75)
  2813.     48 = CONNECT 7200
  2814.     49 = CONNECT 12000
  2815.     50 = CONNECT FAST (not on T1600/3000)
  2816.     52 = RRING
  2817.     53 = DIALING
  2818.     54 = NO PROMPTTONE
  2819.     61 = CONNECT FAST/KERM (Kermit spoof)
  2820.     70 = CONNECT FAST/COMP (PEP + compression)
  2821.     71 = CONNECT FAST/KERM/COMP (PEP + compression + Kermit spoof)
  2822. */
  2823. #define NBUFL 8
  2824.         {                /* Nonverbal response code handler */
  2825.         char nbuf[NBUFL+1];        /* Response buffer */
  2826.         int i, j;            /* Buffer pointers */
  2827.         debug(F101,"RESPONSE mdmecho","",mdmecho);
  2828.         if (mdmecho) {        /* Sponge up dialing string echo. */
  2829.         while (1) {
  2830.             c = ddinc(0) & 0x7f;
  2831.             debug(F000,"SPONGE","",c);
  2832.             dialoc(c);
  2833.             if (c == CR) break;
  2834.         }
  2835.         }
  2836.         while (mdmstat == 0) {    /* Read response */
  2837.         for (i = 0; i < NBUFL; i++) /* Clear the buffer */
  2838.           nbuf[i] = '\0';
  2839.         i = 0;            /* Reset the buffer pointer. */
  2840.         c = ddinc(0) & 0177;    /* Get first digit of response. */
  2841.                     /* using an untimed, blocking read. */
  2842.         debug(F000,"RESPONSE-A","",c);
  2843.         dialoc(c);        /* Echo it if requested. */
  2844.         if (!isdigit(c))    /* If not a digit, keep looking. */
  2845.           continue;
  2846.         nbuf[i++] = c;        /* Got first digit, save it. */
  2847.         while (c != CR && i < 8) { /* Now read characters up to CR */
  2848.             x = ddinc(0) & 0177; /* Get a character. */
  2849.             c = (char) x;    /* Got it OK. */
  2850.             debug(F000,"RESPONSE-C","",c);
  2851.             if (c != CR)    /* If it's not a carriage return, */
  2852.               nbuf[i++] = c;    /*  save it. */
  2853.             dialoc(c);        /* Echo it. */
  2854.         }
  2855.         nbuf[i] = '\0';        /* Done, terminate the buffer. */
  2856.         debug(F111,"dial hayesnv lbuf",lbuf,n);
  2857.         debug(F111,"dial hayesnv got",nbuf,i);
  2858.         /*
  2859.           Separate any non-numeric suffix from the numeric result code
  2860.           with a null.
  2861.         */
  2862.         for (j = i-1; (j > -1) && !isdigit(nbuf[j]); j--)
  2863.           nbuf[j+1] = nbuf[j];
  2864.         j++;
  2865.         nbuf[j++] = '\0';
  2866.         debug(F110,"dial hayesnv numeric",nbuf,0);
  2867.         debug(F111,"dial hayesnv suffix ",nbuf+j,j);
  2868.         if ((int)strlen(nbuf) > 3) /* Probably phone number echoing. */
  2869.           continue;
  2870.         /*
  2871.           Now read and interpret the results...
  2872.         */
  2873.         i = atoi(nbuf);        /* Convert to integer */
  2874.         switch (i) {
  2875.           case 1:        /* CONNECT */
  2876.             mdmstat = CONNECTED; /* Could be any speed */
  2877.             break;
  2878.           case 2:        /* RING */
  2879.             if (dialdpy) printf("\r\n Local phone is ringing!\r\n");
  2880.             mdmstat = FAILED;
  2881.             dialsta = DIA_RING;
  2882.             break;
  2883.           case 3:        /* NO CARRIER */
  2884.             if (dialdpy) printf("\r\n No Carrier.\r\n");
  2885.             mdmstat = FAILED;
  2886.             dialsta = DIA_NOCA;
  2887.             break;
  2888.           case 4:        /* ERROR */
  2889.             if (dialdpy) printf("\r\n Modem Command Error.\r\n");
  2890.             mdmstat = FAILED;
  2891.             dialsta = DIA_ERR;
  2892.             break;
  2893.           case 5:        /* CONNECT 1200 */
  2894.             spdchg(1200L);    /* Change speed if necessary. */
  2895.             mdmstat = CONNECTED;
  2896.             break;
  2897.           case 6:        /* NO DIALTONE */
  2898.             if (dialdpy) printf("\r\n No Dialtone.\r\n");
  2899.             mdmstat = FAILED;
  2900.             dialsta = DIA_NODT;
  2901.             break;
  2902.           case 7:        /* BUSY */
  2903.             if (dialdpy) printf("\r\n Busy.\r\n");
  2904.             mdmstat = FAILED;
  2905.             dialsta = DIA_BUSY;
  2906.             break;
  2907.           case 8:        /* NO ANSWER */
  2908.             if (dialdpy) printf("\r\n No Answer.\r\n");
  2909.             mdmstat = FAILED;
  2910.             dialsta = DIA_NOAN;
  2911.             break;
  2912.           case 9:        /* CONNECT 2400 */
  2913.           case 10:
  2914.             spdchg(2400L);    /* Change speed if necessary. */
  2915.             mdmstat = CONNECTED;
  2916.             break;
  2917.           case 11:        /* CONNECT 4800 */
  2918.             spdchg(4800L);
  2919.             mdmstat = CONNECTED;
  2920.             break;
  2921.           case 12:        /* CONNECT 9600 */
  2922.             spdchg(9600L);
  2923.             mdmstat = CONNECTED;
  2924.             break;
  2925.           case 13:        /* CONNECT 14400 */
  2926.             spdchg(14400L);
  2927.             mdmstat = CONNECTED;
  2928.             break;
  2929.           case 14:
  2930.             spdchg(19200L);    /* CONNECT 19200 */
  2931.             mdmstat = CONNECTED;
  2932.             break;
  2933.           case 15:        /* CONNECT 34800 */
  2934.             spdchg(38400L);
  2935.             mdmstat = CONNECTED;
  2936.             break;
  2937.           case 16:        /* CONNECT 57600 */
  2938.             spdchg(57600L);
  2939.             mdmstat = CONNECTED;
  2940.             break;
  2941.           case 20:        /* CONNECT 300/REL */
  2942.             spdchg(300L);
  2943.             mdmstat = CONNECTED;
  2944.             break;
  2945.           case 22:        /* CONNECT 1200/REL */
  2946.             spdchg(1200L);
  2947.             mdmstat = CONNECTED;
  2948.             break;
  2949.           case 23:        /* CONNECT 2400/REL */
  2950.             spdchg(2400L);
  2951.             mdmstat = CONNECTED;
  2952.             break;
  2953.           case 46:        /* CONNECT 7512 */
  2954.             spdchg(8880L);    /* 75/1200 split speed */
  2955.             mdmstat = CONNECTED; /* (special C-Kermit code) */
  2956.             break;
  2957.           case 47:        /* CONNECT 1200/75 */
  2958.             mdmstat = CONNECTED; /* Speed not supported by Kermit */
  2959.             printf("CONNECT 1200/75 - Not support by C-Kermit\r\n");
  2960.             break;
  2961.           case 48:        /* CONNECT 7200 */
  2962.             spdchg(7200L);
  2963.             mdmstat = CONNECTED;
  2964.             break;
  2965.           case 49:        /* CONNECT 12000 */
  2966.             spdchg(12000L);
  2967.             mdmstat = CONNECTED;
  2968.             break;
  2969. #ifndef MINIDIAL
  2970.           case 50:        /* CONNECT FAST */
  2971.             if (mymdmtyp == n_TELEBIT) /* Early models only */
  2972.               mdmstat = CONNECTED;
  2973.             break;
  2974.           case 52:        /* RRING */
  2975.             if (mymdmtyp == n_TELEBIT)
  2976.               if (dialdpy) printf(" Ringing...\r\n");
  2977.             break;
  2978.           case 53:        /* DIALING */
  2979.             if (mymdmtyp == n_TELEBIT)
  2980.               if (dialdpy) printf(" Dialing...\r\n");
  2981.             break;
  2982.           case 54:        /* NO PROMPTTONE */
  2983.             if (mymdmtyp == n_TELEBIT) {
  2984.             if (dialdpy) printf("\r\n No Prompttone.\r\n");
  2985.             mdmstat = FAILED;
  2986.             dialsta = DIA_NODT;
  2987.             }
  2988.             break;
  2989.           case 61:        /* Various Telebit PEP modes */
  2990.           case 62:
  2991.           case 63:
  2992.           case 70:
  2993.           case 71:
  2994.           case 72:
  2995.           case 73:
  2996.             if (mymdmtyp == n_TELEBIT) /* Early models only */
  2997.               mdmstat = CONNECTED;
  2998.             break;
  2999. #endif /* MINIDIAL */
  3000.           default:
  3001.             break;
  3002.         }
  3003.         }
  3004.         if (mdmstat == CONNECTED && nbuf[j] != '\0') {
  3005.         if (dialdpy) {
  3006.             printf("\r\n");
  3007.             if (nbuf[j] == 'R') printf("RELIABLE");
  3008.             if (nbuf[j] == 'L') printf("LAPM");
  3009.             if (nbuf[j+1] == 'C') printf(" COMPRESSED");
  3010.             printf("\r\n");
  3011.         }
  3012.         }
  3013.     }
  3014.         break;
  3015.  
  3016.     case n_UNKNOWN: {
  3017.             int x, y = waitct;
  3018.         mdmstat = FAILED;    /* Assume failure. */
  3019.         while (y-- > -1) {
  3020.             x = ttchk();
  3021.             if (x > 0) {
  3022.             if (x > LBUFL) x = LBUFL;
  3023.             x = ttxin(x,(CHAR *)lbuf);
  3024.             if ((x > 0) && dialdpy) conol(lbuf);
  3025.             }
  3026.             x = ttgmdm();    /* Try to read modem signals */
  3027.             if (x < 0) break;    /* Can't, fail. */
  3028.             if (x & BM_DCD) {    /* Got signals OK.  Carrier present? */
  3029.             mdmstat = CONNECTED; /* Yes, done. */
  3030.             break;
  3031.             }            /* No, keep waiting. */
  3032.             sleep(1);
  3033.         }
  3034.             break;
  3035.           }
  3036.     }                /* switch (augmdmtyp) */
  3037.     }                    /* while (mdmstat == 0) */
  3038.     x = alarm(0);            /* Turn off alarm. */
  3039.     debug(F101,"ckdial alarm off","",x);
  3040.     if ( mdmstat != CONNECTED )        /* Failure detected by modem  */
  3041.       return(dialfail(F_MODEM));
  3042.  
  3043.     msleep(1000);            /* In case DTR blinks  */
  3044.     debug(F100,"dial succeeded","",0);
  3045.     if (
  3046. #ifndef MINIDIAL
  3047.     augmdmtyp != n_ROLM        /* Rolm has weird modem signaling */
  3048. #else
  3049.     1
  3050. #endif /* MINIDIAL */
  3051.     ) {
  3052.     alarm(3);            /* In case ttpkt() gets stuck... */
  3053.     ttpkt(speed,FLO_DIAX,parity);    /* Cancel dialing state ioctl */
  3054.     }
  3055.     dreset();                /* Reset alarms and signals. */
  3056.     if (!quiet && !backgrd)
  3057.     if (dialdpy) {            /* If DIAL DISPLAY ON, */
  3058.     p = ck_time();            /* include timestamp.  */
  3059.     if (*p) printf(" Call complete: %s.\07\n",p);
  3060.     } else
  3061.       printf (" Call complete.\07\n");
  3062. #ifdef DYNAMIC
  3063.     if (lbuf) free(lbuf); lbuf = NULL;
  3064.     if (rbuf) free(rbuf); rbuf = NULL;
  3065.     if (fbuf) free(fbuf); fbuf = NULL;
  3066. #endif /* DYNAMIC */
  3067.     dialsta = DIA_OK;
  3068.     return(1);                /* Return successfully */
  3069. }
  3070.  
  3071. /*
  3072.   getok() - wait up to n seconds for OK (0) or ERROR (4) response from modem.
  3073.   Use with Hayeslike or CCITT modems for reading the reply to a nondialing
  3074.   command.
  3075.  
  3076.   Second argument says whether to be strict about numeric result codes, i.e.
  3077.   to require they be preceded by CR or else be the first character in the
  3078.   response, e.g. to prevent the ATH0<CR> echo from looking like a valid
  3079.   response.  Strict == 0 is needed for ATI on Telebit, which can return the
  3080.   model number concatenated with the numeric response code, e.g. "9620"
  3081.   ("962" is the model number, "0" is the response code).  getok() Returns:
  3082.  
  3083.    0 if it timed out,
  3084.    1 if it succeeded,
  3085.   -1 on modem command, i/o, or other error.
  3086. */
  3087. #ifdef CK_POSIX_SIG            /* Jump-buf for getok(). */
  3088. static sigjmp_buf okbuf;
  3089. #else
  3090. static jmp_buf okbuf;
  3091. #endif /* CK_POSIX_SIG */
  3092.  
  3093. static SIGTYP
  3094. oktimo(foo) int foo; {            /* Alarm handler for getok(). */
  3095. #ifdef OSK                /* OS-9, see comment in dialtime(). */
  3096.     sigmask(-1);
  3097. #endif /* OSK */
  3098. #ifdef CK_POSIX_SIG
  3099.     siglongjmp(okbuf,1);
  3100. #else
  3101.     longjmp(okbuf,1);
  3102. #endif /* CK_POSIX_SIG */
  3103. }
  3104.  
  3105. static int
  3106. getok(n, strict) int n, strict; {
  3107.     CHAR c;
  3108.     int i, x, status, oldalarm;
  3109.     SIGTYP (*saval)();            /* For saving alarm handler locally */
  3110.  
  3111.     debug(F101,"getok entry n","",n);
  3112.  
  3113. #ifdef DYNAMIC
  3114.     if (!rbuf) {
  3115.     if (!(rbuf = malloc(RBUFL+1))) { /* Allocate input line buffer */
  3116.         dialsta = DIA_IE;
  3117.         return(-1);
  3118.     }
  3119.     debug(F101,"GETOK rbuf malloc ok","",RBUFL+1);
  3120.     }
  3121. #endif /* DYNAMIC */
  3122.  
  3123.     mdmecho = 0;            /* Assume no echoing of commands */
  3124.     saval = signal(SIGALRM,oktimo);    /* Set response timer, */
  3125.     oldalarm = alarm(n);        /* saving old one. */
  3126.     debug(F101,"getok alarm ok","",oldalarm);
  3127.     if (
  3128. #ifdef CK_POSIX_SIG
  3129.     sigsetjmp(okbuf,1)
  3130. #else
  3131.     setjmp(okbuf)
  3132. #endif /* CK_POSIX_SIG */
  3133.     ) {        /* Timed out. */
  3134.     alarm(oldalarm);        /* Restore old alarm */
  3135.      if (saval) signal(SIGALRM,saval); /* and alarm handler */
  3136.     debug(F100,"getok timeout","",0);
  3137.     ttflui();            /* Flush input buffer */
  3138.     return(0);            /* and return timeout indication */
  3139.  
  3140.     } else if (augmdmtyp == n_CCITT    /* CCITT, easy... */
  3141. #ifndef MINIDIAL
  3142.            || augmdmtyp == n_DIGITEL /* Digitel, ditto. */
  3143. #endif /* MINIDIAL */
  3144.            ) {
  3145.     waitfor("VAL");
  3146.         return(1);
  3147.  
  3148.     } else {                /* Hayes & friends, start here... */
  3149.     status = 0;            /* No status yet. */
  3150.     for (x = 0; x < RBUFL; x++)    /* Initialize response buffer */
  3151.       rbuf[x] = SP;            /*  to all spaces */
  3152.     rbuf[RBUFL] = NUL;        /* and terminate with NUL. */
  3153.     debug(F100,"getok rbuf init ok","",0);
  3154.     while (status == 0) {        /* While no status... */
  3155.         x = ddinc(n);        /* Read a character */
  3156.         if (x < 0) {        /* I/O error */
  3157.         alarm(oldalarm);    /* Turn off alarm */
  3158.         if (saval) signal(SIGALRM,saval); /* and restore handler. */
  3159.         return(-1);        /* Return error code. */
  3160.         }
  3161.         debug(F101,"getok ddinc","",x); /* Got a character. */
  3162.         c = x & 0x7f;        /* Get low order 7 bits */
  3163.         if (!c)            /* Don't deposit NULs */
  3164.           continue;            /* or else didweget() won't work */
  3165.         if (dialdpy) conoc((char)c); /* Echo it if requested */
  3166.         for (i = 0; i < RBUFL-1; i++) /* Rotate buffer */
  3167.           rbuf[i] = rbuf[i+1];
  3168.         rbuf[RBUFL-1] = c;        /* Deposit character at end */
  3169.         debug(F000,"getok:",rbuf,(int) c); /* Log it */
  3170.         switch (c) {        /* Interpret it. */
  3171.           case CR:            /* Got a carriage return. */
  3172.         switch(rbuf[RBUFL-2]) {    /* Look at character before it. */
  3173.           case '0':        /* 0 = OK numeric response */
  3174.             if (!strict ||
  3175.             rbuf[RBUFL-3] == CR || rbuf[RBUFL-3] == SP) {
  3176.             augmdmtyp |= DIAL_NV; /* OR in the "nonverbal" bit. */
  3177.             status = 1;    /* Good response */
  3178.             }
  3179.             break;
  3180.           case '4':        /* 4 = ERROR numeric response */
  3181. #ifndef MINIDIAL
  3182.             /* Or Telebit model number 964! */
  3183.             if (mymdmtyp == n_TELEBIT &&
  3184.             isdigit(rbuf[RBUFL-3]) &&
  3185.             isdigit(rbuf[RBUFL-4]))
  3186.               break;
  3187.             else
  3188. #endif /* MINIDIAL */
  3189.               if (!strict ||
  3190.             rbuf[RBUFL-3] == CR || rbuf[RBUFL-3] == SP) {
  3191.             augmdmtyp |= DIAL_NV; /* OR in the nonverbal bit. */
  3192.             status = -1;    /* Bad command */
  3193.             }
  3194.             break;
  3195.         }
  3196.         if (dialdpy && (augmdmtyp & DIAL_NV)) /* If numeric results, */
  3197.           conoc(LF);          /* echo a linefeed too. */
  3198.         break;
  3199.           case LF:            /* Got a linefeed. */
  3200.         /*
  3201.           Note use of explicit octal codes in the string for
  3202.           CR and LF.  We want real CR and LF here, not whatever
  3203.           the compiler happens to replace \r and \n with...
  3204.         */
  3205.         if (!strcmp(rbuf+RBUFL-4,"OK\015\012")) /* Good response */
  3206.           status = 1;
  3207.         else if (!strcmp(rbuf+RBUFL-7,"ERROR\015\012"))    /* Error */
  3208.           status = -1;
  3209.         augmdmtyp &= ~(DIAL_NV); /* Turn off the nonverbal bit */
  3210.         break;
  3211.           /* Check whether modem echoes its commands... */
  3212.           case 't':            /* Got little t */
  3213.         if (!strcmp(rbuf+RBUFL-3,"\015at") || /* See if it's "at" */
  3214.             !strcmp(rbuf+RBUFL-3," at"))
  3215.             mdmecho = 1;
  3216.         debug(F111,"MDMECHO-t",rbuf+RBUFL-2,mdmecho);
  3217.         break;
  3218.           case 'T':            /* Got Big T */
  3219.         if (!strcmp(rbuf+RBUFL-3,"\015AT") ||    /* See if it's "AT" */
  3220.             !strcmp(rbuf+RBUFL-3," AT"))
  3221.             mdmecho = 1;
  3222.         debug(F111,"MDMECHO-T",rbuf+RBUFL-3,mdmecho);
  3223.         break;
  3224.           default:            /* Other characters, accumulate. */
  3225.         status = 0;
  3226.         break;
  3227.         }
  3228.     }
  3229.     debug(F101,"getok returns","",status);
  3230.     alarm(oldalarm);        /* Restore previous alarm */
  3231.     if (saval) signal(SIGALRM,saval); /* and handler */
  3232.     ttflui();            /* Flush input buffer */
  3233.     return(status);            /* Return status */
  3234.     }
  3235. }
  3236.  
  3237. /* Maybe hang up the phone, depending on various SET DIAL parameters. */
  3238.  
  3239. int
  3240. dialhup() {
  3241.     int x = 0;
  3242.     if (dialhng) {            /* DIAL HANGUP ON? */
  3243.     x = mdmhup();            /* Try modem-specific method first */
  3244.     debug(F101,"dialhup mdmhup","",x);
  3245.     if (x > 0) {            /* If it worked, */
  3246.         if (dialdpy)
  3247.           printf(" Modem hangup OK\r\n"); /* fine. */
  3248.     } else if (network) {        /* If we're telnetted to */
  3249.         if (dialdpy)        /* a modem server, just print a msg */
  3250.           printf(" Warning: modem hangup failed\r\n"); /* don't hangup! */
  3251.         return(0);
  3252.     } else {            /* Otherwise */
  3253.         x = tthang();        /* Tell the OS to turn off DTR. */
  3254.         if (dialdpy) {        /* DIAL DISPLAY ON? */
  3255.         if (x > 0)        /* Yes, tell results from tthang() */
  3256.           printf(" Hangup OK\r\n");
  3257.         else if (x == 0)
  3258.           printf(" Hangup skipped\r\n");
  3259.         else
  3260.           perror(" Hangup error");
  3261.         }
  3262.     }
  3263.     } else if (dialdpy) printf(" Hangup skipped\r\n"); /* DIAL HANGUP OFF */
  3264.     return(x);
  3265. }
  3266.  
  3267. /*
  3268.   M D M H U P  --
  3269.  
  3270.   Sends escape sequence to modem, then sends its hangup command.  Returns:
  3271.    0: If modem type is 0 (direct serial connection),
  3272.       or if modem type is < 0 (network connection),
  3273.       or if no action taken because DIAL MODEM-HANGUP is OFF)
  3274.         or because no hangup string for current modem type,
  3275.       or C-Kermit is in remote mode,
  3276.       or if action taken but there was no positive response from modem;
  3277.    1: Success: modem is in command state and acknowledged the hangup command;
  3278.   -1: On modem command error.
  3279. */
  3280. int
  3281. mdmhup() {
  3282. #ifdef MDMHUP
  3283.     MDMINF *p;                /* Modem info structure pointer */
  3284.     int m, x = 0;
  3285.     int xparity;
  3286.  
  3287.     if (dialmhu == 0 || local == 0)    /* If DIAL MODEM-HANGUP is OFF, */
  3288.       return(0);            /*  or not in local mode, fail. */
  3289.  
  3290. #ifdef OS2
  3291. /*
  3292.   In OS/2, if CARRIER is OFF, and there is indeed no carrier signal, any
  3293.   attempt to do i/o at this point can hang the program.  This might be true
  3294.   for other operating systems too.
  3295. */
  3296.     if (!network) {            /* Not a network connection */
  3297.     m = ttgmdm();            /* Get modem signals */
  3298.     if ((m > -1) && (m & BM_DCD == 0)) /* Check for carrier */
  3299.       return(0);            /* No carrier, skip the rest */
  3300.     }
  3301. #endif /* OS2 */
  3302.  
  3303.     m = mdmtyp & 0xff;            /* Get basic modem type (no bits!). */
  3304.     if ((m < 1) || (m > MAX_MDM))    /* If modem type not in range, */
  3305.       return(0);            /*  fail. */
  3306.     p = ptrtab[m-1];            /* Get modem info pointer */
  3307.     if (!(p->hup_str) || !*(p->hup_str)) { /* No hangup string? */
  3308.     debug(F100,"mdmhup no hup_str","",0); /* No, */
  3309.     return(0);            /*  fail. */
  3310.     } else {
  3311.     debug(F110,"mdmhup hup_str",p->hup_str,0); /* Yes. */
  3312.     if (p->esc_str && *(p->esc_str)) { /* Have escape sequence? */
  3313.         debug(F110,"mdmhup esc_str",p->esc_str,0);
  3314.         debug(F101,"mdmhup esc_time","",p->esc_time);
  3315.         xparity = parity;        /* Set PARITY to NONE temporarily */
  3316.         parity = 0;
  3317.         if (ttpkt(speed,FLO_DIAL,parity) < 0) { /* Condition line */
  3318.         parity = xparity;
  3319.         return(-1);        /*  for dialing. */
  3320.         }
  3321.         if (p->esc_time)        /* If we have a guard time */
  3322.           msleep(p->esc_time);    /* Pause for guard time */
  3323.         debug(F100,"mdmhup pause 1 OK","",0);
  3324. #ifdef NETCONN
  3325.         /* Send modem's escape sequence */
  3326.         if (network) {        /* Must catch errors here. */
  3327.         if (ttol((CHAR *)(p->esc_str),(int)strlen(p->esc_str)) < 0) {
  3328.             parity = xparity;
  3329.             return(-1);
  3330.         }
  3331.         } else {
  3332.         ttslow(p->esc_str,p->wake_rate); /* Send escape sequence */
  3333.         debug(F110,"mdmhup ttslow ok",p->esc_str,0);
  3334.         }
  3335. #else
  3336.         ttslow(p->esc_str,p->wake_rate); /* Send escape sequence */
  3337.         debug(F110,"mdmhup ttslow ok",p->esc_str,0);
  3338. #endif /* NETCONN */
  3339.         if (p->esc_time)        /* Pause for guard time again */
  3340.           msleep(p->esc_time);
  3341.         msleep(500);        /* Wait half a sec for echoes. */
  3342.         debug(F100,"mdmhup pause 1 OK","",0);
  3343.         ttflui();            /* Flush response or echo, if any */
  3344.         debug(F100,"mdmhup ttflui OK","",0);
  3345.     }
  3346.     ttslow(p->hup_str,p->wake_rate); /* Now Send hangup string */
  3347.     debug(F110,"mdmhup ttslow ok",p->hup_str,0);
  3348.     if (p->ok_fn) {            /* Look for OK response */
  3349.         debug(F100,"mdmhup calling response function","",0);
  3350.         x = (*(p->ok_fn))(3,1);    /* Give it 3 seconds, be strict. */
  3351.         debug(F101,"mdmhup hangup response","",x);
  3352.     } else {            /* No OK function, */
  3353.         x = 1;            /* so assume it worked */
  3354.         debug(F101,"mdmhup no ok_fn","",x);
  3355.     }
  3356.     parity = xparity;        /* Restore prevailing parity */
  3357.     return(x);            /* Return OK function's return code. */
  3358.     }
  3359. #else                    /* MDMHUP not defined. */
  3360.     return(0);                /* Always fail. */
  3361. #endif /* MDMHUP */
  3362. }
  3363.  
  3364. char *                    /* Let external routines ask */
  3365. getdws(mdmtyp) int mdmtyp; {        /* about dial init-string. */
  3366.     MDMINF * p;
  3367.     if (dialini) return(dialini);
  3368.     if ((mdmtyp & 0xff) < 1 || (mdmtyp & 0xff) > MAX_MDM)
  3369.       return("");
  3370.     p = ptrtab[(mdmtyp & 0xff) -1];
  3371.     return(p->wake_str);
  3372. }
  3373.  
  3374. char *
  3375. getdcs(mdmtyp) int mdmtyp; {        /* Same deal for dial-command */
  3376.     MDMINF * p;
  3377.     if (dialcmd) return(dialcmd);
  3378.     if ((mdmtyp & 0xff) < 1 || (mdmtyp & 0xff) > MAX_MDM)
  3379.       return("");
  3380.     p = ptrtab[(mdmtyp & 0xff) -1];
  3381.     return(p->dial_str);
  3382. }
  3383.  
  3384. #else /* NODIAL */
  3385.  
  3386. char *dialv = "Dial Command Disabled";
  3387.  
  3388. int                    /* To allow NODIAL versions to */
  3389. mdmhup() {                /* call mdmhup(), so calls to  */
  3390.     return(0);                /* mdmhup() need not be within */
  3391. }                    /* #ifndef NODIAL conditionals */
  3392.  
  3393. #endif /* NODIAL */
  3394. #endif /* NOLOCAL */
  3395.