date and time created 83/07/02 17:56:33 by sam
[unix-history] / usr / src / usr.bin / uucp / uucico / condevs.c
CommitLineData
572555ee
SL
1#ifndef lint
2static 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
40extern char devSel[]; /* name to pass to delock() in close */
41extern int errno, next_fd;
42extern jmp_buf Sjbuf;
43extern int alarmtr();
44int nulldev(), nodev(), Acuopn(), diropn(), dircls();
45
46#ifdef DATAKIT
47int dkopn();
48#endif
49#ifdef DN11
50int dnopn(), dncls();
51#endif
52#ifdef HAYES
53int hysopn(), hyscls();
54#endif
55#ifdef HAYESQ
56int hysqopn(), hysqcls(); /* a version of hayes that doesn't use ret codes */
57#endif
58#ifdef DF02
59int df2opn(), df2cls();
60#endif
61#ifdef PNET
62int pnetopn();
63#endif
64#ifdef VENTEL
65int ventopn(), ventcls();
66#endif
67#ifdef UNET
68#include <UNET/unetio.h>
69#include <UNET/tcp.h>
70int unetopn(), unetcls();
71#endif UNET
72#ifdef VADIC
73int vadopn(), vadcls();
74#endif VADIC
75#ifdef RVMACS
76int rvmacsopn(), rvmacscls();
77#endif
78#ifdef MICOM
79int micopn(), miccls();
80#endif MICOM
81
82struct 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 */
124int nulldev()
125{
126 return(CF_DIAL);
127}
128
129/***
130 * nodev a null device (returns CF_NODEV)
131 */
132int 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
155diropn(flds)
156register 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
203dircls(fd)
204register 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
225dkopn(flds)
226char *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
262pnetopn(flds)
263char *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
307unetopn(flds)
308register 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 */
340unetcls(fd)
341register 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 */
363micopn(flds)
364register 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
450miccls(fd)
451register 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
470char devSel[20]; /* used for later unlock() */
471
472Acuopn(flds)
473register 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
531dnopn(ph, flds, dev)
532char *ph;
533char *flds[];
534struct 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(&lt)) != 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 */
650dncls(fd)
651register 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
677df2opn(ph, flds, dev)
678char *ph;
679char *flds[];
680struct 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(&lt)) != 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
800df2cls(fd)
801register 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
825hysopn(telno, flds, dev)
826char *telno;
827char *flds[];
828struct 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
878hyscls(fd)
879int 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
949hysqopn(telno, flds, dev)
950register char *telno, *flds[];
951struct 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
1021hysqcls(fd)
1022int 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
1064ventopn(telno, flds, dev)
1065char *flds[], *telno;
1066struct 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>
1153catch alarm sig
1154SIGALRM
1155struct itimerval itimerval;
1156itimerval.itimer_reload =
1157itimerval.rtime.itimer_interval =
1158itimerval.rtime.itimer_value =
1159settimer(ITIMER_REAL, &itimerval);
1160pause();
1161alarm comes in
1162turn 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. */
1168nap (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>
1183ftimedelay(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); }
1197busyloop(n)
1198 {
1199 DELAY(n);
1200 }
1201#endif BUSYLOOP
1202
1203slowrite(fd, str)
1204register 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
1217ventcls(fd)
1218int 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
1238vadopn(telno, flds, dev)
1239char *telno;
1240char *flds[];
1241struct 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
1336vadcls(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
1367rvmacsopn(ph, flds, dev)
1368char *ph, *flds[];
1369struct 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;
1463failret:
1464 i = CF_DIAL;
1465ret:
1466 alarm(0);
1467 if (child != -1)
1468 kill(child, SIGKILL);
1469 close(va);
1470 return(i);
1471}
1472
1473rvmacscls(fd)
1474register 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