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