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