Commit | Line | Data |
---|---|---|
572555ee SL |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)condevs.c 5.1 (Berkeley) %G%"; | |
3 | #endif | |
4 | ||
5 | /* | |
6 | * Here are various dialers to establish the machine-machine connection. | |
7 | * conn.c/condevs.c was glued together by Mike Mitchell. | |
8 | * The dialers were supplied by many people, to whom we are grateful. | |
9 | * | |
10 | * --------------------------------------------------------------------- | |
11 | * NOTE: | |
12 | * There is a bug that occurs at least on PDP11s due to a limitation of | |
13 | * setjmp/longjmp. If the routine that does a setjmp is interrupted | |
14 | * and longjmp-ed to, it loses its register variables (on a pdp11). | |
15 | * What works is if the routine that does the setjmp | |
16 | * calls a routine and it is the *subroutine* that is interrupted. | |
17 | * | |
18 | * Anyway, in conclusion, condevs.c is plagued with register variables | |
19 | * that are used inside | |
20 | * if (setjmp(...)) { | |
21 | * .... | |
22 | * } | |
23 | * | |
24 | * THE FIX: In dnopn(), for example, delete the 'register' Devices *dev. | |
25 | * (That was causing a core dump; deleting register fixed it.) | |
26 | * Also for dnopn delete 'register' int dnf... . | |
27 | * In pkopn, delete 'register' flds... . | |
28 | * There may be others, especially mcm's version of hysopen. | |
29 | * You could just delete all references to register, that is safest. | |
30 | * This problem might not occur on 4.1bsd, I am not sure. | |
31 | * Tom Truscott | |
32 | */ | |
33 | #include <sys/types.h> | |
34 | #include <errno.h> | |
35 | #include <setjmp.h> | |
36 | #include <signal.h> | |
37 | #include <sgtty.h> | |
38 | #include "uucp.h" | |
39 | ||
40 | extern char devSel[]; /* name to pass to delock() in close */ | |
41 | extern int errno, next_fd; | |
42 | extern jmp_buf Sjbuf; | |
43 | extern int alarmtr(); | |
44 | int nulldev(), nodev(), Acuopn(), diropn(), dircls(); | |
45 | ||
46 | #ifdef DATAKIT | |
47 | int dkopn(); | |
48 | #endif | |
49 | #ifdef DN11 | |
50 | int dnopn(), dncls(); | |
51 | #endif | |
52 | #ifdef HAYES | |
53 | int hysopn(), hyscls(); | |
54 | #endif | |
55 | #ifdef HAYESQ | |
56 | int hysqopn(), hysqcls(); /* a version of hayes that doesn't use ret codes */ | |
57 | #endif | |
58 | #ifdef DF02 | |
59 | int df2opn(), df2cls(); | |
60 | #endif | |
61 | #ifdef PNET | |
62 | int pnetopn(); | |
63 | #endif | |
64 | #ifdef VENTEL | |
65 | int ventopn(), ventcls(); | |
66 | #endif | |
67 | #ifdef UNET | |
68 | #include <UNET/unetio.h> | |
69 | #include <UNET/tcp.h> | |
70 | int unetopn(), unetcls(); | |
71 | #endif UNET | |
72 | #ifdef VADIC | |
73 | int vadopn(), vadcls(); | |
74 | #endif VADIC | |
75 | #ifdef RVMACS | |
76 | int rvmacsopn(), rvmacscls(); | |
77 | #endif | |
78 | #ifdef MICOM | |
79 | int micopn(), miccls(); | |
80 | #endif MICOM | |
81 | ||
82 | struct condev condevs[] = { | |
83 | { "DIR", "direct", diropn, nulldev, dircls }, | |
84 | #ifdef DATAKIT | |
85 | { "DK", "datakit", dkopn, nulldev, nulldev }, | |
86 | #endif | |
87 | #ifdef PNET | |
88 | { "PNET", "pnet", pnetopn, nulldev, nulldev }, | |
89 | #endif | |
90 | #ifdef UNET | |
91 | { "UNET", "UNET", unetopn, nulldev, unetcls }, | |
92 | #endif UNET | |
93 | #ifdef MICOM | |
94 | { "MICOM", "micom", micopn, nulldev, miccls }, | |
95 | #endif MICOM | |
96 | #ifdef DN11 | |
97 | { "ACU", "dn11", Acuopn, dnopn, dncls }, | |
98 | #endif | |
99 | #ifdef HAYES | |
100 | { "ACU", "hayes", Acuopn, hysopn, hyscls }, | |
101 | #endif HAYES | |
102 | #ifdef HAYESQ /* a version of hayes that doesn't use result codes */ | |
103 | { "ACU", "hayesq", Acuopn, hysqopn, hysqcls }, | |
104 | #endif HATESQ | |
105 | #ifdef DF02 | |
106 | { "ACU", "DF02", Acuopn, df2opn, df2cls }, | |
107 | #endif | |
108 | #ifdef VENTEL | |
109 | { "ACU", "ventel", Acuopn, ventopn, ventcls }, | |
110 | #endif VENTEL | |
111 | #ifdef VADIC | |
112 | { "ACU", "vadic", Acuopn, vadopn, vadcls }, | |
113 | #endif VADIC | |
114 | #ifdef RVMACS | |
115 | { "ACU", "rvmacs", Acuopn, rvmacsopn, rvmacscls }, | |
116 | #endif RVMACS | |
117 | ||
118 | /* Insert new entries before this line */ | |
119 | { NULL, NULL, NULL, NULL, NULL } }; | |
120 | ||
121 | /*** | |
122 | * nulldev a null device (returns CF_DIAL) | |
123 | */ | |
124 | int nulldev() | |
125 | { | |
126 | return(CF_DIAL); | |
127 | } | |
128 | ||
129 | /*** | |
130 | * nodev a null device (returns CF_NODEV) | |
131 | */ | |
132 | int nodev() | |
133 | { | |
134 | return(CF_NODEV); | |
135 | } | |
136 | ||
137 | ||
138 | /* | |
139 | * The first things in this file are the generic devices. | |
140 | * Generic devices look through L-devices and call the CU_open routines for | |
141 | * appropriate devices. Some things, like the Unet interface, or direct | |
142 | * connect, do not use the CU_open entry. ACUs must search to find the' | |
143 | * right routine to call. | |
144 | */ | |
145 | ||
146 | /*** | |
147 | * diropn(flds) connect to hardware line | |
148 | * char *flds[]; | |
149 | * | |
150 | * return codes: | |
151 | * >0 - file number - ok | |
152 | * FAIL - failed | |
153 | */ | |
154 | ||
155 | diropn(flds) | |
156 | register char *flds[]; | |
157 | { | |
158 | register int dcr, status; | |
159 | struct Devices dev; | |
160 | char dcname[20]; | |
161 | FILE *dfp; | |
162 | dfp = fopen(DEVFILE, "r"); | |
163 | ASSERT(dfp != NULL, "CAN'T OPEN", DEVFILE, 0); | |
164 | while ((status = rddev(dfp, &dev)) != FAIL) { | |
165 | if (strcmp(flds[F_CLASS], dev.D_class) != SAME) | |
166 | continue; | |
167 | if (strcmp(flds[F_PHONE], dev.D_line) != SAME) | |
168 | continue; | |
169 | if (mlock(dev.D_line) != FAIL) | |
170 | break; | |
171 | } | |
172 | fclose(dfp); | |
173 | if (status == FAIL) { | |
174 | logent("DEVICE", "NO"); | |
175 | return(CF_NODEV); | |
176 | } | |
177 | ||
178 | sprintf(dcname, "/dev/%s", dev.D_line); | |
179 | if (setjmp(Sjbuf)) { | |
180 | delock(dev.D_line); | |
181 | return(FAIL); | |
182 | } | |
183 | signal(SIGALRM, alarmtr); | |
184 | alarm(10); | |
185 | getnextfd(); | |
186 | errno = 0; | |
187 | dcr = open(dcname, 2); /* read/write */ | |
188 | next_fd = -1; | |
189 | if (dcr < 0 && errno == EACCES) | |
190 | logent(dcname, "CAN'T OPEN"); | |
191 | alarm(0); | |
192 | if (dcr < 0) { | |
193 | delock(dev.D_line); | |
194 | return(FAIL); | |
195 | } | |
196 | fflush(stdout); | |
197 | fixline(dcr, dev.D_speed); | |
198 | strcpy(devSel, dev.D_line); /* for latter unlock */ | |
199 | CU_end = dircls; | |
200 | return(dcr); | |
201 | } | |
202 | ||
203 | dircls(fd) | |
204 | register int fd; | |
205 | { | |
206 | if (fd > 0) { | |
207 | close(fd); | |
208 | delock(devSel); | |
209 | } | |
210 | } | |
211 | ||
212 | #ifdef DATAKIT | |
213 | ||
214 | #include <dk.h> | |
215 | #define DKTRIES 2 | |
216 | ||
217 | /*** | |
218 | * dkopn(flds) make datakit connection | |
219 | * | |
220 | * return codes: | |
221 | * >0 - file number - ok | |
222 | * FAIL - failed | |
223 | */ | |
224 | ||
225 | dkopn(flds) | |
226 | char *flds[]; | |
227 | { | |
228 | int dkphone; | |
229 | register char *cp; | |
230 | register ret, i; | |
231 | ||
232 | if (setjmp(Sjbuf)) | |
233 | return(FAIL); | |
234 | ||
235 | signal(SIGALRM, alarmtr); | |
236 | dkphone = 0; | |
237 | cp = flds[F_PHONE]; | |
238 | while(*cp) | |
239 | dkphone = 10 * dkphone + (*cp++ - '0'); | |
240 | DEBUG(4, "dkphone (%d) ", dkphone); | |
241 | for (i = 0; i < DKTRIES; i++) { | |
242 | getnextfd(); | |
243 | ret = dkdial(D_SH, dkphone, 0); | |
244 | next_fd = -1; | |
245 | DEBUG(4, "dkdial (%d)\n", ret); | |
246 | if (ret > -1) | |
247 | break; | |
248 | } | |
249 | return(ret); | |
250 | } | |
251 | #endif | |
252 | ||
253 | #ifdef PNET | |
254 | /*** | |
255 | * pnetopn(flds) | |
256 | * | |
257 | * call remote machine via Purdue network | |
258 | * use dial string as host name, speed as socket number | |
259 | * Author: Steve Bellovin | |
260 | */ | |
261 | ||
262 | pnetopn(flds) | |
263 | char *flds[]; | |
264 | { | |
265 | int fd; | |
266 | int socket; | |
267 | register char *cp; | |
268 | ||
269 | fd = pnetfile(); | |
270 | DEBUG(4, "pnet fd - %d\n", fd); | |
271 | if (fd < 0) { | |
272 | logent("AVAILABLE DEVICE", "NO"); | |
273 | return(CF_NODEV); | |
274 | } | |
275 | socket = 0; | |
276 | for (cp = flds[F_CLASS]; *cp; cp++) | |
277 | socket = 10*socket + (*cp - '0'); | |
278 | DEBUG(4, "socket - %d\n", socket); | |
279 | if (setjmp(Sjbuf)) { | |
280 | DEBUG(4, "pnet timeout - %s\n", flds[F_PHONE]); | |
281 | return(FAIL); | |
282 | } | |
283 | signal(SIGALRM, alarmtr); | |
284 | DEBUG(4, "host - %s\n", flds[F_PHONE]); | |
285 | alarm(15); | |
286 | if (pnetscon(fd, flds[F_PHONE], socket) < 0) { | |
287 | DEBUG(4, "pnet connect failed - %s\n", flds[F_PHONE]); | |
288 | return(FAIL); | |
289 | } | |
290 | alarm(0); | |
291 | return(fd); | |
292 | } | |
293 | #endif PNET | |
294 | ||
295 | #ifdef UNET | |
296 | /*** | |
297 | * unetopn -- make UNET (tcp-ip) connection | |
298 | * | |
299 | * return codes: | |
300 | * >0 - file number - ok | |
301 | * FAIL - failed | |
302 | */ | |
303 | ||
304 | /* Default port of uucico server */ | |
305 | #define DFLTPORT 33 | |
306 | ||
307 | unetopn(flds) | |
308 | register char *flds[]; | |
309 | { | |
310 | register int ret, port; | |
311 | int unetcls(); | |
312 | ||
313 | port = atoi(flds[F_PHONE]); | |
314 | if (port <= 0 || port > 255) | |
315 | port = DFLTPORT; | |
316 | DEBUG(4, "unetopn host %s, ", flds[F_NAME]); | |
317 | DEBUG(4, "port %d\n", port); | |
318 | if (setjmp(Sjbuf)) { | |
319 | logent("tcpopen", "TIMEOUT"); | |
320 | endhnent(); /* see below */ | |
321 | return(CF_DIAL); | |
322 | } | |
323 | signal(SIGALRM, alarmtr); | |
324 | alarm(30); | |
325 | ret = tcpopen(flds[F_NAME], port, 0, TO_ACTIVE, "rw"); | |
326 | alarm(0); | |
327 | endhnent(); /* wave magic wand at 3com and incant "eat it, bruce" */ | |
328 | if (ret < 0) { | |
329 | DEBUG(5, "tcpopen failed: errno %d\n", errno); | |
330 | logent("tcpopen", "FAILED"); | |
331 | return(CF_DIAL); | |
332 | } | |
333 | CU_end = unetcls; | |
334 | return(ret); | |
335 | } | |
336 | ||
337 | /* | |
338 | * unetcls -- close UNET connection. | |
339 | */ | |
340 | unetcls(fd) | |
341 | register int fd; | |
342 | { | |
343 | DEBUG(4, "UNET CLOSE called\n", 0); | |
344 | if (fd > 0) { | |
345 | /* disable this until a timeout is put in | |
346 | if (ioctl(fd, UIOCCLOSE, STBNULL)) | |
347 | logent("UNET CLOSE", "FAILED"); | |
348 | */ | |
349 | close(fd); | |
350 | DEBUG(4, "closed fd %d\n", fd); | |
351 | } | |
352 | } | |
353 | #endif UNET | |
354 | ||
355 | #ifdef MICOM | |
356 | ||
357 | /* | |
358 | * micopn: establish connection through a micom. | |
359 | * Returns descriptor open to tty for reading and writing. | |
360 | * Negative values (-1...-7) denote errors in connmsg. | |
361 | * Be sure to disconnect tty when done, via HUPCL or stty 0. | |
362 | */ | |
363 | micopn(flds) | |
364 | register char *flds[]; | |
365 | { | |
366 | extern errno; | |
367 | char *rindex(), *fdig(), dcname[20]; | |
368 | int dh, ok = 0, speed; | |
369 | register struct condev *cd; | |
370 | register FILE *dfp; | |
371 | struct Devices dev; | |
372 | ||
373 | dfp = fopen(DEVFILE, "r"); | |
374 | ASSERT(dfp != NULL, "Can't open", DEVFILE, 0); | |
375 | ||
376 | signal(SIGALRM, alarmtr); | |
377 | dh = -1; | |
378 | for(cd = condevs; ((cd->CU_meth != NULL)&&(dh < 0)); cd++) { | |
379 | if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) { | |
380 | fseek(dfp, (off_t)0, 0); | |
381 | while(rddev(dfp, &dev) != FAIL) { | |
382 | if (strcmp(flds[F_CLASS], dev.D_class) != SAME) | |
383 | continue; | |
384 | if (snccmp(flds[F_LINE], dev.D_type) != SAME) | |
385 | continue; | |
386 | if (mlock(dev.D_line) == FAIL) | |
387 | continue; | |
388 | ||
389 | sprintf(dcname, "/dev/%s", dev.D_line); | |
390 | getnextfd(); | |
391 | alarm(10); | |
392 | if (setjmp(Sjbuf)) { | |
393 | delock(dev.D_line); | |
394 | logent(dev.D_line,"micom open TIMEOUT"); | |
395 | dh = -1; | |
396 | break; | |
397 | } | |
398 | dh = open(dcname, 2); | |
399 | alarm(0); | |
400 | next_fd = -1; | |
401 | if (dh > 0) { | |
402 | break; | |
403 | } | |
404 | devSel[0] = '\0'; | |
405 | delock(dev.D_line); | |
406 | } | |
407 | } | |
408 | } | |
409 | fclose(dfp); | |
410 | if (dh < 0) | |
411 | return(CF_NODEV); | |
412 | ||
413 | speed = atoi(fdig(flds[F_CLASS])); | |
414 | fixline(dh, speed); | |
415 | sleep(1); | |
416 | ||
417 | /* negotiate with micom */ | |
418 | if (speed != 4800) /* damn their eyes! */ | |
419 | write(dh, "\r", 1); | |
420 | else | |
421 | write(dh, " ", 1); | |
422 | ||
423 | DEBUG(4, "wanted %s ", "NAME"); | |
424 | ok = expect("NAME", dh); | |
425 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
426 | if (ok == 0) { | |
427 | write(dh, flds[F_PHONE], strlen(flds[F_PHONE])); | |
428 | sleep(1); | |
429 | write(dh, "\r", 1); | |
430 | DEBUG(4, "wanted %s ", "GO"); | |
431 | ok = expect("GO", dh); | |
432 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
433 | } | |
434 | ||
435 | if (ok != 0) { | |
436 | if (dh > 2) | |
437 | close(dh); | |
438 | DEBUG(4, "micom failed\n", ""); | |
439 | delock(dev.D_line); | |
440 | return(CF_DIAL); | |
441 | } else | |
442 | DEBUG(4, "micom ok\n", ""); | |
443 | ||
444 | CU_end = cd->CU_clos; | |
445 | strcat(devSel, dev.D_line); /* for later unlock */ | |
446 | return(dh); | |
447 | ||
448 | } | |
449 | ||
450 | miccls(fd) | |
451 | register int fd; | |
452 | { | |
453 | ||
454 | if (fd > 0) { | |
455 | close(fd); | |
456 | delock(devSel); | |
457 | } | |
458 | } | |
459 | #endif MICOM | |
460 | ||
461 | /*** | |
462 | * Acuopn - open an ACU and dial the number. The condevs table | |
463 | * will be searched until a dialing unit is found that is | |
464 | * free. | |
465 | * | |
466 | * return codes: >0 - file number - o.k. | |
467 | * FAIL - failed | |
468 | */ | |
469 | ||
470 | char devSel[20]; /* used for later unlock() */ | |
471 | ||
472 | Acuopn(flds) | |
473 | register char *flds[]; | |
474 | { | |
475 | char phone[MAXPH+1]; | |
476 | register struct condev *cd; | |
477 | register int fd; | |
478 | register FILE *dfp; | |
479 | struct Devices dev; | |
480 | ||
481 | exphone(flds[F_PHONE], phone); | |
482 | devSel[0] = '\0'; | |
483 | DEBUG(4, "Dialing %s\n", phone); | |
484 | dfp = fopen(DEVFILE, "r"); | |
485 | ASSERT(dfp != NULL, "Can't open", DEVFILE, 0); | |
486 | ||
487 | for(cd = condevs; cd->CU_meth != NULL; cd++) { | |
488 | if (snccmp(flds[F_LINE], cd->CU_meth) == SAME) { | |
489 | fseek(dfp, (off_t)0, 0); | |
490 | while(rddev(dfp, &dev) != FAIL) { | |
491 | if (strcmp(flds[F_CLASS], dev.D_class) != SAME) | |
492 | continue; | |
493 | if (snccmp(flds[F_LINE], dev.D_type) != SAME) | |
494 | continue; | |
495 | if (dev.D_brand[0] == '\0') | |
496 | logent("Acuopn","No 'brand' name on ACU"); | |
497 | else if (snccmp(dev.D_brand, cd->CU_brand) != SAME) | |
498 | continue; | |
499 | if (mlock(dev.D_line) == FAIL) | |
500 | continue; | |
501 | ||
502 | DEBUG(4, "Using %s\n", cd->CU_brand); | |
503 | fd = (*(cd->CU_open))(phone, flds, &dev); | |
504 | if (fd > 0) { | |
505 | CU_end = cd->CU_clos; /* point CU_end at close func */ | |
506 | fclose(dfp); | |
507 | strcpy(devSel, dev.D_line); /* save for later unlock() */ | |
508 | return(fd); | |
509 | } | |
510 | delock(dev.D_line); | |
511 | } | |
512 | } | |
513 | } | |
514 | fclose(dfp); | |
515 | return(FAIL); | |
516 | } | |
517 | ||
518 | #ifdef DN11 | |
519 | ||
520 | /*** | |
521 | * dnopn(ph, flds, dev) dial remote machine | |
522 | * char *ph; | |
523 | * char *flds[]; | |
524 | * struct Devices *dev; | |
525 | * | |
526 | * return codes: | |
527 | * file descriptor - succeeded | |
528 | * FAIL - failed | |
529 | */ | |
530 | ||
531 | dnopn(ph, flds, dev) | |
532 | char *ph; | |
533 | char *flds[]; | |
534 | struct Devices *dev; | |
535 | { | |
536 | char dcname[20], dnname[20], phone[MAXPH+2], c = 0; | |
537 | #ifdef SYSIII | |
538 | struct termio ttbuf; | |
539 | #endif | |
540 | int dnf, dcf; | |
541 | int nw, lt, pid, status; | |
542 | unsigned timelim; | |
543 | ||
544 | sprintf(dnname, "/dev/%s", dev->D_calldev); | |
545 | errno = 0; | |
546 | ||
547 | if (setjmp(Sjbuf)) { | |
548 | logent(dnname, "CAN'T OPEN"); | |
549 | DEBUG(4, "%s Open timed out\n", dnname); | |
550 | return(CF_NODEV); | |
551 | } | |
552 | signal(SIGALRM, alarmtr); | |
553 | getnextfd(); | |
554 | alarm(10); | |
555 | dnf = open(dnname, 1); | |
556 | alarm(0); | |
557 | next_fd = -1; | |
558 | if (dnf < 0 && errno == EACCES) { | |
559 | logent(dnname, "CAN'T OPEN"); | |
560 | logent("DEVICE", "NO"); | |
561 | return(CF_NODEV); | |
562 | } | |
563 | /* rti!trt: avoid passing acu file descriptor to children */ | |
564 | fioclex(dnf); | |
565 | ||
566 | sprintf(dcname, "/dev/%s", dev->D_line); | |
567 | sprintf(phone, "%s%s", ph, ACULAST); | |
568 | DEBUG(4, "dc - %s, ", dcname); | |
569 | DEBUG(4, "acu - %s\n", dnname); | |
570 | pid = 0; | |
571 | if (setjmp(Sjbuf)) { | |
572 | logent("DIALUP DN write", "TIMEOUT"); | |
573 | if (pid) | |
574 | kill(pid, 9); | |
575 | delock(dev->D_line); | |
576 | if (dnf) | |
577 | close(dnf); | |
578 | return(FAIL); | |
579 | } | |
580 | signal(SIGALRM, alarmtr); | |
581 | timelim = 5 * strlen(phone); | |
582 | alarm(timelim < 30 ? 30 : timelim); | |
583 | if ((pid = fork()) == 0) { | |
584 | sleep(2); | |
585 | fclose(stdin); | |
586 | fclose(stdout); | |
587 | #ifdef TIOCFLUSH | |
588 | ioctl(dnf, TIOCFLUSH, STBNULL); | |
589 | #endif | |
590 | nw = write(dnf, phone, lt = strlen(phone)); | |
591 | if (nw != lt) { | |
592 | logent("DIALUP ACU write", "FAILED"); | |
593 | exit(1); | |
594 | } | |
595 | DEBUG(4, "ACU write ok%s\n", ""); | |
596 | exit(0); | |
597 | } | |
598 | /* open line - will return on carrier */ | |
599 | /* RT needs a sleep here because it returns immediately from open */ | |
600 | ||
601 | #if RT | |
602 | sleep(15); | |
603 | #endif | |
604 | ||
605 | getnextfd(); | |
606 | errno = 0; | |
607 | dcf = open(dcname, 2); | |
608 | next_fd = -1; | |
609 | if (dcf < 0 && errno == EACCES) | |
610 | logent(dcname, "CAN'T OPEN"); | |
611 | DEBUG(4, "dcf is %d\n", dcf); | |
612 | if (dcf < 0) { | |
613 | logent("DIALUP LINE open", "FAILED"); | |
614 | alarm(0); | |
615 | kill(pid, 9); | |
616 | close(dnf); | |
617 | delock(dev->D_line); | |
618 | return(FAIL); | |
619 | } | |
620 | /* brl-bmd.351 (Doug Kingston) says the next ioctl is unneeded . */ | |
621 | /* ioctl(dcf, TIOCHPCL, STBNULL);*/ | |
622 | while ((nw = wait(<)) != pid && nw != -1) | |
623 | ; | |
624 | #ifdef SYSIII | |
625 | ioctl(dcf, TCGETA, &ttbuf); | |
626 | if(!(ttbuf.c_cflag & HUPCL)) { | |
627 | ttbuf.c_cflag |= HUPCL; | |
628 | ioctl(dcf, TCSETA, &ttbuf); | |
629 | } | |
630 | #endif | |
631 | alarm(0); | |
632 | fflush(stdout); | |
633 | fixline(dcf, dev->D_speed); | |
634 | DEBUG(4, "Fork Stat %o\n", lt); | |
635 | if (lt != 0) { | |
636 | close(dcf); | |
637 | if (dnf) | |
638 | close(dnf); | |
639 | delock(dev->D_line); | |
640 | return(FAIL); | |
641 | } | |
642 | return(dcf); | |
643 | } | |
644 | ||
645 | /*** | |
646 | * dncls() close dn type call unit | |
647 | * | |
648 | * return codes: None | |
649 | */ | |
650 | dncls(fd) | |
651 | register int fd; | |
652 | { | |
653 | if (fd > 0) { | |
654 | close(fd); | |
655 | sleep(5); | |
656 | delock(devSel); | |
657 | } | |
658 | } | |
659 | #endif DN11 | |
660 | ||
661 | #ifdef DF02 | |
662 | /*** | |
663 | * df2opn(ph, flds, dev) dial remote machine | |
664 | * char *ph; | |
665 | * char *flds[]; | |
666 | * struct Devices *dev; | |
667 | * | |
668 | * return codes: | |
669 | * file descriptor - succeeded | |
670 | * FAIL - failed | |
671 | * | |
672 | * Modified 9/28/81 by Bill Shannon (DEC) | |
673 | * Changed to use DEC DF02 or DF03 ACU | |
674 | */ | |
675 | ||
676 | ||
677 | df2opn(ph, flds, dev) | |
678 | char *ph; | |
679 | char *flds[]; | |
680 | struct Devices *dev; | |
681 | { | |
682 | char dcname[20], dnname[20], phone[MAXPH+2], c = 0; | |
683 | #ifdef SYSIII | |
684 | struct termio ttbuf; | |
685 | #endif | |
686 | int dcf, dnf; | |
687 | int nw, lt, pid, st, status; | |
688 | unsigned timelim; | |
689 | ||
690 | sprintf(dnname, "/dev/%s", dev->D_calldev); | |
691 | if (setjmp(Sjbuf)) { | |
692 | logent(dnname, "CAN'T OPEN"); | |
693 | DEBUG(4, "%s Open timed out\n", dnname); | |
694 | return(CF_NODEV); | |
695 | } | |
696 | signal(SIGALRM, alarmtr); | |
697 | getnextfd(); | |
698 | errno = 0; | |
699 | alarm(10); | |
700 | dnf = open(dnname, 2 ); | |
701 | alarm(0); | |
702 | next_fd = -1; | |
703 | if (dnf < 0 && errno == EACCES) { | |
704 | logent(dnname, "CAN'T OPEN"); | |
705 | delock(dev->D_line); | |
706 | logent("DEVICE", "NO"); | |
707 | return(CF_NODEV); | |
708 | } | |
709 | /* rti!trt: avoid passing acu file descriptor to children */ | |
710 | fioclex(dnf); | |
711 | ||
712 | sprintf(dcname, "/dev/%s", dev->D_line); | |
713 | fixline(dnf, dev->D_speed); | |
714 | sprintf(phone, "\02%s", ph); | |
715 | DEBUG(4, "dc - %s, ", dcname); | |
716 | DEBUG(4, "acu - %s\n", dnname); | |
717 | pid = 0; | |
718 | if (setjmp(Sjbuf)) { | |
719 | logent("DIALUP DN write", "TIMEOUT"); | |
720 | if (pid) | |
721 | kill(pid, 9); | |
722 | delock(dev->D_line); | |
723 | if (dnf) | |
724 | close(dnf); | |
725 | return(FAIL); | |
726 | } | |
727 | signal(SIGALRM, alarmtr); | |
728 | timelim = 5 * strlen(phone); | |
729 | alarm(timelim < 30 ? 30 : timelim); | |
730 | if ((pid = fork()) == 0) { | |
731 | sleep(2); | |
732 | fclose(stdin); | |
733 | fclose(stdout); | |
734 | #ifdef TIOCFLUSH | |
735 | ioctl(dnf, TIOCFLUSH, STBNULL); | |
736 | #endif | |
737 | write(dnf, "\01", 1); | |
738 | sleep(1); | |
739 | nw = write(dnf, phone, lt = strlen(phone)); | |
740 | if (nw != lt) { | |
741 | logent("DIALUP ACU write", "FAILED"); | |
742 | exit(1); | |
743 | } | |
744 | DEBUG(4, "ACU write ok%s\n", ""); | |
745 | exit(0); | |
746 | } | |
747 | /* open line - will return on carrier */ | |
748 | /* RT needs a sleep here because it returns immediately from open */ | |
749 | ||
750 | #if RT | |
751 | sleep(15); | |
752 | #endif | |
753 | ||
754 | if (read(dnf, &c, 1) != 1 || c != 'A') | |
755 | dcf = -1; | |
756 | else | |
757 | dcf = 0; | |
758 | DEBUG(4, "dcf is %d\n", dcf); | |
759 | if (dcf < 0) { | |
760 | logent("DIALUP LINE open", "FAILED"); | |
761 | alarm(0); | |
762 | kill(pid, 9); | |
763 | close(dnf); | |
764 | delock(dev->D_line); | |
765 | return(FAIL); | |
766 | } | |
767 | dcf = dnf; | |
768 | dnf = 0; | |
769 | /* brl-bmd.351 (Doug Kingston) says the next ioctl is unneeded . */ | |
770 | /* ioctl(dcf, TIOCHPCL, STBNULL);*/ | |
771 | while ((nw = wait(<)) != pid && nw != -1) | |
772 | ; | |
773 | #ifdef SYSIII | |
774 | ioctl(dcf, TCGETA, &ttbuf); | |
775 | if(!(ttbuf.c_cflag & HUPCL)) { | |
776 | ttbuf.c_cflag |= HUPCL; | |
777 | ioctl(dcf, TCSETA, &ttbuf); | |
778 | } | |
779 | #endif | |
780 | alarm(0); | |
781 | fflush(stdout); | |
782 | fixline(dcf, dev->D_speed); | |
783 | DEBUG(4, "Fork Stat %o\n", lt); | |
784 | if (lt != 0) { | |
785 | close(dcf); | |
786 | if (dnf) | |
787 | close(dnf); | |
788 | delock(dev->D_line); | |
789 | return(FAIL); | |
790 | } | |
791 | return(dcf); | |
792 | } | |
793 | ||
794 | /* | |
795 | * df2cls() close the DF02/DF03 call unit | |
796 | * | |
797 | * return codes: none | |
798 | */ | |
799 | ||
800 | df2cls(fd) | |
801 | register int fd; | |
802 | { | |
803 | if (fd > 0) { | |
804 | close(fd); | |
805 | sleep(5); | |
806 | delock(devSel); | |
807 | } | |
808 | } | |
809 | #endif DF02 | |
810 | ||
811 | #ifdef HAYES | |
812 | /*** | |
813 | * hysopn(telno, flds, dev) connect to hayes smartmodem | |
814 | * char *flds[], *dev[]; | |
815 | * | |
816 | * return codes: | |
817 | * >0 - file number - ok | |
818 | * CF_DIAL,CF_DEVICE - failed | |
819 | */ | |
820 | /* | |
821 | * Define HAYSTONE if you have touch tone dialing. | |
822 | */ | |
823 | /*#define HAYSTONE */ | |
824 | ||
825 | hysopn(telno, flds, dev) | |
826 | char *telno; | |
827 | char *flds[]; | |
828 | struct Devices *dev; | |
829 | { | |
830 | int dh = -1; | |
831 | extern errno; | |
832 | char dcname[20]; | |
833 | ||
834 | sprintf(dcname, "/dev/%s", dev->D_line); | |
835 | DEBUG(4, "dc - %s\n", dcname); | |
836 | if (setjmp(Sjbuf)) { | |
837 | DEBUG(1, "timeout hayes open %s\n", dcname); | |
838 | logent("hayes open", "TIMEOUT"); | |
839 | if (dh >= 0) | |
840 | close(dh); | |
841 | delock(dev->D_line); | |
842 | return(CF_DIAL); | |
843 | } | |
844 | signal(SIGALRM, alarmtr); | |
845 | getnextfd(); | |
846 | alarm(10); | |
847 | dh = open(dcname, 2); /* read/write */ | |
848 | alarm(0); | |
849 | ||
850 | /* modem is open */ | |
851 | next_fd = -1; | |
852 | if (dh >= 0) { | |
853 | fixline(dh, dev->D_speed); | |
854 | #ifdef HAYSTONE | |
855 | write(dh, "\rATDT", 5); | |
856 | #else | |
857 | write(dh, "\rATDP", 5); | |
858 | #endif | |
859 | write(dh, telno, strlen(telno)); | |
860 | write(dh, "\r", 1); | |
861 | ||
862 | if (expect("CONNECT", dh) != 0) { | |
863 | logent("HSM no carrier", "FAILED"); | |
864 | strcpy(devSel, dev->D_line); | |
865 | hyscls(dh); | |
866 | return(CF_DIAL); | |
867 | } | |
868 | ||
869 | } | |
870 | if (dh < 0) { | |
871 | DEBUG(4, "hayes failed\n", ""); | |
872 | delock(dev->D_line); | |
873 | } | |
874 | DEBUG(4, "hayes ok\n", ""); | |
875 | return(dh); | |
876 | } | |
877 | ||
878 | hyscls(fd) | |
879 | int fd; | |
880 | { | |
881 | char dcname[20]; | |
882 | struct sgttyb hup, sav; | |
883 | ||
884 | if (fd > 0) { | |
885 | sprintf(dcname, "/dev/%s", devSel); | |
886 | DEBUG(4, "Hanging up fd = %d\n", fd); | |
887 | /* | |
888 | * code to drop DTR -- change to 0 baud then back to default. | |
889 | */ | |
890 | gtty(fd, &hup); | |
891 | gtty(fd, &sav); | |
892 | hup.sg_ispeed = B0; | |
893 | hup.sg_ospeed = B0; | |
894 | stty(fd, &hup); | |
895 | sleep(2); | |
896 | stty(fd, &sav); | |
897 | /* | |
898 | * now raise DTR -- close the device & open it again. | |
899 | */ | |
900 | sleep(2); | |
901 | close(fd); | |
902 | sleep(2); | |
903 | fd = open(dcname, 2); | |
904 | /* | |
905 | * Since we have a getty sleeping on this line, when it wakes up it sends | |
906 | * all kinds of garbage to the modem. Unfortunatly, the modem likes to | |
907 | * execute the previous command when it sees the garbage. The previous | |
908 | * command was to dial the phone, so let's make the last command reset | |
909 | * the modem. | |
910 | */ | |
911 | sleep(2); | |
912 | write(fd, "\rATZ\r", 5); | |
913 | close(fd); | |
914 | delock(devSel); | |
915 | } | |
916 | } | |
917 | ||
918 | #endif HAYES | |
919 | ||
920 | #ifdef HAYESQ | |
921 | /* | |
922 | * New dialout routine to work with Hayes' SMART MODEM | |
923 | * 13-JUL-82, Mike Mitchell | |
924 | * Modified 23-MAR-83 to work with Tom Truscott's (rti!trt) | |
925 | * version of UUCP (ncsu!mcm) | |
926 | * | |
927 | * The modem should be set to NOT send any result codes to | |
928 | * the system (switch 3 up, 4 down). This end will figure out | |
929 | * what is wrong. | |
930 | * | |
931 | * I had lots of problems with the modem sending | |
932 | * result codes since I am using the same modem for both incomming and | |
933 | * outgoing calls. I'd occasionally miss the result code (getty would | |
934 | * grab it), and the connect would fail. Worse yet, the getty would | |
935 | * think the result code was a user name, and send garbage to it while | |
936 | * it was in the command state. I turned off ALL result codes, and hope | |
937 | * for the best. 99% of the time the modem is in the correct state. | |
938 | * Occassionally it doesn't connect, or the phone was busy, etc., and | |
939 | * uucico sits there trying to log in. It eventually times out, calling | |
940 | * clsacu() in the process, so it resets itself for the next attempt. | |
941 | */ | |
942 | ||
943 | /* | |
944 | * Define HAYSTONE if touch-tone dialing is to be used. If it is not defined, | |
945 | * Pulse dialing is assumed. | |
946 | */ | |
947 | /*#define HAYSTONE*/ | |
948 | ||
949 | hysqopn(telno, flds, dev) | |
950 | register char *telno, *flds[]; | |
951 | struct Devices *dev; | |
952 | { | |
953 | char dcname[20], phone[MAXPH+10], c = 0; | |
954 | #ifdef SYSIII | |
955 | struct termio ttbuf; | |
956 | #endif | |
957 | int status, dnf; | |
958 | unsigned timelim; | |
959 | ||
960 | signal(SIGALRM, alarmtr); | |
961 | sprintf(dcname, "/dev/%s", dev->D_line); | |
962 | ||
963 | getnextfd(); | |
964 | if (setjmp(Sjbuf)) { | |
965 | delock(dev->D_line); | |
966 | logent("DEVICE", "NO"); | |
967 | DEBUG(4, "Open timed out %s", dcname); | |
968 | return(CF_NODEV); | |
969 | } | |
970 | alarm(10); | |
971 | ||
972 | if ((dnf = open(dcname, 2)) <= 0) { | |
973 | delock(dev->D_line); | |
974 | logent("DEVICE", "NO"); | |
975 | DEBUG(4, "Can't open %s", dcname); | |
976 | return(CF_NODEV); | |
977 | } | |
978 | ||
979 | alarm(0); | |
980 | next_fd = -1; | |
981 | fixline(dnf, dev->D_speed); | |
982 | DEBUG(4, "Hayes port - %s, ", dcname); | |
983 | ||
984 | #ifdef HAYSTONE | |
985 | sprintf(phone, "\rATDT%s\r", telno); | |
986 | #else | |
987 | sprintf(phone, "\rATDP%s\r", telno); | |
988 | #endif | |
989 | ||
990 | write(dnf, phone, strlen(phone)); | |
991 | ||
992 | /* calculate delay time for the other system to answer the phone. | |
993 | * Default is 15 seconds, add 2 seconds for each comma in the phone | |
994 | * number. | |
995 | */ | |
996 | timelim = 150; | |
997 | while(*telno) { | |
998 | c = *telno++; | |
999 | if (c == ',') | |
1000 | timelim += 20; | |
1001 | else { | |
1002 | #ifdef HAYSTONE | |
1003 | timelim += 2; /* .2 seconds per tone */ | |
1004 | } | |
1005 | #else | |
1006 | if (c == '0') timelim += 10; /* .1 second per digit */ | |
1007 | else if (c > '0' && c <= '9') | |
1008 | timelim += (c - '0'); | |
1009 | } | |
1010 | #endif | |
1011 | } | |
1012 | alarm(timelim/10); | |
1013 | if (setjmp(Sjbuf) == 0) { | |
1014 | read(dnf, &c, 1); | |
1015 | alarm(0); | |
1016 | } | |
1017 | ||
1018 | return(dnf); | |
1019 | } | |
1020 | ||
1021 | hysqcls(fd) | |
1022 | int fd; | |
1023 | { | |
1024 | char dcname[20]; | |
1025 | struct sgttyb hup, sav; | |
1026 | ||
1027 | if (fd > 0) { | |
1028 | sprintf(dcname, "/dev/%s", devSel); | |
1029 | DEBUG(4, "Hanging up fd = %d\n", fd); | |
1030 | /* | |
1031 | * code to drop DTR -- change to 0 baud then back to default. | |
1032 | */ | |
1033 | gtty(fd, &hup); | |
1034 | gtty(fd, &sav); | |
1035 | hup.sg_ispeed = B0; | |
1036 | hup.sg_ospeed = B0; | |
1037 | stty(fd, &hup); | |
1038 | sleep(2); | |
1039 | stty(fd, &sav); | |
1040 | /* | |
1041 | * now raise DTR -- close the device & open it again. | |
1042 | */ | |
1043 | sleep(2); | |
1044 | close(fd); | |
1045 | sleep(2); | |
1046 | fd = open(dcname, 2); | |
1047 | /* | |
1048 | * Since we have a getty sleeping on this line, when it wakes up it sends | |
1049 | * all kinds of garbage to the modem. Unfortunatly, the modem likes to | |
1050 | * execute the previous command when it sees the garbage. The previous | |
1051 | * command was to dial the phone, so let's make the last command reset | |
1052 | * the modem. | |
1053 | */ | |
1054 | sleep(2); | |
1055 | write(fd, "\rATZ\r", 5); | |
1056 | close(fd); | |
1057 | delock(devSel); | |
1058 | } | |
1059 | } | |
1060 | ||
1061 | #endif HAYESQ | |
1062 | ||
1063 | #ifdef VENTEL | |
1064 | ventopn(telno, flds, dev) | |
1065 | char *flds[], *telno; | |
1066 | struct Devices *dev; | |
1067 | { | |
1068 | int dh; | |
1069 | int i, ok = -1; | |
1070 | char dcname[20]; | |
1071 | ||
1072 | sprintf(dcname, "/dev/%s", dev->D_line); | |
1073 | if (setjmp(Sjbuf)) { | |
1074 | DEBUG(1, "timeout ventel open\n", ""); | |
1075 | logent("ventel open", "TIMEOUT"); | |
1076 | if (dh >= 0) | |
1077 | close(dh); | |
1078 | delock(dev->D_line); | |
1079 | return(CF_NODEV); | |
1080 | } | |
1081 | signal(SIGALRM, alarmtr); | |
1082 | getnextfd(); | |
1083 | alarm(10); | |
1084 | dh = open(dcname, 2); | |
1085 | next_fd = -1; | |
1086 | if (dh < 0) { | |
1087 | DEBUG(4,"%s\n", errno == 4 ? "no carrier" : "can't open modem"); | |
1088 | delock(dev->D_line); | |
1089 | return(errno == 4 ? CF_DIAL : CF_NODEV); | |
1090 | } | |
1091 | ||
1092 | /* modem is open */ | |
1093 | fixline(dh, dev->D_speed); | |
1094 | ||
1095 | /* translate - to % and = to & for VenTel */ | |
1096 | DEBUG(4, "calling %s -> ", telno); | |
1097 | for (i = 0; i < strlen(telno); ++i) { | |
1098 | switch(telno[i]) { | |
1099 | case '-': /* delay */ | |
1100 | telno[i] = '%'; | |
1101 | break; | |
1102 | case '=': /* await dial tone */ | |
1103 | telno[i] = '&'; | |
1104 | break; | |
1105 | case '<': | |
1106 | telno[i] = '%'; | |
1107 | break; | |
1108 | } | |
1109 | } | |
1110 | DEBUG(4, "%s\n", telno); | |
1111 | sleep(1); | |
1112 | for(i = 0; i < 5; ++i) { /* make up to 5 tries */ | |
1113 | slowrite(dh, "\r\r");/* awake, thou lowly VenTel! */ | |
1114 | ||
1115 | DEBUG(4, "wanted %s ", "$"); | |
1116 | ok = expect("$", dh); | |
1117 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
1118 | if (ok != 0) | |
1119 | continue; | |
1120 | slowrite(dh, "K"); /* "K" (enter number) command */ | |
1121 | DEBUG(4, "wanted %s ", "DIAL: "); | |
1122 | ok = expect("DIAL: ", dh); | |
1123 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
1124 | if (ok == 0) | |
1125 | break; | |
1126 | } | |
1127 | ||
1128 | if (ok == 0) { | |
1129 | slowrite(dh, telno); /* send telno, send \r */ | |
1130 | slowrite(dh, "\r"); | |
1131 | DEBUG(4, "wanted %s ", "ONLINE"); | |
1132 | ok = expect("ONLINE!", dh); | |
1133 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
1134 | } | |
1135 | if (ok != 0) { | |
1136 | if (dh > 2) | |
1137 | close(dh); | |
1138 | DEBUG(4, "venDial failed\n", ""); | |
1139 | return(CF_DIAL); | |
1140 | } else | |
1141 | DEBUG(4, "venDial ok\n", ""); | |
1142 | return(dh); | |
1143 | } | |
1144 | ||
1145 | ||
1146 | /* | |
1147 | * uucpdelay: delay execution for numerator/denominator seconds. | |
1148 | */ | |
1149 | ||
1150 | #ifdef INTERVALTIMER | |
1151 | #define uucpdelay(num,denom) intervaldelay(1000000*num/denom) | |
1152 | #include <time.h> | |
1153 | catch alarm sig | |
1154 | SIGALRM | |
1155 | struct itimerval itimerval; | |
1156 | itimerval.itimer_reload = | |
1157 | itimerval.rtime.itimer_interval = | |
1158 | itimerval.rtime.itimer_value = | |
1159 | settimer(ITIMER_REAL, &itimerval); | |
1160 | pause(); | |
1161 | alarm comes in | |
1162 | turn off timer. | |
1163 | #endif INTERVALTIMER | |
1164 | ||
1165 | #ifdef FASTTIMER | |
1166 | #define uucpdelay(num,denom) nap(60*num/denom) | |
1167 | /* Sleep in increments of 60ths of second. */ | |
1168 | nap (time) | |
1169 | register int time; | |
1170 | { | |
1171 | static int fd; | |
1172 | ||
1173 | if (fd == 0) | |
1174 | fd = open (FASTTIMER, 0); | |
1175 | ||
1176 | read (fd, 0, time); | |
1177 | } | |
1178 | #endif FASTTIMER | |
1179 | ||
1180 | #ifdef FTIME | |
1181 | #define uucpdelay(num,denom) ftimedelay(1000*num/denom) | |
1182 | #include <sys/timeb.h> | |
1183 | ftimedelay(n) | |
1184 | { | |
1185 | static struct timeb loctime; | |
1186 | ftime(&loctime); | |
1187 | {register i = loctime.millitm; | |
1188 | while (abs((int)(loctime.millitm - i))<n) ftime(&loctime); | |
1189 | } | |
1190 | } | |
1191 | #endif FTIME | |
1192 | ||
1193 | #ifdef BUSYLOOP | |
1194 | #define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom) | |
1195 | #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */ | |
1196 | #define DELAY(n) { register long N = (n); while (--N > 0); } | |
1197 | busyloop(n) | |
1198 | { | |
1199 | DELAY(n); | |
1200 | } | |
1201 | #endif BUSYLOOP | |
1202 | ||
1203 | slowrite(fd, str) | |
1204 | register char *str; | |
1205 | { | |
1206 | DEBUG(6, "slowrite ", ""); | |
1207 | while (*str) { | |
1208 | DEBUG(6, "%c", *str); | |
1209 | uucpdelay(1,10); /* delay 1/10 second */ | |
1210 | write(fd, str, 1); | |
1211 | str++; | |
1212 | } | |
1213 | DEBUG(6, "\n", ""); | |
1214 | } | |
1215 | ||
1216 | ||
1217 | ventcls(fd) | |
1218 | int fd; | |
1219 | { | |
1220 | ||
1221 | if (fd > 0) { | |
1222 | close(fd); | |
1223 | sleep(5); | |
1224 | delock(devSel); | |
1225 | } | |
1226 | } | |
1227 | #endif VENTEL | |
1228 | ||
1229 | #ifdef VADIC | |
1230 | ||
1231 | /* | |
1232 | * vadopn: establish dial-out connection through a Racal-Vadic 3450. | |
1233 | * Returns descriptor open to tty for reading and writing. | |
1234 | * Negative values (-1...-7) denote errors in connmsg. | |
1235 | * Be sure to disconnect tty when done, via HUPCL or stty 0. | |
1236 | */ | |
1237 | ||
1238 | vadopn(telno, flds, dev) | |
1239 | char *telno; | |
1240 | char *flds[]; | |
1241 | struct Devices *dev; | |
1242 | { | |
1243 | int dh = -1; | |
1244 | int i, ok, er = 0; | |
1245 | extern errno; | |
1246 | char dcname[20]; | |
1247 | ||
1248 | sprintf(dcname, "/dev/%s", dev->D_line); | |
1249 | if (setjmp(Sjbuf)) { | |
1250 | DEBUG(1, "timeout vadic open\n", ""); | |
1251 | logent("vadic open", "TIMEOUT"); | |
1252 | if (dh >= 0) | |
1253 | close(dh); | |
1254 | delock(dev->D_line); | |
1255 | return(CF_NODEV); | |
1256 | } | |
1257 | signal(SIGALRM, alarmtr); | |
1258 | getnextfd(); | |
1259 | alarm(10); | |
1260 | dh = open(dcname, 2); | |
1261 | alarm(0); | |
1262 | ||
1263 | /* modem is open */ | |
1264 | next_fd = -1; | |
1265 | if (dh < 0) { | |
1266 | delock(dev->D_line); | |
1267 | return(CF_NODEV); | |
1268 | } | |
1269 | fixline(dh, dev->D_speed); | |
1270 | ||
1271 | /* translate - to % and = to & for VenTel */ | |
1272 | DEBUG(4, "calling %s -> ", telno); | |
1273 | for (i = 0; i < strlen(telno); ++i) { | |
1274 | switch(telno[i]) { | |
1275 | case '=': /* await dial tone */ | |
1276 | case '<': | |
1277 | telno[i] = 'K'; | |
1278 | break; | |
1279 | } | |
1280 | } | |
1281 | DEBUG(4, "%s\n", telno); | |
1282 | sleep(1); | |
1283 | for(i = 0; i < 5; ++i) { /* make 5 tries */ | |
1284 | /* wake up Vadic */ | |
1285 | write(dh, "\005\r", 2); | |
1286 | DEBUG(4, "wanted %s ", "*"); | |
1287 | ok = expect("*", dh); | |
1288 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
1289 | if (ok != 0) | |
1290 | continue; | |
1291 | ||
1292 | write(dh, "D\r", 2); /* "D" (enter number) command */ | |
1293 | DEBUG(4, "wanted %s ", "NUMBER?"); | |
1294 | ok = expect("NUMBER?", dh); | |
1295 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
1296 | if (ok != 0) | |
1297 | continue; | |
1298 | ||
1299 | /* send telno, send \r */ | |
1300 | write(dh, telno, strlen(telno)); | |
1301 | sleep(1); | |
1302 | write(dh, "\r", 1); | |
1303 | ok = expect(telno, dh); | |
1304 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
1305 | if (ok != 0) | |
1306 | continue; | |
1307 | ||
1308 | write(dh, "\r", 1); /* confirm number */ | |
1309 | DEBUG(4, "wanted %s ", "DIALING: "); | |
1310 | ok = expect("DIALING: ", dh); | |
1311 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
1312 | if (ok == 0) | |
1313 | break; | |
1314 | } | |
1315 | ||
1316 | if (ok == 0) { | |
1317 | /* send telno, send \r */ | |
1318 | write(dh, telno, strlen(telno)); | |
1319 | write(dh, "\r", 1); | |
1320 | DEBUG(4, "wanted %s ", "ON LINE"); | |
1321 | ok = expect("ON LINE", dh); | |
1322 | DEBUG(4, "got %s\n", ok ? "?" : "that"); | |
1323 | } | |
1324 | ||
1325 | if (ok != 0) { | |
1326 | if (dh > 2) | |
1327 | close(dh); | |
1328 | DEBUG(4, "vadDial failed\n", ""); | |
1329 | delock(dev->D_line); | |
1330 | return(CF_DIAL); | |
1331 | } | |
1332 | DEBUG(4, "vadic ok\n", ""); | |
1333 | return(dh); | |
1334 | } | |
1335 | ||
1336 | vadcls(fd) { | |
1337 | ||
1338 | if (fd > 0) { | |
1339 | close(fd); | |
1340 | sleep(5); | |
1341 | delock(devSel); | |
1342 | } | |
1343 | } | |
1344 | ||
1345 | #endif VADIC | |
1346 | ||
1347 | #ifdef RVMACS | |
1348 | /* | |
1349 | * Racal-Vadic 'RV820' MACS system with 831 adaptor. | |
1350 | * A typical 300 baud L-devices entry is | |
1351 | * ACU /dev/tty10 /dev/tty11,48 300 rvmacs | |
1352 | * where tty10 is the communication line (D_Line), | |
1353 | * tty11 is the dialer line (D_calldev), | |
1354 | * the '4' is the dialer address + modem type (viz. dialer 0, Bell 103), | |
1355 | * and the '8' is the communication port (they are 1-indexed). | |
1356 | * BUGS: | |
1357 | * Only tested with one dialer, one modem | |
1358 | * uses common speed for dialer and communication line. | |
1359 | * UNTESTED | |
1360 | */ | |
1361 | ||
1362 | #define STX 02 /* Access Adaptor */ | |
1363 | #define ETX 03 /* Transfer to Dialer */ | |
1364 | #define SI 017 /* Buffer Empty (end of phone number) */ | |
1365 | #define SOH 01 /* Abort */ | |
1366 | ||
1367 | rvmacsopn(ph, flds, dev) | |
1368 | char *ph, *flds[]; | |
1369 | struct Devices *dev; | |
1370 | { | |
1371 | register int va, i, child; | |
1372 | register char *p; | |
1373 | char c, acu[20], com[20]; | |
1374 | ||
1375 | child = -1; | |
1376 | if ((p = index(dev->D_calldev, ',')) == NULL) { | |
1377 | DEBUG(2, "No dialer/modem specification\n", 0); | |
1378 | goto failret; | |
1379 | } | |
1380 | *p++ = '\0'; | |
1381 | if (setjmp(Sjbuf)) { | |
1382 | logent("rvmacsopn", "TIMEOUT"); | |
1383 | i = CF_DIAL; | |
1384 | goto ret; | |
1385 | } | |
1386 | DEBUG(4, "STARTING CALL\n", 0); | |
1387 | sprintf(acu, "/dev/%s", dev->D_calldev); | |
1388 | getnextfd(); | |
1389 | signal(SIGALRM, alarmtr); | |
1390 | alarm(30); | |
1391 | if ((va = open(acu, 2)) < 0) { | |
1392 | logent(acu, "CAN'T OPEN"); | |
1393 | i = CF_NODEV; | |
1394 | goto ret; | |
1395 | } | |
1396 | fixline(va, dev->D_speed); | |
1397 | ||
1398 | p_chwrite(va, STX); /* access adaptor */ | |
1399 | i = *p++ - '0'; | |
1400 | if (i < 0 || i > 7) { | |
1401 | logent(p-1, "Bad dialer address/modem type\n"); | |
1402 | goto failret; | |
1403 | } | |
1404 | p_chwrite(va, i); /* Send Dialer Address Digit */ | |
1405 | i = *p - '0'; | |
1406 | if (i <= 0 || i > 14) { | |
1407 | logent(p-1, "Bad modem address\n"); | |
1408 | goto failret; | |
1409 | } | |
1410 | p_chwrite(va, i-1); /* Send Modem Address Digit */ | |
1411 | write(va, ph, strlen(ph)); /* Send Phone Number */ | |
1412 | p_chwrite(va, SI); /* Send Buffer Empty */ | |
1413 | p_chwrite(va, ETX); /* Initiate Call */ | |
1414 | sprintf(com, "/dev/%s", dev->D_line); | |
1415 | ||
1416 | /* create child to open comm line */ | |
1417 | if ((child = fork()) == 0) { | |
1418 | signal(SIGINT, SIG_DFL); | |
1419 | open(com, 0); | |
1420 | sleep(5); | |
1421 | exit(1); | |
1422 | } | |
1423 | ||
1424 | if (read(va, &c, 1) != 1) { | |
1425 | logent("ACU READ", "FAILED"); | |
1426 | goto failret; | |
1427 | } | |
1428 | switch(c) { | |
1429 | case 'A': | |
1430 | /* Fine! */ | |
1431 | break; | |
1432 | case 'B': | |
1433 | DEBUG(2, "CALL ABORTED\n", 0); | |
1434 | goto failret; | |
1435 | case 'D': | |
1436 | DEBUG(2, "Dialer format error\n", 0); | |
1437 | goto failret; | |
1438 | case 'E': | |
1439 | DEBUG(2, "Dialer parity error\n", 0); | |
1440 | goto failret; | |
1441 | case 'F': | |
1442 | DEBUG(2, "Phone number too long\n", 0); | |
1443 | goto failret; | |
1444 | case 'G': | |
1445 | DEBUG(2, "Busy signal\n", 0); | |
1446 | goto failret; | |
1447 | default: | |
1448 | DEBUG(2, "Unknown MACS return code '%c'\n", i); | |
1449 | goto failret; | |
1450 | } | |
1451 | /* | |
1452 | * open line - will return on carrier | |
1453 | */ | |
1454 | if ((i = open(com, 2)) < 0) { | |
1455 | if (errno == EIO) | |
1456 | logent("carrier", "LOST"); | |
1457 | else | |
1458 | logent("dialup open", "FAILED"); | |
1459 | goto failret; | |
1460 | } | |
1461 | fixline(i, dev->D_speed); | |
1462 | goto ret; | |
1463 | failret: | |
1464 | i = CF_DIAL; | |
1465 | ret: | |
1466 | alarm(0); | |
1467 | if (child != -1) | |
1468 | kill(child, SIGKILL); | |
1469 | close(va); | |
1470 | return(i); | |
1471 | } | |
1472 | ||
1473 | rvmacscls(fd) | |
1474 | register int fd; | |
1475 | { | |
1476 | DEBUG(2, "MACS close %d\n", fd); | |
1477 | p_chwrite(fd, SOH); | |
1478 | /* ioctl(fd, TIOCCDTR, NULL);*/ | |
1479 | close(fd); | |
1480 | } | |
1481 | #endif |