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