|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)condevs.c 5.20 (Berkeley) 5/4/88";
3: #endif
4:
5: extern int errno;
6: extern char *sys_errlist[];
7:
8: /*
9: * Here are various dialers to establish the machine-machine connection.
10: * conn.c/condevs.c was glued together by Mike Mitchell.
11: * The dialers were supplied by many people, to whom we are grateful.
12: *
13: * ---------------------------------------------------------------------
14: * NOTE:
15: * There is a bug that occurs at least on PDP11s due to a limitation of
16: * setjmp/longjmp. If the routine that does a setjmp is interrupted
17: * and longjmp-ed to, it loses its register variables (on a pdp11).
18: * What works is if the routine that does the setjmp
19: * calls a routine and it is the *subroutine* that is interrupted.
20: *
21: * Anyway, in conclusion, condevs.c is plagued with register variables
22: * that are used inside
23: * if (setjmp(...)) {
24: * ....
25: * }
26: *
27: * THE FIX: Don't declare variables to be register
28: */
29:
30: #include "condevs.h"
31:
32: struct condev condevs[] = {
33: { "DIR", "direct", diropn, nulldev, dircls },
34: #ifdef DATAKIT
35: { "DK", "datakit", dkopn, nulldev, nulldev },
36: #endif DATAKIT
37: #ifdef PNET
38: { "PNET", "pnet", pnetopn, nulldev, nulldev },
39: #endif PNET
40: #ifdef UNETTCP
41: { "TCP", "TCP", unetopn, nulldev, unetcls },
42: #endif UNETTCP
43: #ifdef BSDTCP
44: { "TCP", "TCP", bsdtcpopn, nulldev, bsdtcpcls },
45: #endif BSDTCP
46: #ifdef MICOM
47: { "MICOM", "micom", micopn, nulldev, miccls },
48: #endif MICOM
49: #ifdef DN11
50: { "ACU", "dn11", Acuopn, dnopn, dncls },
51: #endif DN11
52: #ifdef HAYES
53: { "ACU", "hayes", Acuopn, hyspopn, hyscls },
54: { "ACU", "hayespulse", Acuopn, hyspopn, hyscls },
55: { "ACU", "hayestone", Acuopn, hystopn, hyscls },
56: { "WATS", "hayestone", Acuopn, hystopn, hyscls },
57: #endif HAYES
58: #ifdef HAYES2400
59: { "ACU", "hayes2400", Acuopn, hyspopn24, hyscls24 },
60: { "ACU", "hayes2400pulse", Acuopn, hyspopn24, hyscls24 },
61: { "ACU", "hayes2400tone", Acuopn, hystopn24, hyscls24 },
62: #endif HAYES2400
63: #ifdef HAYESQ /* a version of hayes that doesn't use result codes */
64: { "ACU", "hayesq", Acuopn, hysqpopn, hysqcls },
65: { "ACU", "hayesqpulse", Acuopn, hysqpopn, hysqcls },
66: { "ACU", "hayesqtone", Acuopn, hysqtopn, hysqcls },
67: #endif HAYESQ
68: #ifdef CDS224
69: { "ACU", "cds224", Acuopn, cdsopn224, cdscls224},
70: #endif CDS224
71: #ifdef NOVATION
72: { "ACU", "novation", Acuopn, novopn, novcls},
73: #endif NOVATION
74: #ifdef DF02
75: { "ACU", "DF02", Acuopn, df2opn, df2cls },
76: #endif DF02
77: #ifdef DF112
78: { "ACU", "DF112P", Acuopn, df12popn, df12cls },
79: { "ACU", "DF112T", Acuopn, df12topn, df12cls },
80: #endif DF112
81: #ifdef VENTEL
82: { "ACU", "ventel", Acuopn, ventopn, ventcls },
83: #endif VENTEL
84: #ifdef PENRIL
85: { "ACU", "penril", Acuopn, penopn, pencls },
86: #endif PENRIL
87: #ifdef VADIC
88: { "ACU", "vadic", Acuopn, vadopn, vadcls },
89: #endif VADIC
90: #ifdef VA212
91: { "ACU", "va212", Acuopn, va212opn, va212cls },
92: #endif VA212
93: #ifdef VA811S
94: { "ACU", "va811s", Acuopn, va811opn, va811cls },
95: #endif VA811S
96: #ifdef VA820
97: { "ACU", "va820", Acuopn, va820opn, va820cls },
98: { "WATS", "va820", Acuopn, va820opn, va820cls },
99: #endif VA820
100: #ifdef RVMACS
101: { "ACU", "rvmacs", Acuopn, rvmacsopn, rvmacscls },
102: #endif RVMACS
103: #ifdef VMACS
104: { "ACU", "vmacs", Acuopn, vmacsopn, vmacscls },
105: #endif VMACS
106: #ifdef SYTEK
107: { "SYTEK", "sytek", sykopn, nulldev, sykcls },
108: #endif SYTEK
109: #ifdef ATT2224
110: { "ACU", "att", Acuopn, attopn, attcls },
111: #endif ATT2224
112:
113:
114: /* Insert new entries before this line */
115: { NULL, NULL, NULL, NULL, NULL }
116: };
117:
118: /*
119: * nulldev a null device (returns CF_DIAL)
120: */
121: nulldev()
122: {
123: return CF_DIAL;
124: }
125:
126: /*
127: * nodev a null device (returns CF_NODEV)
128: */
129: nodev()
130: {
131: return CF_NODEV;
132: }
133:
134: /*
135: * Generic devices look through L-devices and call the CU_open routines for
136: * appropriate devices. Some things, like the tcp/ip interface, or direct
137: * connect, do not use the CU_open entry. ACUs must search to find the
138: * right routine to call.
139: */
140:
141: /*
142: * diropn(flds) connect to hardware line
143: *
144: * return codes:
145: * > 0 - file number - ok
146: * FAIL - failed
147: */
148: diropn(flds)
149: register char *flds[];
150: {
151: register int dcr, status;
152: struct Devices dev;
153: char dcname[20];
154: FILE *dfp;
155: #ifdef VMSDTR /* Modem control on vms(works dtr) */
156: int modem_control;
157: short iosb[4];
158: int sys$qiow(); /* use this for long reads on vms */
159: int ret;
160: long mode[2];
161: modem_control = 0;
162: #endif
163: dfp = fopen(DEVFILE, "r");
164: if (dfp == NULL) {
165: syslog(LOG_ERR, "fopen(%s) failed: %m", DEVFILE);
166: cleanup(FAIL);
167: }
168: while ((status = rddev(dfp, &dev)) != FAIL) {
169: #ifdef VMSDTR /* Modem control on vms(works dtr) */
170: /* If we find MOD in the device type field we go into action */
171: if (strcmp(dev.D_type, "MOD") == SAME) {
172: modem_control = 1;
173: DEBUG(7, "Setting Modem control to %d",modem_control);
174: }
175: if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
176: continue;
177: /*
178: * Modem control on vms(works dtr) Take anything in MOD class.
179: * It probably should work differently anyway so we can have
180: * multiple hardwired lines.
181: */
182: if (!modem_control&&strcmp(flds[F_PHONE], dev.D_line) != SAME)
183: #else !VMSDTR
184: if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
185: continue;
186: if (strcmp(flds[F_PHONE], dev.D_line) != SAME)
187: #endif !VMSDTR
188: continue;
189: if (mlock(dev.D_line) != FAIL)
190: break;
191: }
192: fclose(dfp);
193: if (status == FAIL) {
194: logent("DEVICE", "NO");
195: return CF_NODEV;
196: }
197:
198: sprintf(dcname, "/dev/%s", dev.D_line);
199: if (setjmp(Sjbuf)) {
200: DEBUG(4, "Open timed out\n", CNULL);
201: delock(dev.D_line);
202: return CF_DIAL;
203: }
204: signal(SIGALRM, alarmtr);
205: /* For PC Pursuit, it could take a while to call back */
206: alarm( strcmp(flds[F_LINE], "PCP") ? 10 : MAXMSGTIME*4 );
207: getnextfd();
208: errno = 0;
209: DEBUG(4,"Opening %s\n",dcname);
210: dcr = open(dcname, 2); /* read/write */
211: #ifdef VMSDTR /* Modem control on vms(works dtr) */
212: fflush(stdout);
213: if (modem_control) { /* Did we have MOD in the device type field ? */
214: /* Sense the current terminal setup and save it */
215: if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv,
216: IO$_SENSEMODE,iosb,0,0,mode,8,0,0,0,0))
217: != SS$_NORMAL) {
218: DEBUG(7, "ret status on sense failed on Modem sense=%x<", ret);
219: return CF_DIAL;
220: }
221: mode[1] |= TT$M_MODEM; /* Or in modem control(DTR) */
222: /* Now set the new terminal characteristics */
223: /* This is temporary and will go away when we let go of it */
224: if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv,
225: IO$_SETMODE,iosb,0,0,mode,8,0,0,0,0))
226: != SS$_NORMAL) {
227: DEBUG(7, "ret status on sense failed on Modem setup=%x<", ret);
228: return CF_DIAL;
229: }
230: }
231: #endif VMSDTR
232: next_fd = -1;
233: alarm(0);
234: if (dcr < 0) {
235: if (errno == EACCES)
236: logent(dev.D_line, "CANT OPEN");
237: DEBUG(4, "OPEN FAILED: errno %d\n", errno);
238: delock(dev.D_line);
239: return CF_DIAL;
240: }
241: fflush(stdout);
242: if (fixline(dcr, dev.D_speed) == FAIL) {
243: DEBUG(4, "FIXLINE FAILED\n", CNULL);
244: return CF_DIAL;
245: }
246: strcpy(devSel, dev.D_line); /* for latter unlock */
247: CU_end = dircls;
248: return dcr;
249: }
250:
251: dircls(fd)
252: register int fd;
253: {
254: if (fd > 0) {
255: close(fd);
256: delock(devSel);
257: }
258: }
259:
260: /*
261: * open an ACU and dial the number. The condevs table
262: * will be searched until a dialing unit is found that is free.
263: *
264: * return codes: >0 - file number - o.k.
265: * FAIL - failed
266: */
267: char devSel[20]; /* used for later unlock() */
268:
269: Acuopn(flds)
270: register char *flds[];
271: {
272: char phone[MAXPH+1];
273: register struct condev *cd;
274: register int fd, acustatus;
275: register FILE *dfp;
276: struct Devices dev;
277: int retval = CF_NODEV;
278: char nobrand[MAXPH], *line;
279:
280: exphone(flds[F_PHONE], phone);
281: if (snccmp(flds[F_LINE], "LOCAL") == SAME)
282: line = "ACU";
283: else
284: line = flds[F_LINE];
285: devSel[0] = '\0';
286: nobrand[0] = '\0';
287: DEBUG(4, "Dialing %s\n", phone);
288: dfp = fopen(DEVFILE, "r");
289: if (dfp == NULL) {
290: syslog(LOG_ERR, "fopen(%s) failed: %m", DEVFILE);
291: cleanup(FAIL);
292: }
293:
294: acustatus = 0; /* none found, none locked */
295: while (rddev(dfp, &dev) != FAIL) {
296: /*
297: * for each ACU L.sys line, try at most twice
298: * (TRYCALLS) to establish carrier. The old way tried every
299: * available dialer, which on big sites takes forever!
300: * Sites with a single auto-dialer get one try.
301: * Sites with multiple dialers get a try on each of two
302: * different dialers.
303: * To try 'harder' to connect to a remote site,
304: * use multiple L.sys entries.
305: */
306: if (acustatus > TRYCALLS)
307: break;
308: if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
309: continue;
310: if (snccmp(line, dev.D_type) != SAME)
311: continue;
312: if (dev.D_brand[0] == '\0') {
313: logent("Acuopn","No 'brand' name on ACU");
314: continue;
315: }
316: for(cd = condevs; cd->CU_meth != NULL; cd++) {
317: if (snccmp(line, cd->CU_meth) == SAME) {
318: if (snccmp(dev.D_brand, cd->CU_brand) == SAME) {
319: nobrand[0] = '\0';
320: break;
321: }
322: strncpy(nobrand, dev.D_brand, sizeof nobrand);
323: }
324: }
325:
326: if (acustatus < 1)
327: acustatus = 1; /* has been found */
328:
329: if (mlock(dev.D_line) == FAIL)
330: continue;
331:
332: #ifdef DIALINOUT
333: #ifdef ALLACUINOUT
334: if (1) {
335: #else !ALLACUINOUT
336: if (snccmp("inout", dev.D_calldev) == SAME) {
337: #endif !ALLACUINOUT
338: if (disable(dev.D_line) == FAIL) {
339: delock(dev.D_line);
340: continue;
341: }
342: } else
343: reenable();
344: #endif DIALINOUT
345:
346: DEBUG(4, "Using %s\n", cd->CU_brand);
347: acustatus++;
348: fd = (*(cd->CU_open))(phone, flds, &dev);
349: if (fd > 0) {
350: CU_end = cd->CU_clos; /* point CU_end at close func */
351: fclose(dfp);
352: strcpy(devSel, dev.D_line); /* save for later unlock() */
353: return fd;
354: } else
355: delock(dev.D_line);
356: retval = CF_DIAL;
357: }
358: fclose(dfp);
359: if (acustatus == 0) {
360: if (nobrand[0])
361: logent(nobrand, "unsupported ACU type");
362: else
363: logent("L-devices", "No appropriate ACU");
364: }
365: if (acustatus == 1)
366: logent("DEVICE", "NO");
367: return retval;
368: }
369:
370: /*
371: * intervaldelay: delay execution for numerator/denominator seconds.
372: */
373:
374: #ifdef INTERVALTIMER
375: #include <sys/time.h>
376: #define uucpdelay(num,denom) intervaldelay(num,denom)
377: intervaldelay(num,denom)
378: int num, denom;
379: {
380: struct timeval tv;
381: tv.tv_sec = num / denom;
382: tv.tv_usec = (num * 1000000L / denom ) % 1000000L;
383: (void) select (0, (int *)0, (int *)0, (int *)0, &tv);
384: }
385: #endif INTERVALTIMER
386:
387: #ifdef FASTTIMER
388: #define uucpdelay(num,denom) nap(60*num/denom)
389: /* Sleep in increments of 60ths of second. */
390: nap (time)
391: register int time;
392: {
393: static int fd;
394:
395: if (fd == 0)
396: fd = open (FASTTIMER, 0);
397:
398: read (fd, 0, time);
399: }
400: #endif FASTTIMER
401:
402: #ifdef FTIME
403: #define uucpdelay(num,denom) ftimedelay(1000*num/denom)
404: ftimedelay(n)
405: {
406: static struct timeb loctime;
407: register i = loctime.millitm;
408:
409: ftime(&loctime);
410: while (abs((int)(loctime.millitm - i))<n) ftime(&loctime)
411: ;
412: }
413: #endif FTIME
414:
415: #ifdef BUSYLOOP
416: #define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom)
417: #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */
418: #define DELAY(n) { register long N = (n); while (--N > 0); }
419: busyloop(n)
420: {
421: DELAY(n);
422: }
423: #endif BUSYLOOP
424:
425: slowrite(fd, str)
426: register char *str;
427: {
428: DEBUG(6, "slowrite ", CNULL);
429: while (*str) {
430: DEBUG(6, "%c", *str);
431: uucpdelay(1, 10); /* delay 1/10 second */
432: write(fd, str, 1);
433: str++;
434: }
435: DEBUG(6, "\n", CNULL);
436: }
437:
438: #define BSPEED B150
439:
440: /*
441: * send a break
442: */
443: genbrk(fn, bnulls)
444: register int fn, bnulls;
445: {
446: #ifdef USG
447: if (ioctl(fn, TCSBRK, STBNULL) < 0)
448: DEBUG(5, "break TCSBRK %s\n", sys_errlist[errno]);
449: #else !USG
450: # ifdef TIOCSBRK
451: if (ioctl(fn, TIOCSBRK, STBNULL) < 0)
452: DEBUG(5, "break TIOCSBRK %s\n", sys_errlist[errno]);
453: # ifdef TIOCCBRK
454: uucpdelay(bnulls, 10);
455: if (ioctl(fn, TIOCCBRK, STBNULL) < 0)
456: DEBUG(5, "break TIOCCBRK %s\n", sys_errlist[errno]);
457: # endif TIOCCBRK
458: DEBUG(4, "ioctl %f second break\n", (float) bnulls/10 );
459: # else !TIOCSBRK
460: struct sgttyb ttbuf;
461: register int sospeed;
462:
463: if (ioctl(fn, TIOCGETP, &ttbuf) < 0)
464: DEBUG(5, "break TIOCGETP %s\n", sys_errlist[errno]);
465: sospeed = ttbuf.sg_ospeed;
466: ttbuf.sg_ospeed = BSPEED;
467: if (ioctl(fn, TIOCSETP, &ttbuf) < 0)
468: DEBUG(5, "break TIOCSETP %s\n", sys_errlist[errno]);
469: if (write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls) != bnulls) {
470: badbreak:
471: logent(sys_errlist[errno], "BAD WRITE genbrk");
472: alarm(0);
473: longjmp(Sjbuf, 3);
474: }
475: ttbuf.sg_ospeed = sospeed;
476: if (ioctl(fn, TIOCSETP, &ttbuf) < 0)
477: DEBUG(5, "break ioctl %s\n", sys_errlist[errno]);
478: if (write(fn, "@", 1) != 1)
479: goto badbreak;
480: DEBUG(4, "sent BREAK nulls - %d\n", bnulls);
481: #endif !TIOCSBRK
482: #endif !USG
483: }
484:
485:
486: #ifdef DIALINOUT
487: /* DIALIN/OUT CODE (WLS) */
488: /*
489: * disable and reenable: allow a single line to be use for dialin/dialout
490: *
491: */
492:
493: char enbdev[16];
494:
495: disable(dev)
496: register char *dev;
497: {
498: register char *rdev;
499:
500: /* strip off directory prefixes */
501: rdev = dev;
502: while (*rdev)
503: rdev++;
504: while (--rdev >= dev && *rdev != '/')
505: ;
506: rdev++;
507:
508: if (enbdev[0]) {
509: if (strcmp(enbdev, rdev) == SAME)
510: return SUCCESS; /* already disabled */
511: delock(enbdev);
512: reenable(); /* else, reenable the old one */
513: }
514: DEBUG(4, "Disable %s\n", rdev);
515: if (enbcall("disable", rdev) == FAIL)
516: return FAIL;
517: strcpy(enbdev, rdev);
518: return SUCCESS;
519: }
520:
521: reenable()
522: {
523: if (enbdev[0] == '\0')
524: return;
525: DEBUG(4, "Reenable %s\n", enbdev);
526: (void) enbcall("enable", enbdev);
527: enbdev[0] = '\0';
528: }
529:
530: enbcall(type, dev)
531: char *type, *dev;
532: {
533: int pid;
534: register char *p;
535: int fildes[2];
536: int status;
537: FILE *fil;
538: char buf[80];
539:
540: fflush(stderr);
541: fflush(stdout);
542: pipe(fildes);
543: if ((pid = fork()) == 0) {
544: DEBUG(4, DIALINOUT, CNULL);
545: DEBUG(4, " %s", type);
546: DEBUG(4, " %s\n", dev);
547: close(fildes[0]);
548: close(0); close(1); close(2);
549: open("/dev/null",0);
550: dup(fildes[1]); dup(fildes[1]);
551: setuid(geteuid()); /* for chown(uid()) in acu program */
552: execl(DIALINOUT, "acu", type, dev, Rmtname, (char *)0);
553: exit(-1);
554: }
555: if (pid<0)
556: return FAIL;
557:
558: close(fildes[1]);
559: fil = fdopen(fildes[0],"r");
560: if (fil!=NULL) {
561: #ifdef BSD4_2
562: setlinebuf(fil);
563: #endif BSD4_2
564: while (fgets(buf, sizeof buf, fil) != NULL) {
565: p = buf + strlen(buf) - 1;
566: if (*p == '\n')
567: *p = '\0';
568: DEBUG(4, "ACUCNTRL: %s\n", buf);
569: }
570: }
571: while(wait(&status) != pid)
572: ;
573: fclose(fil);
574: return status ? FAIL : SUCCESS;
575: }
576: #endif DIALINOUT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.