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: }

Defined functions

dial defined in line 503; used 1 times
dialint defined in line 451; used 2 times
dialtime defined in line 447; used 2 times
didWeGet defined in line 479; used 20 times
reset defined in line 491; used 2 times
ttolSlow defined in line 456; used 4 times
waitFor defined in line 471; used 2 times

Defined variables

F_reason defined in line 434; used 1 times
dialv defined in line 1; used 1 times
lbuf defined in line 440; used 28 times
mdmtab defined in line 401; used 2 times
nmdm defined in line 417; used 1 times
sjbuf defined in line 442; used 6 times
tries defined in line 437; used 1 times

Defined macros

CONNECT defined in line 420; used 1 times
CONNECTED defined in line 422; used 11 times
DIALING defined in line 419; used 1 times
FAILED defined in line 423; used 15 times
F_int defined in line 429; used 1 times
F_minit defined in line 431; used 1 times
F_modem defined in line 430; used 1 times
F_time defined in line 428; used 1 times
GOT_A defined in line 637; used 2 times
GOT_O defined in line 636; used 2 times
IGNORE defined in line 635; used 3 times
LBUFL defined in line 439; used 2 times
MDMINF defined in line 124; used 14 times
OKAY defined in line 634; used 3 times
n_CERMETEK defined in line 154; used 1 times
n_DF03 defined in line 155; used 1 times
n_DF100 defined in line 156; used 1 times
n_DF200 defined in line 157; used 1 times
n_GDC defined in line 158; used 1 times
n_HAYES defined in line 159; used 3 times
n_HAYESNV defined in line 175; used 1 times
n_PENRIL defined in line 160; used 1 times
n_RACAL defined in line 161; used 2 times
n_UNKNOWN defined in line 162; used 1 times
n_USROBOT defined in line 163; used 1 times
n_VENTEL defined in line 164; used 1 times
Last modified: 1985-08-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1778
Valid CSS Valid XHTML 1.0 Strict