|
|
1.1 ! root 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: [email protected]. ! 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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.