|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)condevs.c 5.15 (Berkeley) 2/12/86";
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: ASSERT(dfp != NULL, "CAN'T OPEN", DEVFILE, 0);
165: while ((status = rddev(dfp, &dev)) != FAIL) {
166: #ifdef VMSDTR /* Modem control on vms(works dtr) */
167: /* If we find MOD in the device type field we go into action */
168: if (strcmp(dev.D_type, "MOD") == SAME) {
169: modem_control = 1;
170: DEBUG(7, "Setting Modem control to %d",modem_control);
171: }
172: if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
173: continue;
174: /*
175: * Modem control on vms(works dtr) Take anything in MOD class.
176: * It probably should work differently anyway so we can have
177: * multiple hardwired lines.
178: */
179: if (!modem_control&&strcmp(flds[F_PHONE], dev.D_line) != SAME)
180: #else !VMSDTR
181: if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
182: continue;
183: if (strcmp(flds[F_PHONE], dev.D_line) != SAME)
184: #endif !VMSDTR
185: continue;
186: if (mlock(dev.D_line) != FAIL)
187: break;
188: }
189: fclose(dfp);
190: if (status == FAIL) {
191: logent("DEVICE", "NO");
192: return CF_NODEV;
193: }
194:
195: sprintf(dcname, "/dev/%s", dev.D_line);
196: if (setjmp(Sjbuf)) {
197: DEBUG(4, "Open timed out\n", CNULL);
198: delock(dev.D_line);
199: return CF_DIAL;
200: }
201: signal(SIGALRM, alarmtr);
202: /* For PC Pursuit, it could take a while to call back */
203: alarm( strcmp(flds[F_LINE], "PCP") ? 10 : MAXMSGTIME*4 );
204: getnextfd();
205: errno = 0;
206: DEBUG(4,"Opening %s\n",dcname);
207: dcr = open(dcname, 2); /* read/write */
208: #ifdef VMSDTR /* Modem control on vms(works dtr) */
209: fflush(stdout);
210: if (modem_control) { /* Did we have MOD in the device type field ? */
211: /* Sense the current terminal setup and save it */
212: if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv,
213: IO$_SENSEMODE,iosb,0,0,mode,8,0,0,0,0))
214: != SS$_NORMAL) {
215: DEBUG(7, "ret status on sense failed on Modem sense=%x<", ret);
216: return CF_DIAL;
217: }
218: mode[1] |= TT$M_MODEM; /* Or in modem control(DTR) */
219: /* Now set the new terminal characteristics */
220: /* This is temporary and will go away when we let go of it */
221: if ((ret = sys$qiow(_$EFN,(fd_fab_pointer[dcr]->fab).fab$l_stv,
222: IO$_SETMODE,iosb,0,0,mode,8,0,0,0,0))
223: != SS$_NORMAL) {
224: DEBUG(7, "ret status on sense failed on Modem setup=%x<", ret);
225: return CF_DIAL;
226: }
227: }
228: #endif VMSDTR
229: next_fd = -1;
230: alarm(0);
231: if (dcr < 0) {
232: if (errno == EACCES)
233: logent(dev.D_line, "CANT OPEN");
234: DEBUG(4, "OPEN FAILED: errno %d\n", errno);
235: delock(dev.D_line);
236: return CF_DIAL;
237: }
238: fflush(stdout);
239: if (fixline(dcr, dev.D_speed) == FAIL) {
240: DEBUG(4, "FIXLINE FAILED\n", CNULL);
241: return CF_DIAL;
242: }
243: strcpy(devSel, dev.D_line); /* for latter unlock */
244: CU_end = dircls;
245: return dcr;
246: }
247:
248: dircls(fd)
249: register int fd;
250: {
251: if (fd > 0) {
252: close(fd);
253: delock(devSel);
254: }
255: }
256:
257: /*
258: * open an ACU and dial the number. The condevs table
259: * will be searched until a dialing unit is found that is free.
260: *
261: * return codes: >0 - file number - o.k.
262: * FAIL - failed
263: */
264: char devSel[20]; /* used for later unlock() */
265:
266: Acuopn(flds)
267: register char *flds[];
268: {
269: char phone[MAXPH+1];
270: register struct condev *cd;
271: register int fd, acustatus;
272: register FILE *dfp;
273: struct Devices dev;
274: int retval = CF_NODEV;
275: char nobrand[MAXPH], *line;
276:
277: exphone(flds[F_PHONE], phone);
278: if (snccmp(flds[F_LINE], "LOCAL") == SAME)
279: line = "ACU";
280: else
281: line = flds[F_LINE];
282: devSel[0] = '\0';
283: nobrand[0] = '\0';
284: DEBUG(4, "Dialing %s\n", phone);
285: dfp = fopen(DEVFILE, "r");
286: ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
287:
288: acustatus = 0; /* none found, none locked */
289: while (rddev(dfp, &dev) != FAIL) {
290: /*
291: * for each ACU L.sys line, try at most twice
292: * (TRYCALLS) to establish carrier. The old way tried every
293: * available dialer, which on big sites takes forever!
294: * Sites with a single auto-dialer get one try.
295: * Sites with multiple dialers get a try on each of two
296: * different dialers.
297: * To try 'harder' to connect to a remote site,
298: * use multiple L.sys entries.
299: */
300: if (acustatus > TRYCALLS)
301: break;
302: if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
303: continue;
304: if (snccmp(line, dev.D_type) != SAME)
305: continue;
306: if (dev.D_brand[0] == '\0') {
307: logent("Acuopn","No 'brand' name on ACU");
308: continue;
309: }
310: for(cd = condevs; cd->CU_meth != NULL; cd++) {
311: if (snccmp(line, cd->CU_meth) == SAME) {
312: if (snccmp(dev.D_brand, cd->CU_brand) == SAME)
313: break;
314: strncpy(nobrand, dev.D_brand, sizeof nobrand);
315: }
316: }
317:
318: if (mlock(dev.D_line) == FAIL) {
319: acustatus++;
320: continue;
321: }
322: if (acustatus < 1)
323: acustatus = 1; /* has been found */
324: #ifdef DIALINOUT
325: #ifdef ALLACUINOUT
326: if (1) {
327: #else !ALLACUINOUT
328: if (snccmp("inout", dev.D_calldev) == SAME) {
329: #endif !ALLACUINOUT
330: if (disable(dev.D_line) == FAIL) {
331: delock(dev.D_line);
332: continue;
333: }
334: } else
335: reenable();
336: #endif DIALINOUT
337:
338: DEBUG(4, "Using %s\n", cd->CU_brand);
339: acustatus++;
340: fd = (*(cd->CU_open))(phone, flds, &dev);
341: if (fd > 0) {
342: CU_end = cd->CU_clos; /* point CU_end at close func */
343: fclose(dfp);
344: strcpy(devSel, dev.D_line); /* save for later unlock() */
345: return fd;
346: } else
347: delock(dev.D_line);
348: retval = CF_DIAL;
349: }
350: fclose(dfp);
351: if (acustatus == 0) {
352: if (nobrand[0])
353: logent(nobrand, "unsupported ACU type");
354: else
355: logent("L-devices", "No appropriate ACU");
356: }
357: if (acustatus == 1)
358: logent("DEVICE", "NO");
359: return retval;
360: }
361:
362: /*
363: * intervaldelay: delay execution for numerator/denominator seconds.
364: */
365:
366: #ifdef INTERVALTIMER
367: #include <sys/time.h>
368: #define uucpdelay(num,denom) intervaldelay(num,denom)
369: intervaldelay(num,denom)
370: int num, denom;
371: {
372: struct timeval tv;
373: tv.tv_sec = num / denom;
374: tv.tv_usec = (num * 1000000L / denom ) % 1000000L;
375: (void) select (0, (int *)0, (int *)0, (int *)0, &tv);
376: }
377: #endif INTERVALTIMER
378:
379: #ifdef FASTTIMER
380: #define uucpdelay(num,denom) nap(60*num/denom)
381: /* Sleep in increments of 60ths of second. */
382: nap (time)
383: register int time;
384: {
385: static int fd;
386:
387: if (fd == 0)
388: fd = open (FASTTIMER, 0);
389:
390: read (fd, 0, time);
391: }
392: #endif FASTTIMER
393:
394: #ifdef FTIME
395: #define uucpdelay(num,denom) ftimedelay(1000*num/denom)
396: ftimedelay(n)
397: {
398: static struct timeb loctime;
399: register i = loctime.millitm;
400:
401: ftime(&loctime);
402: while (abs((int)(loctime.millitm - i))<n) ftime(&loctime)
403: ;
404: }
405: #endif FTIME
406:
407: #ifdef BUSYLOOP
408: #define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom)
409: #define CPUSPEED 1000000 /* VAX 780 is 1MIPS */
410: #define DELAY(n) { register long N = (n); while (--N > 0); }
411: busyloop(n)
412: {
413: DELAY(n);
414: }
415: #endif BUSYLOOP
416:
417: slowrite(fd, str)
418: register char *str;
419: {
420: DEBUG(6, "slowrite ", CNULL);
421: while (*str) {
422: DEBUG(6, "%c", *str);
423: uucpdelay(1, 10); /* delay 1/10 second */
424: write(fd, str, 1);
425: str++;
426: }
427: DEBUG(6, "\n", CNULL);
428: }
429:
430: #define BSPEED B150
431:
432: /*
433: * send a break
434: */
435: genbrk(fn, bnulls)
436: register int fn, bnulls;
437: {
438: #ifdef USG
439: if (ioctl(fn, TCSBRK, STBNULL) < 0)
440: DEBUG(5, "break TCSBRK %s\n", sys_errlist[errno]);
441: #else !USG
442: # ifdef TIOCSBRK
443: if (ioctl(fn, TIOCSBRK, STBNULL) < 0)
444: DEBUG(5, "break TIOCSBRK %s\n", sys_errlist[errno]);
445: # ifdef TIOCCBRK
446: uucpdelay(bnulls, 10);
447: if (ioctl(fn, TIOCCBRK, STBNULL) < 0)
448: DEBUG(5, "break TIOCCBRK %s\n", sys_errlist[errno]);
449: # endif TIOCCBRK
450: DEBUG(4, "ioctl %f second break\n", (float) bnulls/10 );
451: # else !TIOCSBRK
452: struct sgttyb ttbuf;
453: register int sospeed;
454:
455: if (ioctl(fn, TIOCGETP, &ttbuf) < 0)
456: DEBUG(5, "break TIOCGETP %s\n", sys_errlist[errno]);
457: sospeed = ttbuf.sg_ospeed;
458: ttbuf.sg_ospeed = BSPEED;
459: if (ioctl(fn, TIOCSETP, &ttbuf) < 0)
460: DEBUG(5, "break TIOCSETP %s\n", sys_errlist[errno]);
461: if (write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls) != bnulls) {
462: badbreak:
463: logent(sys_errlist[errno], "BAD WRITE genbrk");
464: alarm(0);
465: longjmp(Sjbuf, 3);
466: }
467: ttbuf.sg_ospeed = sospeed;
468: if (ioctl(fn, TIOCSETP, &ttbuf) < 0)
469: DEBUG(5, "break ioctl %s\n", sys_errlist[errno]);
470: if (write(fn, "@", 1) != 1)
471: goto badbreak;
472: DEBUG(4, "sent BREAK nulls - %d\n", bnulls);
473: #endif !TIOCSBRK
474: #endif !USG
475: }
476:
477:
478: #ifdef DIALINOUT
479: /* DIALIN/OUT CODE (WLS) */
480: /*
481: * disable and reenable: allow a single line to be use for dialin/dialout
482: *
483: */
484:
485: char enbdev[16];
486:
487: disable(dev)
488: register char *dev;
489: {
490: register char *rdev;
491:
492: /* strip off directory prefixes */
493: rdev = dev;
494: while (*rdev)
495: rdev++;
496: while (--rdev >= dev && *rdev != '/')
497: ;
498: rdev++;
499:
500: if (enbdev[0]) {
501: if (strcmp(enbdev, rdev) == SAME)
502: return SUCCESS; /* already disabled */
503: delock(enbdev);
504: reenable(); /* else, reenable the old one */
505: }
506: DEBUG(4, "Disable %s\n", rdev);
507: if (enbcall("disable", rdev) == FAIL)
508: return FAIL;
509: strcpy(enbdev, rdev);
510: return SUCCESS;
511: }
512:
513: reenable()
514: {
515: if (enbdev[0] == '\0')
516: return;
517: DEBUG(4, "Reenable %s\n", enbdev);
518: (void) enbcall("enable", enbdev);
519: enbdev[0] = '\0';
520: }
521:
522: enbcall(type, dev)
523: char *type, *dev;
524: {
525: int pid;
526: register char *p;
527: int fildes[2];
528: int status;
529: FILE *fil;
530: char buf[80];
531:
532: fflush(stderr);
533: fflush(stdout);
534: pipe(fildes);
535: if ((pid = fork()) == 0) {
536: DEBUG(4, DIALINOUT, CNULL);
537: DEBUG(4, " %s", type);
538: DEBUG(4, " %s\n", dev);
539: close(fildes[0]);
540: close(0); close(1); close(2);
541: open("/dev/null",0);
542: dup(fildes[1]); dup(fildes[1]);
543: setuid(geteuid()); /* for chown(uid()) in acu program */
544: execl(DIALINOUT, "acu", type, dev, 0);
545: exit(-1);
546: }
547: if (pid<0)
548: return FAIL;
549:
550: close(fildes[1]);
551: fil = fdopen(fildes[0],"r");
552: if (fil!=NULL) {
553: #ifdef BSD4_2
554: setlinebuf(fil);
555: #endif BSD4_2
556: while (fgets(buf, sizeof buf, fil) != NULL) {
557: p = buf + strlen(buf) - 1;
558: if (*p == '\n')
559: *p = '\0';
560: logent(buf,"ACUCNTRL:");
561: }
562: }
563: while(wait(&status) != pid)
564: ;
565: fclose(fil);
566: return status ? FAIL : SUCCESS;
567: }
568: #endif DIALINOUT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.