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