Commit | Line | Data |
---|---|---|
d34dfbc0 KB |
1 | /*- |
2 | * Copyright (c) 1985 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.proprietary.c% | |
6 | */ | |
7 | ||
a8e0ea6c | 8 | #ifndef lint |
d34dfbc0 KB |
9 | static char sccsid[] = "@(#)conn.c 5.17 (Berkeley) %G%"; |
10 | #endif /* not lint */ | |
55a580e3 | 11 | |
55a580e3 | 12 | #include <signal.h> |
941b257e | 13 | #include "uucp.h" |
55a580e3 SL |
14 | #include <setjmp.h> |
15 | #include <ctype.h> | |
55a580e3 | 16 | #include <errno.h> |
46b15d8a | 17 | #ifdef USG |
55a580e3 SL |
18 | #include <termio.h> |
19 | #include <fcntl.h> | |
20 | #endif | |
46b15d8a | 21 | #ifndef USG |
55a580e3 SL |
22 | #include <sgtty.h> |
23 | #endif | |
46b15d8a RC |
24 | #ifdef BSD4_2 |
25 | #include <sys/time.h> | |
26 | #else | |
27 | #include <time.h> | |
28 | #endif | |
55a580e3 SL |
29 | |
30 | #define MAXC 1000 | |
31 | ||
32 | extern jmp_buf Sjbuf; | |
46b15d8a | 33 | jmp_buf Cjbuf; |
1a85e9d2 | 34 | extern int errno, onesys; |
46b15d8a | 35 | extern char *sys_errlist[]; |
1a85e9d2 | 36 | extern char MaxGrade, DefMaxGrade; |
55a580e3 SL |
37 | |
38 | /* Parity control during login procedure */ | |
39 | #define P_ZERO 0 | |
40 | #define P_ONE 1 | |
41 | #define P_EVEN 2 | |
42 | #define P_ODD 3 | |
55a580e3 | 43 | |
46b15d8a RC |
44 | #define ABORT -2 |
45 | ||
46 | char *AbortOn = NULL; | |
47 | char par_tab[128]; /* must be power of two */ | |
48 | int linebaudrate; /* used for the sleep test in pk1.c */ | |
55a580e3 | 49 | int next_fd = -1; /* predicted fd to close interrupted opens */ |
2af814a5 JB |
50 | |
51 | char *PCP = "PCP"; /* PC Pursuit device type */ | |
01af9d69 JB |
52 | /* |
53 | * catch alarm routine for "expect". | |
55a580e3 | 54 | */ |
41654125 | 55 | void |
55a580e3 SL |
56 | alarmtr() |
57 | { | |
58 | signal(SIGALRM, alarmtr); | |
59 | if (next_fd >= 0) { | |
60 | if (close(next_fd)) | |
61 | logent("FAIL", "ACU LINE CLOSE"); | |
62 | next_fd = -1; | |
63 | } | |
64 | longjmp(Sjbuf, 1); | |
65 | } | |
66 | ||
2af814a5 JB |
67 | /* This template is for seismo to call ihnp4 |
68 | * the 3 lines marked ---> will be overwritten for the appropriate city | |
69 | */ | |
70 | #define PCP_BAUD 3 | |
71 | #define PCP_PHONE 4 | |
f43a5ec5 RA |
72 | #define PCP_CITY 14 |
73 | #define PCP_PASSWORD 16 | |
74 | #define PCP_RPHONE 20 | |
75 | #define NPCFIELDS 23 | |
2af814a5 JB |
76 | |
77 | static char *PCFlds[] = { | |
78 | "PC-PURSUIT", | |
79 | "Any", | |
80 | "ACU", | |
81 | "1200", | |
f43a5ec5 RA |
82 | CNULL, |
83 | CNULL, | |
84 | "P_ZERO", /* Telenet insists on zero parity */ | |
2af814a5 | 85 | "ABORT", |
f43a5ec5 RA |
86 | "BUSY", /* Abort on Busy Signal */ |
87 | CNULL, | |
88 | "\\d\\d\\r\\d\\r", /* Get telenet's attention */ | |
89 | "TERMINAL=~3-\r-TERM~3-\r-TERM~5", /* Terminal type ? */ | |
90 | "\\r", | |
91 | "@", /* telenet's prompt */ | |
92 | "D/DCWAS/21,telenetloginstring", /* overwritten later */ | |
93 | "PASSWORD", | |
94 | CNULL, /* telenet password */ | |
95 | "CONNECTED", /* We're now talking to a Hayes in the remote city */ | |
96 | "ATZ", /* Reset it */ | |
97 | "OK", | |
98 | "ATDT6907171", /* overwritten */ | |
99 | "CONNECT", | |
100 | "\\d\\r", /* We're in !*/ | |
101 | CNULL, | |
2af814a5 JB |
102 | }; |
103 | ||
f43a5ec5 | 104 | static char PCP_brand[25]; |
ac09522b RA |
105 | int Dcf = -1; |
106 | char *Flds[MAXC/10]; | |
107 | char LineType[10]; | |
108 | extern int LocalOnly; | |
2af814a5 | 109 | |
1a85e9d2 RC |
110 | /* |
111 | * place a telephone call to system and login, etc. | |
55a580e3 SL |
112 | * |
113 | * return codes: | |
114 | * CF_SYSTEM: don't know system | |
115 | * CF_TIME: wrong time to call | |
116 | * CF_DIAL: call failed | |
117 | * CF_NODEV: no devices available to place call | |
118 | * CF_LOGIN: login/password dialog failed | |
119 | * | |
120 | * >0 - file no. - connect ok | |
55a580e3 | 121 | */ |
55a580e3 SL |
122 | conn(system) |
123 | char *system; | |
124 | { | |
2af814a5 | 125 | int nf; |
1a85e9d2 | 126 | char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE]; |
55a580e3 SL |
127 | register FILE *fsys; |
128 | int fcode = 0; | |
129 | ||
130 | nf = 0; | |
55a580e3 SL |
131 | |
132 | fsys = fopen(SYSFILE, "r"); | |
7dd5932d RA |
133 | if (fsys == NULL) { |
134 | syslog(LOG_ERR, "fopen(%s) failed: %m", SYSFILE); | |
135 | cleanup(FAIL); | |
136 | } | |
55a580e3 | 137 | |
46b15d8a | 138 | DEBUG(4, "finds (%s) called\n", system); |
01af9d69 | 139 | keeplooking: |
46b15d8a | 140 | while((nf = finds(fsys, system, info, Flds)) > 0) { |
9313cec6 | 141 | strncpy(LineType, Flds[F_LINE], 10); |
46b15d8a | 142 | if (LocalOnly) { |
9313cec6 JB |
143 | if (strcmp("TCP", LineType) |
144 | && strcmp("DIR", LineType) | |
145 | && strcmp("LOCAL", LineType) ) { | |
2af814a5 JB |
146 | fcode = CF_TIME; |
147 | continue; | |
148 | } | |
46b15d8a | 149 | } |
941b257e | 150 | sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname); |
1a85e9d2 | 151 | if (!onesys && MaxGrade != DefMaxGrade && |
2af814a5 JB |
152 | !iswrk(file, "chk", Spool, wkpre)) { |
153 | fcode = CF_TIME; | |
154 | continue; | |
55a580e3 | 155 | } |
2af814a5 | 156 | /* For GTE's PC Pursuit */ |
9313cec6 | 157 | if (snccmp(LineType, PCP) == SAME) { |
2af814a5 JB |
158 | FILE *dfp; |
159 | int status; | |
160 | static struct Devices dev; | |
f43a5ec5 | 161 | |
2af814a5 | 162 | dfp = fopen(DEVFILE, "r"); |
7dd5932d RA |
163 | if (dfp == NULL) { |
164 | syslog(LOG_ERR, "fopen(%s) failed: %m", | |
165 | DEVFILE); | |
166 | cleanup(FAIL); | |
167 | } | |
2af814a5 JB |
168 | while ((status=rddev(dfp, &dev)) != FAIL |
169 | && strcmp(PCP, dev.D_type) != SAME) | |
170 | ; | |
171 | fclose(dfp); | |
172 | if (status == FAIL) | |
173 | continue; | |
174 | if (mlock(PCP) == FAIL) { | |
175 | fcode = CF_NODEV; | |
176 | logent("DEVICE", "NO"); | |
177 | continue; | |
178 | } | |
179 | PCFlds[PCP_BAUD] = dev.D_class; | |
180 | PCFlds[PCP_PHONE] = dev.D_calldev; | |
f43a5ec5 RA |
181 | sprintf(PCFlds[PCP_CITY], "c d/%s%s,%s", |
182 | Flds[F_CLASS], | |
183 | index(Flds[F_CLASS], '/') == NULL ? "/12" : "", | |
184 | dev.D_arg[D_CHAT]); | |
185 | PCFlds[PCP_PASSWORD] = dev.D_line; | |
186 | strncpy(&PCFlds[PCP_RPHONE][4], Flds[F_PHONE], 7); | |
2af814a5 | 187 | strncpy(PCP_brand, dev.D_brand, sizeof(PCP_brand)); |
f43a5ec5 RA |
188 | if ((fcode = getto(PCFlds)) < 0) { |
189 | rmlock(PCP); | |
2af814a5 | 190 | continue; |
f43a5ec5 | 191 | } |
2af814a5 JB |
192 | Dcf = fcode; |
193 | fcode = login(NPCFIELDS, PCFlds, Dcf); | |
f43a5ec5 RA |
194 | if (fcode == SUCCESS) |
195 | break; | |
196 | fcode = CF_DIAL; | |
197 | rmlock(PCP); | |
198 | /* end PC Pursuit */ | |
199 | } else if ((fcode = getto(Flds)) > 0) { | |
200 | Dcf = fcode; | |
2af814a5 | 201 | break; |
f43a5ec5 | 202 | } |
55a580e3 | 203 | } |
55a580e3 | 204 | |
01af9d69 JB |
205 | if (nf <= 0) { |
206 | fclose(fsys); | |
46b15d8a | 207 | return fcode ? fcode : nf; |
01af9d69 | 208 | } |
55a580e3 | 209 | |
2af814a5 | 210 | |
2af814a5 JB |
211 | if (fcode >= 0) { |
212 | DEBUG(4, "login %s\n", "called"); | |
ac09522b | 213 | setproctitle("login"); |
f43a5ec5 | 214 | fcode = login(nf, Flds, Dcf); } |
2af814a5 | 215 | if (fcode < 0) { |
55a580e3 | 216 | clsacu(); |
2af814a5 | 217 | if (fcode == ABORT) { |
01af9d69 JB |
218 | fcode = CF_DIAL; |
219 | goto keeplooking; | |
220 | } else { | |
221 | fclose(fsys); | |
941b257e | 222 | return CF_LOGIN; |
01af9d69 | 223 | } |
55a580e3 | 224 | } |
01af9d69 | 225 | fclose(fsys); |
2af814a5 JB |
226 | fioclex(Dcf); |
227 | return Dcf; | |
55a580e3 SL |
228 | } |
229 | ||
ac09522b RA |
230 | int nulldev(); |
231 | int (*CU_end)() = nulldev; | |
232 | ||
01af9d69 JB |
233 | /* |
234 | * connect to remote machine | |
55a580e3 SL |
235 | * |
236 | * return codes: | |
237 | * >0 - file number - ok | |
238 | * FAIL - failed | |
239 | */ | |
55a580e3 SL |
240 | getto(flds) |
241 | register char *flds[]; | |
242 | { | |
243 | register struct condev *cd; | |
21038734 | 244 | int diropn(); |
01af9d69 | 245 | char *line; |
55a580e3 | 246 | |
46b15d8a | 247 | DEBUG(4, "getto: call no. %s ", flds[F_PHONE]); |
55a580e3 SL |
248 | DEBUG(4, "for sys %s\n", flds[F_NAME]); |
249 | ||
01af9d69 JB |
250 | if (snccmp(flds[F_LINE], "LOCAL") == SAME) |
251 | line = "ACU"; | |
252 | else | |
253 | line = flds[F_LINE]; | |
254 | #ifdef DIALINOUT | |
255 | if (snccmp(line, "ACU") != SAME) | |
256 | reenable(); | |
257 | #endif DIALINOUT | |
55a580e3 | 258 | CU_end = nulldev; |
2af814a5 JB |
259 | if (snccmp(line, PCP) == SAME) { |
260 | for(cd = condevs; cd->CU_meth != NULL; cd++) { | |
261 | if (snccmp(PCP_brand, cd->CU_brand) == SAME) { | |
262 | CU_end = cd->CU_clos; | |
263 | return diropn(flds); | |
264 | } | |
55a580e3 | 265 | } |
2af814a5 JB |
266 | logent(PCP_brand, "UNSUPPORTED ACU TYPE"); |
267 | } else { | |
268 | for (cd = condevs; cd->CU_meth != NULL; cd++) { | |
269 | if (snccmp(cd->CU_meth, line) == SAME) { | |
270 | DEBUG(4, "Using %s to call\n", cd->CU_meth); | |
271 | return (*(cd->CU_gen))(flds); | |
272 | } | |
273 | } | |
274 | DEBUG(1, "Can't find %s, assuming DIR\n", flds[F_LINE]); | |
55a580e3 | 275 | } |
46b15d8a RC |
276 | return diropn(flds); /* search failed, so use direct */ |
277 | } | |
55a580e3 | 278 | |
01af9d69 JB |
279 | /* |
280 | * close call unit | |
55a580e3 SL |
281 | * |
282 | * return codes: none | |
283 | */ | |
55a580e3 SL |
284 | clsacu() |
285 | { | |
46b15d8a RC |
286 | /* make *sure* Dcf is no longer exclusive. |
287 | * Otherwise dual call-in/call-out modems could get stuck. | |
288 | * Unfortunately, doing this here is not ideal, but it is the | |
289 | * easiest place to put the call. | |
290 | * Hopefully everyone honors the LCK protocol, of course | |
291 | */ | |
2af814a5 | 292 | #ifdef TIOCNXCL |
941b257e JB |
293 | if (!IsTcpIp && Dcf >= 0 && ioctl(Dcf, TIOCNXCL, STBNULL) < 0) |
294 | DEBUG(5, "clsacu ioctl %s\n", sys_errlist[errno]); | |
46b15d8a RC |
295 | #endif |
296 | if (setjmp(Sjbuf)) | |
297 | logent(Rmtname, "CLOSE TIMEOUT"); | |
298 | else { | |
299 | signal(SIGALRM, alarmtr); | |
300 | alarm(20); | |
301 | (*(CU_end))(Dcf); | |
302 | alarm(0); | |
303 | } | |
55a580e3 SL |
304 | if (close(Dcf) == 0) { |
305 | DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf); | |
306 | logent("clsacu", "NOT CLOSED by CU_clos"); | |
307 | } | |
308 | Dcf = -1; | |
309 | CU_end = nulldev; | |
310 | } | |
311 | ||
01af9d69 JB |
312 | /* |
313 | * expand phone number for given prefix and number | |
55a580e3 | 314 | */ |
55a580e3 SL |
315 | exphone(in, out) |
316 | register char *in, *out; | |
317 | { | |
318 | FILE *fn; | |
319 | char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH]; | |
320 | char buf[BUFSIZ]; | |
321 | register char *s1; | |
322 | ||
46b15d8a | 323 | if (!isascii(*in) || !isalpha(*in)) { |
55a580e3 SL |
324 | strcpy(out, in); |
325 | return; | |
326 | } | |
327 | ||
328 | s1=pre; | |
46b15d8a | 329 | while (isascii(*in) && isalpha(*in)) |
55a580e3 SL |
330 | *s1++ = *in++; |
331 | *s1 = '\0'; | |
332 | s1 = npart; | |
333 | while (*in != '\0') | |
334 | *s1++ = *in++; | |
335 | *s1 = '\0'; | |
336 | ||
337 | tpre[0] = '\0'; | |
338 | if ((fn = fopen(DIALFILE, "r")) == NULL) | |
339 | DEBUG(2, "CAN'T OPEN %s\n", DIALFILE); | |
340 | else { | |
341 | while (cfgets(buf, BUFSIZ, fn)) { | |
46b15d8a RC |
342 | if (sscanf(buf, "%s%s", p, tpre) != 2) |
343 | continue; | |
55a580e3 SL |
344 | if (strcmp(p, pre) == SAME) |
345 | goto found; | |
346 | tpre[0] = '\0'; | |
347 | } | |
348 | DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre); | |
349 | found:; | |
350 | fclose(fn); | |
351 | } | |
352 | ||
353 | strcpy(out, tpre); | |
354 | strcat(out, npart); | |
55a580e3 SL |
355 | } |
356 | ||
1a85e9d2 RC |
357 | /* |
358 | * read and decode a line from device file | |
55a580e3 SL |
359 | * |
360 | * return code - FAIL at end-of file; 0 otherwise | |
361 | */ | |
55a580e3 SL |
362 | rddev(fp, dev) |
363 | register struct Devices *dev; | |
364 | FILE *fp; | |
365 | { | |
46b15d8a RC |
366 | register int na; |
367 | ||
368 | if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp)) | |
369 | return FAIL; | |
370 | na = getargs(dev->D_argbfr, dev->D_arg, 20); | |
7dd5932d RA |
371 | if (na < 4) { |
372 | syslog(LOG_ERR, "%s: invalid device entry", dev->D_argbfr); | |
373 | cleanup(FAIL); | |
374 | } | |
46b15d8a RC |
375 | if (na == 4) { |
376 | dev->D_brand = ""; | |
377 | na++; | |
378 | } | |
55a580e3 | 379 | dev->D_speed = atoi(fdig(dev->D_class)); |
46b15d8a RC |
380 | dev->D_numargs = na; |
381 | return 0; | |
55a580e3 SL |
382 | } |
383 | ||
1a85e9d2 RC |
384 | /* |
385 | * set system attribute vector | |
55a580e3 SL |
386 | * |
387 | * return codes: | |
388 | * >0 - number of arguments in vector - succeeded | |
389 | * CF_SYSTEM - system name not found | |
390 | * CF_TIME - wrong time to call | |
391 | */ | |
55a580e3 SL |
392 | finds(fsys, sysnam, info, flds) |
393 | char *sysnam, info[], *flds[]; | |
394 | FILE *fsys; | |
395 | { | |
55a580e3 SL |
396 | int na; |
397 | int fcode = 0; | |
398 | ||
399 | /* format of fields | |
400 | * 0 name; | |
401 | * 1 time | |
402 | * 2 acu/hardwired | |
403 | * 3 speed | |
404 | * etc | |
405 | */ | |
406 | while (cfgets(info, MAXC, fsys) != NULL) { | |
46b15d8a | 407 | na = getargs(info, flds, MAXC/10); |
941b257e | 408 | if (strncmp(sysnam, flds[F_NAME], MAXBASENAME) != SAME) |
55a580e3 | 409 | continue; |
1a85e9d2 | 410 | if (ifdate(flds[F_TIME]) != FAIL) |
55a580e3 | 411 | /* found a good entry */ |
46b15d8a | 412 | return na; |
55a580e3 SL |
413 | DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]); |
414 | fcode = CF_TIME; | |
415 | } | |
46b15d8a | 416 | return fcode ? fcode : CF_SYSTEM; |
55a580e3 SL |
417 | } |
418 | ||
1a85e9d2 RC |
419 | /* |
420 | * do login conversation | |
55a580e3 | 421 | * |
941b257e | 422 | * return codes: SUCCESS | FAIL |
55a580e3 | 423 | */ |
55a580e3 SL |
424 | login(nf, flds, fn) |
425 | register char *flds[]; | |
426 | int nf, fn; | |
427 | { | |
428 | register char *want, *altern; | |
55a580e3 SL |
429 | int k, ok; |
430 | ||
7dd5932d RA |
431 | if (nf < 4) { |
432 | syslog(LOG_ERR, "Too few log fields: %d", nf); | |
433 | cleanup(FAIL); | |
434 | } | |
46b15d8a RC |
435 | if (setjmp(Cjbuf)) |
436 | return FAIL; | |
437 | AbortOn = NULL; | |
55a580e3 SL |
438 | for (k = F_LOGIN; k < nf; k += 2) { |
439 | want = flds[k]; | |
f43a5ec5 RA |
440 | if (want == NULL) |
441 | want = ""; | |
55a580e3 | 442 | ok = FAIL; |
46b15d8a | 443 | while (ok != SUCCESS) { |
55a580e3 SL |
444 | altern = index(want, '-'); |
445 | if (altern != NULL) | |
446 | *altern++ = '\0'; | |
46b15d8a RC |
447 | if (strcmp(want, "ABORT") == 0) { |
448 | AbortOn = flds[k+1]; | |
449 | DEBUG(4, "ABORT ON: %s\n", AbortOn); | |
450 | goto nextfield; | |
55a580e3 | 451 | } |
2af814a5 | 452 | DEBUG(4, "wanted \"%s\"\n", want); |
46b15d8a RC |
453 | ok = expect(want, fn); |
454 | DEBUG(4, "got: %s\n", ok ? "?" : "that"); | |
455 | if (ok == FAIL) { | |
456 | if (altern == NULL) { | |
457 | logent("LOGIN", _FAILED); | |
458 | return FAIL; | |
459 | } | |
460 | want = index(altern, '-'); | |
461 | if (want != NULL) | |
462 | *want++ = '\0'; | |
463 | sendthem(altern, fn); | |
464 | } else | |
465 | if (ok == ABORT) { | |
f43a5ec5 RA |
466 | char sbuf[MAXFULLNAME]; |
467 | sprintf(sbuf, "LOGIN ABORTED on \"%s\"", AbortOn); | |
468 | logent(sbuf, _FAILED); | |
941b257e | 469 | return ABORT; |
46b15d8a | 470 | } |
55a580e3 | 471 | } |
46b15d8a | 472 | sleep(1); |
55a580e3 SL |
473 | if (k+1 < nf) |
474 | sendthem(flds[k+1], fn); | |
46b15d8a | 475 | nextfield: ; |
55a580e3 | 476 | } |
46b15d8a | 477 | return SUCCESS; |
55a580e3 SL |
478 | } |
479 | ||
480 | ||
46b15d8a | 481 | /* conditional table generation to support odd speeds */ |
55a580e3 SL |
482 | struct sg_spds {int sp_val, sp_name;} spds[] = { |
483 | #ifdef B50 | |
484 | { 50, B50}, | |
485 | #endif | |
486 | #ifdef B75 | |
487 | { 75, B75}, | |
488 | #endif | |
489 | #ifdef B110 | |
490 | { 110, B110}, | |
491 | #endif | |
492 | #ifdef B150 | |
493 | { 150, B150}, | |
494 | #endif | |
495 | #ifdef B200 | |
496 | { 200, B200}, | |
497 | #endif | |
498 | #ifdef B300 | |
499 | { 300, B300}, | |
500 | #endif | |
501 | #ifdef B600 | |
502 | {600, B600}, | |
503 | #endif | |
504 | #ifdef B1200 | |
505 | {1200, B1200}, | |
506 | #endif | |
507 | #ifdef B1800 | |
508 | {1800, B1800}, | |
509 | #endif | |
510 | #ifdef B2000 | |
511 | {2000, B2000}, | |
512 | #endif | |
513 | #ifdef B2400 | |
514 | {2400, B2400}, | |
515 | #endif | |
516 | #ifdef B3600 | |
517 | {3600, B3600}, | |
518 | #endif | |
519 | #ifdef B4800 | |
520 | {4800, B4800}, | |
521 | #endif | |
522 | #ifdef B7200 | |
523 | {7200, B7200}, | |
524 | #endif | |
525 | #ifdef B9600 | |
526 | {9600, B9600}, | |
527 | #endif | |
528 | #ifdef B19200 | |
46b15d8a RC |
529 | {19200, B19200}, |
530 | #endif | |
531 | #ifdef EXTA | |
532 | {19200, EXTA}, | |
55a580e3 SL |
533 | #endif |
534 | {0, 0} | |
535 | }; | |
536 | ||
1a85e9d2 RC |
537 | /* |
538 | * set speed/echo/mode... | |
55a580e3 SL |
539 | * |
540 | * return codes: none | |
541 | */ | |
55a580e3 SL |
542 | fixline(tty, spwant) |
543 | int tty, spwant; | |
544 | { | |
46b15d8a | 545 | #ifdef USG |
55a580e3 | 546 | struct termio ttbuf; |
46b15d8a | 547 | #else !USG |
55a580e3 | 548 | struct sgttyb ttbuf; |
46b15d8a | 549 | #endif !USG |
55a580e3 SL |
550 | register struct sg_spds *ps; |
551 | int speed = -1; | |
55a580e3 SL |
552 | |
553 | for (ps = spds; ps->sp_val; ps++) | |
554 | if (ps->sp_val == spwant) | |
555 | speed = ps->sp_name; | |
7dd5932d RA |
556 | if (speed < 0) { |
557 | syslog(LOG_ERR, "unrecognized speed: %d", speed); | |
558 | cleanup(FAIL); | |
559 | } | |
46b15d8a | 560 | #ifdef USG |
941b257e JB |
561 | if (ioctl(tty, TCGETA, &ttbuf) < 0) |
562 | return FAIL; | |
55a580e3 SL |
563 | /* ttbuf.sg_flags = (ANYP|RAW); |
564 | ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */ | |
565 | ttbuf.c_iflag = (ushort)0; | |
566 | ttbuf.c_oflag = (ushort)0; | |
567 | ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD); | |
568 | ttbuf.c_lflag = (ushort)0; | |
569 | ttbuf.c_cc[VMIN] = 6; | |
570 | ttbuf.c_cc[VTIME] = 1; | |
941b257e JB |
571 | if (ioctl(tty, TCSETA, &ttbuf) < 0) |
572 | return FAIL; | |
46b15d8a | 573 | #else !USG |
941b257e JB |
574 | if (ioctl(tty, TIOCGETP, &ttbuf) < 0) |
575 | return FAIL; | |
55a580e3 SL |
576 | ttbuf.sg_flags = (ANYP|RAW); |
577 | ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; | |
941b257e JB |
578 | if (ioctl(tty, TIOCSETP, &ttbuf) < 0) |
579 | return FAIL; | |
55a580e3 | 580 | #endif |
46b15d8a | 581 | #ifndef USG |
941b257e JB |
582 | if (ioctl(tty, TIOCHPCL, STBNULL) < 0) |
583 | return FAIL; | |
584 | if (ioctl(tty, TIOCEXCL, STBNULL) < 0) | |
585 | return FAIL; | |
55a580e3 | 586 | #endif |
46b15d8a | 587 | linebaudrate = spwant; |
941b257e | 588 | return SUCCESS; |
55a580e3 SL |
589 | } |
590 | ||
46b15d8a | 591 | #define MR 100 |
55a580e3 | 592 | |
1a85e9d2 RC |
593 | /* |
594 | * look for expected string | |
55a580e3 SL |
595 | * |
596 | * return codes: | |
597 | * 0 - found | |
598 | * FAIL - lost line or too many characters read | |
599 | * some character - timed out | |
600 | */ | |
55a580e3 SL |
601 | expect(str, fn) |
602 | register char *str; | |
603 | int fn; | |
604 | { | |
50cde384 | 605 | char rdvec[MR]; |
46b15d8a RC |
606 | register char *rp = rdvec, *strptr; |
607 | int kr, cnt_char; | |
55a580e3 | 608 | char nextch; |
01af9d69 | 609 | int timo = MAXMSGTIME; |
55a580e3 | 610 | |
46b15d8a RC |
611 | if (*str == '\0' || strcmp(str, "\"\"") == SAME) |
612 | return SUCCESS; | |
613 | /* Cleanup str, convert \0xx strings to one char */ | |
614 | for (strptr = str; *strptr; strptr++) { | |
615 | if (*strptr == '\\') | |
616 | switch(*++strptr) { | |
617 | case 's': | |
618 | DEBUG(5, "BLANK\n", CNULL); | |
ac09522b | 619 | strptr--; |
46b15d8a | 620 | *strptr = ' '; |
ac09522b | 621 | strcpy(&strptr[1], &strptr[4]); |
46b15d8a RC |
622 | break; |
623 | default: | |
624 | strptr--; /* back up to backslash */ | |
625 | sscanf(strptr + 1,"%o", &cnt_char); | |
626 | DEBUG(6, "BACKSLASHED %02xH\n", cnt_char); | |
627 | *strptr = (char) (cnt_char); | |
628 | strcpy(&strptr[1], &strptr[4]); | |
629 | } | |
55a580e3 | 630 | } |
46b15d8a | 631 | |
01af9d69 JB |
632 | strptr = index(str, '~'); |
633 | if (strptr != NULL) { | |
634 | *strptr++ = '\0'; | |
635 | timo = atoi(strptr); | |
636 | if (timo <= 0) | |
637 | timo = MAXMSGTIME; | |
638 | } | |
639 | ||
46b15d8a RC |
640 | if (setjmp(Sjbuf)) |
641 | return FAIL; | |
55a580e3 | 642 | signal(SIGALRM, alarmtr); |
01af9d69 JB |
643 | alarm(timo); |
644 | *rp = 0; | |
55a580e3 | 645 | while (notin(str, rdvec)) { |
2af814a5 | 646 | int c; |
46b15d8a RC |
647 | if(AbortOn != NULL && !notin(AbortOn, rdvec)) { |
648 | DEBUG(1, "Call aborted on '%s'\n", AbortOn); | |
649 | alarm(0); | |
650 | return ABORT; | |
651 | } | |
55a580e3 SL |
652 | kr = read(fn, &nextch, 1); |
653 | if (kr <= 0) { | |
654 | alarm(0); | |
655 | DEBUG(4, "lost line kr - %d\n, ", kr); | |
656 | logent("LOGIN", "LOST LINE"); | |
46b15d8a | 657 | return FAIL; |
55a580e3 | 658 | } |
55a580e3 | 659 | c = nextch & 0177; |
2af814a5 JB |
660 | if (c == '\0') |
661 | continue; | |
662 | DEBUG(4, (isprint(c) || isspace(c)) ? "%c" : "\\%03o", c); | |
663 | *rp++ = c; | |
55a580e3 | 664 | if (rp >= rdvec + MR) { |
46b15d8a RC |
665 | register char *p; |
666 | for (p = rdvec+MR/2; p < rp; p++) | |
667 | *(p-MR/2) = *p; | |
668 | rp -= MR/2; | |
55a580e3 SL |
669 | } |
670 | *rp = '\0'; | |
671 | } | |
672 | alarm(0); | |
46b15d8a | 673 | return SUCCESS; |
55a580e3 SL |
674 | } |
675 | ||
676 | ||
677 | /* | |
678 | * Determine next file descriptor that would be allocated. | |
679 | * This permits later closing of a file whose open was interrupted. | |
680 | * It is a UNIX kernel problem, but it has to be handled. | |
681 | * unc!smb (Steve Bellovin) probably first discovered it. | |
682 | */ | |
683 | getnextfd() | |
684 | { | |
685 | close(next_fd = open("/", 0)); | |
686 | } | |
687 | ||
46b15d8a RC |
688 | /* |
689 | * send line of login sequence | |
55a580e3 SL |
690 | * |
691 | * return codes: none | |
692 | */ | |
55a580e3 SL |
693 | sendthem(str, fn) |
694 | register char *str; | |
695 | int fn; | |
696 | { | |
697 | register char *strptr; | |
698 | int i, n, cr = 1; | |
46b15d8a | 699 | register char c; |
55a580e3 SL |
700 | static int p_init = 0; |
701 | ||
2af814a5 | 702 | DEBUG(5, "send \"%s\"\n", str); |
55a580e3 SL |
703 | |
704 | if (!p_init) { | |
705 | p_init++; | |
7dd5932d | 706 | bld_partab(P_ZERO); |
55a580e3 SL |
707 | } |
708 | ||
709 | if (prefix("BREAK", str)) { | |
710 | sscanf(&str[5], "%1d", &i); | |
711 | if (i <= 0 || i > 10) | |
712 | i = 3; | |
713 | /* send break */ | |
714 | genbrk(fn, i); | |
715 | return; | |
716 | } | |
717 | ||
718 | if (prefix("PAUSE", str)) { | |
719 | sscanf(&str[5], "%1d", &i); | |
720 | if (i <= 0 || i > 10) | |
721 | i = 3; | |
722 | /* pause for a while */ | |
723 | sleep((unsigned)i); | |
724 | return; | |
725 | } | |
726 | ||
727 | if (strcmp(str, "EOT") == SAME) { | |
728 | p_chwrite(fn, '\04'); | |
729 | return; | |
730 | } | |
731 | ||
55a580e3 | 732 | /* Send a '\n' */ |
2af814a5 JB |
733 | if (strcmp(str, "LF") == SAME) { |
734 | p_chwrite(fn, '\n'); | |
735 | return; | |
736 | } | |
55a580e3 SL |
737 | |
738 | /* Send a '\r' */ | |
2af814a5 JB |
739 | if (strcmp(str, "CR") == SAME) { |
740 | p_chwrite(fn, '\r'); | |
741 | return; | |
742 | } | |
55a580e3 SL |
743 | |
744 | /* Set parity as needed */ | |
745 | if (strcmp(str, "P_ZERO") == SAME) { | |
746 | bld_partab(P_ZERO); | |
747 | return; | |
748 | } | |
749 | if (strcmp(str, "P_ONE") == SAME) { | |
750 | bld_partab(P_ONE); | |
751 | return; | |
752 | } | |
753 | if (strcmp(str, "P_EVEN") == SAME) { | |
754 | bld_partab(P_EVEN); | |
755 | return; | |
756 | } | |
757 | if (strcmp(str, "P_ODD") == SAME) { | |
758 | bld_partab(P_ODD); | |
759 | return; | |
760 | } | |
761 | ||
762 | /* If "", just send '\r' */ | |
46b15d8a RC |
763 | if (strcmp(str, "\"\"") == SAME) { |
764 | p_chwrite(fn, '\r'); | |
765 | return; | |
766 | } | |
767 | ||
2af814a5 JB |
768 | strptr = str; |
769 | while ((c = *strptr++) != '\0') { | |
46b15d8a RC |
770 | if (c == '\\') { |
771 | switch(*strptr++) { | |
2af814a5 JB |
772 | case '\0': |
773 | DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL); | |
774 | --strptr; | |
775 | continue; | |
46b15d8a RC |
776 | case 's': |
777 | DEBUG(5, "BLANK\n", CNULL); | |
2af814a5 | 778 | c = ' '; |
46b15d8a RC |
779 | break; |
780 | case 'd': | |
781 | DEBUG(5, "DELAY\n", CNULL); | |
782 | sleep(1); | |
783 | continue; | |
2af814a5 JB |
784 | case 'n': |
785 | DEBUG(5, "NEW LINE\n", CNULL); | |
786 | c = '\n'; | |
787 | break; | |
46b15d8a RC |
788 | case 'r': |
789 | DEBUG(5, "RETURN\n", CNULL); | |
2af814a5 | 790 | c = '\r'; |
46b15d8a RC |
791 | break; |
792 | case 'b': | |
793 | if (isdigit(*strptr)) { | |
794 | i = (*strptr++ - '0'); | |
795 | if (i <= 0 || i > 10) | |
796 | i = 3; | |
797 | } else | |
55a580e3 | 798 | i = 3; |
46b15d8a RC |
799 | /* send break */ |
800 | genbrk(fn, i); | |
801 | if (*strptr == '\0') | |
802 | cr = 0; | |
55a580e3 | 803 | continue; |
46b15d8a RC |
804 | case 'c': |
805 | if (*strptr == '\0') { | |
806 | DEBUG(5, "NO CR\n", CNULL); | |
807 | cr = 0; | |
2af814a5 JB |
808 | } else |
809 | DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL); | |
55a580e3 | 810 | continue; |
2af814a5 | 811 | #define isoctal(x) ((x >= '0') && (x <= '7')) |
46b15d8a | 812 | default: |
2af814a5 | 813 | if (isoctal(strptr[-1])) { |
46b15d8a RC |
814 | i = 0; |
815 | n = 0; | |
2af814a5 JB |
816 | --strptr; |
817 | while (isoctal(*strptr) && ++n <= 3) | |
818 | i = i * 8 + (*strptr++ - '0'); | |
819 | DEBUG(5, "\\%o\n", i); | |
46b15d8a RC |
820 | p_chwrite(fn, (char)i); |
821 | continue; | |
822 | } | |
55a580e3 | 823 | } |
2af814a5 JB |
824 | } |
825 | p_chwrite(fn, c); | |
55a580e3 SL |
826 | } |
827 | ||
55a580e3 SL |
828 | if (cr) |
829 | p_chwrite(fn, '\r'); | |
830 | return; | |
831 | } | |
832 | ||
833 | p_chwrite(fd, c) | |
834 | int fd; | |
46b15d8a | 835 | char c; |
55a580e3 | 836 | { |
46b15d8a RC |
837 | c = par_tab[c&0177]; |
838 | if (write(fd, &c, 1) != 1) { | |
839 | logent(sys_errlist[errno], "BAD WRITE"); | |
840 | longjmp(Cjbuf, 2); | |
841 | } | |
55a580e3 SL |
842 | } |
843 | ||
844 | /* | |
845 | * generate parity table for use by p_chwrite. | |
846 | */ | |
847 | bld_partab(type) | |
848 | int type; | |
849 | { | |
850 | register int i, j, n; | |
851 | ||
852 | for (i = 0; i < sizeof(par_tab); i++) { | |
853 | n = 0; | |
854 | for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j) | |
855 | n++; | |
856 | par_tab[i] = i; | |
857 | if (type == P_ONE | |
858 | || (type == P_EVEN && (n&01) != 0) | |
859 | || (type == P_ODD && (n&01) == 0)) | |
860 | par_tab[i] |= sizeof(par_tab); | |
861 | } | |
862 | } | |
863 | ||
1a85e9d2 RC |
864 | /* |
865 | * check for occurrence of substring "sh" | |
55a580e3 SL |
866 | * |
867 | * return codes: | |
868 | * 0 - found the string | |
869 | * 1 - not in the string | |
870 | */ | |
55a580e3 SL |
871 | notin(sh, lg) |
872 | register char *sh, *lg; | |
873 | { | |
874 | while (*lg != '\0') { | |
55a580e3 | 875 | if (wprefix(sh, lg)) |
1a85e9d2 | 876 | return 0; |
55a580e3 SL |
877 | else |
878 | lg++; | |
879 | } | |
1a85e9d2 | 880 | return 1; |
55a580e3 SL |
881 | } |
882 | ||
1a85e9d2 | 883 | /* |
941b257e | 884 | * Allow multiple date specifications separated by ','. |
55a580e3 | 885 | */ |
1a85e9d2 RC |
886 | ifdate(p) |
887 | register char *p; | |
55a580e3 | 888 | { |
2af814a5 | 889 | register char *np; |
1a85e9d2 | 890 | register int ret, g; |
941b257e JB |
891 | int rtime, i; |
892 | ||
893 | /* pick up retry time for failures */ | |
894 | /* global variable Retrytime is set here */ | |
895 | if ((np = index(p, ';')) == NULL) { | |
896 | Retrytime = RETRYTIME; | |
897 | } else { | |
898 | i = sscanf(np+1, "%d", &rtime); | |
899 | if (i < 1 || rtime < 0) | |
900 | rtime = 5; | |
901 | Retrytime = rtime * 60; | |
902 | } | |
1a85e9d2 RC |
903 | |
904 | ret = FAIL; | |
905 | MaxGrade = '\0'; | |
906 | do { | |
941b257e JB |
907 | np = strpbrk(p, ",|"); /* prefer , but allow | for compat */ |
908 | if (np) | |
909 | *np = '\0'; | |
1a85e9d2 RC |
910 | g = ifadate(p); |
911 | DEBUG(11,"ifadate returns %o\n", g); | |
912 | if (g != FAIL) { | |
913 | ret = SUCCESS; | |
914 | if (g > MaxGrade) | |
915 | MaxGrade = g; | |
916 | } | |
941b257e JB |
917 | if (np) |
918 | *np = ','; | |
919 | p = np + 1; | |
920 | } while (np); | |
921 | if (MaxGrade == '\0') | |
922 | MaxGrade = DefMaxGrade; | |
1a85e9d2 | 923 | return ret; |
55a580e3 SL |
924 | } |
925 | ||
1a85e9d2 RC |
926 | /* |
927 | * this routine will check a string (string) | |
55a580e3 SL |
928 | * like "MoTu0800-1730" to see if the present |
929 | * time is within the given limits. | |
930 | * SIDE EFFECT - Retrytime is set | |
931 | * | |
55a580e3 SL |
932 | * return codes: |
933 | * 0 - not within limits | |
934 | * 1 - within limits | |
935 | */ | |
936 | ||
1a85e9d2 RC |
937 | ifadate(string) |
938 | char *string; | |
55a580e3 SL |
939 | { |
940 | static char *days[]={ | |
941 | "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0 | |
942 | }; | |
943 | time_t clock; | |
1a85e9d2 | 944 | register char *s = string; |
46b15d8a | 945 | int i, tl, th, tn, dayok=0; |
55a580e3 SL |
946 | struct tm *localtime(); |
947 | struct tm *tp; | |
1a85e9d2 | 948 | char *p, MGrade; |
55a580e3 | 949 | |
941b257e | 950 | if ((p = index(s, '/')) == NULL) |
1a85e9d2 RC |
951 | MGrade = DefMaxGrade; |
952 | else | |
953 | MGrade = p[1]; | |
954 | ||
55a580e3 SL |
955 | time(&clock); |
956 | tp = localtime(&clock); | |
46b15d8a | 957 | while (isascii(*s) && isalpha(*s)) { |
55a580e3 SL |
958 | for (i = 0; days[i]; i++) { |
959 | if (prefix(days[i], s)) | |
960 | if (tp->tm_wday == i) | |
961 | dayok = 1; | |
962 | } | |
963 | ||
964 | if (prefix("Wk", s)) | |
965 | if (tp->tm_wday >= 1 && tp->tm_wday <= 5) | |
966 | dayok = 1; | |
967 | if (prefix("Any", s)) | |
968 | dayok = 1; | |
46b15d8a RC |
969 | if (prefix("Evening", s)) { |
970 | /* Sat or Sun */ | |
971 | if (tp->tm_wday == 6 || tp->tm_wday == 0 | |
972 | || tp->tm_hour >= 17 || tp->tm_hour < 8) | |
973 | dayok = 1; | |
974 | } | |
975 | if (prefix("Night", s)) { | |
976 | if (tp->tm_wday == 6 /* Sat */ | |
1a85e9d2 RC |
977 | || tp->tm_hour >= 23 || tp->tm_hour < 8 |
978 | /* Sunday before 5pm */ | |
979 | || (tp->tm_wday == 0 && tp->tm_hour < 17)) | |
46b15d8a RC |
980 | dayok = 1; |
981 | } | |
2af814a5 JB |
982 | if (prefix("NonPeak", s)) { /* For Tymnet and PC Pursuit */ |
983 | /* Sat or Sun */ | |
984 | if (tp->tm_wday == 6 || tp->tm_wday == 0 | |
985 | || tp->tm_hour >= 18 || tp->tm_hour < 7) | |
986 | dayok = 1; | |
987 | } | |
55a580e3 SL |
988 | s++; |
989 | } | |
990 | ||
1a85e9d2 RC |
991 | if (dayok == 0 && s != string) |
992 | return FAIL; | |
55a580e3 | 993 | i = sscanf(s, "%d-%d", &tl, &th); |
1a85e9d2 RC |
994 | if (i < 2) |
995 | return MGrade; | |
46b15d8a | 996 | tn = tp->tm_hour * 100 + tp->tm_min; |
1a85e9d2 RC |
997 | if (th < tl) { /* crosses midnight */ |
998 | if (tl <= tn || tn < th) | |
999 | return MGrade; | |
9313cec6 | 1000 | } else { |
46b15d8a | 1001 | if (tl <= tn && tn < th) |
1a85e9d2 | 1002 | return MGrade; |
9313cec6 | 1003 | } |
1a85e9d2 | 1004 | return FAIL; |
55a580e3 SL |
1005 | } |
1006 | ||
1a85e9d2 RC |
1007 | /* |
1008 | * find first digit in string | |
55a580e3 SL |
1009 | * |
1010 | * return - pointer to first digit in string or end of string | |
1011 | */ | |
55a580e3 SL |
1012 | char * |
1013 | fdig(cp) | |
1014 | register char *cp; | |
1015 | { | |
1016 | register char *c; | |
1017 | ||
1018 | for (c = cp; *c; c++) | |
1019 | if (*c >= '0' && *c <= '9') | |
1020 | break; | |
46b15d8a | 1021 | return c; |
55a580e3 SL |
1022 | } |
1023 | ||
55a580e3 SL |
1024 | /* |
1025 | * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0 | |
1026 | * Strings are compared as if they contain all capital letters. | |
1027 | */ | |
55a580e3 SL |
1028 | snccmp(s1, s2) |
1029 | register char *s1, *s2; | |
1030 | { | |
1031 | char c1, c2; | |
1032 | ||
01af9d69 JB |
1033 | if (islower(*s1)) |
1034 | c1 = toupper(*s1); | |
1035 | else | |
1036 | c1 = *s1; | |
1037 | if (islower(*s2)) | |
1038 | c2 = toupper(*s2); | |
1039 | else | |
1040 | c2 = *s2; | |
55a580e3 SL |
1041 | |
1042 | while (c1 == c2) { | |
01af9d69 | 1043 | if (*s1++ == '\0') |
46b15d8a | 1044 | return 0; |
55a580e3 | 1045 | s2++; |
01af9d69 JB |
1046 | if (islower(*s1)) |
1047 | c1 = toupper(*s1); | |
1048 | else | |
1049 | c1 = *s1; | |
1050 | if (islower(*s2)) | |
1051 | c2 = toupper(*s2); | |
1052 | else | |
1053 | c2 = *s2; | |
55a580e3 | 1054 | } |
46b15d8a RC |
1055 | return c1 - c2; |
1056 | } | |
01af9d69 JB |
1057 | |
1058 | /* | |
1059 | * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0 | |
1060 | * Strings are compared as if they contain all capital letters. | |
1061 | */ | |
1062 | sncncmp(s1, s2, n) | |
1063 | register char *s1, *s2; | |
1064 | register int n; | |
1065 | { | |
1066 | char c1, c2; | |
1067 | ||
1068 | if (islower(*s1)) | |
1069 | c1 = toupper(*s1); | |
1070 | else | |
1071 | c1 = *s1; | |
1072 | if (islower(*s2)) | |
1073 | c2 = toupper(*s2); | |
1074 | else | |
1075 | c2 = *s2; | |
1076 | ||
1077 | while ( --n >= 0 && c1 == c2) { | |
1078 | if (*s1++ == '\0') | |
1079 | return 0; | |
1080 | s2++; | |
1081 | if (islower(*s1)) | |
1082 | c1 = toupper(*s1); | |
1083 | else | |
1084 | c1 = *s1; | |
1085 | if (islower(*s2)) | |
1086 | c2 = toupper(*s2); | |
1087 | else | |
1088 | c2 = *s2; | |
1089 | } | |
1090 | return n<0 ? 0 : (c1 - c2); | |
1091 | } | |
46b15d8a RC |
1092 | /* |
1093 | * do chat script | |
1094 | * occurs after local port is opened, | |
1095 | * before 'dialing' the other machine. | |
1096 | */ | |
1097 | dochat(dev, flds, fd) | |
1098 | register struct Devices *dev; | |
1099 | char *flds[]; | |
1100 | int fd; | |
1101 | { | |
1102 | register int i; | |
1103 | register char *p; | |
1104 | char bfr[sizeof(dev->D_argbfr)]; | |
1105 | ||
1106 | if (dev->D_numargs <= 5) | |
1107 | return(0); | |
1108 | DEBUG(4, "dochat called %d\n", dev->D_numargs); | |
1109 | for (i = 0; i < dev->D_numargs-5; i++) { | |
1110 | sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]); | |
1111 | if (strcmp(bfr, dev->D_arg[D_CHAT+i])) { | |
1112 | p = malloc((unsigned)strlen(bfr)+1); | |
1113 | if (p != NULL) { | |
1114 | strcpy(p, bfr); | |
1115 | dev->D_arg[D_CHAT+i] = p; | |
1116 | } | |
1117 | } | |
1118 | } | |
1119 | /* following is a kludge because login() arglist is a kludge */ | |
1120 | i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd); | |
1121 | /* | |
1122 | * If login() last did a sendthem(), must pause so things can settle. | |
1123 | * But don't bother if chat failed. | |
1124 | */ | |
1125 | if (i == 0 && (dev->D_numargs&01)) | |
1126 | sleep(2); | |
1127 | return(i); | |
55a580e3 | 1128 | } |
2af814a5 JB |
1129 | |
1130 | /* | |
1131 | * fix kill/echo/raw on line | |
1132 | * | |
1133 | * return codes: none | |
1134 | */ | |
1135 | fixmode(tty) | |
1136 | register int tty; | |
1137 | { | |
1138 | #ifdef USG | |
1139 | struct termio ttbuf; | |
1140 | #else !USG | |
1141 | struct sgttyb ttbuf; | |
1142 | #endif !USG | |
1143 | register struct sg_spds *ps; | |
1144 | int speed; | |
1145 | ||
1146 | if (IsTcpIp) | |
1147 | return; | |
1148 | #ifdef USG | |
1149 | ioctl(tty, TCGETA, &ttbuf); | |
1150 | ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0; | |
1151 | speed = ttbuf.c_cflag &= (CBAUD); | |
1152 | ttbuf.c_cflag |= (CS8|CREAD); | |
1153 | ttbuf.c_cc[VMIN] = 6; | |
1154 | ttbuf.c_cc[VTIME] = 1; | |
1155 | ioctl(tty, TCSETA, &ttbuf); | |
1156 | #else !USG | |
1157 | ioctl(tty, TIOCGETP, &ttbuf); | |
1158 | ttbuf.sg_flags = (ANYP | RAW); | |
1159 | ioctl(tty, TIOCSETP, &ttbuf); | |
1160 | speed = ttbuf.sg_ispeed; | |
1161 | ioctl(tty, TIOCEXCL, STBNULL); | |
1162 | #endif !USG | |
1163 | ||
1164 | for (ps = spds; ps->sp_val; ps++) | |
1165 | if (ps->sp_name == speed) { | |
1166 | linebaudrate = ps->sp_val; | |
1167 | DEBUG(9,"Incoming baudrate is %d\n", linebaudrate); | |
1168 | return; | |
1169 | } | |
7dd5932d RA |
1170 | if (linebaudrate < 0) { |
1171 | syslog(LOG_ERR, "unrecognized speed: %d", linebaudrate); | |
1172 | cleanup(FAIL); | |
1173 | } | |
2af814a5 | 1174 | } |