|
|
1.1 root 1: #ifndef NODIAL
2: char *dialv = "Dial Command, 5A(046) 2 Nov 92";
3:
4: /* C K U D I A -- Module for automatic modem dialing. */
5:
6: /*
7: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
8: York. Permission is granted to any individual or institution to use this
9: software as long as it is not sold for profit. This copyright notice must be
10: retained. This software may not be included in commercial products without
11: written permission of Columbia University.
12:
13: Original (version 1, 1985) author: Herm Fischer, Encino, CA.
14: Contributed to Columbia University in 1985 for inclusion in C-Kermit 4.0.
15: Author and maintainer since 1985: Frank da Cruz, Columbia University,
16: [email protected].
17:
18: Contributions by many others throughout the years, including: Fernando
19: Cabral, John Chmielewski, Joe Doupnik, Richard Hill, Larry Jacobs, Eric
20: Jones, Tom Kloos, Bob Larson, Peter Mauzey, Joe Orost, Kevin O'Gorman, Kai
21: Uwe Rommel, Dan Schullman, Warren Tucker, and others too numerous to list
22: here (but see acknowledgements in ckcmai.c).
23:
24: This module calls externally defined system-dependent functions for
25: communications i/o, as defined in CKCPLM.DOC, the C-Kermit Program Logic
26: Manual, and thus should be portable to all systems that implement those
27: functions, and where alarm() and signal() work as they do in UNIX.
28: */
29:
30: /*
31: To add support for another modem, do the following, all in this module:
32:
33: 1. Define a modem-type number symbol (n_XXX) for it.
34:
35: 2. Adjust MAX_MDM to the new number of modem types.
36:
37: 3. Create a MDMINF structure for it.
38:
39: 4. Add the address of the MDMINF structure to the ptrtab[] array,
40: according to the numerical value of the modem-type number.
41:
42: 5. Add the user-visible (SET MODEM) name and corresponding modem
43: number to the mdmtab[] array, in alphabetical order by modem-name string.
44:
45: 6. Read through the code and add modem-specific sections as necessary.
46:
47: NOTE: The MINIDIAL symbol is used to build this module to include support
48: for only a minimum number of standard and/or generally useful modem types,
49: namely Hayes, CCITT V.25bis, "Unknown", and None. When adding support for
50: a new modem type, keep it outside of the MINIDIAL sections.
51: */
52:
53: #include "ckcdeb.h"
54: #ifndef MAC
55: #include <signal.h>
56: #endif /* MAC */
57: #include "ckcasc.h"
58: #include "ckcker.h"
59: #include "ckucmd.h"
60: #include "ckcnet.h"
61:
62: #ifndef ZILOG
63: #include <setjmp.h> /* Longjumps */
64: #else
65: #include <setret.h>
66: #endif /* ZILOG */
67:
68: #ifdef MAC
69: #define signal msignal
70: #define SIGTYP long
71: #define alarm malarm
72: #define SIG_IGN 0
73: #define SIGALRM 1
74: #define SIGINT 2
75: SIGTYP (*msignal(int type, SIGTYP (*func)(int)))(int);
76: #endif /* MAC */
77:
78: int /* SET DIAL parameters */
79: dialhng = 1, /* DIAL HANGUP, default is ON */
80: dialdpy = 0, /* DIAL DISPLAY, default is OFF */
81: mdmspd = 1, /* DIAL SPEED-MATCHING (1 = ON) */
82: dialtmo = 0, /* DIAL TIMEOUT */
83: dialksp = 0, /* DIAL KERMIT-SPOOF */
84: dialmnp = 0, /* DIAL MNP-ENABLE */
85: #ifdef NOMDMHUP
86: dialmhu = 0; /* DIAL MODEM-HANGUP */
87: #else
88: dialmhu = 1; /* DIAL MODEM-HANGUP */
89: #endif /* NOMDMHUP */
90:
91: char *dialdir = NULL; /* DIAL DIRECTORY, default none */
92: char *dialini = NULL; /* DIAL INIT-STRING, default none */
93: char *dialcmd = NULL; /* DIAL DIAL-COMMAND, default none */
94: char *dialnpr = NULL; /* DIAL NUMBER-PREFIX, ditto */
95: FILE * dialfd = NULL; /* File descriptor of dial directory */
96:
97: #ifndef MINIDIAL
98: /*
99: Telebit model codes:
100:
101: ATI Model Numbers Examples
102: --- ------------- --------
103: 123 Telebit in "total Hayes-1200" emulation mode
104: 960 Telebit in Conventional Command (Hayes) mode
105: 961 RA12C IBM PC internal original Trailblazer
106: 962 RA12E External original Trailblazer
107: 963 RM12C Rackmount original Trailblazer
108: 964 T18PC IBM PC internal Trailblazer-Plus (TB+)
109: 965 T18SA, T2SAA, T2SAS External TB+, T1600, T2000, T3000, WB, and later
110: 966 T18RMM Rackmount TB+
111: 967 T2MC IBM PS/2 internal TB+
112: 968 T1000 External T1000
113: 969 ? Qblazer
114: 971 T2500 External T2500
115: 972 T2500 Rackmount T2500
116: */
117:
118: /* Telebit model codes */
119:
120: #define TB_UNK 0 /* Unknown Telebit model */
121: #define TB_BLAZ 1 /* Original TrailBlazer */
122: #define TB_PLUS 2 /* TrailBlazer Plus */
123: #define TB_1000 3 /* T1000 */
124: #define TB_1500 4 /* T1500 */
125: #define TB_1600 5 /* T1600 */
126: #define TB_2000 6 /* T2000 */
127: #define TB_2500 7 /* T2500 */
128: #define TB_3000 8 /* T3000 */
129: #define TB_QBLA 9 /* Qblazer */
130: #define TB_WBLA 10 /* WorldBlazer */
131: #define TB__MAX 10 /* Highest number */
132:
133: char *tb_name[] = { /* Array of model names */
134: "Unknown", /* TB_UNK */
135: "TrailBlazer", /* TB_BLAZ */
136: "TrailBlazer-Plus", /* TB_PLUS */
137: "T1000", /* TB_1000 */
138: "T1500", /* TB_1500 */
139: "T1600", /* TB_1600 */
140: "T2000", /* TB_2000 */
141: "T2500", /* TB_2500 */
142: "T3000", /* TB_3000 */
143: "Qblazer", /* TB_QBLA */
144: "WorldBlazer", /* TB_WBLA */
145: ""
146: };
147: #endif /* MINIDIAL */
148:
149: extern int flow, local, mdmtyp, quiet, backgrd, parity, seslog, network;
150: extern int carrier, duplex;
151: #ifdef NETCONN
152: extern int ttnproto;
153: #endif /* NETCONN */
154: extern CHAR stchr;
155: extern long speed;
156: extern char ttname[], sesfil[];
157:
158: /*
159: * Failure reasons for use with the 'longjmp' exit.
160: */
161: #define F_time 1 /* timeout */
162: #define F_int 2 /* interrupt */
163: #define F_modem 3 /* modem-detected failure */
164: #define F_minit 4 /* cannot initialize modem */
165:
166: static int mymdmtyp; /* Local copy of modem type. */
167: static int n1 = F_time;
168:
169: _PROTOTYP (static int ddinc, (int) );
170: _PROTOTYP (int dialhup, (void) );
171: _PROTOTYP (int getok, (int,int) );
172: _PROTOTYP (char * getdws, (int) );
173: _PROTOTYP (static VOID ttslow, (char *s, int millisec) );
174: _PROTOTYP (VOID xcpy, (char *to, char *from, unsigned len) );
175: _PROTOTYP (static VOID waitfor, (char *s) );
176: _PROTOTYP (static VOID dialoc, (char c) );
177: _PROTOTYP (static int didweget, (char *s, char *r) );
178: _PROTOTYP (static VOID spdchg, (long s) );
179: _PROTOTYP (static VOID tbati3, (int n) );
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: int esc_time; /* guard time on escape sequence (msecs) */
196: char *esc_str; /* escape sequence */
197: char *hup_str; /* hangup string */
198: _PROTOTYP( int (*ok_fn), (int,int) ); /* func to read response string */
199: };
200:
201: /*
202: * Define symbolic modem numbers.
203: *
204: * The numbers MUST correspond to the ordering of entries
205: * within the ptrtab array, and start at one (1).
206: *
207: * It is assumed that there are relatively few of these
208: * values, and that the high(er) bytes of the value may
209: * be used for modem-specific mode information.
210: *
211: * REMEMBER that only the first eight characters of these
212: * names are guaranteed to be unique.
213: */
214:
215: #ifdef MINIDIAL /* Minimum dialer support */
216: /* Only for CCITT, HAYES, and UNK */
217: #define n_CCITT 1
218: #define n_HAYES 2
219: #define n_UNKNOWN 3
220: #define MAX_MDM 3 /* Number of modem types */
221:
222: #else /* Full-blown dialer support */
223:
224: #define n_ATTDTDM 1
225: #define n_ATTISN 2
226: #define n_ATTMODEM 3
227: #define n_CCITT 4
228: #define n_CERMETEK 5
229: #define n_DF03 6
230: #define n_DF100 7
231: #define n_DF200 8
232: #define n_GDC 9
233: #define n_HAYES 10
234: #define n_PENRIL 11
235: #define n_RACAL 12
236: #define n_UNKNOWN 13
237: #define n_USROBOT 14
238: #define n_VENTEL 15
239: #define n_CONCORD 16
240: #define n_ATTUPC 17 /* aka UNIX PC and ATT7300 */
241: #define n_ROLM 18 /* Rolm CBX DCM */
242: #define n_MICROCOM 19
243: #define n_HST 20
244: #define n_TELEBIT 21 /* Telebits of all kinds */
245: #define n_DIGITEL 22 /* Digitel DT-22 (CCITT variant) */
246: #define MAX_MDM 22 /* Number of modem types */
247:
248: #endif /* MINIDIAL */
249:
250: /*
251: * Declare modem "variant" numbers for any of the above for which it is
252: * necessary to note various operational modes, using the second byte
253: * of a modem number.
254: *
255: * It is assumed that such modem modes share the same modem-specific
256: * information (see MDMINF structure) but may differ in some of the actions
257: * that are performed.
258: */
259:
260: /* Warning - this is starting to get kind of hokey... */
261:
262: #define DIAL_NV 256
263: #define n_HAYESNV ( n_HAYES | DIAL_NV )
264:
265: #ifndef MINIDIAL
266: #define DIAL_PEP 512
267: #define DIAL_V32 1024
268: #define DIAL_V42 2048
269: #define DIAL_SLO 4096
270: #define n_TBPEP ( n_TELEBIT | DIAL_PEP )
271: #define n_TB3 ( n_TELEBIT | DIAL_V32 )
272: #define n_TBNV ( n_TELEBIT | DIAL_NV )
273: #define n_TBPNV ( n_TELEBIT | DIAL_NV | DIAL_PEP )
274: #define n_TB3NV ( n_TELEBIT | DIAL_NV | DIAL_V32 )
275: #define n_TB4 ( n_TELEBIT | DIAL_V42 )
276: #define n_TBS ( n_TELEBIT | DIAL_SLO )
277: #define n_TB4NV ( n_TELEBIT | DIAL_NV | DIAL_V42 )
278: #define n_TBSNV ( n_TELEBIT | DIAL_NV | DIAL_SLO )
279: #endif /* MINIDIAL */
280:
281: /*
282: * Declare structures containing modem-specific information.
283: *
284: * REMEMBER that only the first SEVEN characters of these
285: * names are guaranteed to be unique.
286: */
287:
288: #ifndef MINIDIAL
289: static
290: MDMINF ATTISN = /* AT&T ISN Network */
291: {
292: 30, /* Dial time */
293: "", /* Pause characters */
294: 0, /* Pause time */
295: "\015\015\015\015", /* Wake string */
296: 900, /* Wake rate */
297: "DIAL", /* Wake prompt */
298: "", /* dmode_str */
299: "", /* dmode_prompt */
300: "%s\015", /* dial_str */
301: 0, /* dial_rate */
302: 0, /* esc_time */
303: "", /* esc_str */
304: "", /* hup_str */
305: NULL /* ok_fn */
306: };
307:
308: static
309: MDMINF ATTMODEM = /* information for AT&T switched-network modems */
310: /* "Number" following "dial" can include: p's and
311: * t's to indicate pulse or tone (default) dialing,
312: * + for wait for dial tone, , for pause, r for
313: * last number dialed, and, except for 2224B, some
314: * comma-delimited options like o12=y, before number.
315:
316: * "Important" options for the modems:
317: *
318: * All: Except for 2224B, enable option 12 for "transparent
319: * data," o12=y. If a computer port used for both
320: * incoming and outgoing calls is connected to the
321: * modem, disable "enter interactive mode on carriage
322: * return," EICR. The Kermit "dial" command can
323: * function with EIA leads standard, EIAS.
324: *
325: * 2212C: Internal hardware switches at their default
326: * positions (four rockers down away from numbers)
327: * unless EICR is not wanted (rocker down at the 4).
328: * For EIAS, rocker down at the 1.
329: *
330: * 2224B: Front-panel switch position 1 must be up (at the 1,
331: * closed). Disable EICR with position 2 down.
332: * For EIAS, position 4 down.
333: * All switches on the back panel down.
334: *
335: * 2224CEO: All front-panel switches down except either 5 or 6.
336: * Enable interactive flow control with o16=y.
337: * Select normal asynchronous mode with o34=0 (zero).
338: * Disable EICR with position 3 up. For EIAS, 1 up.
339: * Reset the modem after changing switches.
340: *
341: * 2296A: If option 00 (zeros) is present, use o00=0.
342: * Enable interactive flow control with o16=y.
343: * Select normal asynchronous mode with o34=0 (zero).
344: * (available in Microcom Networking version, but
345: * not necessarily other models of the 2296A).
346: * Enable modem-port flow control (if available) with
347: * o42=y. Enable asynchronous operation with o50=y.
348: * Disable EICR with o69=n. For EIAS, o66=n, using
349: * front panel.
350: */
351: {
352: 20, /* dial_time */
353: ",", /* pause_chars */
354: 2, /* pause_time */
355: "+", /* wake_str */
356: 0, /* wake_rate */
357: "", /* wake_prompt */
358: "", /* dmode_str */
359: "", /* dmode_prompt */
360: "at%s\015", /* dial_str */
361: 0, /* dial_rate */
362: 0, /* esc_time */
363: "", /* esc_str */
364: "", /* hup_str */
365: NULL /* ok_fn */
366: };
367:
368: static
369: MDMINF ATTDTDM = /* information for AT&T Digital Terminal Data Module
370: * For dialing: KYBD switch down, others usually up. */
371: {
372: 20, /* dial_time */
373: "", /* pause_chars */
374: 0, /* pause_time */
375: "", /* wake_str */
376: 0, /* wake_rate */
377: "", /* wake_prompt */
378: "", /* dmode_str */
379: "", /* dmode_prompt */
380: "%s\015", /* dial_str */ /* not used */
381: 0, /* dial_rate */
382: 0, /* esc_time */
383: "", /* esc_str */
384: "", /* hup_str */
385: NULL /* ok_fn */
386: };
387: #endif /* MINIDIAL */
388:
389: static
390: MDMINF CCITT = /* CCITT V.25bis autodialer */
391: /*
392: According to V.25bis:
393: . Even parity is required for giving commands to the modem.
394: . Commands might or might not echo.
395: . Responses ("Indications") from the modem are terminated by CR and LF.
396: . Call setup is accomplished by:
397: - DTE raises DTR (V.24 circuit 108) [ttopen() does this]
398: - Modem raises CTS (V.24 circuit 106) [C-Kermit ignores this]
399: - DTE issues a call request command ("CRN")
400: - Modem responds with "VAL" ("command accepted")
401: - If the call is completed:
402: modem responds with "CNX" ("call connected");
403: modem turns CTS (106) OFF;
404: modem turns DSR (107) ON;
405: else:
406: modem responds with "CFI <parameter>" ("call failure indication").
407: . To clear a call, the DTE turns DTR (108) OFF.
408: . There is no mention of the Carrier Detect circuit (109) in the standard.
409: . There is no provision for "escaping back" to the modem's command mode.
410:
411: It is not known whether there exists in real life a pure V.25bis modem.
412: If there is, this code has never been tested on it. See the Digitel entry.
413: */
414: {
415: 40, /* dial_time -- programmable -- */
416: ",:", /* pause_chars -- "," waits for programmable time */
417: /* ":" waits for dial tone */
418: 10, /* pause_time (seconds, just a guess) */
419: "", /* wake_str (none) */
420: 200, /* wake_rate (msec) */
421: "VAL", /* wake_prompt */
422: "", /* dmode_str (none) */
423: "", /* dmode_prompt (none) */
424: "CRN%s\015", /* dial_str */
425: 200, /* dial_rate (msec) */
426: 0, /* No esc_time */
427: "", /* No esc_str */
428: "", /* No hup_str */
429: NULL /* No ok_fn */
430: };
431:
432: #ifndef MINIDIAL /* Don't include the following if -DMINIDIAL ... */
433:
434: static
435: MDMINF CERMETEK = /* Information for "Cermetek Info-Mate 212 A" modem */
436: {
437: 20, /* dial_time */
438: "BbPpTt", /* pause_chars */
439: 0, /* pause_time */ /** unknown -- DS **/
440: " XY\016R\015", /* wake_str */
441: 200, /* wake_rate */
442: "", /* wake_prompt */
443: "", /* dmode_str */
444: NULL, /* dmode_prompt */
445: "\016D '%s'\015", /* dial_str */
446: 200, /* dial_rate */
447: 0, /* esc_time */
448: "", /* esc_str */
449: "", /* hup_str */
450: NULL /* ok_fn */
451: };
452:
453: static
454: MDMINF DF03 = /* information for "DEC DF03-AC" modem */
455: {
456: 27, /* dial_time */
457: "=", /* pause_chars */ /* wait for second dial tone */
458: 15, /* pause_time */
459: "\001\002", /* wake_str */
460: 0, /* wake_rate */
461: "", /* wake_prompt */
462: "", /* dmode_str */
463: NULL, /* dmode_prompt */
464: "%s", /* dial_str */
465: 0, /* dial_rate */
466: 0, /* esc_time */
467: "", /* esc_str */
468: "", /* hup_str */
469: NULL /* ok_fn */
470: };
471:
472: static
473: MDMINF DF100 = /* information for "DEC DF100-series" modem */
474: /*
475: * The telephone "number" can include "P"s and/or "T"s
476: * within it to indicate that subsequent digits are
477: * to be dialed using pulse or tone dialing. The
478: * modem defaults to pulse dialing. You may modify
479: * the dial string below to explicitly default all
480: * dialing to pulse or tone, but doing so prevents
481: * the use of phone numbers that you may have stored
482: * in the modem's memory.
483: */
484: {
485: 30, /* dial_time */
486: "=", /* pause_chars */ /* wait for second dial tone */
487: 15, /* pause_time */
488: "\001", /* wake_str */
489: 0, /* wake_rate */
490: "", /* wake_prompt */
491: "", /* dmode_str */
492: NULL, /* dmode_prompt */
493: "%s#", /* dial_str */
494: 0, /* dial_rate */
495: 0, /* esc_time */
496: "", /* esc_str */
497: "", /* hup_str */
498: NULL /* ok_fn */
499: };
500:
501: static
502: MDMINF DF200 = /* information for "DEC DF200-series" modem */
503: /*
504: * The telephone "number" can include "P"s and/or "T"s
505: * within it to indicate that subsequent digits are
506: * to be dialed using pulse or tone dialing. The
507: * modem defaults to pulse dialing. You may modify
508: * the dial string below to explicitly default all
509: * dialing to pulse or tone, but doing so prevents
510: * the use of phone numbers that you may have stored
511: * in the modem's memory.
512: */
513: {
514: 30, /* dial_time */
515: "=W", /* pause_chars */ /* =: second tone; W: 5 secs */
516: 15, /* pause_time */ /* worst case */
517: "\002", /* wake_str */ /* allow stored number usage */
518: 0, /* wake_rate */
519: "", /* wake_prompt */
520: "", /* dmode_str */
521: NULL, /* dmode_prompt */
522: "%s!", /* dial_str */
523: 0, /* dial_rate */
524: 0, /* esc_time */
525: "", /* esc_str */
526: "", /* hup_str */
527: NULL /* ok_fn */
528: };
529:
530: static
531: MDMINF DIGITEL = /* Digitel DT-22 CCITT variant used in Brazil */
532: /*
533: Attempts to adhere strictly to the V.25bis specification do not produce good
534: results in real life. The modem for which this code was developed: (a)
535: ignores parity; (b) sometimes terminates responses with LF CR instead of CR
536: LF; (c) has a Hayes-like escape sequence; (d) supports a hangup ("HUP")
537: command. Information from Fernando Cabral in Brasilia.
538: */
539: {
540: 40, /* dial_time -- programmable -- */
541: ",:", /* pause_chars -- "," waits for programmable time */
542: /* ":" waits for dial tone */
543: 10, /* pause_time (seconds, just a guess) */
544: "HUP\015", /* wake_str (Not Standard CCITT) */
545: 200, /* wake_rate (msec) */
546: "VAL", /* wake_prompt */
547: "", /* dmode_str (none) */
548: "", /* dmode_prompt (none) */
549: "CRN%s\015", /* dial_str */
550: 200, /* dial_rate (msec) */
551: 1100, /* esc_time (Not Standard CCITT) */
552: "+++", /* esc_str (Not Standard CCITT) */
553: "HUP\015", /* hup_str (Not Standard CCITT) */
554: getok /* ok_fn */
555: };
556:
557: static
558: MDMINF GDC = /* information for "GeneralDataComm 212A/ED" modem */
559: {
560: 32, /* dial_time */
561: "%", /* pause_chars */
562: 3, /* pause_time */
563: "\015\015", /* wake_str */
564: 500, /* wake_rate */
565: "$", /* wake_prompt */
566: "D\015", /* dmode_str */
567: ":", /* dmode_prompt */
568: "T%s\015", /* dial_str */
569: 0, /* dial_rate */
570: 0, /* esc_time */
571: "", /* esc_str */
572: "", /* hup_str */
573: NULL /* ok_fn */
574: };
575: #endif /* MINIDIAL */
576:
577: static
578: MDMINF HAYES = /* Information for Hayes and Hayes-like modems */
579: {
580: 35, /* dial_time */
581: ",", /* pause_chars */
582: 2, /* pause_time */
583: "ATQ0\015", /* wake_str */
584: /*
585: Note: Other wake_str's are possible here. For a Hayes 2400 that is to
586: be used for both in and out calls, AT&F&D3 might be best. For out calls
587: only, maybe AT&F&D2. See Hayes 2400 manual.
588: */
589: 0, /* wake_rate */
590: "", /* wake_prompt */
591: "", /* dmode_str */
592: "", /* dmode_prompt */
593: "ATD%s\015", /* dial_str, note: user can supply D or T */
594: 0, /* dial_rate */
595: 1100, /* esc_time */
596: "+++", /* esc_str */
597: "ATQ0H0\015", /* hup_str */
598: getok /* ok_fn */
599: };
600:
601: #ifndef MINIDIAL
602:
603: static
604: MDMINF PENRIL = /* information for "Penril" modem */
605: {
606: 50, /* dial_time */
607: "", /* pause_chars */ /** unknown -- HF **/
608: 0, /* pause_time */
609: "\015\015", /* wake_str */
610: 300, /* wake_rate */
611: ">", /* wake_prompt */
612: "k\015", /* dmode_str */
613: ":", /* dmode_prompt */
614: "%s\015", /* dial_str */
615: 0, /* dial_rate */
616: 0, /* esc_time */
617: "", /* esc_str */
618: "", /* hup_str */
619: NULL /* ok_fn */
620: };
621:
622: static
623: MDMINF RACAL = /* information for "Racal Vadic" modem, e.g. VA4492E */
624: {
625: 35, /* dial_time (manual says modem is hardwired to 60) */
626: "Kk", /* pause_chars */
627: 5, /* pause_time */
628: "\005\015", /* wake_str, ^E^M */
629: 50, /* wake_rate */
630: "*", /* wake_prompt */
631: "D\015", /* dmode_str */
632: "?", /* dmode_prompt */
633: "%s\015", /* dial_str */
634: 0, /* dial_rate */
635: 1100, /* esc_time */
636: "\003\004", /* esc_str, ^C^D (this actually hangs up) */
637: "\005", /* hup_str, ^E (this goes back to command mode) */
638: NULL /* ok_fn */
639: };
640: #endif /* MINIDIAL */
641:
642: /*
643: The intent of the "unknown" modem is to allow KERMIT to support
644: unknown modems by having the user type the entire autodial sequence
645: (possibly including control characters, etc.) as the "phone number".
646: The protocol and other characteristics of this modem are unknown, with
647: some "reasonable" values being chosen for some of them. The only way to
648: detect if a connection is made is to look for carrier.
649: */
650: static
651: MDMINF UNKNOWN = /* information for "Unknown" modem */
652: {
653: 30, /* dial_time */
654: "", /* pause_chars */
655: 0, /* pause_time */
656: "", /* wake_str */
657: 0, /* wake_rate */
658: "", /* wake_prompt */
659: "", /* dmode_str */
660: NULL, /* dmode_prompt */
661: "%s\015", /* dial_str */
662: 0, /* dial_rate */
663: 0, /* esc_time */
664: "", /* esc_str */
665: "", /* hup_str */
666: NULL /* ok_fn */
667: };
668:
669: #ifndef MINIDIAL
670:
671: static
672: MDMINF USROBOT = /* information for "US Robotics 212A" modem */
673: {
674: 30, /* dial_time */
675: ",", /* pause_chars */
676: 2, /* pause_time */
677: "ATS2=01\015", /* wake_str */
678: 0, /* wake_rate */
679: "OK\015", /* wake_prompt */
680: "", /* dmode_str */
681: NULL, /* dmode_prompt */
682: "ATTD%s\015", /* dial_str */
683: 0, /* dial_rate */
684: 0, /* esc_time */
685: "", /* esc_str */
686: "", /* hup_str */
687: NULL /* ok_fn */
688: };
689:
690: #ifdef COMMENT
691: /* Reportedly this does not work at all. */
692: static
693: MDMINF VENTEL = /* information for "Ventel" modem */
694: {
695: 20, /* dial_time */
696: "%", /* pause_chars */
697: 5, /* pause_time */
698: "\015\015\015", /* wake_str */
699: 300, /* wake_rate */
700: "$", /* wake_prompt */
701: "", /* dmode_str */
702: NULL, /* dmode_prompt */
703: "<K\015%s\015>", /* dial_str (was "<K%s\r>") */
704: 0, /* dial_rate */
705: 0, /* esc_time */
706: "", /* esc_str */
707: "", /* hup_str */
708: NULL /* ok_fn */
709: };
710: #else
711: /* and this does. */
712: static
713: MDMINF VENTEL = /* information for "Ventel" modem */
714: {
715: 20, /* dial_time */
716: "%", /* pause_chars */
717: 5, /* pause_time */
718: "\015\015\015", /* wake_str */
719: 300, /* wake_rate */
720: "$", /* wake_prompt */
721: "K\015", /* dmode_str (was "") */
722: "Number to call: ", /* dmode_prompt (was NULL) */
723: "%s\015", /* dial_str (was "<K%s\r>") */
724: 0, /* dial_rate */
725: 0, /* esc_time */
726: "", /* esc_str */
727: "", /* hup_str */
728: NULL /* ok_fn */
729: };
730: #endif /* COMMENT */
731:
732: static
733: MDMINF CONCORD = /* Info for Condor CDS 220 2400b modem */
734: {
735: 35, /* dial_time */
736: ",", /* pause_chars */
737: 2, /* pause_time */
738: "\015\015", /* wake_str */
739: 20, /* wake_rate */
740: "CDS >", /* wake_prompt */
741: "", /* dmode_str */
742: NULL, /* dmode_prompt */
743: "<D M%s\015>", /* dial_str */
744: 0, /* dial_rate */
745: 0, /* esc_time */
746: "", /* esc_str */
747: "", /* hup_str */
748: NULL /* ok_fn */
749: };
750:
751: static
752: MDMINF ATTUPC = /* dummy information for "ATT7300/Unix PC" internal modem */
753: {
754: 30, /* dial_time */
755: "", /* pause_chars */
756: 0, /* pause_time */
757: "", /* wake_str */
758: 0, /* wake_rate */
759: "", /* wake_prompt */
760: "", /* dmode_str */
761: NULL, /* dmode_prompt */
762: "%s\015", /* dial_str */
763: 0, /* dial_rate */
764: 0, /* esc_time */
765: "", /* esc_str */
766: "", /* hup_str */
767: NULL /* ok_fn */
768: };
769:
770: static
771: MDMINF ROLM = /* IBM / Siemens / Rolm 8000, 9000, 9751 CBX */
772: {
773: 60, /* dial_time */
774: "", /* pause_chars */
775: 0, /* pause_time */
776: "\015\015", /* wake_str */
777: 5, /* wake_rate */
778: "MODIFY?", /* wake_prompt */
779: "", /* dmode_str */
780: "", /* dmode_prompt */
781: "CALL %s\015", /* dial_str */
782: 0, /* dial_rate */
783: 0, /* esc_time */
784: "", /* esc_str */
785: "", /* hup_str */
786: NULL /* ok_fn */
787: };
788:
789: static
790: MDMINF MICROCOM = /* information for "Microcom" modems in native mode */
791: /* (long answer only) */
792: {
793: 35, /* dial_time */
794: ",!@", /* pause_chars (! and @ aren't pure pauses) */
795: 3, /* pause_time */
796: "\015", /* wake_str */
797: 100, /* wake_rate */
798: "!", /* wake_prompt */
799: "", /* dmode_str */
800: NULL, /* dmode_prompt */
801: "d%s\015", /* dial_str */
802: 0, /* dial_rate */
803: 0, /* esc_time */
804: "", /* esc_str */
805: "", /* hup_str */
806: NULL /* ok_fn */
807: };
808:
809: static
810: MDMINF HST = /* information for Courier HST modem */
811: {
812: 35, /* dial_time */
813: ",", /* pause_chars */
814: 2, /* pause_time */
815: "ATQ0S2=43X7&B1&M4\015", /* wake_str */
816: 0, /* wake_rate */
817: "OK\015", /* wake_prompt */
818: "", /* dmode_str */
819: "", /* dmode_prompt */
820: "ATD%s\015", /* dial_str */
821: 0, /* dial_rate */
822: 1100, /* esc_time */
823: "+++", /* esc_str */
824: "ATQ0H0\015", /* hup_str */
825: getok /* ok_fn */
826: };
827:
828: static
829: MDMINF TELEBIT = /* information for Telebits */
830: {
831: 60, /* dial_time */
832: ",", /* pause_chars */
833: 2, /* pause_time */
834: /*
835: NOTE: The wake_string MUST contain the I command (model query), and otherwise
836: must contain commands that work on ALL Telebit models. Here we ensure that
837: result codes are returned (Q0), and ask for extended result codes (X1), and
838: ensure that the escape sequence is +++ and it is enabled. And also, make
839: sure the final character is not a digit (whose echo might be mistaken for a
840: result code). The Ctrl-Q and multiple A's are recommended by Telebit.
841: */
842: "\021AAAATQ0X1S12=50 S2=43 I\015", /* wake_str. */
843: 100, /* wake_rate = 100 msec */
844: "OK\015", /* wake_prompt */
845: "", /* dmode_str */
846: "", /* dmode_prompt */
847: "ATD%s\015", /* dial_str, Note: no T or P */
848: 80, /* dial_rate */
849: 1100, /* esc_time (guard time) */
850: "+++", /* esc_str */
851: "ATQ0H0\015", /* hup_str */
852: getok /* ok_fn */
853: };
854: #endif /* MINIDIAL */
855:
856: /*
857: * Declare table for converting modem numbers to information pointers.
858: *
859: * The entries MUST be in ascending order by modem number, without any
860: * "gaps" in the numbers, and starting from one (1).
861: *
862: * This table should NOT include entries for the "variant" modem numbers,
863: * since they share the same information as the normal value.
864: */
865: static
866: MDMINF *ptrtab[] = {
867: #ifdef MINIDIAL
868: &CCITT,
869: &HAYES,
870: &UNKNOWN
871: #else
872: &ATTDTDM,
873: &ATTISN,
874: &ATTMODEM,
875: &CCITT,
876: &CERMETEK,
877: &DF03,
878: &DF100,
879: &DF200,
880: &GDC,
881: &HAYES,
882: &PENRIL,
883: &RACAL,
884: &UNKNOWN,
885: &USROBOT,
886: &VENTEL,
887: &CONCORD,
888: &ATTUPC,
889: &ROLM,
890: &MICROCOM,
891: &HST,
892: &TELEBIT,
893: &DIGITEL
894: #endif /* MINIDIAL */
895: };
896: /*
897: * Declare modem names and associated numbers for command parsing,
898: * and also for doing number-to-name translation.
899: *
900: * The entries must be in alphabetical order by modem name.
901: */
902: struct keytab mdmtab[] = {
903: #ifndef MINIDIAL
904: "attdtdm", n_ATTDTDM, 0,
905: "attisn", n_ATTISN, 0,
906: "attmodem", n_ATTMODEM, 0,
907: "att7300", n_ATTUPC, 0,
908: #endif /* MINIDIAL */
909: "ccitt-v25bis", n_CCITT, 0,
910: #ifndef MINIDIAL
911: "cermetek", n_CERMETEK, 0,
912: "concord", n_CONCORD, 0,
913: "df03-ac", n_DF03, 0,
914: "df100-series", n_DF100, 0,
915: "df200-series", n_DF200, 0,
916: "digitel-dt22", n_DIGITEL, 0,
917: #endif /* MINIDIAL */
918: "direct", 0, CM_INV, /* Synonym for NONE */
919: #ifndef MINIDIAL
920: "gdc-212a/ed", n_GDC, 0,
921: "gendatacomm", n_GDC, CM_INV, /* Synonym for GDC */
922: #endif /* MINIDIAL */
923: "hayes", n_HAYES, 0,
924: #ifndef MINIDIAL
925: "hst-courier", n_HST, 0,
926: "microcom", n_MICROCOM, 0,
927: #endif /* MINIDIAL */
928: "none", 0, 0,
929: #ifndef MINIDIAL
930: "penril", n_PENRIL, 0,
931: "pep-telebit", n_TBPEP, 0,
932: "racalvadic", n_RACAL, 0,
933: "rolm", n_ROLM, 0,
934: "slow-telebit", n_TBS, 0,
935: "telebit", n_TELEBIT, 0,
936: #endif /* MINIDIAL */
937: "unknown", n_UNKNOWN, 0,
938: #ifndef MINIDIAL
939: "usrobotics-212a", n_USROBOT, 0,
940: "v32-telebit", n_TB3, 0,
941: "v42-telebit", n_TB4, 0,
942: "ventel", n_VENTEL, 0
943: #endif /* MINIDIAL */
944: };
945: int nmdm = (sizeof(mdmtab) / sizeof(struct keytab)); /* Number of modems */
946:
947: #define CONNECTED 1 /* For completion status */
948: #define FAILED 2
949:
950: static
951: char *F_reason[5] = { /* Failure reasons for message */
952: "Unknown", "Timeout", "Interrupt", "Modem", "Initialize" };
953:
954: static int tries = 0;
955: static int mdmecho = 0; /* assume modem does not echo */
956: static int augmdmtyp; /* "augmented" modem type, to handle modem modes */
957:
958: static char *p; /* For command strings & messages */
959:
960: #define LBUFL 100
961: #ifdef DYNAMIC
962: static char *lbuf = NULL;
963: #else
964: static char lbuf[LBUFL];
965: #endif /* DYNAMIC */
966:
967: #define RBUFL 63
968: static char rbuf[RBUFL+1]; /* Modem response buffer */
969:
970: static jmp_buf sjbuf;
971:
972: static SIGTYP (*savalrm)(); /* For saving alarm handler */
973: static SIGTYP (*savint)(); /* For saving interrupt handler */
974:
975: #ifndef MINIDIAL
976: int tbmodel = 0; /* Telebit modem model */
977:
978: char *
979: gtbmodel() { /* Function to return name of Telebit model */
980: if (tbmodel < 0 || tbmodel > TB__MAX) tbmodel = TB_UNK;
981: return(tb_name[tbmodel]);
982: }
983:
984: VOID
985: xcpy(to,from,len) /* Copy the given number of bytes */
986: register char *to, *from;
987: register unsigned len; {
988: while (len--) *to++ = *from++;
989: }
990: #endif /* MINIDIAL */
991:
992: SIGTYP
993: dialtime(foo) int foo; { /* Timer interrupt handler */
994: n1 = F_time; /* Failure reason = timeout */
995:
996: #ifdef __EMX__
997: signal(SIGALRM, SIG_ACK); /* Needed for OS/2 */
998: #endif /* __EMX__ */
999:
1000: #ifdef OSK /* OS-9 */
1001: /*
1002: We are in an intercept routine but do not perform a F$RTE (done implicitly
1003: by RTS), so we have to decrement the sigmask as F$RTE does. Warning:
1004: longjump only restores the CPU registers, NOT the FPU registers. So, don't
1005: use FPU at all or at least don't use common FPU (double or float) register
1006: variables.
1007: */
1008: sigmask(-1);
1009: #endif /* OSK */
1010:
1011: longjmp( sjbuf, F_time );
1012: }
1013:
1014: SIGTYP
1015: dialint(foo) int foo; { /* Keyboard interrupt handler */
1016: n1 = F_int;
1017: #ifdef __EMX__
1018: signal(SIGINT, SIG_ACK); /* Needed for OS/2 */
1019: #endif /* __EMX__ */
1020: #ifdef OSK /* OS-9, see comment in dialtime() */
1021: sigmask(-1);
1022: #endif /* OSK */
1023: longjmp( sjbuf, F_int );
1024: }
1025:
1026: /*
1027: Routine to read a character from communication device, handling TELNET
1028: protocol negotiations in case we're connected to the modem through a
1029: TCP/IP TELNET modem server.
1030: */
1031: static int
1032: ddinc(n) int n; {
1033: int c;
1034:
1035: #ifdef TNCODE
1036: int done = 0;
1037: while (!done) {
1038: c = ttinc(n);
1039: debug(F000,"ddinc","",c);
1040: if (c < 0) return(c);
1041: if (c == IAC && network && ttnproto == NP_TELNET) {
1042: switch (tn_doop((CHAR)(c & 0xff),duplex,ttinc)) {
1043: case 2: duplex = 0; continue;
1044: case 1: duplex = 1;
1045: default: continue;
1046: }
1047: } else done = 1;
1048: }
1049: return(c & 0xff);
1050: #else
1051: return(ttinc(n));
1052: #endif /* TNCODE */
1053: }
1054:
1055: static VOID
1056: ttslow(s,millisec) char *s; int millisec; { /* Output s-l-o-w-l-y */
1057: for (; *s; s++) {
1058: ttoc(*s);
1059: msleep(millisec);
1060: }
1061: }
1062:
1063: /*
1064: * Wait for a string of characters.
1065: *
1066: * The characters are waited for individually, and other characters may
1067: * be received "in between". This merely guarantees that the characters
1068: * ARE received, and in the order specified.
1069: */
1070: static VOID
1071: waitfor(s) char *s; {
1072: CHAR c, x;
1073: while ( c = *s++ ) { /* while more characters remain... */
1074: do { /* wait for the character */
1075: x = ddinc(0) & 0177;
1076: debug(F000,"dial waitfor got","",x);
1077: if (dialdpy) {
1078: if (x != LF) conoc(x);
1079: if (x == CR) conoc(LF);
1080: }
1081: } while ( x != c);
1082: }
1083: }
1084:
1085: static int
1086: didweget(s,r) char *s, *r; { /* Looks in string s for response r */
1087: int lr = (int)strlen(r); /* 0 means not found, 1 means found it */
1088: int i;
1089: debug(F110,"didweget",r,0);
1090: debug(F110," in",s,0);
1091: for (i = (int)strlen(s)-lr; i >= 0; i--)
1092: if ( s[i] == r[0] ) if ( !strncmp(s+i,r,lr) ) return( 1 );
1093: return( 0 );
1094: }
1095:
1096:
1097: /* R E S E T -- Reset alarms, etc. on exit. */
1098:
1099: static VOID
1100: dreset() {
1101: alarm(0);
1102: signal(SIGALRM,savalrm); /* restore alarm handler */
1103: signal(SIGINT,savint); /* restore interrupt handler */
1104: }
1105:
1106: /*
1107: Call this routine when the modem reports that it has connected at a certain
1108: speed, giving that speed as the argument. If the connection speed is not
1109: the same as Kermit's current communication speed, AND the modem interface
1110: speed is not locked (i.e. DIAL SPEED-MATCHING is not ON), then change the
1111: device speed to the one given.
1112: */
1113: static VOID
1114: #ifdef CK_ANSIC
1115: spdchg(long s)
1116: #else
1117: spdchg(s) long s;
1118: #endif /* CK_ANSIC */
1119: /* spdchg */ {
1120: int s2;
1121: if (!mdmspd) /* If modem interface speed locked, */
1122: return; /* don't do this. */
1123: if (speed != s) { /* Speeds differ? */
1124: s2 = s / 10L; /* Convert to cps expressed as int */
1125: if (ttsspd(s2) < 0) { /* Change speed. */
1126: printf(" Warning: speed change to %ld failed.\r\n",s);
1127: } else {
1128: printf(" Speed changed to %ld.\r\n",s);
1129: speed = s; /* Update global speed variable */
1130: }
1131: }
1132: }
1133:
1134: /*
1135: Display all characters received from modem dialer through this routine,
1136: for consistent handling of carriage returns and linefeeds.
1137: */
1138: static VOID
1139: #ifdef CK_ANSIC
1140: dialoc(char c)
1141: #else
1142: dialoc(c) char c;
1143: #endif /* CK_ANSIC */
1144: { /* dialoc */ /* Dial Output Character */
1145: if (dialdpy) {
1146: if (c != LF) conoc(c); /* Don't echo LF */
1147: if (c == CR) conoc(LF); /* Echo CR as CRLF */
1148: }
1149: }
1150:
1151: #ifndef MINIDIAL
1152: /*
1153: tbati3() -- Routine to find out Telebit model when ATI reports "965"
1154: or "971". This routine sends another query, ATI3, to get further info
1155: to narrow down the model number. Argument is ATI response as integer.
1156: Result: sets tbmodel variable to Telebit model.
1157: */
1158: static VOID
1159: tbati3(n) int n; {
1160: int status;
1161: ttflui(); /* Flush input buffer */
1162: ttslow("ATI3\015",100); /* Send ATI3<CR> */
1163: status = getok(5,0); /* Get OK response, nonstrict */
1164: if (status < 1) { /* ERROR or timeout */
1165: tbmodel = TB_UNK;
1166: debug(F111,"tbati3 fails",rbuf,status);
1167: return;
1168: }
1169: debug(F110,"tbati3 rbuf",rbuf,0);
1170:
1171: /* Got a good response, check the model info */
1172:
1173: if (n == 965) { /* "965" - various models. */
1174: if (didweget(rbuf,"T1600")) {
1175: tbmodel = TB_1600; /* T1600 */
1176: } else if (didweget(rbuf,"T3000")) {
1177: tbmodel = TB_3000; /* T3000 */
1178: } else if (didweget(rbuf,"World")) {
1179: tbmodel = TB_WBLA; /* WorldBlazer */
1180: } else if (didweget(rbuf,"Version B") || /* TrailBlazer-Plus models */
1181: didweget(rbuf,"TBSA") ||
1182: didweget(rbuf,"TBRM") ||
1183: didweget(rbuf,"DC")) { /* Ven-Tel EC18K */
1184: tbmodel = TB_PLUS;
1185: } else tbmodel = TB_UNK; /* Others: Unknown */
1186:
1187: } else if (n == 971) { /* "971" could be T1500 or T1600. */
1188: if (didweget(rbuf,"T1500"))
1189: tbmodel = TB_1500;
1190: else tbmodel = TB_2500;
1191: } /* Other, don't change tbmodel. */
1192: }
1193: #endif /* MINIDIAL */
1194:
1195:
1196: /* C K D I A L -- Dial up the remote system */
1197:
1198: /* Returns 1 if call completed, 0 otherwise */
1199:
1200: static int waitct, mdmwait, mdmstat = 0;
1201:
1202: int
1203: ckdial(telnbr) char *telnbr; {
1204:
1205: char c, c2;
1206: char errmsg[50], *erp; /* for error messages */
1207: char fullnum[100]; /* for full (prefixed) phone number */
1208: MDMINF *pmdminf; /* pointer to modem-specific info */
1209: int x, m, n = F_time;
1210: char *s, *pc, *ws;
1211:
1212: long conspd;
1213: char *cptr;
1214:
1215: mymdmtyp = mdmtyp; /* Make local copy of modem type */
1216:
1217: #ifndef MINIDIAL
1218: tbmodel = TB_UNK; /* Initialize Telebit model */
1219: #endif /* MINIDIAL */
1220:
1221: if (mymdmtyp < 1) {
1222: if (network)
1223: printf("Please SET HOST first, and then SET MODEM\n");
1224: else
1225: printf("Sorry, you must SET MODEM first\n");
1226: return(0);
1227: }
1228: if (!local) {
1229: printf("Sorry, you must SET LINE or SET HOST first\n");
1230: return(0);
1231: }
1232: if (!network && speed < 0L) {
1233: printf("Sorry, you must SET SPEED first\n");
1234: return(0);
1235: }
1236: debug(F110,"dial number",telnbr,0);
1237: debug(F110,"dial prefix",(dialnpr ? dialnpr : ""), 0);
1238:
1239: /* Add prefix to phone number */
1240:
1241: if (dialnpr && *dialnpr) {
1242: sprintf(fullnum,"%s%s",(dialnpr ? dialnpr : ""),telnbr);
1243: telnbr = fullnum;
1244: }
1245: debug(F110,"prefixed number", telnbr, 0);
1246:
1247: #ifdef DYNAMIC
1248: if (!(lbuf = malloc(LBUFL+1))) { /* Allocate input line buffer */
1249: printf("Sorry, DIAL memory buffer can't be allocated\n");
1250: return(0);
1251: }
1252: #endif /* DYNAMIC */
1253:
1254: if (ttopen(ttname,&local,mymdmtyp,0) < 0) { /* Open, no carrier wait */
1255: erp = errmsg;
1256: sprintf(erp,"Sorry, can't open %s",ttname);
1257: perror(errmsg);
1258: return(0);
1259: }
1260:
1261: /* Condition console terminal and communication line */
1262:
1263: /* Place line into "clocal" dialing state, */
1264: /* important mainly for System V UNIX. */
1265:
1266: if (ttpkt(speed,FLO_DIAL,parity) < 0) {
1267: ttclos(0); /* If ttpkt fails do all this... */
1268: if (ttopen(ttname,&local,mymdmtyp,0) < 0) {
1269: erp = errmsg;
1270: sprintf(erp,"Sorry, can't reopen %s",ttname);
1271: perror(errmsg);
1272: return(0);
1273: } /* And try again. */
1274: if (ttpkt(speed,FLO_DIAL,parity) < 0) {
1275: printf("Sorry, Can't condition communication line\n");
1276: printf("Try 'set line %s' again\n",ttname);
1277: return(0);
1278: }
1279: }
1280: msleep(500);
1281:
1282: pmdminf = ptrtab[ (mymdmtyp & 0xff) -1 ]; /* set pointer to modem info */
1283: augmdmtyp = mymdmtyp; /* initialize "augmented" modem type */
1284: mymdmtyp &= 0xff; /* major modem type */
1285:
1286: /* Interdigit waits for tone dial */
1287:
1288: if (dialtmo < 1) { /* Automatic computation. */
1289: waitct = 1 * (int)strlen(telnbr) ; /* Compute worst case dial time */
1290: waitct += pmdminf->dial_time; /* dialtone + completion wait times */
1291: for (s = telnbr; *s; s++) { /* add in pause characters time */
1292: for (p=pmdminf->pause_chars; *p; p++)
1293: if (*s == *p) {
1294: waitct += pmdminf->pause_time;
1295: break;
1296: }
1297: }
1298: #ifndef MINIDIAL
1299: if (augmdmtyp == n_TBPEP || augmdmtyp == n_TBPNV) {
1300: waitct += 30; /* Longer connect wait for PEP call */
1301: }
1302: #endif /* MINIDIAL */
1303: } else { /* User-specified timeout */
1304: waitct = dialtmo;
1305: }
1306: /*
1307: waitct is our alarm() timer.
1308: mdmwait is how long we tell the modem to wait for carrier.
1309: We set mdmwait to be 1 second less than waitct, to increase the
1310: chance that we get a response from the modem before timing out.
1311: */
1312: if (waitct < 0) waitct = 0;
1313: mdmwait = (waitct > 5) ? waitct - 5 : waitct;
1314:
1315: for (m = 0; m < nmdm; m++) { /* Look up modem type. */
1316: if (mdmtab[m].kwval == mymdmtyp) {
1317: break;
1318: }
1319: }
1320: if (!quiet && !backgrd) { /* Print information messages. */
1321: printf(" Dialing: %s\n", telnbr);
1322: if (network) {
1323: printf(" Via modem server: %s, modem-dialer: %s\n",
1324: ttname, (m >= nmdm ? "(unknown)" : mdmtab[m].kwd) );
1325: } else {
1326: printf(" Device: %s, modem-dialer: %s",
1327: ttname, (m >= nmdm ? "(unknown)" : mdmtab[m].kwd) );
1328: if (speed > -1L)
1329: printf(", speed: %ld\n", speed);
1330: else
1331: printf(", speed: (unknown)\n", speed);
1332: }
1333: printf(" Dial timeout: %d seconds\n",waitct);
1334: printf(
1335: #ifdef MAC
1336: " Type Command-. to cancel dialing\n"
1337: #else
1338: #ifdef UNIX
1339: " To cancel: type your interrupt character (normally Ctrl-C)\n"
1340: #else
1341: " To cancel: type Ctrl-C\n"
1342: #endif /* UNIX */
1343: #endif /* MAC */
1344: );
1345: }
1346: debug(F111,"ckdial",ttname,(int) (speed / 10L));
1347: debug(F101,"ckdial timeout","",waitct);
1348:
1349: /* Hang up the modem (in case it wasn't "on hook") */
1350: /* But only if SET DIAL HANGUP ON... */
1351:
1352: if (dialhup() < 0) {
1353: debug(F100,"ckdial dialhup failed","",0);
1354: #ifndef MINIDIAL
1355: if (mymdmtyp == n_TELEBIT) /* Telebit might need a BREAK */
1356: ttsndb(); /* first. */
1357: #endif /* MINIDIAL */
1358: if (dialhng) { /* If it failed, */
1359: ttclos(0); /* close and reopen the device. */
1360: if (ttopen(ttname,&local,mymdmtyp,0) < 0) {
1361: printf("Sorry, Can't hang up communication device\n");
1362: printf("Try 'set line %s' again\n",ttname);
1363: return(0);
1364: }
1365: }
1366: }
1367: #ifndef MINIDIAL
1368: if (augmdmtyp == n_ROLM) /* Don't start talking to Rolm */
1369: msleep(500); /* too soon... */
1370: #endif /* MINIDIAL */
1371:
1372: /*
1373: Establish jump vector, or handle "failure" jumps.
1374: longjmp() sets global failure reason, n1.
1375: */
1376: if (setjmp(sjbuf)) { /* if a "failure jump" was taken... */
1377: n = n1;
1378: alarm(0); /* disable timeouts */
1379: if (setjmp(sjbuf)) { /* failure while handling failure */
1380: printf ("%s failure while handling failure.\n", F_reason[n1]);
1381: } else { /* first (i.e., non-nested) failure */
1382: signal(SIGALRM, dialtime); /* be sure to catch signals */
1383: #ifdef MAC
1384: signal(SIGINT, dialint);
1385: #else /* MAC */
1386: #ifdef OSK
1387: if (signal(SIGINT, SIG_IGN) != (SIGTYP (*)()) SIG_IGN)
1388: signal(SIGINT, dialint);
1389: #else
1390: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1391: signal(SIGINT, dialint);
1392: #endif /* OS9 */
1393: #endif /* MAC */
1394: alarm(10); /* Be sure to exit this section */
1395: }
1396: switch (n) { /* Type of failure */
1397: case F_time: { /* Timed out */
1398: printf ("DIAL TIMEOUT interval expired.\n");
1399: if (mymdmtyp == n_HAYES
1400: #ifndef MINIDIAL
1401: || mymdmtyp == n_TELEBIT || mymdmtyp == n_HST
1402: #endif /* MINIDIAL */
1403: )
1404: ttoc('\015'); /* Send CR to interrupt dialing */
1405: /* some hayes modems don't fail with BUSY on busy lines */
1406: debug(F110,"dial","timeout",0);
1407: break;
1408: }
1409: case F_int: { /* Dialing interrupted */
1410: printf ("Dialing interrupted.\n");
1411: debug(F110,"dial","interrupted",0);
1412: if (mymdmtyp == n_HAYES
1413: #ifndef MINIDIAL
1414: || mymdmtyp == n_TELEBIT || mymdmtyp == n_HST
1415: #endif /* MINIDIAL */
1416: )
1417: ttoc('\015'); /* Send CR to interrupt dialing */
1418: break;
1419: }
1420: case F_modem: { /* Modem detected a failure */
1421: printf ("Call failed (\"");
1422: for (pc = lbuf; *pc; pc++)
1423: if (isprint(*pc))
1424: putchar(*pc); /* Display printable reason */
1425: printf ("\").\n");
1426: debug(F110,"dial",lbuf,0);
1427: break;
1428: }
1429: case F_minit: { /* Cannot initialize modem */
1430: printf ("Can't initialize modem.\n");
1431: debug(F110,"dial","modem init",0);
1432: break;
1433: }
1434: }
1435: dreset(); /* reset alarms, etc. */
1436: #ifdef DYNAMIC
1437: if (lbuf) free(lbuf);
1438: #endif /* DYNAMIC */
1439: return(0); /* exit with failure code */
1440: }
1441:
1442: /* Set timer and interrupt handlers. */
1443:
1444: alarm(0); /* No alarms yet. */
1445: #ifdef MAC
1446: savint = signal(SIGINT, dialint); /* And terminal interrupt handler. */
1447: #else /* MAC */
1448: #ifdef OSK
1449: if ((savint = signal(SIGINT,SIG_IGN)) != (SIGTYP (*)()) SIG_IGN)
1450: signal(SIGINT,dialint);
1451: #else
1452: if ((savint = signal(SIGINT,SIG_IGN)) != SIG_IGN )
1453: signal(SIGINT,dialint);
1454: #endif /* OS-9 */
1455: #endif /* MAC */
1456:
1457: /* Put modem in command mode. */
1458:
1459: switch (augmdmtyp) { /* Send the wakeup string */
1460:
1461: #ifdef ATT7300
1462: case n_ATTUPC: {
1463: /*
1464: For ATT7300/Unix PC's with their special internal modem. Timeout
1465: and user interrupts are enabled during dialing. attdial() is in
1466: file ckutio.c. - jrd
1467: */
1468: _PROTOTYP( int attdial, (char *, long, char *) );
1469: savalrm = signal(SIGALRM,dialtime); /* Set alarm handler. */
1470: alarm(waitct); /* do alarm properly */
1471: if (attdial(ttname,speed,telnbr)) { /* dial internal modem */
1472: dreset(); /* reset alarms, etc. */
1473: printf(" Call failed.\r\n");
1474: dialhup(); /* Hangup the call */
1475: #ifdef DYNAMIC
1476: if (lbuf) free(lbuf);
1477: #endif /* DYNAMIC */
1478: return(0); /* return failure */
1479: }
1480: dreset(); /* reset alarms, etc. */
1481: ttpkt(speed,FLO_DIAX,parity); /* cancel dialing ioctl */
1482: if (!quiet && !backgrd) {
1483: if (dialdpy) printf("\n");
1484: printf(" Call complete.\07\r\n");
1485: }
1486: #ifdef DYNAMIC
1487: if (lbuf) free(lbuf);
1488: #endif /* DYNAMIC */
1489: return(1); /* no conversation with modem to complete dialing */
1490: }
1491: #endif /* ATT7300 */
1492:
1493: /*
1494: For Hayes modem command language, figure out if modem is giving verbose
1495: or digit result codes.
1496: */
1497: case n_HAYES:
1498: case n_HAYESNV:
1499: #ifndef MINIDIAL
1500: case n_HST:
1501: if (augmdmtyp == n_HST)
1502: m = 255;
1503: else
1504: #endif /* MINIDIAL */
1505: m = 60; /* Maximum value for S7 */
1506: ws = dialini ? dialini : HAYES.wake_str;
1507: for (tries = 4; tries > 0; tries--) {
1508: ttslow(ws,pmdminf->wake_rate);
1509: mdmstat = getok(4,1);
1510: if (mdmstat > 0) break;
1511: sleep(1); /* Wait before retrying */
1512: }
1513: if (mdmstat > 0) { /* Initialized OK. */
1514: char hbuf[10];
1515: /*
1516: Now tell the modem about our dial timeout. For Hayes 1200, the maximum
1517: is 60 seconds. For Hayes 2400 (the manual says) it is 30 seconds, but I'm
1518: not sure I believe this (I don't have one handy to see for myself).
1519: If you give the modem a value larger than its maximum, it sets the timeout
1520: to its maximum. The manual does not say what happens when the value is 0,
1521: but experimentation shows that it allows the modem to wait forever, in
1522: which case Kermit will time out at the desired time.
1523: */
1524: /*
1525: Note by Kai Uwe Rommel:
1526: This is not acceptable for general use of the hayes modem type with other
1527: compatible modems. Most other modems allow a range of 1..255 while 0 is
1528: invalid on several modems. Let it be the user's responsibility to make
1529: sure a valid value is used. Higher values are desirable for users with
1530: rotary dialing and with high speed modems, where protocol negotiation takes
1531: quite a long time.
1532: */
1533: #ifdef COMMENT
1534: if (mdmwait > m) /* If larger than maximum, */
1535: mdmwait = 0; /* make it infinite. */
1536: #else
1537: if (mdmwait > 255) /* If larger than maximum, */
1538: mdmwait = 255; /* make it maximum. */
1539: #endif /* COMMENT */
1540:
1541: sprintf(hbuf,"ATS7=%d%c",mdmwait,13); /* S7 = Carrier wait time */
1542: ttslow(hbuf,pmdminf->wake_rate); /* Set it. */
1543: mdmstat = getok(4,1); /* Get response from modem */
1544: debug(F101,"S7 mdmstat","",mdmstat);
1545: break; /* Errors here are not fatal */
1546: }
1547: /* modem-initialization failure */
1548: n1 = (mdmstat == 0) ? F_minit : F_modem;
1549: longjmp( sjbuf, n1 );
1550:
1551: #ifndef MINIDIAL
1552:
1553: /*
1554: Telebit modems fall into two basic groups: old and new. The functions and
1555: command sets are different between the two groups, and also vary by specific
1556: models within each group, and even by firmware ROM revision number. Read
1557: ckcker.bwr for details.
1558:
1559: Commands used by C-Kermit include:
1560:
1561: Old New Meaning
1562: ------- -------- ----------------------------------------
1563: Q0 Q0 Enable result codes.
1564: X1 X1 Extended result codes.
1565: X1 X1 Extended result codes + BUSY, NO DIALTONE, etc.
1566: I I Model number inquiry.
1567: I3 I3 Additional model information inquiry.
1568: S12=50 S12=50 Escape sequence guard time (1 sec).
1569: S2=43 S2=43 Escape character is '+'.
1570: S7=xx S7=xx DIAL TIMEOUT, calculated or SET by user.
1571: S48=0 S48=0 7-bit data (Kermit's PARITY is not NONE).
1572: S48=1 S48=1 8-bit data (Kermit's PARITY is NONE).
1573: S50=0 S50=0 Automatic speed & protocol determination.
1574: S50=3 S50=3 2400/1200/300 bps.
1575: S50=6 S50=6 V.32 (9600 bps).
1576: S50=255 S50=255 PEP mode.
1577: S110=1 S190=1 S191=7 Allow compression in PEP mode.
1578: S51=? S51=? DTE interface speed (left alone by Kermit).
1579: S54=3 S61=0 S63=0 Pass BREAK signal (always).
1580: S58=2 S58=2 RTS/CTS flow control if Kermit's FLOW is RTS/CTS.
1581: S58=? S58=? S58 unchanged if Kermit's FLOW is not RTS/CTS.
1582: S68=255 S68=255 Use flow control specified by S58 (always).
1583: S95=0 S180=0 MNP disabled (SET DIAL MNP-ENABLE OFF)
1584: S95=2 S180=3 MNP, fallback to direct (also as V.42 fallback)
1585: S97=1 S180=2 Enable V.42 (LAPM) error correction
1586: S98=3 Enable compression in both directions
1587: S106=1 V.42bis compression enable
1588:
1589: For Kermit Spoof (same commands for all models that support it):
1590:
1591: S111=0 No Kermit spoofing
1592: S111=10 Kermit with no parity
1593: S111=11 Kermit with odd parity
1594: S111=12 Kermit with even parity
1595: S111=13 Kermit with mark parity
1596: S111=14 Kermit with space parity
1597: S112=?? Kermit's start-of-packet character (stchr).
1598: */
1599: case n_TELEBIT: /* Telebits... */
1600: case n_TBPEP:
1601: case n_TB3:
1602: case n_TB4:
1603: case n_TBS:
1604: case n_TBNV:
1605: case n_TBPNV:
1606: case n_TB3NV:
1607: case n_TB4NV:
1608: case n_TBSNV: {
1609: int S111; /* Telebit Kermit spoof register */
1610: char tbcmdbuf[64]; /* Telebit modem command buffer */
1611: char *mnpstr = ""; /* Pointer to MNP-enable string */
1612: char *dprstr = ""; /* Pointer to dial protocol string */
1613: /*
1614: If user defined a DIAL INIT-STRING, send that now, otherwise send built-in
1615: Telebit string. Try up to 4 times to get OK or 0 response from modem.
1616: NOTE: The default init string *must* be independent of Telebit model.
1617: */
1618: ws = dialini ? dialini : TELEBIT.wake_str;
1619: debug(F110,"ckdial telebit init string",ws,0);
1620: for (tries = 4; tries > 0; tries--) {
1621: ttsndb(); /* Begin by sending BREAK */
1622: ttslow(ws,pmdminf->wake_rate); /* Send wakeup string */
1623: mdmstat = getok(5,0); /* Get modem's response */
1624: if (mdmstat) break; /* If response OK, done */
1625: msleep(300); /* Otherwise, sleep 1/3 second */
1626: dialhup(); /* Hang up */
1627: ttflui(); /* Flush input buffer and try again */
1628: }
1629: if (mdmstat < 1) { /* If we didn't get a response */
1630: n1 = F_minit; /* fail, reason = can't initialize */
1631: longjmp( sjbuf, F_minit );
1632: }
1633: if (!dialini) { /* If using built-in init strings... */
1634: /*
1635: Try to get the model number. It should be in the getok() response buffer,
1636: rbuf[], because the Telebit init string asks for it with the "I" command.
1637: If the model number is 965, we have to make another query to narrow it down.
1638: */
1639: if (didweget(rbuf,"962") || /* Check model number */
1640: didweget(rbuf,"961") ||
1641: didweget(rbuf,"963")) {
1642: tbmodel = TB_BLAZ; /* Trailblazer */
1643: } else if (didweget(rbuf,"972")) {
1644: tbmodel = TB_2500; /* T2500 */
1645: } else if (didweget(rbuf,"968")) {
1646: tbmodel = TB_1000; /* T1000 */
1647: } else if (didweget(rbuf,"966") ||
1648: didweget(rbuf,"967") ||
1649: didweget(rbuf,"964")) {
1650: tbmodel = TB_PLUS; /* Trailblazer-Plus */
1651: } else if (didweget(rbuf,"969")) {
1652: tbmodel = TB_QBLA; /* Qblazer */
1653: } else if (didweget(rbuf,"965")) { /* Most new models */
1654: tbati3(965); /* Go find out */
1655: } else if (didweget(rbuf,"971")) { /* T1500 or T2500 */
1656: tbati3(971); /* Go find out */
1657: } else if (didweget(rbuf,"123") || didweget(rbuf,"960")) {
1658: tbmodel = TB_UNK; /* Telebit in Hayes mode */
1659: }
1660: debug(F111,"Telebit model",tb_name[tbmodel],tbmodel);
1661: if (dialdpy)
1662: printf("Telebit model: %s\n",tb_name[tbmodel]);
1663: ttflui();
1664: /*
1665: Dial timeout. S7 is set to the DIAL TIMEOUT value, or else to 255 if the
1666: dial timeout is greater than 255, which is the maximum value for Telebits.
1667: S7 can't be set to 0 on Telebits -- it gives an error.
1668: */
1669: if (mdmwait > 255) /* If dial timeout too big */
1670: mdmwait = 255; /* make it as big as possible. */
1671: /*
1672: Flow control. If C-Kermit's FLOW-CONTROL is RTS/CTS, then we set this on
1673: the modem too. Unfortunately, many versions of UNIX only allow RTS/CTS
1674: to be set outside of Kermit (e.g. by selecting a special device name).
1675: In that case, Kermit doesn't know that it should set RTS/CTS on the modem,
1676: in which case the user can add the appropriate Telebit command with
1677: SET DIAL DIAL-COMMAND.
1678: */
1679: if (flow == FLO_RTSC) { /* RTS/CTS active in Kermit */
1680: sprintf(tbcmdbuf,
1681: "ATS7=%d S48=%d S50=0 S58=2 S68=255\015",
1682: mdmwait, parity ? 0 : 1);
1683: } else
1684: sprintf(tbcmdbuf, /* Otherwise, don't touch modem's */
1685: "ATS7=%d S48=%d S50=0 S68=255\015", /* flow control */
1686: mdmwait, parity ? 0 : 1); /* setting. */
1687: s = tbcmdbuf;
1688: debug(F110,"ckdial Telebit init step 2",s,0);
1689: for (tries = 4; tries > 0; tries--) {
1690: ttslow(s,pmdminf->wake_rate);
1691: mdmstat = getok(5,1);
1692: if (mdmstat) break;
1693: msleep(500);
1694: ttflui();
1695: }
1696: if (mdmstat < 1) {
1697: n1 = F_minit;
1698: longjmp( sjbuf, F_minit ); /* Failed. */
1699: }
1700: /*
1701: Model-dependent items, but constant per model.
1702: */
1703: switch(tbmodel) {
1704: case TB_BLAZ:
1705: case TB_PLUS: /* TrailBlazer-Plus */
1706: case TB_1000: /* T1000 */
1707: case TB_2000: /* T2000 */
1708: case TB_2500: /* T2500 */
1709: #ifdef COMMENT
1710: /* Code from edit 183 told modem to follow RS-232 wrt CD and DTR */
1711: /* DTR, CD, follow RS-232, pass BREAK */
1712: sprintf(tbcmdbuf,"ATS52=1 S53=4 S54=3\015");
1713: #else
1714: /* But everybody agreed we should not touch modem's CD and DTR settings. */
1715: /* Just pass BREAK */
1716: sprintf(tbcmdbuf,"ATS54=3\015");
1717: #endif /* COMMENT */
1718: break;
1719: case TB_1600: /* T1600 */
1720: case TB_3000: /* T3000 */
1721: case TB_WBLA: /* WorldBlazer */
1722: case TB_QBLA: /* Qblazer */
1723: #ifdef COMMENT
1724: /* Code from edit 183 */
1725: /* Follow RS-232, No CONNECT suffix, pass BREAK */
1726: sprintf(tbcmdbuf,"AT&C1&D2&Q0 S59=0 S61=0 S63=0\015");
1727: #else
1728: /* Everybody agrees we should not touch modem's CD and DTR settings. */
1729: /* Also no more &Q0, no more S59=0 (doesn't matter, so don't touch). */
1730: /* So this section now deals only with treatment of BREAK. */
1731: /* Here we also raise the result code from X1 to X2, which allows */
1732: /* the T1600, T3000, and WB to supply NO DIALTONE, BUSY, RRING, and DIALING. */
1733: /* X2 means something else on the other models. */
1734: /* Transmit BREAK in sequence, raise result code. */
1735: sprintf(tbcmdbuf,"ATX2 S61=0 S63=0\015");
1736: #endif /* COMMENT */
1737: break;
1738: default: /* Others, do nothing */
1739: tbcmdbuf[0] = NUL;
1740: break;
1741: }
1742: s = tbcmdbuf;
1743: if (*s) {
1744: debug(F110,"ckdial Telebit init step 3",s,0);
1745: for (tries = 4; tries > 0; tries--) {
1746: ttslow(s,pmdminf->wake_rate);
1747: mdmstat = getok(5,1);
1748: if (mdmstat) break;
1749: msleep(500);
1750: ttflui();
1751: }
1752: if (mdmstat < 1) {
1753: n1 = F_minit;
1754: longjmp( sjbuf, F_minit ); /* Failed. */
1755: }
1756: } else debug(F100,"ckdial Telebit init step 3 skipped","",0);
1757:
1758: /* Error correction, MNP or V.42 */
1759:
1760: if (augmdmtyp & DIAL_V42) { /* User wants V.42 */
1761: switch (tbmodel) { /* which implies fallback to MNP. */
1762: case TB_PLUS: /* BC7.00 and up firmware */
1763: case TB_2000: /* now really the same as TB+ ? */
1764: case TB_2500: /* LAPM+compress->MNP->direct */
1765: mnpstr = "S50=0 S95=2 S97=1 S98=3 S106=1";
1766: break;
1767: case TB_1600:
1768: case TB_3000:
1769: case TB_WBLA:
1770: case TB_QBLA:
1771: #ifdef COMMENT
1772: mnpstr = "S180=2 S181=0"; /* V.42, fallback = lock speed */
1773: #else
1774: /* Better not to mess with S181, let it be used however user has it set. */
1775: /* S180=2 allows fallback to MNP, S180=1 disallows fallback to MNP. */
1776: mnpstr = "S180=2"; /* V.42 */
1777: #endif /* COMMENT */
1778: break;
1779: default:
1780: if (dialdpy)
1781: printf("V.42 not supported by this Telebit model\n");
1782: }
1783: } else { /* Handle DIAL MNP-ENABLE setting */
1784: switch (tbmodel) {
1785: case TB_BLAZ: /* TrailBlazer */
1786: case TB_PLUS: /* TrailBlazer-Plus */
1787: case TB_1000: /* T1000 */
1788: case TB_2000: /* T2000 */
1789: case TB_2500: /* T2500 */
1790: mnpstr = dialmnp ? "S95=2" : "S95=0"; /* ON, OFF */
1791: break;
1792: case TB_1600: /* T1600 */
1793: case TB_3000: /* T3000 */
1794: case TB_WBLA: /* WorldBlazer */
1795: case TB_QBLA: /* Qblazer */
1796: mnpstr = dialmnp ? "S180=3" : "S180=0"; /* ON, OFF */
1797: /* (Leave S181 fallback method alone) */
1798: break;
1799: default:
1800: mnpstr = "";
1801: }
1802: }
1803:
1804: /* Dialing protocol */
1805:
1806: dprstr = ""; /* Initialize dialing protocol string */
1807: p = ""; /* and message string */
1808: switch (augmdmtyp) {
1809: case n_TELEBIT: /* Start at highest and work down */
1810: case n_TBNV:
1811: p = "standard";
1812: switch (tbmodel) { /* First group starts with PEP */
1813: case TB_BLAZ: /* TrailBlazer */
1814: case TB_PLUS: /* TrailBlazer-Plus */
1815: case TB_1000: /* T1000 */
1816: case TB_2000: /* T2000 */
1817: case TB_2500: /* T2500 */
1818: dprstr = "S50=0 S110=1"; /* PEP, compression allowed. */
1819: break;
1820: case TB_WBLA: /* WorldBlazer has PEP */
1821: dprstr = "S50=0 S190=1 S191=7"; /* PEP, */
1822: break; /* compression allowed. */
1823: case TB_1600: /* T1600 doesn't have PEP */
1824: case TB_3000: /* T3000 doesn't */
1825: case TB_QBLA: /* Qblazer doesn't*/
1826: default:
1827: dprstr = "S50=0"; /* No PEP available */
1828: break;
1829: }
1830: break;
1831:
1832: case n_TBS: /* Telebit up to 2400 Baud */
1833: case n_TBSNV: /* i.e. "Slow mode". */
1834: p = "300/1200/2400 Baud"; /* Leave S90 alone assuming it is */
1835: dprstr = "S50=3"; /* already set for V.22 vs 212A */
1836: break;
1837: case n_TB3: /* Telebit V.32 */
1838: case n_TB3NV:
1839: if (tbmodel == TB_3000 || tbmodel == TB_1600 ||
1840: tbmodel == TB_2500 || tbmodel == TB_WBLA) {
1841: p = "V.32";
1842: /* Note: we don't touch S51 (interface speed) here. */
1843: /* We're already talking to the modem, and the modem */
1844: /* SHOULD be able to make a V.32 call no matter what */
1845: /* its interface speed is. (In practice, however, */
1846: /* that is not always true.) */
1847: dprstr = "S50=6";
1848: } else if (dialdpy)
1849: printf("V.32 not supported by this Telebit model.\n");
1850: break;
1851: case n_TBPEP: /* Force PEP Protocol */
1852: case n_TBPNV:
1853: if (tbmodel != TB_1600 && /* Models that don't support PEP */
1854: tbmodel != TB_3000 &&
1855: tbmodel != TB_QBLA) {
1856: p = "PEP";
1857: if (tbmodel == TB_WBLA) /* WorldBlazer */
1858: dprstr = "S50=255 S190=1 S191=7";
1859: else if (tbmodel != TB_1000)
1860: dprstr = "S50=255 S110=1"; /* TrailBlazer, etc. */
1861: else dprstr = "S50=255"; /* T1000, no compression */
1862: } else if (dialdpy)
1863: printf("PEP not supported by this Telebit model.\n");
1864: break;
1865: }
1866:
1867: /* Kermit Spoof */
1868:
1869: if (dialksp) {
1870: p = "Kermit Spoof";
1871: switch (parity) { /* S111 value depends on parity */
1872: case 'e': S111 = 12; break;
1873: case 'm': S111 = 13; break;
1874: case 'o': S111 = 11; break;
1875: case 's': S111 = 14; break;
1876: case 0:
1877: default: S111 = 10; break;
1878:
1879: }
1880: #ifdef COMMENT
1881: /*
1882: This code forced the use of PEP mode if DIAL KERMIT-SPOOF was ON, which
1883: prevented successful connection if the other modem did not support PEP.
1884: */
1885: if (tbmodel == TB_BLAZ || /* Must force PEP on old models */
1886: tbmodel == TB_PLUS ||
1887: tbmodel == TB_1000 ||
1888: tbmodel == TB_2000 ||
1889: tbmodel == TB_2500)
1890: sprintf(tbcmdbuf,"AT%s %s S50=255 S111=%d S112=%d\015",
1891: mnpstr,dprstr,S111,stchr);
1892: /* PEP is not required on T1500, T1600, T3000, and WB */
1893: /* (but MNP is, but that is user's responsibility). */
1894: else
1895: #endif /* COMMENT */
1896: if (tbmodel != TB_QBLA)
1897: sprintf(tbcmdbuf,"AT%s %s S111=%d S112=%d\015",
1898: mnpstr,dprstr,S111,stchr);
1899: else { /* Qblazer has no Kermit spoof */
1900: sprintf(tbcmdbuf,"AT%s %s\015", mnpstr,dprstr);
1901: p = "No Kermit Spoof";
1902: if (dialdpy)
1903: printf("Kermit Spoof not supported by Qblazer\n");
1904: }
1905: } else { /* No Kermit spoof */
1906: p = "No Kermit Spoof";
1907: sprintf(tbcmdbuf,"AT%s %s %s\015",
1908: mnpstr, dprstr,
1909: (tbmodel == TB_QBLA) ? "" : "S111=0 S112=0");
1910: }
1911: s = tbcmdbuf;
1912: debug(F111,"ckdial Telebit config",p,speed);
1913: debug(F110,"ckdial Telebit init step 4",s,0);
1914: if (*s) {
1915: for (tries = 4; tries > 0; tries--) {
1916: ttslow(s,pmdminf->wake_rate);
1917: mdmstat = getok(5,1);
1918: if (mdmstat) break;
1919: msleep(500);
1920: ttflui();
1921: }
1922: debug(F101,"ckdial telebit init mdmstat","",mdmstat);
1923: if (mdmstat < 1) {
1924: n1 = F_minit;
1925: longjmp(sjbuf, F_minit);
1926: }
1927: }
1928: }
1929: /* Done with Telebit protocols, remove bits from modem type */
1930: /* Except nonverbal bit */
1931: augmdmtyp &= ~(DIAL_PEP|DIAL_V32|DIAL_V42|DIAL_SLO);
1932: debug(F101,"ckdial Telebit augmdmtyp","",augmdmtyp);
1933: break;
1934: }
1935:
1936: case n_MICROCOM: /* Interdigit waits for tone dial */
1937: {
1938: jmp_buf savejmp;
1939: alarm(0);
1940: savalrm = signal(SIGALRM,dialtime); /* Set alarm handler. */
1941: xcpy((char *)savejmp, (char *)sjbuf, sizeof savejmp);
1942: if (setjmp(sjbuf)) {
1943: /* try the autobaud sequence */
1944: xcpy((char *)sjbuf, (char *)savejmp, sizeof savejmp);
1945: alarm(5);
1946: ttslow("44445", MICROCOM.wake_rate);
1947: waitfor(MICROCOM.wake_str);
1948: } else {
1949: alarm(2);
1950: ws = dialini ? dialini : MICROCOM.wake_str;
1951: ttslow(ws, MICROCOM.wake_rate);
1952: waitfor(ws);
1953: #ifdef COMMENT
1954: /*
1955: Kermit spoof for Microcom modems. Untested.
1956: This is reportedly the way to do it for QX/3296c, QX/4232hs, QX/4232bis,
1957: and QX/9624c. The effect on other models is unknown.
1958: */
1959: ws = dialksp ? "APM1\015" : "APM0\015"; /* Kermit spoof */
1960: ttslow(ws, MICROCOM.wake_rate);
1961: waitfor(ws);
1962: #endif /* COMMENT */
1963: alarm(0);
1964: signal(SIGALRM,savalrm); /* Set alarm handler. */
1965: xcpy((char *)sjbuf, (char *)savejmp, sizeof savejmp);
1966: }
1967: }
1968: break;
1969:
1970: case n_ATTDTDM: /* DTDM requires BREAK to wake up */
1971: ttsndb(); /* Send BREAK */
1972: break; /* ttsndb() defined in ckutio.c */
1973:
1974: #endif /* MINIDIAL */
1975:
1976: default: /* Place modem into command mode */
1977: ws = dialini ? dialini : pmdminf->wake_str;
1978: if (ws && (int)strlen(ws) > 0) {
1979: debug(F111,"ckdial default, wake string", ws, pmdminf->wake_rate);
1980: ttslow(ws, pmdminf->wake_rate);
1981: } else debug(F100,"ckdial no wake_str","",0);
1982: if (pmdminf->wake_prompt && (int)strlen(pmdminf->wake_prompt) > 0) {
1983: debug(F110,"ckdial default, waiting for wake_prompt",
1984: pmdminf->wake_prompt,0);
1985: savalrm = signal(SIGALRM,dialtime);
1986: alarm(10);
1987: waitfor(pmdminf->wake_prompt);
1988: } else debug(F100,"ckdial no wake_prompt","",0);
1989: break;
1990: }
1991: alarm(0); /* Turn off alarm */
1992: signal(SIGALRM,savalrm); /* Restore alarm handler. */
1993: debug(F100,"ckdial got wake prompt","",0);
1994: msleep(500); /* Allow settling time */
1995:
1996: #ifndef MINIDIAL
1997:
1998: /* Enable/disable MNP (Telebit already done above) */
1999:
2000: switch (augmdmtyp) {
2001: case n_HST:
2002: if (dialmnp)
2003: ttslow("AT&K2\015",pmdminf->wake_rate);
2004: else
2005: ttslow("AT&K0\015",pmdminf->wake_rate);
2006: getok(5,1); /* Get response */
2007: break;
2008:
2009: /* Add others here ... */
2010:
2011: default:
2012: break;
2013: }
2014: #endif /* MINIDIAL */
2015:
2016: /* Put modem into dialing mode, if the modem requires it. */
2017:
2018: if (pmdminf->dmode_str && *(pmdminf->dmode_str)) {
2019: ttslow(pmdminf->dmode_str, pmdminf->dial_rate);
2020: savalrm = signal(SIGALRM,dialtime);
2021: alarm(10);
2022: if (pmdminf->dmode_prompt) { /* Wait for prompt, if any expected */
2023: waitfor(pmdminf->dmode_prompt);
2024: msleep(300);
2025: }
2026: alarm(0); /* Turn off alarm on dialing prompts */
2027: signal(SIGALRM,savalrm); /* Restore alarm */
2028: ttflui(); /* Clear out stuff from waking modem up */
2029: }
2030:
2031: /* Dial the number. First form the dialing string. */
2032:
2033: sprintf(lbuf, dialcmd ? dialcmd : pmdminf->dial_str, telnbr);
2034: debug(F110,"dialing",lbuf,0);
2035: ttslow(lbuf,pmdminf->dial_rate); /* Send the dialing string */
2036:
2037: savalrm = signal(SIGALRM,dialtime); /* Time to allow for connecting */
2038: x = alarm(waitct); /* This much time... */
2039: debug(F101,"ckdial old alarm","",x);
2040: debug(F101,"ckdial waitct","",waitct);
2041:
2042: #ifndef MINIDIAL
2043: switch (augmdmtyp) {
2044: case n_RACAL: /* Acknowledge printout of dialing string */
2045: sleep(3);
2046: ttflui();
2047: ttoc('\015');
2048: break;
2049: case n_VENTEL:
2050: waitfor("\012\012"); /* Ignore the first two strings */
2051: break;
2052: default:
2053: break;
2054: }
2055: #endif /* MINIDIAL */
2056:
2057: /* Check for connection */
2058:
2059: mdmstat = 0; /* No status yet */
2060: strcpy(lbuf,"No Connection"); /* Default reason for failure */
2061: debug(F101,"dial awaiting response, augmdmtyp","",augmdmtyp);
2062: while (mdmstat == 0) {
2063: switch (augmdmtyp) {
2064: default:
2065: for (n = -1; n < LBUFL-1; ) { /* Accumulate response */
2066: c2 = ddinc(0); /* Read a character, blocking */
2067: if (c2 == 0 || c2 == -1) /* Ignore NULs and errors */
2068: continue; /* (Timeout will handle errors) */
2069: else /* Real character, keep it */
2070: lbuf[++n] = c2 & 0177;
2071: dialoc(lbuf[n]); /* Maybe echo it */
2072: if (augmdmtyp == n_CCITT) { /* V.25 bis dialing... */
2073: /*
2074: This assumes that V.25bis indications are all at least 3 characters long
2075: and are terminated by either CRLF or LFCR.
2076: */
2077: if (n < 3) continue;
2078: if ((lbuf[n] == CR) && (lbuf[n-1] == LF)) break;
2079: if ((lbuf[n] == LF) && (lbuf[n-1] == CR)) break;
2080: }
2081: #ifndef MINIDIAL
2082: else if (augmdmtyp == n_DIGITEL) {
2083: if ((lbuf[n] == CR) && (lbuf[n-1] == LF) ||
2084: (lbuf[n] == LF) && (lbuf[n-1] == CR))
2085: break;
2086: else
2087: continue;
2088: }
2089: #endif /* MINIDIAL */
2090: else { /* All others, break on CR or LF */
2091: if ( lbuf[n] == CR || lbuf[n] == LF ) break;
2092: }
2093: }
2094: lbuf[++n] = '\0'; /* Terminate response from modem */
2095: debug(F111,"dial modem response",lbuf,n);
2096: if (n) { /* If one or more characters present */
2097: switch (augmdmtyp) { /* check for modem response message. */
2098: #ifndef MINIDIAL
2099: case n_ATTMODEM:
2100: /* Careful - "Connected" / "Not Connected" */
2101: if (didweget(lbuf,"Busy") ||
2102: didweget(lbuf,"Not connected") ||
2103: didweget(lbuf,"Not Connected") ||
2104: didweget(lbuf,"No dial tone") ||
2105: didweget(lbuf,"No Dial Tone") ||
2106: didweget(lbuf,"No answer") ||
2107: didweget(lbuf,"No Answer"))
2108: mdmstat = FAILED;
2109: else if (didweget(lbuf,"Answered") ||
2110: didweget(lbuf,"Connected"))
2111: mdmstat = CONNECTED;
2112: break;
2113:
2114: case n_ATTISN:
2115: if (didweget(lbuf,"ANSWERED"))
2116: mdmstat = CONNECTED;
2117: else if (didweget(lbuf,"BUSY") ||
2118: didweget(lbuf,"DISCONNECT") ||
2119: didweget(lbuf,"NO ANSWER") ||
2120: didweget(lbuf,"WRONG ADDRESS"))
2121: mdmstat = FAILED;
2122: break;
2123:
2124: case n_ATTDTDM:
2125: if (didweget(lbuf,"ANSWERED"))
2126: mdmstat = CONNECTED;
2127: else if (didweget(lbuf,"BUSY") ||
2128: didweget(lbuf,"CHECK OPTIONS") ||
2129: didweget(lbuf,"DISCONNECTED") ||
2130: didweget(lbuf,"DENIED"))
2131: mdmstat = FAILED;
2132: #ifdef DEBUG
2133: #ifdef ATT6300
2134: else if (deblog && didweget(lbuf,"~~"))
2135: mdmstat = CONNECTED;
2136: #endif /* ATT6300 */
2137: #endif /* DEBUG */
2138: break;
2139: #endif /* MINIDIAL */
2140:
2141: case n_CCITT: /* CCITT V.25bis */
2142: #ifndef MINIDIAL
2143: case n_DIGITEL: /* or Digitel variant */
2144: #endif /* MINIDIAL */
2145: if (didweget(lbuf,"VAL")) { /* Dial command confirmation */
2146: #ifndef MINIDIAL
2147: if (augmdmtyp == n_CCITT)
2148: #endif /* MINIDIAL */
2149: continue; /* Go back and read more */
2150: #ifndef MINIDIAL
2151: /* Digitel doesn't give an explicit connect confirmation message */
2152: else {
2153: int n;
2154: for (n = -1; n < LBUFL-1; ) {
2155: lbuf[++n] = c2 = ddinc(0) & 0177;
2156: dialoc(lbuf[n]);
2157: if ((lbuf[n] == CR) && (lbuf[n-1] == LF) ||
2158: (lbuf[n] == LF) && (lbuf[n-1] == CR))
2159: break;
2160: }
2161: mdmstat = CONNECTED; /* Assume we're connected */
2162: if (dialdpy && carrier != CAR_OFF) {
2163: sleep(1); /* Wait a second */
2164: n = ttgmdm(); /* Try to read modem signals */
2165: if ((n > -1) && (n & BM_DCD == 0))
2166: printf("Warning: No Carrier\n");
2167: }
2168: }
2169: #endif /* MINIDIAL */
2170: } else if (didweget(lbuf,"CNX")) { /* Connected */
2171: mdmstat = CONNECTED;
2172: } else if (didweget(lbuf, "INV")) {
2173: mdmstat = FAILED; /* Command error */
2174: strcpy(lbuf,"INV");
2175: } else if (didweget(lbuf,"CFI")) { /* Call Failure */
2176: #ifdef COMMENT
2177: /*
2178: V.25 bis says that the failure reason comes on the same line, so
2179: we don't need to read any more characters here.
2180: */
2181: for (n = 0; n < LBUFL-1; n++) { /* Read reason */
2182: lbuf[n] = c2 = (ddinc(0) & 0177);
2183: if (c2 == LF) /* Modem answers LF CR */
2184: continue;
2185: dialoc(lbuf[n]);
2186: if (lbuf[n] == CR || lbuf[n] == LF) break;
2187: }
2188: #endif /* COMMENT */
2189: if (didweget(lbuf,"AB")) /* Interpret reason code */
2190: strcpy(lbuf,"AB: Timed out");
2191: else if (didweget(lbuf,"CB"))
2192: strcpy(lbuf,"CB: Local DCE Busy");
2193: else if (didweget(lbuf,"ET"))
2194: strcpy(lbuf,"ET: Busy");
2195: else if (didweget(lbuf, "NS"))
2196: strcpy(lbuf,"NS: Number not stored");
2197: else if (didweget(lbuf,"NT"))
2198: strcpy(lbuf,"NT: No answer");
2199: else if (didweget(lbuf,"RT"))
2200: strcpy(lbuf,"RT: Ring tone");
2201: else if (didweget(lbuf,"PV"))
2202: strcpy(lbuf,"PV: Parameter value error");
2203: else if (didweget(lbuf,"PS"))
2204: strcpy(lbuf,"PS: Parameter syntax error");
2205: else if (didweget(lbuf,"MS"))
2206: strcpy(lbuf,"MS: Message syntax error");
2207: else if (didweget(lbuf,"CU"))
2208: strcpy(lbuf,"CU: Command unknown");
2209: else if (didweget(lbuf,"FC"))
2210: strcpy(lbuf,"FC: Forbidden call");
2211: mdmstat = FAILED;
2212: } else if (didweget(lbuf,"INC")) { /* Incoming Call */
2213: strcpy(lbuf,"INC: Incoming call");
2214: mdmstat = FAILED;
2215: } else if (didweget(lbuf,"DLC")) { /* Delayed Call */
2216: strcpy(lbuf,"DLC: Delayed call");
2217: mdmstat = FAILED;
2218: } else /* Response was probably an echo. */
2219: #ifndef MINIDIAL
2220: if (augmdmtyp == n_CCITT)
2221: #endif /* MINIDIAL */
2222: continue;
2223: #ifndef MINIDIAL
2224: else /* Digitel: If no error, then connect. */
2225: mdmstat = CONNECTED;
2226: #endif /* MINIDIAL */
2227: break;
2228:
2229: #ifndef MINIDIAL
2230: case n_CERMETEK:
2231: if (didweget(lbuf,"\016A")) {
2232: mdmstat = CONNECTED;
2233: ttslow("\016U 1\015",200); /* make transparent*/
2234: }
2235: break;
2236:
2237: case n_DF100: /* DF100 has short response codes */
2238: if (strcmp(lbuf,"A") == 0)
2239: mdmstat = CONNECTED; /* Attached */
2240: else if (strcmp(lbuf,"N") == 0 || /* No Ans or Dialtone */
2241: strcmp(lbuf,"E") == 0 || /* Error */
2242: strcmp(lbuf,"R") == 0) { /* Ready */
2243: mdmstat = FAILED;
2244: break;
2245: }
2246: /* otherwise fall thru... */
2247:
2248: case n_DF200:
2249: if (didweget(lbuf,"Attached"))
2250: mdmstat = CONNECTED;
2251: /*
2252: * The DF100 will respond with "Attached" even if DTR
2253: * and/or carrier are not present. Another reason to
2254: * (also) wait for carrier?
2255: */
2256: else if (didweget(lbuf,"Busy") ||
2257: didweget(lbuf,"Disconnected") ||
2258: didweget(lbuf,"Error") ||
2259: didweget(lbuf,"No answer") ||
2260: didweget(lbuf,"No dial tone") ||
2261: didweget(lbuf,"Speed:"))
2262: mdmstat = FAILED;
2263: /*
2264: * It appears that the "Speed:..." response comes after an
2265: * "Attached" response, so this is never seen. HOWEVER,
2266: * it would be very handy to detect this and temporarily
2267: * reset the speed, since it's a nuisance otherwise.
2268: * If we wait for some more input from the modem, how do
2269: * we know if it's from the remote host or the modem?
2270: * Carrier reportedly doesn't get set until after the
2271: * "Speed:..." response (if any) is sent. Another reason
2272: * to (also) wait for carrier.
2273: */
2274: break;
2275:
2276: case n_GDC:
2277: if (didweget(lbuf,"ON LINE"))
2278: mdmstat = CONNECTED;
2279: else if (didweget(lbuf,"NO CONNECT"))
2280: mdmstat = FAILED;
2281: break;
2282:
2283: case n_USROBOT:
2284: case n_HST:
2285: case n_TELEBIT:
2286: #endif /* MINIDIAL */
2287: case n_HAYES:
2288: if (mdmspd && !network) {
2289: s = lbuf;
2290: while (*s != '\0' && *s != 'C') s++;
2291: cptr = (*s == 'C') ? s : NULL;
2292: conspd = 0L;
2293: if ((cptr != NULL) && !strncmp(cptr,"CONNECT ",8)) {
2294: if ((int)strlen(cptr) < 9) /* Just CONNECT, */
2295: conspd = 300L; /* use 300 bps */
2296: else if (isdigit(*(cptr+8))) /* not CONNECT FAST */
2297: conspd = atol(cptr + 8); /* CONNECT nnnn */
2298: if (conspd != speed) {
2299: if ((conspd / 10L) > 0) {
2300: if (ttsspd((int) (conspd / 10L)) < 0) {
2301: printf(" Can't change speed to %lu\r\n",
2302: conspd);
2303: } else {
2304: speed = conspd;
2305: mdmstat = CONNECTED;
2306: if ( !quiet && !backgrd )
2307: printf(" Speed changed to %lu\r\n",
2308: conspd);
2309: }
2310: }
2311: } /* Expanded to handle any conceivable speed */
2312: }
2313: }
2314: #ifndef MINIDIAL
2315: if (mymdmtyp == n_TELEBIT) {
2316: if (didweget(lbuf,"CONNECT FAST/KERM")) {
2317: mdmstat = CONNECTED;
2318: if (!quiet && !backgrd) printf("FAST/KERM ");
2319: break;
2320: }
2321: }
2322: #endif /* MINIDIAL */
2323: if (didweget(lbuf,"RRING") ||
2324: didweget(lbuf,"RINGING") ||
2325: didweget(lbuf,"DIALING")) {
2326: mdmstat = 0;
2327: } else if (didweget(lbuf,"CONNECT")) {
2328: mdmstat = CONNECTED;
2329: } else if (didweget(lbuf,"NO CARRIER") ||
2330: didweget(lbuf,"NO DIALTONE") ||
2331: didweget(lbuf,"NO DIAL TONE") ||
2332: didweget(lbuf,"BUSY") ||
2333: didweget(lbuf,"NO ANSWER") ||
2334: didweget(lbuf,"VOICE") ||
2335: didweget(lbuf,"RING") ||
2336: didweget(lbuf,"ERROR")) {
2337: mdmstat = FAILED;
2338: }
2339: break;
2340: #ifndef MINIDIAL
2341: case n_PENRIL:
2342: if (didweget(lbuf,"OK"))
2343: mdmstat = CONNECTED;
2344: else if (didweget(lbuf,"BUSY") ||
2345: didweget(lbuf,"NO RING"))
2346: mdmstat = FAILED;
2347: break;
2348: case n_RACAL:
2349: if (didweget(lbuf,"ON LINE"))
2350: mdmstat = CONNECTED;
2351: else if (didweget(lbuf,"FAILED CALL"))
2352: mdmstat = FAILED;
2353: break;
2354: case n_ROLM:
2355: if (didweget(lbuf,"CALLING"))
2356: mdmstat = 0;
2357: else if (didweget(lbuf,"COMPLETE"))
2358: mdmstat = CONNECTED;
2359: else if (didweget(lbuf,"FAILED") ||
2360: didweget(lbuf,"NOT AVAILABLE") ||
2361: didweget(lbuf,"LACKS PERMISSION") ||
2362: didweget(lbuf,"NOT A DATALINE") ||
2363: didweget(lbuf,"INVALID GROUP NAME") ||
2364: didweget(lbuf,"BUSY") ||
2365: didweget(lbuf,"ABANDONDED") ||
2366: didweget(lbuf,"DOES NOT ANSWER") ||
2367: didweget(lbuf,"INVALID DATA LINE NUMBER"))
2368: mdmstat = FAILED;
2369: break;
2370: case n_VENTEL:
2371: if (didweget(lbuf,"ONLINE!") ||
2372: didweget(lbuf,"Online!"))
2373: mdmstat = CONNECTED;
2374: else if (didweget(lbuf,"BUSY") ||
2375: didweget(lbuf,"DEAD PHONE") ||
2376: didweget(lbuf,"Busy"))
2377: mdmstat = FAILED;
2378: break;
2379: case n_CONCORD:
2380: if (didweget(lbuf,"INITIATING"))
2381: mdmstat = CONNECTED;
2382: else if (didweget(lbuf,"BUSY") ||
2383: didweget(lbuf,"CALL FAILED"))
2384: mdmstat = FAILED;
2385: break;
2386: case n_MICROCOM:
2387: /* "RINGBACK" means phone line ringing, continue */
2388: if (didweget(lbuf,"NO CONNECT") ||
2389: didweget(lbuf,"BUSY") ||
2390: didweget(lbuf,"NO DIALTONE") ||
2391: didweget(lbuf,"COMMAND ERROR") ||
2392: didweget(lbuf,"IN USE"))
2393: mdmstat = FAILED;
2394: else if (didweget(lbuf,"CONNECT"))
2395: mdmstat = CONNECTED;
2396: /* trailing speed ignored */
2397: break;
2398: #endif /* MINIDIAL */
2399: }
2400: }
2401: break;
2402:
2403: #ifndef MINIDIAL
2404: case n_DF03: /* because response lacks CR or NL */
2405: c = ddinc(0) & 0177;
2406: dialoc(c);
2407: debug(F000,"dial df03 got","",c);
2408: if ( c == 'A' ) mdmstat = CONNECTED;
2409: if ( c == 'B' ) mdmstat = FAILED;
2410: break;
2411:
2412: case n_TBNV: /* Hayeslike modems in digit */
2413: case n_TB3NV /* response mode... */:
2414: case n_TBPNV:
2415: case n_TB4NV:
2416: case n_TBSNV:
2417: #endif /* MINIDIAL */
2418: case n_HAYESNV:
2419:
2420: /*
2421: The method for reading Hayes numeric result codes has been totally
2422: redone as of 5A(174) to account for all of the following. Not all have
2423: been tested, and others probably need to be added.
2424:
2425: Hayes numeric result codes (Hayes 1200 and higher):
2426: 0 = OK
2427: 1 = CONNECT at 300 bps (or 1200 bps on Hayes 1200 with basic code set)
2428: 2 = RING
2429: 3 = NO CARRIER
2430: 4 = ERROR (in command line)
2431: 5 = CONNECT 1200 (extended code set)
2432: Hayes 2400 and higher:
2433: 6 = NO DIALTONE
2434: 7 = BUSY
2435: 8 = NO ANSWER
2436: 9 = (there is no 9)
2437: 10 = CONNECT 2400
2438: Reportedly, the codes for Hayes V.32 modems are:
2439: 1x = CONNECT <suffix>
2440: 5x = CONNECT 1200 <suffix>
2441: 9x = CONNECT 2400 <suffix>
2442: 11x = CONNECT 4800 <suffix>
2443: 12x = CONNECT 9600 <suffix>
2444: Where:
2445: x: suffix:
2446: R = RELIABLE
2447: RC = RELIABLE COMPRESSED
2448: L = LAPM
2449: LC = LAPM COMPRESSED
2450: And for Telebits, all the above, except no suffix in numeric mode, plus:
2451: 11 = CONNECT 4800
2452: 12 = CONNECT 9600
2453: 13 = CONNECT 14400
2454: 14 = CONNECT 19200
2455: 15 = CONNECT 38400
2456: 16 = CONNECT 57600
2457: 20 = CONNECT 300/REL (= MNP)
2458: 22 = CONNECT 1200/REL (= MNP)
2459: 23 = CONNECT 2400/REL (= MNP)
2460: 46 = CONNECT 7512 (i.e. 75/1200)
2461: 47 = CONNECT 1275 (i.e. 1200/75)
2462: 48 = CONNECT 7200
2463: 49 = CONNECT 12000
2464: 50 = CONNECT FAST (not on T1600/3000)
2465: 52 = RRING
2466: 53 = DIALING
2467: 54 = NO PROMPTTONE
2468: 61 = CONNECT FAST/KERM (Kermit spoof)
2469: 70 = CONNECT FAST/COMP (PEP + compression)
2470: 71 = CONNECT FAST/KERM/COMP (PEP + compression + Kermit spoof)
2471: */
2472: #define NBUFL 8
2473: { /* Nonverbal response code handler */
2474: char nbuf[NBUFL+1]; /* Response buffer */
2475: int i, j; /* Buffer pointers */
2476: debug(F101,"RESPONSE mdmecho","",mdmecho);
2477: if (mdmecho) { /* Sponge up dialing string echo. */
2478: while (1) {
2479: c = ddinc(0) & 0x7f;
2480: debug(F000,"SPONGE","",c);
2481: dialoc(c);
2482: if (c == CR) break;
2483: }
2484: }
2485: while (mdmstat == 0) { /* Read response */
2486: for (i = 0; i < NBUFL; i++) /* Clear the buffer */
2487: nbuf[i] = '\0';
2488: i = 0; /* Reset the buffer pointer. */
2489: c = ddinc(0) & 0177; /* Get first digit of response. */
2490: /* using an untimed, blocking read. */
2491: debug(F000,"RESPONSE-A","",c);
2492: dialoc(c); /* Echo it if requested. */
2493: if (!isdigit(c)) /* If not a digit, keep looking. */
2494: continue;
2495: nbuf[i++] = c; /* Got first digit, save it. */
2496: while (c != CR && i < 8) { /* Now read characters up to CR */
2497: x = ddinc(0) & 0177; /* Get a character. */
2498: c = (char) x; /* Got it OK. */
2499: debug(F000,"RESPONSE-C","",c);
2500: if (c != CR) /* If it's not a carriage return, */
2501: nbuf[i++] = c; /* save it. */
2502: dialoc(c); /* Echo it. */
2503: }
2504: nbuf[i] = '\0'; /* Done, terminate the buffer. */
2505: debug(F111,"dial hayesnv lbuf",lbuf,n);
2506: debug(F111,"dial hayesnv got",nbuf,i);
2507: /*
2508: Separate any non-numeric suffix from the numeric result code
2509: with a null.
2510: */
2511: for (j = i-1; (j > -1) && !isdigit(nbuf[j]); j--)
2512: nbuf[j+1] = nbuf[j];
2513: j++;
2514: nbuf[j++] = '\0';
2515: debug(F110,"dial hayesnv numeric",nbuf,0);
2516: debug(F111,"dial hayesnv suffix ",nbuf+j,j);
2517: if ((int)strlen(nbuf) > 3) /* Probably phone number echoing. */
2518: continue;
2519: /*
2520: Now read and interpret the results...
2521: */
2522: i = atoi(nbuf); /* Convert to integer */
2523: switch (i) {
2524: case 1: /* CONNECT */
2525: mdmstat = CONNECTED; /* Could be any speed */
2526: break;
2527: case 2: /* RING */
2528: if (dialdpy) printf("\r\n Local phone is ringing!\r\n");
2529: mdmstat = FAILED;
2530: break;
2531: case 3: /* NO CARRIER */
2532: if (dialdpy) printf("\r\n No Carrier.\r\n");
2533: mdmstat = FAILED;
2534: break;
2535: case 4: /* ERROR */
2536: if (dialdpy) printf("\r\n Modem Command Error.\r\n");
2537: mdmstat = FAILED;
2538: break;
2539: case 5: /* CONNECT 1200 */
2540: spdchg(1200L); /* Change speed if necessary. */
2541: mdmstat = CONNECTED;
2542: break;
2543: case 6: /* NO DIALTONE */
2544: if (dialdpy) printf("\r\n No Dialtone.\r\n");
2545: mdmstat = FAILED;
2546: break;
2547: case 7: /* BUSY */
2548: if (dialdpy) printf("\r\n Busy.\r\n");
2549: mdmstat = FAILED;
2550: break;
2551: case 8: /* NO ANSWER */
2552: if (dialdpy) printf("\r\n No Answer.\r\n");
2553: mdmstat = FAILED;
2554: break;
2555: case 9: /* CONNECT 2400 */
2556: case 10:
2557: spdchg(2400L); /* Change speed if necessary. */
2558: mdmstat = CONNECTED;
2559: break;
2560: case 11: /* CONNECT 4800 */
2561: spdchg(4800L);
2562: mdmstat = CONNECTED;
2563: break;
2564: case 12: /* CONNECT 9600 */
2565: spdchg(9600L);
2566: mdmstat = CONNECTED;
2567: break;
2568: case 13: /* CONNECT 14400 */
2569: spdchg(14400L);
2570: mdmstat = CONNECTED;
2571: break;
2572: case 14:
2573: spdchg(19200L); /* CONNECT 19200 */
2574: mdmstat = CONNECTED;
2575: break;
2576: case 15: /* CONNECT 34800 */
2577: spdchg(38400L);
2578: mdmstat = CONNECTED;
2579: break;
2580: case 16: /* CONNECT 57600 */
2581: spdchg(57600L);
2582: mdmstat = CONNECTED;
2583: break;
2584: case 20: /* CONNECT 300/REL */
2585: spdchg(300L);
2586: mdmstat = CONNECTED;
2587: break;
2588: case 22: /* CONNECT 1200/REL */
2589: spdchg(1200L);
2590: mdmstat = CONNECTED;
2591: break;
2592: case 23: /* CONNECT 2400/REL */
2593: spdchg(2400L);
2594: mdmstat = CONNECTED;
2595: break;
2596: case 46: /* CONNECT 7512 */
2597: spdchg(8880L); /* 75/1200 split speed */
2598: mdmstat = CONNECTED; /* (special C-Kermit code) */
2599: break;
2600: case 47: /* CONNECT 1200/75 */
2601: mdmstat = CONNECTED; /* Speed not supported by Kermit */
2602: printf("CONNECT 1200/75 - Not support by C-Kermit\r\n");
2603: break;
2604: case 48: /* CONNECT 7200 */
2605: spdchg(7200L);
2606: mdmstat = CONNECTED;
2607: break;
2608: case 49: /* CONNECT 12000 */
2609: spdchg(12000L);
2610: mdmstat = CONNECTED;
2611: break;
2612: #ifndef MINIDIAL
2613: case 50: /* CONNECT FAST */
2614: if (mymdmtyp == n_TELEBIT) /* Early models only */
2615: mdmstat = CONNECTED;
2616: break;
2617: case 52: /* RRING */
2618: if (mymdmtyp == n_TELEBIT)
2619: if (dialdpy) printf(" Ringing...\r\n");
2620: break;
2621: case 53: /* DIALING */
2622: if (mymdmtyp == n_TELEBIT)
2623: if (dialdpy) printf(" Dialing...\r\n");
2624: break;
2625: case 54: /* NO PROMPTTONE */
2626: if (mymdmtyp == n_TELEBIT) {
2627: if (dialdpy) printf("\r\n No Prompttone.\r\n");
2628: mdmstat = FAILED;
2629: }
2630: break;
2631: case 61: /* Various Telebit PEP modes */
2632: case 62:
2633: case 63:
2634: case 70:
2635: case 71:
2636: case 72:
2637: case 73:
2638: if (mymdmtyp == n_TELEBIT) /* Early models only */
2639: mdmstat = CONNECTED;
2640: break;
2641: #endif /* MINIDIAL */
2642: default:
2643: break;
2644: }
2645: }
2646: if (mdmstat == CONNECTED && nbuf[j] != '\0') {
2647: if (dialdpy) {
2648: printf("\r\n");
2649: if (nbuf[j] == 'R') printf("RELIABLE");
2650: if (nbuf[j] == 'L') printf("LAPM");
2651: if (nbuf[j+1] == 'C') printf(" COMPRESSED");
2652: printf("\r\n");
2653: }
2654: }
2655: }
2656: break;
2657:
2658: case n_UNKNOWN: {
2659: int x, y = waitct;
2660: mdmstat = FAILED; /* Assume failure. */
2661: while (y-- > -1) {
2662: x = ttchk();
2663: if (x > 0) {
2664: if (x > LBUFL) x = LBUFL;
2665: x = ttxin(x,(CHAR *)lbuf);
2666: if ((x > 0) && dialdpy) conol(lbuf);
2667: }
2668: x = ttgmdm(); /* Try to read modem signals */
2669: if (x < 0) break; /* Can't, fail. */
2670: if (x & BM_DCD) { /* Got signals OK. Carrier present? */
2671: mdmstat = CONNECTED; /* Yes, done. */
2672: break;
2673: } /* No, keep waiting. */
2674: sleep(1);
2675: }
2676: break;
2677: }
2678: } /* switch (augmdmtyp) */
2679: } /* while (mdmstat == 0) */
2680: x = alarm(0); /* Turn off alarm. */
2681: debug(F101,"ckdial alarm off","",x);
2682: if ( mdmstat != CONNECTED ) { /* Modem-detected failure */
2683: n1 = F_modem;
2684: longjmp( sjbuf, F_modem ); /* Exit (with reason in lbuf) */
2685: }
2686: msleep(1000); /* In case DTR blinks */
2687: alarm(3); /* Precaution in case of trouble */
2688: debug(F110,"dial","succeeded",0);
2689: #ifndef MINIDIAL
2690: if (augmdmtyp != n_ROLM) /* Rolm has wierd modem signaling */
2691: #endif /* MINIDIAL */
2692: ttpkt(speed,FLO_DIAX,parity); /* Cancel dialing state ioctl */
2693: dreset(); /* Reset alarms, etc. */
2694: if (!quiet && !backgrd)
2695: printf (" Call complete.\07\n");
2696: #ifdef DYNAMIC
2697: if (lbuf) free(lbuf);
2698: #endif /* DYNAMIC */
2699: return(1); /* Return successfully */
2700: }
2701:
2702: /*
2703: getok() - wait up to n seconds for OK (0) or ERROR (4) response from modem.
2704: Use with Hayeslike or CCITT modems for reading the reply to a nondialing
2705: command.
2706:
2707: Second argument says whether to be strict about numeric result codes, i.e.
2708: to require they be preceded by CR or else be the first character in the
2709: response, e.g. to prevent the ATH0<CR> echo from looking like a valid
2710: response. Strict == 0 is needed for ATI on Telebit, which can return the
2711: model number concatenated with the numeric response code, e.g. "9620"
2712: ("962" is the model number, "0" is the response code). getok() Returns:
2713:
2714: 0 if it timed out,
2715: 1 if it succeeded,
2716: -1 on modem command, i/o, or other error.
2717: */
2718: static jmp_buf okbuf; /* Jump-buf for getok(). */
2719:
2720: SIGTYP
2721: oktimo(foo) int foo; { /* Alarm handler for getok(). */
2722: #ifdef OSK /* OS-9, see comment in dialtime(). */
2723: sigmask(-1);
2724: #endif /* OSK */
2725: longjmp(okbuf,1);
2726: }
2727:
2728: int
2729: getok(n, strict) int n, strict; {
2730: CHAR c;
2731: int i, x, status, oldalarm;
2732: SIGTYP (*saval)(); /* For saving alarm handler locally */
2733:
2734: mdmecho = 0; /* Assume no echoing of commands */
2735: saval = signal(SIGALRM,oktimo); /* Set response timer, */
2736: oldalarm = alarm(n); /* saving old one. */
2737: if (setjmp(okbuf)) { /* Timed out. */
2738: alarm(oldalarm); /* Restore old alarm */
2739: if (saval) signal(SIGALRM,saval); /* and alarm handler */
2740: debug(F100,"getok timeout","",0);
2741: ttflui(); /* Flush input buffer */
2742: return(0); /* and return timeout indication */
2743:
2744: } else if (augmdmtyp == n_CCITT /* CCITT, easy... */
2745: #ifndef MINIDIAL
2746: || augmdmtyp == n_DIGITEL /* Digitel, ditto. */
2747: #endif /* MINIDIAL */
2748: ) {
2749: waitfor("VAL");
2750: return(1);
2751:
2752: } else { /* Hayes & friends, start here... */
2753: status = 0; /* No status yet. */
2754: for (x = 0; x < RBUFL; x++) /* Initialize response buffer */
2755: rbuf[x] = SP; /* to all spaces */
2756: rbuf[RBUFL] = NUL; /* and terminate with NUL. */
2757: while (status == 0) { /* While no status... */
2758: x = ddinc(0); /* Read a character */
2759: if (x < 0) { /* I/O error */
2760: alarm(oldalarm); /* Turn off alarm */
2761: if (saval) signal(SIGALRM,saval); /* and restore handler. */
2762: return(-1); /* Return error code. */
2763: }
2764: debug(F101,"getok ddinc","",x); /* Got a character. */
2765: c = x & 0x7f; /* Get low order 7 bits */
2766: if (!c) /* Don't deposit NULs */
2767: continue; /* or else didweget() won't work */
2768: if (dialdpy) conoc((char)c); /* Echo it if requested */
2769: for (i = 0; i < RBUFL-1; i++) /* Rotate buffer */
2770: rbuf[i] = rbuf[i+1];
2771: rbuf[RBUFL-1] = c; /* Deposit character at end */
2772: debug(F000,"getok:",rbuf,(int) c); /* Log it */
2773: switch (c) { /* Interpret it. */
2774: case CR: /* Got a carriage return. */
2775: switch(rbuf[RBUFL-2]) { /* Look at character before it. */
2776: case '0': /* 0 = OK numeric response */
2777: if (!strict ||
2778: rbuf[RBUFL-3] == CR || rbuf[RBUFL-3] == SP) {
2779: augmdmtyp |= DIAL_NV; /* OR in the "nonverbal" bit. */
2780: status = 1; /* Good response */
2781: }
2782: break;
2783: case '4': /* 4 = ERROR numeric response */
2784: if (!strict ||
2785: rbuf[RBUFL-3] == CR || rbuf[RBUFL-3] == SP) {
2786: augmdmtyp |= DIAL_NV; /* OR in the nonverbal bit. */
2787: status = -1; /* Bad command */
2788: }
2789: break;
2790: }
2791: if (dialdpy && (augmdmtyp & DIAL_NV)) /* If numeric results, */
2792: conoc(LF); /* echo a linefeed too. */
2793: break;
2794: case LF: /* Got a linefeed. */
2795: /*
2796: Note use of explicit octal codes in the string for
2797: CR and LF. We want real CR and LF here, not whatever
2798: the compiler happens to define \r and \n as...
2799: */
2800: if (!strcmp(rbuf+RBUFL-4,"OK\015\012")) /* Good response */
2801: status = 1;
2802: else if (!strcmp(rbuf+RBUFL-7,"ERROR\015\012")) /* Error */
2803: status = -1;
2804: augmdmtyp &= ~(DIAL_NV); /* Turn off the nonverbal bit */
2805: break;
2806: /* Check whether modem echoes its commands... */
2807: case 't': /* Got little t */
2808: if (!strcmp(rbuf+RBUFL-3,"\015at") || /* See if it's "at" */
2809: !strcmp(rbuf+RBUFL-3," at"))
2810: mdmecho = 1;
2811: debug(F111,"MDMECHO-t",rbuf+RBUFL-2,mdmecho);
2812: break;
2813: case 'T': /* Got Big T */
2814: if (!strcmp(rbuf+RBUFL-3,"\015AT") || /* See if it's "AT" */
2815: !strcmp(rbuf+RBUFL-3," AT"))
2816: mdmecho = 1;
2817: debug(F111,"MDMECHO-T",rbuf+RBUFL-3,mdmecho);
2818: break;
2819: default: /* Other characters, accumulate. */
2820: status = 0;
2821: break;
2822: }
2823: }
2824: debug(F101,"getok returns","",status);
2825: alarm(oldalarm); /* Restore previous alarm */
2826: if (saval) signal(SIGALRM,saval); /* and handler */
2827: ttflui(); /* Flush input buffer */
2828: return(status); /* Return status */
2829: }
2830: }
2831:
2832: /* Maybe hang up the phone, depending on various SET DIAL parameters. */
2833:
2834: int
2835: dialhup() {
2836: int x = 0;
2837: if (dialhng) { /* DIAL HANGUP ON? */
2838: x = mdmhup(); /* Try modem-specific method first */
2839: debug(F101,"dialhup mdmhup","",x);
2840: if (x > 0) { /* If it worked, */
2841: if (dialdpy)
2842: printf(" Modem hangup OK\r\n"); /* fine. */
2843: } else if (network) { /* If we're telnetted to */
2844: if (dialdpy) /* a modem server, just print a msg */
2845: printf(" Warning: modem hangup failed\r\n"); /* don't hangup! */
2846: return(0);
2847: } else { /* Otherwise */
2848: x = tthang(); /* Tell the OS to turn off DTR. */
2849: if (dialdpy) { /* DIAL DISPLAY ON? */
2850: if (x > 0) /* Yes, tell results from tthang() */
2851: printf(" Hangup OK\r\n");
2852: else if (x == 0)
2853: printf(" Hangup skipped\r\n");
2854: else
2855: perror(" Hangup error");
2856: }
2857: }
2858: } else if (dialdpy) printf(" Hangup skipped\r\n"); /* DIAL HANGUP OFF */
2859: return(x);
2860: }
2861:
2862: /*
2863: M D M H U P --
2864:
2865: Sends escape sequence to modem, then sends its hangup command. Returns:
2866: 0: If modem type is 0 (direct serial connection),
2867: or if modem type is < 0 (network connection),
2868: or if no action taken because DIAL MODEM-HANGUP is OFF)
2869: or because no hangup string for current modem type,
2870: or C-Kermit is in remote mode,
2871: or if action taken but there was no positive response from modem;
2872: 1: Success: modem is in command state and acknowledged the hangup command;
2873: -1: On modem command error.
2874: */
2875: int
2876: mdmhup() {
2877: #ifdef MDMHUP
2878: MDMINF *p; /* Modem info structure pointer */
2879: int m, x = 0;
2880:
2881: if (dialmhu == 0 || local == 0) /* If DIAL MODEM-HANGUP is OFF, */
2882: return(0); /* or not in local mode, fail. */
2883:
2884: #ifdef OS2
2885: /*
2886: In OS/2, if CARRIER is OFF, and there is indeed no carrier signal, any
2887: attempt to do i/o at this point can hang the program. This might be true
2888: for other operating systems too.
2889: */
2890: if (!network) { /* Not a network connection */
2891: m = ttgmdm(); /* Get modem signals */
2892: if ((m > -1) && (m & BM_DCD == 0)) /* Check for carrier */
2893: return(0); /* No carrier, skip the rest */
2894: }
2895: #endif /* OS2 */
2896:
2897: m = mdmtyp & 0xff; /* Get basic modem type (no bits!). */
2898: if ((m < 1) || (m > MAX_MDM)) /* If modem type not in range, */
2899: return(0); /* fail. */
2900: p = ptrtab[m-1]; /* Get modem info pointer */
2901: if (!(p->hup_str) || !*(p->hup_str)) { /* No hangup string? */
2902: debug(F100,"mdmhup no hup_str","",0); /* No, */
2903: return(0); /* fail. */
2904: } else {
2905: debug(F110,"mdmhup hup_str",p->hup_str,0); /* Yes. */
2906: if (p->esc_str && *(p->esc_str)) { /* Have escape sequence? */
2907: debug(F110,"mdmhup esc_str",p->esc_str,0);
2908: debug(F101,"mdmhup esc_time","",p->esc_time);
2909: if (ttpkt(speed,FLO_DIAL,parity) < 0) /* Condition line */
2910: return(-1); /* for dialing. */
2911: if (p->esc_time) /* If we have a guard time */
2912: msleep(p->esc_time); /* Pause for guard time */
2913: #ifdef NETCONN
2914: /* Send modem's escape sequence */
2915: if (network) { /* Must catch errors here. */
2916: if (ttol((CHAR *)(p->esc_str),(int)strlen(p->esc_str)) < 0)
2917: return(-1);
2918: } else {
2919: ttslow(p->esc_str,p->wake_rate); /* Send escape sequence */
2920: }
2921: #else
2922: ttslow(p->esc_str,p->wake_rate); /* Send escape sequence */
2923: #endif /* NETCONN */
2924: if (p->esc_time) /* Pause for guard time again */
2925: msleep(p->esc_time);
2926: msleep(500); /* Wait half a sec for echoes. */
2927: ttflui(); /* Flush response or echo, if any */
2928: }
2929: #ifdef NETCONN
2930: /* Send modem's hangup command */
2931: if (network) { /* Must catch errors here. */
2932: if (ttol((CHAR *)(p->hup_str),(int)strlen(p->hup_str)) < 0)
2933: return(-1);
2934: } else {
2935: ttslow(p->hup_str,p->wake_rate);
2936: }
2937: #else
2938: ttslow(p->hup_str,p->wake_rate); /* Now Send hangup string */
2939: #endif /* NETCONN */
2940: if (p->ok_fn) { /* Look for OK response */
2941: x = (*(p->ok_fn))(3,1); /* Give it 3 seconds, be strict. */
2942: debug(F101,"mdmhup hangup response","",x);
2943: } else { /* No OK function, */
2944: x = 1; /* so assume it worked */
2945: debug(F101,"mdmhup no ok_fn","",x);
2946: }
2947: return(x); /* Return OK function's return code. */
2948: }
2949: #else /* MDMHUP not defined. */
2950: return(0); /* Always fail. */
2951: #endif /* MDMHUP */
2952: }
2953:
2954: char * /* Let external routines ask */
2955: getdws(mdmtyp) int mdmtyp; { /* about dial init-string. */
2956: MDMINF * p;
2957: if ((mdmtyp & 0xff) < 1 || (mdmtyp & 0xff) > MAX_MDM)
2958: return("");
2959: p = ptrtab[(mdmtyp & 0xff) -1];
2960: return(dialini ? dialini : p->wake_str);
2961: }
2962:
2963: char *
2964: getdcs(mdmtyp) int mdmtyp; { /* Same deal for dial-command */
2965: MDMINF * p;
2966: if ((mdmtyp & 0xff) < 1 || (mdmtyp & 0xff) > MAX_MDM)
2967: return("");
2968: p = ptrtab[(mdmtyp & 0xff) -1];
2969: return(dialcmd ? dialcmd : p->dial_str);
2970: }
2971:
2972: #else /* NODIAL */
2973:
2974: char *dialv = "Dial Command Disabled";
2975:
2976: int /* To allow NODIAL versions to */
2977: mdmhup() { /* call mdmhup(), so calls to */
2978: return(0); /* mdmhup() need not be within */
2979: } /* #ifndef NODIAL conditionals */
2980:
2981: #endif /* NODIAL */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.