|
|
1.1 root 1: #ifndef NODIAL
2: char *dialv = "Dial Command, 5A(028) 23 Dec 91";
3:
4: /* C K U D I A -- Dialing program for connection to remote system */
5:
6: /*
7: Original author: Herm Fischer (HFISCHER@USC-ECLB).
8: Contributed to Columbia University for inclusion in C-Kermit.
9: Copyright (C) 1985, Herman Fischer, 16400 Ventura Blvd, Encino CA 91436.
10: Permission is granted to any individual or institution to use, copy, or
11: redistribute this software so long as it is not sold for profit, provided
12: this copyright notice is retained.
13:
14: Os9/68k and Microcom modem support by Bob Larson ([email protected])
15: Additional code by many others over the years.
16:
17: ------
18:
19: This module should work under all versions of Unix. It calls externally
20: defined system-depended functions for i/o, but depends upon the existence
21: of various modem control functions.
22:
23: This module, and the supporting routines in the ckutio.c module, assume
24: that the computer and modem properly utilize the following data communi-
25: cations signals (that means one should prepare the modem to use, not
26: circumvent, these signals):
27:
28: Data Terminal Ready (DTR): This signal is asserted by the computer
29: when Kermit is about to ask the modem to dial a call, and is
30: removed when Kermit wishes to have the modem hang up a call.
31: The signal is asserted both while Kermit is asking the modem
32: to dial a specific number, and after connection, while Kermit
33: is in a data exchange mode.
34:
35: Carrier Detect (CD): This signal must be asserted by the modem when
36: a carrier is detected from a remote modem on a communications
37: circuit. It must be removed by the modem when the circuit
38: disconnects or is hung up. (Carrier Detect is ignored while
39: Kermit is asking the modem to dial the call, because there is
40: no consistant usage of this signal during the dialing phase
41: among different modem manufacturers.)
42: */
43:
44: /*
45: * Modifications:
46: *
47: * 21-Jul-85 Fixed failure returns hanging on no carrier signal
48: * Requires tthang change too (ckutio.c revision)
49: * -- Herm Fischer
50: *
51: * 28-Jun-85 Fixed bug with defaulting the modem-failure message
52: * in lbuf.
53: * -- Dan Schullman
54: *
55: * 27-Jun-85 Merged in code from Joe Orost at Berkeley for
56: * supporting the US Robotics modem, which included
57: * changing the single characters in MDMINF into
58: * multi-character strings and modifying waitfor.
59: * -- Dan Schullman
60: *
61: * 26-Jun-85 Allow interrupts to be used to abort dialing,
62: * and ring the bell when a connection is made.
63: * Reorganized some of the failure paths to use the
64: * same code, and now close the line on failures.
65: * Allow use of stored numbers with the DF100 and
66: * DF200 modems. Handlers now declared after the
67: * call to setjmp.
68: * -- Dan Schullman
69: *
70: * 24-May-85 DF03, DF100-series, DF200-series, and "unknown" modem
71: * support added. Also restructured the various data
72: * tables, fixed some bugs related to missing data and
73: * missing case labels, and modified the failure message
74: * to display the "reason" given by the modem.
75: * -- Dan Schullman
76: * 16-Mar-87 Support for the ATT7300 UNIX PC internal modem was
77: * added.
78: * -- Richard E. Hill
79: *
80: * 21-Feb-88 Os9/68k and microcom modem support.
81: * -- Bob Larson
82: *
83: * 14-Mar-88 Rewrite code for ATT7300 (here and in ckutio.c)
84: * Avoids dial(3c) with it's LCK files, hangs up line
85: * correctly, enables user interrupts and timeouts,
86: * turns on/off the system getty() login procedure.
87: * Correct Hayes command sequence at little.
88: * Procedures: attdial, atthang, ongetty, offgetty.
89: * Parts adapted from work of Richard E. Hill and
90: * Kevin O'Gorman.
91: * -- Joe R. Doupnik
92: *
93: * 13-Jan-89 Added IBM/Siemens/Rolm CBX dialing support.
94: * - F. da Cruz
95: *
96: * 29-Aug-89 Added support for AT&T 2212C, 2224B, 2224CEO, and
97: * 2296A switched-network modems in AT&T mode, and
98: * for the AT&T Digital Terminal Data Module (DTDM).
99: * -- Eric F. Jones
100: *
101: * 4-Jun-90 Added delay on "ANSWERED" for AT&T DTDM
102: * 7-Jun-90 Added support for AT&T ISN Network
103: * - John L. Chmielewski, AT&T
104: *
105: * March 1991 Support for Telebit modems, Kermit spoofing.
106: * Warren Tucker, Larry Jacobs, Frank da Cruz.
107: */
108:
109: /*
110: * To add support for another modem, do the following:
111: *
112: * Define a modem number symbol (n_XXX) for it, keeping the list
113: * in alphabetical and numerical order, and renumbering the values
114: * as necessary. Make sure the n_XXX symbol is unique within 7 chars.
115: *
116: * Create a MDMINF structure for it, again keeping the list alphabetical
117: * for sanity's sake.
118: *
119: * Add the address of the MDMINF structure to the ptrtab array, again
120: * in alphabetical and numerical order.
121: *
122: * Add the "user visible" modem name and corresponding modem number to
123: * the mdmtab array, again in alphabetical order.
124: *
125: * Read through the code and add modem-specific sections as necessary.
126: */
127:
128: /*
129: * The intent of the "unknown" modem is hopefully to allow KERMIT to support
130: * unknown modems by having the user type the entire autodial sequence
131: * (possibly including control characters, etc.) as the "phone number".
132: * The only reason that the CONNECT command cannot be used to do this is
133: * that a remote line cannot normally be opened unless carrier is present.
134: *
135: * The protocol and other characteristics of this modem are unknown, with
136: * some "reasonable" values being chosen for some of them. The only way to
137: * detect if a connection is made is to look for carrier present.
138: */
139: #include "ckcdeb.h"
140: #ifndef MAC
141: #include <signal.h>
142: #endif /* MAC */
143: #include "ckcasc.h"
144: #include "ckcker.h"
145: #include "ckucmd.h"
146:
147: #ifndef ZILOG
148: #include <setjmp.h> /* Longjumps */
149: #else
150: #include <setret.h>
151: #endif /* ZILOG */
152:
153: #ifdef MAC
154: #define signal msignal
155: #define SIGTYP long
156: #define alarm malarm
157: #define SIG_IGN 0
158: #define SIGALRM 1
159: #define SIGINT 2
160: SIGTYP (*msignal(int type, SIGTYP (*func)(int)))(int);
161: #endif /* MAC */
162:
163: extern int flow, local, mdmtyp, quiet, parity, seslog, network, dialhng,
164: dialdpy, mdmspd, dialtmo, dialksp, dialmnp;
165: extern char *dialini;
166: extern CHAR stchr;
167: extern long speed;
168: extern char ttname[], sesfil[];
169:
170: /*
171: * Failure reasons for use with the 'longjmp' exit.
172: */
173: #define F_time 1 /* timeout */
174: #define F_int 2 /* interrupt */
175: #define F_modem 3 /* modem-detected failure */
176: #define F_minit 4 /* cannot initialize modem */
177:
178: static int mymdmtyp; /* Local copy of modem type. */
179: static int n1 = F_time;
180:
181: #define MDMINF struct mdminf
182:
183: MDMINF /* structure for modem-specific information */
184: {
185: int dial_time; /* time modem allows for dialing (secs) */
186: char *pause_chars; /* character(s) to tell modem to pause */
187: int pause_time; /* time associated with pause chars (secs) */
188: char *wake_str; /* string to wakeup modem & put in cmd mode */
189: int wake_rate; /* delay between wake_str characters (msecs) */
190: char *wake_prompt; /* string prompt after wake_str */
191: char *dmode_str; /* string to put modem in dialing mode */
192: char *dmode_prompt; /* string prompt for dialing mode */
193: char *dial_str; /* dialing string, with "%s" for number */
194: int dial_rate; /* delay between dialing characters (msecs) */
195: };
196:
197: /*
198: * Define symbolic modem numbers.
199: *
200: * The numbers MUST correspond to the ordering of entries
201: * within the ptrtab array, and start at one (1).
202: *
203: * It is assumed that there are relatively few of these
204: * values, and that the high(er) bytes of the value may
205: * be used for modem-specific mode information.
206: *
207: * REMEMBER that only the first eight characters of these
208: * names are guaranteed to be unique.
209: */
210:
211: #define n_ATTDTDM 1
212: #define n_ATTISN 2
213: #define n_ATTMODEM 3
214: #define n_CERMETEK 4
215: #define n_DF03 5
216: #define n_DF100 6
217: #define n_DF200 7
218: #define n_GDC 8
219: #define n_HAYES 9
220: #define n_PENRIL 10
221: #define n_RACAL 11
222: #define n_UNKNOWN 12
223: #define n_USROBOT 13
224: #define n_VENTEL 14
225: #define n_CONCORD 15
226: #define n_ATTUPC 16 /* aka Unix PC and ATT7300 */
227: #define n_ROLM 17 /* Rolm CBX DCM */
228: #define n_MICROCOM 18
229: #define n_HST 19
230: #define n_TELEBIT 20 /* Telebit Trailblazer */
231: #define MAX_MDM 20
232: /*
233: * Declare modem "variant" numbers for any of the above for which it is
234: * necessary to note various operational modes, using the second byte
235: * of a modem number.
236: *
237: * It is assumed that such modem modes share the same modem-specific
238: * information (see MDMINF structure) but may differ in some of the actions
239: * that are performed.
240: */
241:
242: /* Warning - this is starting to get kind of hokey... */
243:
244: #define DIAL_NV 256
245: #define DIAL_PEP 512
246: #define DIAL_V32 1024
247: #define DIAL_V42 2048
248: #define DIAL_SLO 4096
249:
250: #define n_HAYESNV ( n_HAYES | DIAL_NV )
251: #define n_TBPEP ( n_TELEBIT | DIAL_PEP )
252: #define n_TB3 ( n_TELEBIT | DIAL_V32 )
253: #define n_TBNV ( n_TELEBIT | DIAL_NV )
254: #define n_TBPNV ( n_TELEBIT | DIAL_NV | DIAL_PEP )
255: #define n_TB3NV ( n_TELEBIT | DIAL_NV | DIAL_V32 )
256: #define n_TB4 ( n_TELEBIT | DIAL_V42 )
257: #define n_TBS ( n_TELEBIT | DIAL_SLO )
258: #define n_TB4NV ( n_TELEBIT | DIAL_NV | DIAL_V42 )
259: #define n_TBSNV ( n_TELEBIT | DIAL_NV | DIAL_SLO )
260:
261: /*
262: * Declare structures containing modem-specific information.
263: *
264: * REMEMBER that only the first SEVEN characters of these
265: * names are guaranteed to be unique.
266: */
267:
268: static
269: MDMINF ATTISN = /* AT&T ISN Network */
270: {
271: 30, /* Dial time */
272: "", /* Pause characters */
273: 0, /* Pause time */
274: "\015\015\015\015", /* Wake string */
275: 900, /* Wake rate */
276: "DIAL", /* Wake prompt */
277: "", /* dmode_str */
278: "", /* dmode_prompt */
279: "%s\015", /* dial_str */
280: 0 /* dial_rate */
281: };
282:
283: static
284: MDMINF ATTMODEM = /* information for AT&T switched-network modems */
285: /* "Number" following "dial" can include: p's and
286: * t's to indicate pulse or tone (default) dialing,
287: * + for wait for dial tone, , for pause, r for
288: * last number dialed, and, except for 2224B, some
289: * comma-delimited options like o12=y, before number.
290:
291: * "Important" options for the modems:
292: *
293: * All: Except for 2224B, enable option 12 for "transparent
294: * data," o12=y. If a computer port used for both
295: * incoming and outgoing calls is connected to the
296: * modem, disable "enter interactive mode on carriage
297: * return," EICR. The Kermit "dial" command can
298: * function with EIA leads standard, EIAS.
299: *
300: * 2212C: Internal hardware switches at their default
301: * positions (four rockers down away from numbers)
302: * unless EICR is not wanted (rocker down at the 4).
303: * For EIAS, rocker down at the 1.
304: *
305: * 2224B: Front-panel switch position 1 must be up (at the 1,
306: * closed). Disable EICR with position 2 down.
307: * For EIAS, position 4 down.
308: * All switches on the back panel down.
309: *
310: * 2224CEO: All front-panel switches down except either 5 or 6.
311: * Enable interactive flow control with o16=y.
312: * Select normal asynchronous mode with o34=0 (zero).
313: * Disable EICR with position 3 up. For EIAS, 1 up.
314: * Reset the modem after changing switches.
315: *
316: * 2296A: If option 00 (zeros) is present, use o00=0.
317: * Enable interactive flow control with o16=y.
318: * Select normal asynchronous mode with o34=0 (zero).
319: * (available in Microcom Networking version, but
320: * not necessarily other models of the 2296A).
321: * Enable modem-port flow control (if available) with
322: * o42=y. Enable asynchronous operation with o50=y.
323: * Disable EICR with o69=n. For EIAS, o66=n, using
324: * front panel.
325: */
326: {
327: 20, /* dial_time */
328: ",", /* pause_chars */
329: 2, /* pause_time */
330: "+", /* wake_str */
331: 0, /* wake_rate */
332: "", /* wake_prompt */
333: "", /* dmode_str */
334: "", /* dmode_prompt */
335: "at%s\015", /* dial_str */
336: 0 /* dial_rate */
337: };
338:
339: static
340: MDMINF ATTDTDM = /* information for AT&T Digital Terminal Data Module
341: * For dialing: KYBD switch down, others usually up. */
342: {
343: 20, /* dial_time */
344: "", /* pause_chars */
345: 0, /* pause_time */
346: "", /* wake_str */
347: 0, /* wake_rate */
348: "", /* wake_prompt */
349: "", /* dmode_str */
350: "", /* dmode_prompt */
351: "%s\015", /* dial_str */ /* not used */
352: 0 /* dial_rate */
353: };
354:
355: static
356: MDMINF CERMETEK = /* information for "Cermetek Info-Mate 212 A" modem */
357: {
358: 20, /* dial_time */
359: "BbPpTt", /* pause_chars */
360: 0, /* pause_time */ /** unknown -- DS **/
361: " XY\016R\015", /* wake_str */
362: 200, /* wake_rate */
363: "", /* wake_prompt */
364: "", /* dmode_str */
365: NULL, /* dmode_prompt */
366: "\016D '%s'\015", /* dial_str */
367: 200 /* dial_rate */
368: };
369:
370: static
371: MDMINF DF03 = /* information for "DEC DF03-AC" modem */
372: {
373: 27, /* dial_time */
374: "=", /* pause_chars */ /* wait for second dial tone */
375: 15, /* pause_time */
376: "\001\002", /* wake_str */
377: 0, /* wake_rate */
378: "", /* wake_prompt */
379: "", /* dmode_str */
380: NULL, /* dmode_prompt */
381: "%s", /* dial_str */
382: 0 /* dial_rate */
383: };
384:
385: static
386: MDMINF DF100 = /* information for "DEC DF100-series" modem */
387: /*
388: * The telephone "number" can include "P"s and/or "T"s
389: * within it to indicate that subsequent digits are
390: * to be dialed using pulse or tone dialing. The
391: * modem defaults to pulse dialing. You may modify
392: * the dial string below to explicitly default all
393: * dialing to pulse or tone, but doing so prevents
394: * the use of phone numbers that you may have stored
395: * in the modem's memory.
396: */
397: {
398: 30, /* dial_time */
399: "=", /* pause_chars */ /* wait for second dial tone */
400: 15, /* pause_time */
401: "\001", /* wake_str */
402: 0, /* wake_rate */
403: "", /* wake_prompt */
404: "", /* dmode_str */
405: NULL, /* dmode_prompt */
406: "%s#", /* dial_str */
407: 0 /* dial_rate */
408: };
409:
410: static
411: MDMINF DF200 = /* information for "DEC DF200-series" modem */
412: /*
413: * The telephone "number" can include "P"s and/or "T"s
414: * within it to indicate that subsequent digits are
415: * to be dialed using pulse or tone dialing. The
416: * modem defaults to pulse dialing. You may modify
417: * the dial string below to explicitly default all
418: * dialing to pulse or tone, but doing so prevents
419: * the use of phone numbers that you may have stored
420: * in the modem's memory.
421: */
422: {
423: 30, /* dial_time */
424: "=W", /* pause_chars */ /* =: second tone; W: 5 secs */
425: 15, /* pause_time */ /* worst case */
426: "\002", /* wake_str */ /* allow stored number usage */
427: 0, /* wake_rate */
428: "", /* wake_prompt */
429: "", /* dmode_str */
430: NULL, /* dmode_prompt */
431: "%s!", /* dial_str */
432: 0 /* dial_rate */
433: };
434:
435: static
436: MDMINF GDC = /* information for "GeneralDataComm 212A/ED" modem */
437: {
438: 32, /* dial_time */
439: "%", /* pause_chars */
440: 3, /* pause_time */
441: "\015\015", /* wake_str */
442: 500, /* wake_rate */
443: "$", /* wake_prompt */
444: "D\015", /* dmode_str */
445: ":", /* dmode_prompt */
446: "T%s\015", /* dial_str */
447: 0 /* dial_rate */
448: };
449:
450: static
451: MDMINF HAYES = /* information for "Hayes" modem */
452: {
453: 35, /* dial_time */
454: ",", /* pause_chars */
455: 2, /* pause_time */
456: "AT\015", /* wake_str */
457: /*
458: Note: Other wake_str's are possible here. For Hayes 2400 that is to
459: be used for both in and out calls, AT&F&D3 might be best. For out calls
460: only, maybe AT&F&D2. See Hayes 2400 manual.
461: */
462: 0, /* wake_rate */
463: "", /* wake_prompt */
464: "", /* dmode_str */
465: "", /* dmode_prompt */
466: "ATD%s\015", /* dial_str, note: user can supply D or T */
467: 0 /* dial_rate */
468: };
469:
470: static
471: MDMINF PENRIL = /* information for "Penril" modem */
472: {
473: 50, /* dial_time */
474: "", /* pause_chars */ /** unknown -- HF **/
475: 0, /* pause_time */
476: "\015\015", /* wake_str */
477: 300, /* wake_rate */
478: ">", /* wake_prompt */
479: "k\015", /* dmode_str */
480: ":", /* dmode_prompt */
481: "%s\015", /* dial_str */
482: 0 /* dial_rate */
483: };
484:
485: static
486: MDMINF RACAL = /* information for "Racal Vadic" modem */
487: {
488: 35, /* dial_time */
489: "Kk", /* pause_chars */
490: 5, /* pause_time */
491: "\005\015", /* wake_str */
492: 50, /* wake_rate */
493: "*", /* wake_prompt */
494: "D\015", /* dmode_str */
495: "?", /* dmode_prompt */
496: "%s\015", /* dial_str */
497: 0 /* dial_rate */
498: };
499:
500: static
501: MDMINF UNKNOWN = /* information for "Unknown" modem */
502: {
503: 30, /* dial_time */
504: "", /* pause_chars */
505: 0, /* pause_time */
506: "", /* wake_str */
507: 0, /* wake_rate */
508: "", /* wake_prompt */
509: "", /* dmode_str */
510: NULL, /* dmode_prompt */
511: "%s\015", /* dial_str */
512: 0 /* dial_rate */
513: };
514:
515: static
516: MDMINF USROBOT = /* information for "US Robotics 212A" modem */
517: {
518: 30, /* dial_time */
519: ",", /* pause_chars */
520: 2, /* pause_time */
521: "ATS2=01\015", /* wake_str */
522: 0, /* wake_rate */
523: "OK\015", /* wake_prompt */
524: "", /* dmode_str */
525: NULL, /* dmode_prompt */
526: "ATTD%s\015", /* dial_str */
527: 0 /* dial_rate */
528: };
529: #ifdef COMMENT
530: /* Reportedly this does not work at all. */
531: static
532: MDMINF VENTEL = /* information for "Ventel" modem */
533: {
534: 20, /* dial_time */
535: "%", /* pause_chars */
536: 5, /* pause_time */
537: "\015\015\015", /* wake_str */
538: 300, /* wake_rate */
539: "$", /* wake_prompt */
540: "", /* dmode_str */
541: NULL, /* dmode_prompt */
542: "<K\015%s\015>", /* dial_str (was "<K%s\r>") */
543: 0 /* dial_rate */
544: };
545: #else
546: /* and this does. */
547: static
548: MDMINF VENTEL = /* information for "Ventel" modem */
549: {
550: 20, /* dial_time */
551: "%", /* pause_chars */
552: 5, /* pause_time */
553: "\015\015\015", /* wake_str */
554: 300, /* wake_rate */
555: "$", /* wake_prompt */
556: "K\015", /* dmode_str (was "") */
557: "Number to call: ", /* dmode_prompt (was NULL) */
558: "%s\015", /* dial_str (was "<K%s\r>") */
559: 0 /* dial_rate */
560: };
561: #endif /* COMMENT */
562:
563: static
564: MDMINF CONCORD = /* Info for Condor CDS 220 2400b modem */
565: {
566: 35, /* dial_time */
567: ",", /* pause_chars */
568: 2, /* pause_time */
569: "\015\015", /* wake_str */
570: 20, /* wake_rate */
571: "CDS >", /* wake_prompt */
572: "", /* dmode_str */
573: NULL, /* dmode_prompt */
574: "<D M%s\015>", /* dial_str */
575: 0 /* dial_rate */
576: };
577:
578: static
579: MDMINF ATTUPC = /* dummy information for "ATT7300/Unix PC" internal modem */
580: {
581: 30, /* dial_time */
582: "", /* pause_chars */
583: 0, /* pause_time */
584: "", /* wake_str */
585: 0, /* wake_rate */
586: "", /* wake_prompt */
587: "", /* dmode_str */
588: NULL, /* dmode_prompt */
589: "%s\015", /* dial_str */
590: 0 /* dial_rate */
591: };
592:
593: static
594: MDMINF ROLM = /* IBM / Siemens / Rolm 8000, 9000, 9751 CBX */
595: {
596: 60, /* dial_time */
597: "", /* pause_chars */
598: 0, /* pause_time */
599: "\015\015", /* wake_str */
600: 5, /* wake_rate */
601: "MODIFY?", /* wake_prompt */
602: "", /* dmode_str */
603: "", /* dmode_prompt */
604: "CALL %s\015", /* dial_str */
605: 0 /* dial_rate */
606: };
607:
608: static
609: MDMINF MICROCOM = /* information for "Microcom" modems in native mode */
610: /* (long answer only) */
611: {
612: 35, /* dial_time */
613: ",!@", /* pause_chars (! and @ aren't pure pauses) */
614: 3, /* pause_time */
615: "\015", /* wake_str */
616: 100, /* wake_rate */
617: "!", /* wake_prompt */
618: "", /* dmode_str */
619: NULL, /* dmode_prompt */
620: "d%s\015", /* dial_str */
621: 0 /* dial_rate */
622: };
623:
624: static
625: MDMINF HST = /* information for Courier HST modem */
626: {
627: 35, /* dial_time */
628: ",", /* pause_chars */
629: 2, /* pause_time */
630: "ATE1Q0S2=43X7&B1&M4\015", /* wake_str */
631: 0, /* wake_rate */
632: "OK\015", /* wake_prompt */
633: "", /* dmode_str */
634: "", /* dmode_prompt */
635: "ATD%s\015", /* dial_str */
636: 0 /* dial_rate */
637: };
638:
639: static
640: MDMINF TELEBIT = /* information for Telebits */
641: {
642: 60, /* dial_time */
643: ",", /* pause_chars */
644: 2, /* pause_time */
645: "AAAAATF1M1Q4X3S2=43\015", /* wake_str */
646: 10, /* wake_rate */
647: "OK\015", /* wake_prompt */
648: "", /* dmode_str */
649: "", /* dmode_prompt */
650: "ATD%s\015", /* dial_str */
651: 80 /* dial_rate */
652: };
653:
654: /*
655: * Declare table for converting modem numbers to information pointers.
656: *
657: * The entries MUST be in ascending order by modem number, without any
658: * "gaps" in the numbers, and starting from one (1).
659: *
660: * This table should NOT include entries for the "variant" modem numbers,
661: * since it is assumed that they share the same information as the normal
662: * value.
663: */
664: static
665: MDMINF *ptrtab[] =
666: {
667: &ATTDTDM,
668: &ATTISN,
669: &ATTMODEM,
670: &CERMETEK,
671: &DF03,
672: &DF100,
673: &DF200,
674: &GDC,
675: &HAYES,
676: &PENRIL,
677: &RACAL,
678: &UNKNOWN,
679: &USROBOT,
680: &VENTEL,
681: &CONCORD,
682: &ATTUPC, /* ATT7300 internal modem, jrd*/
683: &ROLM, /* Rolm CBX, fdc */
684: &MICROCOM,
685: &HST,
686: &TELEBIT
687: };
688:
689: /*
690: * Declare modem names and associated numbers for command parsing,
691: * and also for doing number-to-name translation.
692: *
693: * The entries MUST be in alphabetical order by modem name.
694: */
695: struct keytab mdmtab[] =
696: {
697: "attdtdm", n_ATTDTDM, 0,
698: "attisn", n_ATTISN, 0,
699: "attmodem", n_ATTMODEM, 0,
700: "att7300", n_ATTUPC, 0,
701: "cermetek", n_CERMETEK, 0,
702: "concord", n_CONCORD, 0,
703: "df03-ac", n_DF03, 0,
704: "df100-series", n_DF100, 0,
705: "df200-series", n_DF200, 0,
706: "direct", 0, 0,
707: "gendatacomm", n_GDC, 0,
708: "hayes", n_HAYES, 0,
709: "hst-courier", n_HST, 0,
710: "microcom", n_MICROCOM, 0,
711: "none", 0, 0,
712: "penril", n_PENRIL, 0,
713: "pep-telebit", n_TBPEP, 0,
714: "racalvadic", n_RACAL, 0,
715: "rolm", n_ROLM, 0,
716: "slow-telebit", n_TBS, 0,
717: "telebit", n_TELEBIT, 0,
718: "unknown", n_UNKNOWN, 0,
719: "usrobotics-212a", n_USROBOT, 0,
720: "v32-telebit", n_TB3, 0,
721: "v42-telebit", n_TB4, 0,
722: "ventel", n_VENTEL, 0
723: };
724:
725: int nmdm = (sizeof(mdmtab) / sizeof(struct keytab)); /* number of modems */
726:
727: _PROTOTYP (int dialhup, (void) );
728: _PROTOTYP (int getok, (int) );
729: _PROTOTYP (char * getdws, (int) );
730: _PROTOTYP (static VOID ttslow, (char *s, int millisec) );
731: _PROTOTYP (VOID xcpy, (char *to, char *from, unsigned len) );
732: _PROTOTYP (static VOID waitfor, (char *s) );
733: _PROTOTYP (static VOID dialoc, (char c) );
734: _PROTOTYP (static int didweget, (char *s, char *r) );
735: _PROTOTYP (static VOID spdchg, (long s) );
736:
737: #define DIALING 4 /* for ttpkt parameter */
738: #define CONNECT 5
739:
740: #define CONNECTED 1 /* for completion status */
741: #define FAILED 2
742:
743: static
744: char *F_reason[5] = { /* failure reasons for message */
745: "Unknown", "Timeout", "Interrupt", "Modem", "Initialize" };
746:
747: static int tries = 0;
748: static int mdmecho = 0; /* assume modem does not echo */
749: static int augmdmtyp; /* "augmented" modem type, to handle modem modes */
750:
751: static char *p; /* For command strings & messages */
752:
753: #define LBUFL 100
754: #ifdef DYNAMIC
755: static char *lbuf;
756: #else
757: static char lbuf[LBUFL];
758: #endif /* DYNAMIC */
759:
760: static jmp_buf sjbuf;
761:
762: static SIGTYP (*savalrm)(); /* for saving alarm handler */
763: static SIGTYP (*savint)(); /* for saving interrupt handler */
764:
765: VOID
766: xcpy(to,from,len) /* Copy the given number of bytes */
767: register char *to, *from;
768: register unsigned len; {
769: while (len--) *to++ = *from++;
770: }
771:
772: SIGTYP
773: dialtime(foo) int foo; { /* timer interrupt handler */
774: n1 = F_time;
775: longjmp( sjbuf, F_time );
776: }
777:
778: SIGTYP
779: dialint(foo) int foo; { /* user-interrupt handler */
780: n1 = F_int;
781: longjmp( sjbuf, F_int );
782: }
783:
784: static VOID
785: ttslow(s,millisec) char *s; int millisec; { /* output s-l-o-w-l-y */
786: for (; *s; s++) {
787: ttoc(*s);
788: msleep(millisec);
789: }
790: }
791:
792: /*
793: * Wait for a string of characters.
794: *
795: * The characters are waited for individually, and other characters may
796: * be received "in between". This merely guarantees that the characters
797: * ARE received, and in the order specified.
798: */
799: static VOID
800: waitfor(s) char *s; {
801: CHAR c, x;
802: while ( c = *s++ ) { /* while more characters remain... */
803: do { /* wait for the character */
804: x = ttinc(0) & 0177;
805: debug(F000,"dial waitfor got","",x);
806: if (dialdpy) {
807: if (x != LF) conoc(x);
808: if (x == CR) conoc(LF);
809: }
810: } while ( x != c);
811: }
812: }
813:
814: static int
815: didweget(s,r) char *s, *r; { /* Looks in string s for response r */
816: int lr = (int)strlen(r); /* 0 means not found, 1 means found it */
817: int i;
818: debug(F110,"didweget",r,0);
819: debug(F110," in",s,0);
820: for (i = (int)strlen(s)-lr; i >= 0; i--)
821: if ( s[i] == r[0] ) if ( !strncmp(s+i,r,lr) ) return( 1 );
822: return( 0 );
823: }
824:
825:
826: /* R E S E T -- Reset alarms, etc. on exit. */
827:
828: static VOID
829: reset() {
830: alarm(0);
831: signal(SIGALRM,savalrm); /* restore alarm handler */
832: signal(SIGINT,savint); /* restore interrupt handler */
833: }
834:
835: /*
836: Call this routine when the modem reports that it has connected at a certain
837: speed, giving that speed as the argument. If the connection speed is not
838: the same as Kermit's current communication speed, AND the modem interface
839: speed is not locked (i.e. DIAL SPEED-MATCHING is not ON), then change the
840: device speed to the one given.
841: */
842: static VOID
843: spdchg(s) long s; {
844: int s2;
845: if (!mdmspd) /* If modem interface speed locked, */
846: return; /* don't do this. */
847: if (speed != s) { /* Speeds differ? */
848: s2 = s / 10L; /* Convert to cps expressed as int */
849: if (ttsspd(s2) < 0) { /* Change speed. */
850: printf(" Warning: speed change to %ld failed.\r\n",s);
851: } else {
852: printf(" Speed changed to %ld.\r\n",s);
853: speed = s; /* Update global speed variable */
854: }
855: }
856: }
857:
858: /*
859: Display all characters received from modem dialer through this routine,
860: for consistent handling of carriage returns and linefeeds.
861: */
862:
863: static VOID
864: #ifdef CK_ANSIC
865: dialoc(char c)
866: #else
867: dialoc(c) char c;
868: #endif /* CK_ANSIC */
869: { /* dialoc */ /* Dial Output Character */
870: if (dialdpy) {
871: if (c != LF) conoc(c); /* Don't echo LF */
872: if (c == CR) conoc(LF); /* Echo CR as CRLF */
873: }
874: }
875:
876:
877: /* C K D I A L -- Dial up the remote system */
878:
879: /* Returns 1 if call completed, 0 otherwise */
880:
881: int
882: ckdial(telnbr) char *telnbr; {
883:
884: char c, c2;
885: int waitct, status = 0;
886: char errmsg[50], *erp;
887: MDMINF *pmdminf; /* pointer to modem-specific info */
888: int x, y, m, n;
889: char *s, *pc, *ws;
890:
891: long conspd;
892: char *cptr;
893:
894: mymdmtyp = mdmtyp; /* Make local copy of modem type */
895:
896: if (network) {
897: printf("Sorry, 'dial' not available on network connection\n");
898: return(0);
899: }
900: if (mymdmtyp < 1) {
901: printf("Sorry, you must 'set modem' first\n");
902: return(0);
903: }
904: if (!local) {
905: printf("Sorry, you must 'set line' first\n");
906: return(0);
907: }
908: if (speed < 0L) {
909: printf("Sorry, you must 'set speed' first\n");
910: return(0);
911: }
912: debug(F110,"dial string",telnbr,0);
913:
914: /* Carrier no-wait can be invalidated by ckutio fun and games, jrd */
915: if (ttopen(ttname,&local,mymdmtyp,0) < 0) { /* Open, no carrier wait */
916: erp = errmsg;
917: sprintf(erp,"Sorry, can't open %s",ttname);
918: perror(errmsg);
919: return(0);
920: }
921: pmdminf = ptrtab[(mymdmtyp & 0xff) -1 ]; /* set pointer to modem info */
922: augmdmtyp = mymdmtyp; /* initialize "augmented" modem type */
923: mymdmtyp &= 0xff; /* major modem type */
924:
925: /* interdigit waits for tone dial */
926:
927: if (dialtmo < 1) { /* Automatic computation. */
928: waitct = 1 * (int)strlen(telnbr) ; /* Compute worst case dial time */
929: waitct += pmdminf->dial_time; /* dialtone + completion wait times */
930: for (s = telnbr; *s; s++) { /* add in pause characters time */
931: for (p=pmdminf->pause_chars; *p; p++)
932: if (*s == *p) {
933: waitct += pmdminf->pause_time;
934: break;
935: }
936: }
937: if (augmdmtyp == n_TBPEP || augmdmtyp == n_TBPNV) {
938: waitct += 30; /* Longer connect wait for PEP call */
939: }
940: } else { /* User-specified timeout */
941: waitct = dialtmo;
942: }
943: for (m = 0; m < nmdm; m++) { /* Look up modem type. */
944: if (mdmtab[m].kwval == mymdmtyp) {
945: break;
946: }
947: }
948: printf(" Dialing %s\n",telnbr);
949: printf(" Device=%s, modem=%s, speed=%ld\n",
950: ttname,
951: (m >= nmdm ? "unk" : mdmtab[m].kwd),
952: speed);
953:
954: printf(" The timeout for completing the call is %d seconds.\n",waitct);
955: printf(
956: #ifdef MAC
957: " Type Command-. to cancel the dialing.\n");
958: #else
959: " Type your interrupt character (normally ^C) to cancel the dialing.\n");
960: #endif /* MAC */
961: debug(F111,"ckdial",ttname,(int) (speed / 10L));
962: debug(F101,"ckdial timeout","",waitct);
963:
964: /* Hang up the modem (in case it wasn't "on hook") */
965: /* But only if SET DIAL HANGUP ON... */
966:
967: if (dialhup() < 0) {
968: if (dialhng) {
969: ttclos(0);
970: if (ttopen(ttname,&local,mymdmtyp,0) < 0) {
971: printf("Sorry, Can't hang up tty line\n");
972: printf("Try 'set line %s' again\n",ttname);
973: return(0);
974: }
975: }
976: }
977: if (augmdmtyp == n_ROLM) sleep(1);
978:
979: /* Condition console terminal and communication line */
980:
981: /* Place line into "clocal" dialing state */
982:
983: if (ttpkt(speed,DIALING,parity) < 0) {
984: dialhup(); /* If ttpkt fails do all this... */
985: ttclos(0);
986: if (ttopen(ttname,&local,mymdmtyp,0) < 0) {
987: erp = errmsg;
988: sprintf(erp,"Sorry, can't reopen %s",ttname);
989: perror(errmsg);
990: return(0);
991: } /* And try again. */
992: if (ttpkt(speed,DIALING,parity) < 0) {
993: printf("Sorry, Can't condition communication line\n");
994: printf("Try 'set line %s' again\n",ttname);
995: return(0);
996: }
997: }
998: #ifdef DYNAMIC
999: if (!(lbuf = malloc(LBUFL+1))) { /* Allocate input line buffer */
1000: printf("Sorry, memory buffer can't be allocated\n");
1001: return(0);
1002: }
1003: #endif /* DYNAMIC */
1004: sleep(2); /* Let it finish waking up. */
1005:
1006: /*
1007: Establish jump vector, or handle "failure" jumps.
1008: longjmp() sets global failure reason, n1.
1009: */
1010: if (setjmp(sjbuf)) { /* if a "failure jump" was taken... */
1011: n = n1;
1012: alarm(0); /* disable timeouts */
1013: if (setjmp(sjbuf)) { /* failure while handling failure */
1014: printf ("%s failure while handling failure.\n", F_reason[n1]);
1015: } else { /* first (i.e., non-nested) failure */
1016: signal(SIGALRM, dialtime); /* be sure to catch signals */
1017: #ifdef MAC
1018: signal(SIGINT, dialint);
1019: #else /* MAC */
1020: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1021: signal(SIGINT, dialint);
1022: #endif /* MAC */
1023: alarm(10); /* be sure to exit this section */
1024: }
1025: switch (n) { /* type of failure */
1026: case F_time: { /* timed out */
1027: printf ("No connection made within the allotted time.\n");
1028: if (mymdmtyp == n_HAYES || mymdmtyp == n_TELEBIT)
1029: ttoc('\015'); /* Send CR to interrupt dialing */
1030: /* some hayes modems don't fail with BUSY on busy lines */
1031: debug(F110,"dial","timeout",0);
1032: break;
1033: }
1034: case F_int: { /* dialing interrupted */
1035: printf ("Dialing interrupted.\n");
1036: debug(F110,"dial","interrupted",0);
1037: if (mymdmtyp == n_HAYES || mymdmtyp == n_TELEBIT)
1038: ttoc('\015'); /* Send CR to interrupt dialing */
1039: break;
1040: }
1041: case F_modem: { /* modem detected a failure */
1042: printf ("Failed (\"");
1043: for (pc = lbuf; *pc; pc++)
1044: if (isprint(*pc))
1045: putchar(*pc); /* display printable reason */
1046: printf ("\").\n");
1047: debug(F110,"dial",lbuf,0);
1048: break;
1049: }
1050: case F_minit: { /* cannot initialize modem */
1051: printf ("Can't initialize modem.\n");
1052: debug(F110,"dial","modem init",0);
1053: break;
1054: }
1055: }
1056: reset(); /* reset alarms, etc. */
1057: dialhup(); /* try to hang up phone. */
1058: #ifdef DYNAMIC
1059: if (lbuf) free(lbuf);
1060: #endif /* DYNAMIC */
1061: return(0); /* exit with failure code */
1062: }
1063:
1064: /* Set timer and interrupt handlers. */
1065:
1066: savalrm = signal(SIGALRM,dialtime); /* Set alarm handler */
1067: #ifdef MAC
1068: savint = signal(SIGINT, dialint);
1069: #else /* MAC */
1070: if ((savint = signal(SIGINT,SIG_IGN)) != SIG_IGN )
1071: signal(SIGINT,dialint); /* Set int handler if not ignored */
1072: #endif /* MAC */
1073: #ifdef COMMENT
1074: x = 10; /* Give modem 10 seconds to wake up */
1075: debug(F101,"ckdial wakeup timout","",x);
1076: x = alarm(x);
1077: debug(F101,"ckdial previous alarm","",x);
1078: #endif /* COMMENT */
1079:
1080: /* Put modem in command mode. */
1081:
1082: switch (augmdmtyp) { /* Send the wakeup string */
1083:
1084: #ifdef ATT7300
1085: case n_ATTUPC: {
1086: /*
1087: For ATT7300/Unix PC's with their special internal modem. Timeout
1088: and user interrupts are enabled during dialing. attdial() is in
1089: file ckutio.c. - jrd
1090: */
1091: _PROTOTYP( int attdial, (char *, long, char *) );
1092: alarm(waitct); /* do alarm properly */
1093: if (attdial(ttname,speed,telnbr)) { /* dial internal modem */
1094: reset(); /* reset alarms, etc. */
1095: if (! quiet) printf(" Call did not complete.");
1096: dialhup(); /* Hangup the call */
1097: #ifdef DYNAMIC
1098: if (lbuf) free(lbuf);
1099: #endif /* DYNAMIC */
1100: return(0); /* return failure */
1101: }
1102: reset(); /* reset alarms, etc. */
1103: ttpkt(speed,CONNECT,parity); /* cancel dialing ioctl */
1104: if (! quiet) {
1105: if (dialdpy) printf("\n");
1106: printf(" Call completed.\07\r\n");
1107: }
1108: #ifdef DYNAMIC
1109: if (lbuf) free(lbuf);
1110: #endif /* DYNAMIC */
1111: return(1); /* no conversation with modem to complete dialing */
1112: }
1113: #endif /* ATT7300 */
1114:
1115: /*
1116: For Hayes modem command language, figure out if modem is giving verbose
1117: or digit result codes.
1118: */
1119: case n_HAYES:
1120: case n_HAYESNV:
1121: ws = dialini ? dialini : HAYES.wake_str;
1122: for (tries = 4; tries > 0; tries--) {
1123: ttslow(ws,pmdminf->wake_rate);
1124: status = getok(4);
1125: if (status > 0) break;
1126: sleep(1); /* Wait before retrying */
1127: }
1128: if (status > 0) break; /* Initialized OK. */
1129: /* modem-initialization failure */
1130: n1 = (status == 0) ? F_minit : F_modem;
1131: longjmp( sjbuf, n1 );
1132:
1133: /*
1134: Telebit support: Trailblazer, T1000, T2500.
1135: C-Kermit global variables 'dialksp', 'flow', 'dialini', 'parity',
1136: and local variable 'augmdmtyp' modify our behavior:
1137:
1138: modulation- and confguration-independent initialization:
1139: S11 DTMF timing (left alone)
1140: S45 remote access (left alone)
1141: S48=1 all 8 bits are significant, 0 only 7 bits
1142: S51=255 set serial port baud rate automatically (no typeahead)
1143: S52=2 go on hook when DTR drops and reset to NV-RAM
1144: S53 DCD/DSR control (left alone)
1145: S54=2 pass BREAK signal to remote modem immediately
1146: S55=0 respond to command escape sequence <sec>+++<sec>
1147: depending upon the value of 'flow':
1148: ==FLO_NONE S58=0 DTE uses no flow control
1149: ==FLO_HARD S58=2 DTE uses hardware (CTS/RTS) flow control
1150: ==FLO_XONX S58=3 DTE uses XON/XOFF flow control
1151: S66 lock interface speed: depends on value of mdmspd variable:
1152: mdmspd == 0 sets S66=1 (lock speed, use flow control)
1153: mdmspd != 0 sets S66=0 (change speed, no flow control)
1154: S68=255 DCE uses whatever flow control DTE uses (specified in S58)
1155: S95=0 MNP: depends on value of dialmnp variable:
1156: dialmnp == 0 sets S95=0 (no MNP)
1157: dialmnp != 0 sets S95=2 (auto MNP)
1158: S110=1 use data compression if remote modem agrees
1159:
1160: SET MODEM TELEBIT
1161: "traditional" configuration (PEP, V.22, V.22bis, 212A, 103):
1162: S50=0 use automatic configuration to answering modem
1163:
1164: SET MODEM PEP-TELEBIT
1165: PEP mode with SET DIAL KERMIT-SPOOF ON
1166: S50=255 use PEP + lock DCE speed to DTE speed
1167: S111=10 Kermit with no parity
1168: S111=11 Kermit with odd parity
1169: S111=12 Kermit with even parity
1170: S111=13 Kermit with mark parity
1171: S111=14 Kermit with space parity
1172: S112=?? set to Kermit's start-of-packet character, stchr
1173:
1174: SET MODEM PEP-TELEBIT with SET DIAL KERMIT-SPOOF OFF
1175: S50=255 use PEP + lock DCE speed to DTE speed
1176: S111=0 use normal PEP inter-modem protocol
1177:
1178: SET MODEM V32-TELEBIT (doesn't work with Trailblazer or T1000)
1179: S50=6 use V.32
1180:
1181: SET MODEM V42-TELEBIT
1182: S50=0 auto speed select
1183: S95=1 MNP reliable mode
1184: S96=1 enable MNP data compression
1185: S97=1 enable LAP-M
1186: S98=3 compression in both directions
1187: S106=1 V.42 detection enable
1188:
1189: SET MODEM SLOW-TELEBIT
1190: S94=1 connect to any speed up to maximum specified by S50
1191: S50=3 connect to Bell 103/212a, V.21, V.22 and V.22bis
1192: */
1193: case n_TELEBIT: /* Telebits... */
1194: case n_TBNV:
1195: case n_TBPEP:
1196: case n_TB3:
1197: case n_TB4:
1198: case n_TBS:
1199: case n_TBPNV:
1200: case n_TB3NV:
1201: case n_TB4NV:
1202: case n_TBSNV: {
1203: int S58,S66,S95,S111,S112; /* Some Telebit register names */
1204: char t25buf[64]; /* Modem command buffer */
1205: /*
1206: If user defined a DIAL INIT-STRING, send that now, otherwise send built-in
1207: Telebit string. Try up to 4 times to get OK or 0 response from modem.
1208: */
1209: ws = dialini ? dialini : TELEBIT.wake_str;
1210: debug(F110,"ckdial telebit init string",ws,0);
1211: for (tries = 4; tries > 0; tries--) {
1212: ttslow(ws,pmdminf->wake_rate);
1213: status = getok(5);
1214: if (status) break;
1215: dialhup(); /* Hang up */
1216: ttflui(); /* Flush input buffer */
1217: }
1218: if (status < 1) {
1219: n1 = F_minit;
1220: longjmp( sjbuf, F_minit ); /* Failed. */
1221: }
1222: if (!dialini) { /* If using built-in init strings */
1223: /* Step 2 */
1224: sprintf(t25buf,
1225: "ATS48=%d S51=255 S52=2 S54=2\015",
1226: parity ? 0 : 1);
1227: s = t25buf;
1228: debug(F110,"ckdial Telebit init step 2",s,0);
1229: for (tries = 4; tries > 0; tries--) {
1230: ttslow(s,pmdminf->wake_rate);
1231: status = getok(5);
1232: if (status) break;
1233: msleep(500);
1234: ttflui();
1235: }
1236: if (status < 1) {
1237: n1 = F_minit;
1238: longjmp( sjbuf, F_minit ); /* Failed. */
1239: }
1240: switch (flow) { /* Flow control */
1241: case FLO_HARD: S58 = 2; break; /* RTX/CTS (hardware) */
1242: default: S58 = 0; break; /* NONE (or other) */
1243: }
1244: if (dialmnp) { /* MNP negotiation */
1245: S95 = 2; /* Enabled (auto) */
1246: } else {
1247: S95 = 0; /* Disabled */
1248: }
1249: S66 = mdmspd ? 0 : 1; /* Interface speed locked? */
1250: msleep(500);
1251: sprintf(t25buf,
1252: "ATS58=%d S55=0 S66=%d S68=255 S95=%d\015",S58,S66,S95);
1253: s = t25buf;
1254: debug(F110,"ckdial Telebit init step 3",s,0);
1255: for (tries = 4; tries > 0; tries--) {
1256: ttslow(s,pmdminf->wake_rate);
1257: status = getok(5);
1258: if (status) break;
1259: msleep(500);
1260: ttflui();
1261: }
1262: if (status < 1) {
1263: n1 = F_minit;
1264: longjmp( sjbuf, F_minit ); /* Failed. */
1265: }
1266: p = "";
1267: s = "";
1268: switch (augmdmtyp) { /* we will auto-config */
1269: case n_TELEBIT: /* 103,212,v22bis modulation */
1270: case n_TBNV:
1271: p = "standard"; /* Automatic speed determination */
1272: s = "ATS50=0 S110=0\015";
1273: break;
1274: case n_TBPEP: /* PEP Protocol */
1275: case n_TBPNV:
1276: if (dialksp) { /* SET DIAL KERMIT-SPOOF ON? */
1277: switch (parity) {
1278: case 'e': S111 = 12; break;
1279: case 'm': S111 = 13; break;
1280: case 'o': S111 = 11; break;
1281: case 's': S111 = 14; break;
1282: default:
1283: case 0: S111 = 10; break;
1284: }
1285: S112 = stchr; /* Start-of-packet character */
1286: sprintf(t25buf,
1287: "ATS50=255 S110=1 S111=%d S112=%d\015",S111,S112);
1288: p = "PEP/Kermit";
1289: s = t25buf;
1290: } else { /* SET DIAL KERMIT-SPOOF OFF */
1291: p = "PEP/No-Kermit";
1292: s = "ATS50=255 S110=1\015"; /* Accept any protocol */
1293: }
1294: debug(F101,"ckdial telebit pep waitct","",waitct);
1295: break;
1296:
1297: case n_TB3: /* Telebit V.32 */
1298: case n_TB3NV:
1299: p = "V.32";
1300: s = "ATS50=6\015";
1301: break;
1302:
1303: case n_TB4: /* Telebit V.42 */
1304: case n_TB4NV:
1305: p = "V.42";
1306: s = "ATS50=0 S95=1 S96=1 S97=1 S98=3 S106=1\015";
1307: break;
1308:
1309: case n_TBS: /* Telebit up to 2400 Baud */
1310: case n_TBSNV:
1311: p = "300/1200/2400 Baud";
1312: s = "ATS94=1 S50=3\015";
1313: break;
1314: }
1315: debug(F111,"ckdial Telebit config",p,speed);
1316: debug(F110,"ckdial Telebit init step 4",s,0);
1317: if (*s) {
1318: for (tries = 4; tries > 0; tries--) {
1319: ttslow(s,pmdminf->wake_rate);
1320: status = getok(5);
1321: if (status) break;
1322: msleep(500);
1323: ttflui();
1324: }
1325: debug(F101,"ckdial telebit init status","",status);
1326: if (status < 1) {
1327: n1 = F_minit;
1328: longjmp(sjbuf, F_minit);
1329: }
1330: }
1331: }
1332: /* Done with Telebit protocols, remove bits from modem type */
1333: /* Except nonverbal bit */
1334: augmdmtyp &= ~(DIAL_PEP|DIAL_V32|DIAL_V42|DIAL_SLO);
1335: debug(F101,"ckdial Telebit augmdmtyp","",augmdmtyp);
1336: break;
1337: }
1338:
1339: case n_MICROCOM: /* interdigit waits for tone dial */
1340: {
1341: jmp_buf savejmp;
1342: alarm(0);
1343: xcpy((char *)savejmp, (char *)sjbuf, sizeof savejmp);
1344: if (setjmp(sjbuf)) {
1345: /* try the autobaud sequence */
1346: xcpy((char *)sjbuf, (char *)savejmp, sizeof savejmp);
1347: alarm(5);
1348: ttslow("44445", MICROCOM.wake_rate);
1349: waitfor(MICROCOM.wake_str);
1350: } else {
1351: alarm(2);
1352: ws = dialini ? dialini : MICROCOM.wake_str;
1353: ttslow(ws, MICROCOM.wake_rate);
1354:
1355: waitfor(ws);
1356: alarm(0);
1357: xcpy((char *)sjbuf, (char *)savejmp, sizeof savejmp);
1358: }
1359: }
1360: break;
1361: case n_ATTDTDM: /* DTDM requires BREAK to wake up */
1362: ttsndb(); /* Send BREAK */
1363: break; /* ttsndb() defined in ckutio.c */
1364:
1365: default: /* place modem into command mode */
1366: ws = dialini ? dialini : pmdminf->wake_str;
1367: debug(F111,"ckdial default, wake string",ws,
1368: pmdminf->wake_rate);
1369: ttslow(ws, pmdminf->wake_rate);
1370: debug(F110,"ckdial default, waiting for wake_prompt",
1371: pmdminf->wake_prompt,0);
1372: savalrm = signal(SIGALRM,dialtime);
1373: alarm(10);
1374: waitfor(pmdminf->wake_prompt);
1375: break;
1376: }
1377: alarm(0); /* turn off alarm */
1378: if (augmdmtyp != n_TELEBIT)
1379: debug(F100,"ckdial got wake prompt","",0);
1380: msleep(500); /* give things settling time */
1381:
1382: /* Enable/disable MNP (Telebit already done above) */
1383:
1384: switch (augmdmtyp) {
1385: case n_HST:
1386: if (dialmnp)
1387: ttslow("AT&K2\015",pmdminf->wake_rate);
1388: else
1389: ttslow("AT&K0\015",pmdminf->wake_rate);
1390: getok(5); /* Get response */
1391: break;
1392: default:
1393: break;
1394: }
1395:
1396: /* Dial the number */
1397: /* put modem into dialing mode */
1398: ttslow(pmdminf->dmode_str, pmdminf->dial_rate);
1399: savalrm = signal(SIGALRM,dialtime);
1400: alarm(10);
1401: if (pmdminf->dmode_prompt) { /* wait for prompt, if any expected */
1402: waitfor(pmdminf->dmode_prompt);
1403: msleep(300);
1404: }
1405: alarm(0); /* turn off alarm on dialing prompts */
1406: ttflui(); /* clear out stuff from waking modem up */
1407:
1408: sprintf(lbuf, pmdminf->dial_str, telnbr); /* form dialing string */
1409: debug(F110,"dialing",lbuf,0);
1410: ttslow(lbuf,pmdminf->dial_rate); /* send dialing string */
1411:
1412: savalrm = signal(SIGALRM,dialtime); /* Time to allow for connecting */
1413: x = alarm(waitct); /* This much time... */
1414: debug(F101,"ckdial old alarm","",x);
1415: debug(F101,"ckdial waitct","",waitct);
1416:
1417: switch (augmdmtyp) {
1418: case n_RACAL: /* acknowledge printout of dialing string */
1419: sleep(3);
1420: ttflui();
1421: ttoc('\015');
1422: break;
1423: case n_VENTEL:
1424: waitfor("\012\012"); /* Ignore the first two strings */
1425: break;
1426: default:
1427: break;
1428: }
1429:
1430: /* Check for connection */
1431:
1432: /*
1433: * I believe we also need to look for carrier in order to determine if a
1434: * connection has been made. In fact, for many we may only want to look for
1435: * the "failure" responses in order to short-circuit the timeout, and let
1436: * carrier be the determination of whether a connection has been made. -- DS
1437: */
1438: status = 0;
1439: strcpy(lbuf,"No Connection"); /* default failure reason */
1440: debug(F101,"dial awaiting response, augmdmtyp","",augmdmtyp);
1441: while (status == 0) {
1442: switch (augmdmtyp) {
1443: default:
1444: for (n = 0; n < LBUFL-1; n++) { /* accumulate response */
1445: lbuf[n] = c2 = (ttinc(0) & 0177);
1446: dialoc(c2);
1447: if ( lbuf[n] == CR || lbuf[n] == LF ) break;
1448: }
1449: lbuf[n] = '\0'; /* Terminate response from modem */
1450: debug(F111,"dial modem response",lbuf,n);
1451: if (n) { /* If one or more characters present */
1452: switch (augmdmtyp) { /* check for modem response message. */
1453: case n_ATTMODEM:
1454: /* Careful - "Connected" / "Not Connected" */
1455: if (didweget(lbuf,"Busy") ||
1456: didweget(lbuf,"Not connected") ||
1457: didweget(lbuf,"Not Connected") ||
1458: didweget(lbuf,"No dial tone") ||
1459: didweget(lbuf,"No Dial Tone") ||
1460: didweget(lbuf,"No answer") ||
1461: didweget(lbuf,"No Answer"))
1462: status = FAILED;
1463: else if (didweget(lbuf,"Answered") ||
1464: didweget(lbuf,"Connected"))
1465: status = CONNECTED;
1466: break;
1467:
1468: case n_ATTISN:
1469: if (didweget(lbuf,"ANSWERED"))
1470: status = CONNECTED;
1471: else if (didweget(lbuf,"BUSY") ||
1472: didweget(lbuf,"DISCONNECT") ||
1473: didweget(lbuf,"NO ANSWER") ||
1474: didweget(lbuf,"WRONG ADDRESS"))
1475: status = FAILED;
1476: break;
1477:
1478: case n_ATTDTDM:
1479: if (didweget(lbuf,"ANSWERED"))
1480: status = CONNECTED;
1481: else if (didweget(lbuf,"BUSY") ||
1482: didweget(lbuf,"CHECK OPTIONS") ||
1483: didweget(lbuf,"DISCONNECTED") ||
1484: didweget(lbuf,"DENIED"))
1485: status = FAILED;
1486: #ifdef DEBUG
1487: #ifdef ATT6300
1488: else if (deblog && didweget(lbuf,"~~"))
1489: status = CONNECTED;
1490: #endif /* ATT6300 */
1491: #endif /* DEBUG */
1492: break;
1493:
1494: case n_CERMETEK:
1495: if (didweget(lbuf,"\016A")) {
1496: status = CONNECTED;
1497: ttslow("\016U 1\015",200); /* make transparent*/
1498: }
1499: break;
1500:
1501: case n_DF100: /* DF100 has short response codes */
1502: if (strcmp(lbuf,"A") == 0)
1503: status = CONNECTED; /* Attached */
1504: else if (strcmp(lbuf,"N") == 0 || /* No Ans or Dialtone */
1505: strcmp(lbuf,"E") == 0 || /* Error */
1506: strcmp(lbuf,"R") == 0) { /* Ready */
1507: status = FAILED;
1508: break;
1509: }
1510: /* otherwise fall thru... */
1511:
1512: case n_DF200:
1513: if (didweget(lbuf,"Attached"))
1514: status = CONNECTED;
1515: /*
1516: * The DF100 will respond with "Attached" even if DTR
1517: * and/or carrier are not present. Another reason to
1518: * (also) wait for carrier?
1519: */
1520: else if (didweget(lbuf,"Busy") ||
1521: didweget(lbuf,"Disconnected") ||
1522: didweget(lbuf,"Error") ||
1523: didweget(lbuf,"No answer") ||
1524: didweget(lbuf,"No dial tone") ||
1525: didweget(lbuf,"Speed:"))
1526: status = FAILED;
1527: /*
1528: * It appears that the "Speed:..." response comes after an
1529: * "Attached" response, so this is never seen. HOWEVER,
1530: * it would be very handy to detect this and temporarily
1531: * reset the speed, since it's a nuisance otherwise.
1532: * If we wait for some more input from the modem, how do
1533: * we know if it's from the remote host or the modem?
1534: * Carrier reportedly doesn't get set until after the
1535: * "Speed:..." response (if any) is sent. Another reason
1536: * to (also) wait for carrier.
1537: */
1538: break;
1539:
1540: case n_GDC:
1541: if (didweget(lbuf,"ON LINE"))
1542: status = CONNECTED;
1543: else if (didweget(lbuf,"NO CONNECT"))
1544: status = FAILED;
1545: break;
1546:
1547: case n_HAYES:
1548: case n_USROBOT:
1549: case n_HST:
1550: case n_TELEBIT:
1551: if (mdmspd) {
1552: s = lbuf;
1553: while (*s != '\0' && *s != 'C') s++;
1554: cptr = (*s == 'C') ? s : NULL;
1555: conspd = 0L;
1556: if ((cptr != NULL) && !strncmp(cptr,"CONNECT ",8)) {
1557: if ((int)strlen(cptr) < 9) /* Just CONNECT, */
1558: conspd = 300L; /* use 300 bps */
1559: else if (isdigit(*(cptr+8))) /* not CONNECT FAST */
1560: conspd = atol(cptr + 8); /* CONNECT nnnn */
1561: if (conspd != speed) {
1562: if ((conspd / 10L) > 0) {
1563: if (ttsspd((int) (conspd / 10L)) < 0) {
1564: printf(" Can't change speed to %lu\r\n",
1565: conspd);
1566: } else {
1567: speed = conspd;
1568: status = CONNECTED;
1569: if ( !quiet )
1570: printf(" Speed changed to %lu\r\n",
1571: conspd);
1572: }
1573: }
1574: } /* Expanded to handle any conceivable speed */
1575: }
1576: }
1577: if (mymdmtyp == n_TELEBIT) {
1578: if (didweget(lbuf,"CONNECT FAST/KERM")) {
1579: status = CONNECTED;
1580: if (!quiet) printf("FAST/KERM ");
1581: break;
1582: }
1583: }
1584: if (didweget(lbuf,"RRING") || didweget(lbuf,"RINGING")) {
1585: status = 0;
1586: } else if (didweget(lbuf,"CONNECT")) {
1587: status = CONNECTED;
1588: } else if (didweget(lbuf,"NO CARRIER") ||
1589: didweget(lbuf,"NO DIALTONE") ||
1590: didweget(lbuf,"NO DIAL TONE") ||
1591: didweget(lbuf,"BUSY") ||
1592: didweget(lbuf,"NO ANSWER") ||
1593: didweget(lbuf,"VOICE") ||
1594: didweget(lbuf,"RING") ||
1595: didweget(lbuf,"ERROR")) {
1596: status = FAILED;
1597: }
1598: break;
1599: case n_PENRIL:
1600: if (didweget(lbuf,"OK"))
1601: status = CONNECTED;
1602: else if (didweget(lbuf,"BUSY") ||
1603: didweget(lbuf,"NO RING"))
1604: status = FAILED;
1605: break;
1606: case n_RACAL:
1607: if (didweget(lbuf,"ON LINE"))
1608: status = CONNECTED;
1609: else if (didweget(lbuf,"FAILED CALL"))
1610: status = FAILED;
1611: break;
1612: case n_ROLM:
1613: if (didweget(lbuf,"CALLING"))
1614: status = 0;
1615: else if (didweget(lbuf,"COMPLETE"))
1616: status = CONNECTED;
1617: else if (didweget(lbuf,"FAILED") ||
1618: didweget(lbuf,"NOT AVAILABLE") ||
1619: didweget(lbuf,"LACKS PERMISSION") ||
1620: didweget(lbuf,"NOT A DATALINE") ||
1621: didweget(lbuf,"BUSY") ||
1622: didweget(lbuf,"ABANDONDED") ||
1623: didweget(lbuf,"DOES NOT ANSWER"))
1624: status = FAILED;
1625: /*
1626: Early versions of the Rolm 9751 CBX software do not
1627: give a CALL COMPLETE indication when dialing an
1628: outpool number, but they do seem to return a long
1629: string of DELs at that point. (this doesn't really
1630: work...)
1631: else if (didweget(lbuf,"\177\177\177"))
1632: status = CONNECTED;
1633: */
1634: break;
1635: case n_VENTEL:
1636: if (didweget(lbuf,"ONLINE!") ||
1637: didweget(lbuf,"Online!"))
1638: status = CONNECTED;
1639: else if (didweget(lbuf,"BUSY") ||
1640: didweget(lbuf,"DEAD PHONE") ||
1641: didweget(lbuf,"Busy"))
1642: status = FAILED;
1643: break;
1644: case n_CONCORD:
1645: if (didweget(lbuf,"INITIATING"))
1646: status = CONNECTED;
1647: else if (didweget(lbuf,"BUSY") ||
1648: didweget(lbuf,"CALL FAILED"))
1649: status = FAILED;
1650: break;
1651: case n_MICROCOM:
1652: /* "RINGBACK" means phone line ringing, continue */
1653: if (didweget(lbuf,"NO CONNECT") ||
1654: didweget(lbuf,"BUSY") ||
1655: didweget(lbuf,"NO DIALTONE") ||
1656: didweget(lbuf,"COMMAND ERROR") ||
1657: didweget(lbuf,"IN USE"))
1658: status = FAILED;
1659: else if (didweget(lbuf,"CONNECT"))
1660: status = CONNECTED;
1661: /* trailing speed ignored */
1662: break;
1663: }
1664: }
1665: break;
1666:
1667: case n_DF03: /* because response lacks CR or NL */
1668: c = ttinc(0) & 0177;
1669: dialoc(c);
1670: debug(F000,"dial df03 got","",c);
1671: if ( c == 'A' ) status = CONNECTED;
1672: if ( c == 'B' ) status = FAILED;
1673: break;
1674:
1675: case n_HAYESNV: /* Hayeslike modems in digit */
1676: case n_TBNV: /* response mode... */
1677: case n_TB3NV:
1678: case n_TBPNV:
1679: case n_TB4NV:
1680: case n_TBSNV:
1681: /*
1682: The method for reading Hayes numeric result codes has been totally
1683: redone as of 5A(174) to account for all of the following. Not all have
1684: been tested, and others probably need to be added.
1685:
1686: Hayes numeric result codes (Hayes 1200 and higher):
1687: 0 = OK
1688: 1 = CONNECT at 300 bps (or 1200 bps on Hayes 1200 with basic code set)
1689: 2 = RING
1690: 3 = NO CARRIER
1691: 4 = ERROR (in command line)
1692: 5 = CONNECT 1200 (extended code set)
1693: Hayes 2400 and higher:
1694: 6 = NO DIALTONE
1695: 7 = BUSY
1696: 8 = NO ANSWER
1697: 9 = (there is no 9)
1698: 10 = CONNECT 2400
1699: Reportedly, the codes for Hayes V.32 modems are:
1700: 1x = CONNECT <suffix>
1701: 5x = CONNECT 1200 <suffix>
1702: 9x = CONNECT 2400 <suffix>
1703: 11x = CONNECT 4800 <suffix>
1704: 12x = CONNECT 9600 <suffix>
1705: Where:
1706: x: suffix:
1707: R = RELIABLE
1708: RC = RELIABLE COMPRESSED
1709: L = LAPM
1710: LC = LAPM COMPRESSED
1711: And for Telebits:
1712: 50 = CONNECT FAST
1713: 52 = RRING
1714: What else?
1715: */
1716: { /* Nonverbal response code handler */
1717: char nbuf[8]; /* Response buffer */
1718: int i, j; /* Buffer pointers */
1719: if (mdmecho) { /* Sponge up dialing string echo. */
1720: while ((c = (ttinc(0) & 0177)) != CR)
1721: dialoc(c);
1722: }
1723: while (status == 0) { /* Read response */
1724: for (i = 0; i < 8; i++) /* Clear the buffer */
1725: nbuf[i] = '\0';
1726: i = 0; /* Reset the buffer pointer. */
1727: c = ttinc(0) & 0177; /* Get first digit of response. */
1728: /* using an untimed, blocking read. */
1729: dialoc(c); /* Echo it if requested. */
1730: if (!isdigit(c)) /* If not a digit, keep looking. */
1731: continue;
1732: nbuf[i++] = c; /* Got a digit, save it. */
1733: while (i < 8) { /* Keep reading till we time out */
1734: y = alarm(0) - 1; /* Save current alarm */
1735: x = ttinc(1); /* Read char with 1-sec timeout */
1736: if (y > 0) alarm(y); /* Restore alarm */
1737: if (x > 0) { /* If we didn't time out, */
1738: c = (char) x; /* we got this character. */
1739: if (c != CR) /* Save it, */
1740: nbuf[i++] = c; /* if it's not a carriage return. */
1741: dialoc(c); /* Echo it. */
1742: } else break; /* Otherwise assume end of response. */
1743: }
1744: nbuf[i] = '\0'; /* Terminate the buffer. */
1745: debug(F111,"dial hayesnv lbuf",lbuf,n);
1746: debug(F111,"dial hayesnv got",nbuf,i);
1747: /*
1748: Separate any non-numeric suffix from the numeric result code
1749: with a null.
1750: */
1751: for (j = i-1; (j > -1) && !isdigit(nbuf[j]); j--)
1752: nbuf[j+1] = nbuf[j];
1753: j++;
1754: nbuf[j++] = '\0';
1755: debug(F110,"dial hayesnv numeric",nbuf,0);
1756: debug(F111,"dial hayesnv suffix ",nbuf+j,j);
1757: if ((int)strlen(nbuf) > 3) /* Probably phone number echoing. */
1758: continue;
1759: /*
1760: Now read and interpret the results...
1761: */
1762: i = atoi(nbuf); /* Convert to integer */
1763: switch (i) {
1764: case 1: /* CONNECT */
1765: status = CONNECTED; /* Could be any speed */
1766: break;
1767: case 2: /* RING */
1768: if (dialdpy) printf("\r\n Local phone is ringing!\r\n");
1769: status = FAILED;
1770: break;
1771: case 3: /* NO CARRIER */
1772: if (dialdpy) printf("\r\n No Carrier.\r\n");
1773: status = FAILED;
1774: break;
1775: case 4: /* ERROR */
1776: if (dialdpy) printf("\r\n Modem Command Error.\r\n");
1777: status = FAILED;
1778: break;
1779: case 5: /* CONNECT 1200 */
1780: spdchg(1200L); /* Change speed if necessary. */
1781: status = CONNECTED;
1782: break;
1783: case 6: /* NO DIALTONE */
1784: if (dialdpy) printf("\r\n No Dialtone.\r\n");
1785: status = FAILED;
1786: break;
1787: case 7: /* BUSY */
1788: if (dialdpy) printf("\r\n Busy.\r\n");
1789: status = FAILED;
1790: break;
1791: case 8: /* NO ANSWER */
1792: if (dialdpy) printf("\r\n No Answer.\r\n");
1793: status = FAILED;
1794: break;
1795: case 9: /* CONNECT 2400 */
1796: case 10:
1797: spdchg(2400L); /* Change speed if necessary. */
1798: status = CONNECTED;
1799: break;
1800: case 11: /* CONNECT 4800 */
1801: spdchg(4800L);
1802: status = CONNECTED;
1803: break;
1804: case 12: /* CONNECT 9600 */
1805: spdchg(9600L);
1806: status = CONNECTED;
1807: break;
1808: case 52: /* RRING */
1809: debug(F101,"dial hayesnv 52 mymdmtyp","",mymdmtyp);
1810: debug(F101,"dial hayesnv 52 n_TELEBIT","",n_TELEBIT);
1811: if (mymdmtyp == n_TELEBIT)
1812: if (dialdpy) printf(" Ringing...\r\n");
1813: break;
1814: case 50: /* CONNECT FAST */
1815: if (mymdmtyp == n_TELEBIT)
1816: status = CONNECTED; /* CONNECT FAST */
1817: break;
1818: default:
1819: break;
1820: }
1821: }
1822: if (status == CONNECTED && nbuf[j] != '\0') {
1823: if (dialdpy) {
1824: printf("\r\n");
1825: if (nbuf[j] == 'R') printf("RELIABLE");
1826: if (nbuf[j] == 'L') printf("LAPM");
1827: if (nbuf[j+1] == 'C') printf(" COMPRESSED");
1828: printf("\r\n");
1829: }
1830: }
1831: }
1832: break;
1833:
1834: case n_UNKNOWN: {
1835: int x, y = waitct;
1836: while (y-- > -1) {
1837: x = ttchk();
1838: if (x > 0) {
1839: if (x > LBUFL) x = LBUFL;
1840: x = ttxin(x,(CHAR *)lbuf);
1841: if ((x > 0) && dialdpy) conol(lbuf);
1842: }
1843: x = ttgmdm(); /* Try to read modem signals */
1844: if (x < 0) break; /* Can't, pretend we suceeded */
1845: if (x & BM_DCD) /* Got signals OK. Carrier present? */
1846: break; /* Yes, done. */
1847: sleep(1);
1848: }
1849: status = CONNECTED;
1850: break;
1851: }
1852: } /* switch (augmdmtyp) */
1853: } /* while status == 0 */
1854: x = alarm(0); /* turn off alarm on connecting */
1855: debug(F101,"ckdial alarm off","",x);
1856: if ( status != CONNECTED ) { /* modem-detected failure */
1857: n1 = F_modem;
1858: longjmp( sjbuf, F_modem ); /* exit (with reason in lbuf) */
1859: }
1860: msleep(1000); /* in case DTR blinks */
1861: alarm(3); /* precaution in case of trouble */
1862: debug(F110,"dial","succeeded",0);
1863: if (augmdmtyp != n_ROLM) /* Rolm has wierd modem signaling */
1864: ttpkt(speed,CONNECT,parity); /* cancel dialing state ioctl */
1865: reset(); /* reset alarms, etc. */
1866: if (!quiet)
1867: printf (" Call completed.\07\n");
1868: #ifdef DYNAMIC
1869: if (lbuf) free(lbuf);
1870: #endif /* DYNAMIC */
1871: return(1); /* return, and presumably connect */
1872: }
1873:
1874: /*
1875: getok - wait up to n seconds for "OK<CRLF>" or "<CR>0" from modem.
1876: Use with Hayeslike modems for reading reply to a nondialing command.
1877: Does its own internal timeout handling, but resets alarms to 0.
1878: Returns 0 if it timed out, 1 if it succeeded, -1 on modem command error.
1879: */
1880: static jmp_buf okbuf; /* Jump-buf for getok(). */
1881:
1882: SIGTYP
1883: oktimo(foo) int foo; { /* Alarm handler for getok(). */
1884: longjmp(okbuf,1);
1885: }
1886:
1887: int
1888: getok(n) int n; {
1889: CHAR c;
1890: int i, x, status;
1891: char rbuf[8]; /* response buffer */
1892: SIGTYP (*saval)(); /* for saving alarm handler locally */
1893:
1894: saval = signal(SIGALRM,oktimo); /* set timer */
1895: alarm(n);
1896: if (setjmp(okbuf)) { /* handle timeout */
1897: alarm(0);
1898: if (saval) signal(SIGALRM,saval);
1899: debug(F100,"getok timed out","",0);
1900: ttflui();
1901: return(0);
1902: } else { /* not timed out... */
1903: status = 0;
1904: rbuf[7] = '\0'; /* Terminate response buffer */
1905: while (status == 0) {
1906: x = ttinc(0); /* Read a character */
1907: if (x < 0) return(-1); /* i/o error */
1908: debug(F101,"getok ttinc returns","",x);
1909: c = x & 0x7f; /* Get low order 7 bits */
1910: debug(F101,"getok converts this to char","",c);
1911: if (dialdpy) conoc((char)c); /* Echo it if requested */
1912: for (i = 0; i < 6; i++) /* Rotate buffer */
1913: rbuf[i] = rbuf[i+1];
1914: rbuf[6] = c; /* Deposit character */
1915: debug(F000,"getok",rbuf,(int) c); /* Log it */
1916: switch (c) { /* Interpret it. */
1917: case CR: /* Got carriage return. */
1918: if (augmdmtyp & DIAL_NV) /* If using digit result codes */
1919: conoc(LF); /* echo a linefeed too. */
1920: break;
1921: case LF: /* Got linefeed. */
1922: /*
1923: Note use of explicit octal codes in the string for
1924: CR and LF. We want real CR and LF here, not whatever
1925: the compiler happens to define \r and \n as...
1926: */
1927: if (!strcmp(rbuf+3,"OK\015\012"))
1928: status = 1;
1929: else if (!strcmp(rbuf,"ERROR\015\012"))
1930: status = -1;
1931: augmdmtyp &= ~(DIAL_NV); /* Turn off the nonverbal bit */
1932: break;
1933: /* Check whether modem echoes its commands... */
1934: case 't': /* Got little t */
1935: if (!strcmp(rbuf+4,"\015at")) mdmecho = 1;
1936: break;
1937: case 'T': /* Got Big T */
1938: if (!strcmp(rbuf+4,"\015AT")) mdmecho = 1;
1939: break;
1940: case '0': /* Got 0: Numeric result code? */
1941: if (rbuf[5] == CR) { /* Yes if previous char was CR. */
1942: augmdmtyp |= DIAL_NV; /* OR in the "nonverbal" bit. */
1943: status = 1;
1944: }
1945: break;
1946: case '4': /* Command line error */
1947: if (rbuf[5] == CR) /* if previous char was CR */
1948: status = -1;
1949: break;
1950: default: /* Other characters, accumulate. */
1951: status = 0;
1952: break;
1953: }
1954: }
1955: debug(F101,"getok returns","",status);
1956: alarm(0);
1957: if (saval) signal(SIGALRM,saval);
1958: ttflui();
1959: return(status);
1960: }
1961: }
1962:
1963: /* Maybe hang up the phone, depending on various SET DIAL parameters. */
1964:
1965: int
1966: dialhup() {
1967: int x = 0;
1968: if (dialhng) { /* DIAL HANGUP ON? */
1969: x = tthang();
1970: if (dialdpy) { /* DIAL DISPLAY ON? */
1971: if (x > 0) /* Yes, tell results from tthang() */
1972: printf(" Hangup ok\r\n");
1973: else if (x == 0)
1974: printf(" Hangup skipped\r\n");
1975: else
1976: perror(" Hangup error");
1977: }
1978: } else if (dialdpy) printf(" No hangup\r\n"); /* DIAL HANGUP OFF */
1979: return(x);
1980: }
1981:
1982: char * /* Let external routines ask */
1983: getdws(mdmtyp) int mdmtyp; { /* about dial wake string. */
1984: MDMINF * pmdminf;
1985: if (mdmtyp < 1 || mdmtyp > MAX_MDM) return("");
1986: pmdminf = ptrtab[(mdmtyp & 0xff) -1 ];
1987: return(dialini ? dialini : pmdminf->wake_str);
1988: }
1989:
1990: #else
1991: char *dialv = "Dial Command Disabled";
1992: #endif /* NODIAL */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.