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