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