BSD 4_3 development
[unix-history] / usr / contrib / kermit / ckudia.c
CommitLineData
ee2abe03
C
1char *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
121extern int flow, local, mdmtyp, quiet, speed;
122extern char ttname[], sesfil[];
123\f
124#define MDMINF struct mdminf
125
126MDMINF /* 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\f
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
184static
185MDMINF 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
199static
200MDMINF 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
214static
215MDMINF 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
239static
240MDMINF 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
264static
265MDMINF 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
279static
280MDMINF 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
294static
295MDMINF 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
309static
310MDMINF 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
324static
325MDMINF 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
339static
340MDMINF 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
354static
355MDMINF 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\f
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 */
379static
380MDMINF *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 */
401struct 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
417int nmdm = (sizeof(mdmtab) / sizeof(struct keytab)); /* number of modems */
418\f
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
433static
434char *F_reason[5] = { /* failure reasons for message */
435 "Unknown", "Timeout", "Interrupt", "Modem", "Initialize" };
436
437static int tries = 0;
438
439#define LBUFL 100
440static char lbuf[LBUFL];
441
442static jmp_buf sjbuf;
443
444static int (*savAlrm)(); /* for saving alarm handler */
445static int (*savInt)(); /* for saving interrupt handler */
446
447dialtime() { /* timer interrupt handler */
448 longjmp( sjbuf, F_time );
449}
450
451dialint() /* user-interrupt handler */
452 {
453 longjmp( sjbuf, F_int );
454 }
455
456static
457ttolSlow(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 */
471static
472waitFor(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
479static
480didWeGet(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
491static
492reset ()
493 {
494 alarm(0);
495 signal(SIGALRM,savAlrm); /* restore alarm handler */
496 signal(SIGINT,savInt); /* restore interrupt handler */
497 }
498\f
499
500
501/* D I A L -- Dial up the remote system */
502
503dial(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\f
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\f
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
639switch (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\f
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\f
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}