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

Defined functions

SIGTYP defined in line 973; never used
ckdial defined in line 1202; used 1 times
ddinc defined in line 1031; used 10 times
dialhup defined in line 2834; used 4 times
dialint defined in line 1014; used 6 times
dialoc defined in line 1138; used 8 times
dialtime defined in line 992; used 6 times
didweget defined in line 1085; used 112 times
dreset defined in line 1099; used 4 times
getdcs defined in line 2963; used 1 times
getdws defined in line 2954; used 2 times
getok defined in line 2728; used 13 times
gtbmodel defined in line 978; used 1 times
mdmhup defined in line 2976; used 3 times
oktimo defined in line 2720; used 1 times
spdchg defined in line 1113; used 15 times
tbati3 defined in line 1158; used 3 times
ttslow defined in line 1055; used 21 times
waitfor defined in line 1070; used 8 times
xcpy defined in line 984; used 4 times

Defined variables

F_reason defined in line 951; used 1 times
augmdmtyp defined in line 956; used 26 times
dialv defined in line 2974; used 1 times
lbuf defined in line 964; used 151 times
mdmecho defined in line 955; used 7 times
mdmstat defined in line 1200; used 92 times
mdmwait defined in line 1200; used 10 times
mymdmtyp defined in line 166; used 22 times
n1 defined in line 167; used 11 times
okbuf defined in line 2718; used 2 times
p defined in line 958; used 46 times
rbuf defined in line 968; used 42 times
sjbuf defined in line 970; used 14 times
tries defined in line 954; used 15 times
waitct defined in line 1200; used 16 times

Defined macros

CONNECTED defined in line 947; used 42 times
DIAL_NV defined in line 262; used 10 times
DIAL_PEP defined in line 266; used 3 times
DIAL_SLO defined in line 269; used 3 times
DIAL_V32 defined in line 267; used 3 times
DIAL_V42 defined in line 268; used 4 times
FAILED defined in line 948; used 26 times
F_int defined in line 162; used 2 times
F_minit defined in line 164; used 9 times
F_modem defined in line 163; used 3 times
F_time defined in line 161; used 4 times
LBUFL defined in line 960; used 7 times
MAX_MDM defined in line 246; used 3 times
MDMINF defined in line 181; used 29 times
NBUFL defined in line 2472; used 2 times
RBUFL defined in line 967; used 18 times
SIGALRM defined in line 73; used 15 times
SIGINT defined in line 74; used 12 times
SIGTYP defined in line 70; used 7 times
SIG_IGN defined in line 72; used 8 times
TB_1000 defined in line 123; used 3 times
TB_1500 defined in line 124; used 1 times
TB_1600 defined in line 125; used 3 times
TB_2000 defined in line 126; used 1 times
TB_2500 defined in line 127; used 4 times
TB_3000 defined in line 128; used 3 times
TB_BLAZ defined in line 121; used 2 times
TB_PLUS defined in line 122; used 3 times
TB_QBLA defined in line 129; used 4 times
TB_UNK defined in line 120; used 5 times
TB_WBLA defined in line 130; used 3 times
TB__MAX defined in line 131; used 1 times
alarm defined in line 71; used 20 times
n_ATTDTDM defined in line 224; used 1 times
n_ATTISN defined in line 225; used 1 times
n_ATTMODEM defined in line 226; used 1 times
n_ATTUPC defined in line 240; used 1 times
n_CCITT defined in line 227; used 5 times
n_CERMETEK defined in line 228; used 1 times
n_CONCORD defined in line 239; used 1 times
n_DF03 defined in line 229; used 1 times
n_DF100 defined in line 230; used 1 times
n_DF200 defined in line 231; used 1 times
n_DIGITEL defined in line 245; used 3 times
n_GDC defined in line 232; used 2 times
n_HAYES defined in line 233; used 4 times
n_HAYESNV defined in line 263; never used
n_HST defined in line 243; used 4 times
n_MICROCOM defined in line 242; used 1 times
n_PENRIL defined in line 234; used 1 times
n_RACAL defined in line 235; used 1 times
n_ROLM defined in line 241; used 3 times
n_TB3 defined in line 271; used 1 times
n_TB3NV defined in line 274; never used
n_TB4 defined in line 275; used 1 times
n_TB4NV defined in line 277; never used
n_TBNV defined in line 272; never used
n_TBPEP defined in line 270; used 2 times
n_TBPNV defined in line 273; used 1 times
n_TBS defined in line 276; used 1 times
n_TBSNV defined in line 278; never used
n_TELEBIT defined in line 244; used 19 times
n_UNKNOWN defined in line 236; used 1 times
n_USROBOT defined in line 237; used 1 times
n_VENTEL defined in line 238; used 1 times
signal defined in line 69; used 27 times
Last modified: 1992-11-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 9947
Valid CSS Valid XHTML 1.0 Strict