|
|
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.