Commit | Line | Data |
---|---|---|
572555ee | 1 | #ifndef lint |
d3bcf514 | 2 | static char sccsid[] = "@(#)condevs.c 5.18 (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 | |
b83f9fbc JB |
109 | #ifdef ATT2224 |
110 | { "ACU", "att", Acuopn, attopn, attcls }, | |
111 | #endif ATT2224 | |
112 | ||
572555ee | 113 | |
46b15d8a RC |
114 | /* Insert new entries before this line */ |
115 | { NULL, NULL, NULL, NULL, NULL } | |
116 | }; | |
572555ee | 117 | |
46b15d8a | 118 | /* |
572555ee SL |
119 | * nulldev a null device (returns CF_DIAL) |
120 | */ | |
46b15d8a | 121 | nulldev() |
572555ee | 122 | { |
46b15d8a | 123 | return CF_DIAL; |
572555ee SL |
124 | } |
125 | ||
46b15d8a | 126 | /* |
572555ee SL |
127 | * nodev a null device (returns CF_NODEV) |
128 | */ | |
46b15d8a | 129 | nodev() |
572555ee | 130 | { |
46b15d8a | 131 | return CF_NODEV; |
572555ee SL |
132 | } |
133 | ||
572555ee | 134 | /* |
572555ee | 135 | * Generic devices look through L-devices and call the CU_open routines for |
46b15d8a RC |
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 | |
572555ee SL |
138 | * right routine to call. |
139 | */ | |
140 | ||
46b15d8a | 141 | /* |
572555ee | 142 | * diropn(flds) connect to hardware line |
572555ee SL |
143 | * |
144 | * return codes: | |
46b15d8a | 145 | * > 0 - file number - ok |
572555ee SL |
146 | * FAIL - failed |
147 | */ | |
572555ee SL |
148 | diropn(flds) |
149 | register char *flds[]; | |
150 | { | |
151 | register int dcr, status; | |
152 | struct Devices dev; | |
153 | char dcname[20]; | |
154 | FILE *dfp; | |
46b15d8a RC |
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 | |
572555ee SL |
163 | dfp = fopen(DEVFILE, "r"); |
164 | ASSERT(dfp != NULL, "CAN'T OPEN", DEVFILE, 0); | |
165 | while ((status = rddev(dfp, &dev)) != FAIL) { | |
46b15d8a RC |
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 | |
572555ee SL |
181 | if (strcmp(flds[F_CLASS], dev.D_class) != SAME) |
182 | continue; | |
183 | if (strcmp(flds[F_PHONE], dev.D_line) != SAME) | |
46b15d8a | 184 | #endif !VMSDTR |
572555ee SL |
185 | continue; |
186 | if (mlock(dev.D_line) != FAIL) | |
187 | break; | |
188 | } | |
189 | fclose(dfp); | |
190 | if (status == FAIL) { | |
191 | logent("DEVICE", "NO"); | |
46b15d8a | 192 | return CF_NODEV; |
572555ee SL |
193 | } |
194 | ||
195 | sprintf(dcname, "/dev/%s", dev.D_line); | |
196 | if (setjmp(Sjbuf)) { | |
2af814a5 | 197 | DEBUG(4, "Open timed out\n", CNULL); |
572555ee | 198 | delock(dev.D_line); |
46b15d8a | 199 | return CF_DIAL; |
572555ee SL |
200 | } |
201 | signal(SIGALRM, alarmtr); | |
2af814a5 JB |
202 | /* For PC Pursuit, it could take a while to call back */ |
203 | alarm( strcmp(flds[F_LINE], "PCP") ? 10 : MAXMSGTIME*4 ); | |
572555ee SL |
204 | getnextfd(); |
205 | errno = 0; | |
2af814a5 | 206 | DEBUG(4,"Opening %s\n",dcname); |
572555ee | 207 | dcr = open(dcname, 2); /* read/write */ |
46b15d8a RC |
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 | |
572555ee | 229 | next_fd = -1; |
572555ee SL |
230 | alarm(0); |
231 | if (dcr < 0) { | |
2af814a5 JB |
232 | if (errno == EACCES) |
233 | logent(dev.D_line, "CANT OPEN"); | |
234 | DEBUG(4, "OPEN FAILED: errno %d\n", errno); | |
572555ee | 235 | delock(dev.D_line); |
46b15d8a | 236 | return CF_DIAL; |
572555ee SL |
237 | } |
238 | fflush(stdout); | |
2af814a5 JB |
239 | if (fixline(dcr, dev.D_speed) == FAIL) { |
240 | DEBUG(4, "FIXLINE FAILED\n", CNULL); | |
c8a90aca | 241 | return CF_DIAL; |
2af814a5 | 242 | } |
572555ee SL |
243 | strcpy(devSel, dev.D_line); /* for latter unlock */ |
244 | CU_end = dircls; | |
46b15d8a | 245 | return dcr; |
572555ee SL |
246 | } |
247 | ||
248 | dircls(fd) | |
249 | register int fd; | |
250 | { | |
251 | if (fd > 0) { | |
252 | close(fd); | |
253 | delock(devSel); | |
572555ee | 254 | } |
572555ee SL |
255 | } |
256 | ||
1a85e9d2 RC |
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. | |
572555ee SL |
260 | * |
261 | * return codes: >0 - file number - o.k. | |
262 | * FAIL - failed | |
263 | */ | |
572555ee SL |
264 | char devSel[20]; /* used for later unlock() */ |
265 | ||
266 | Acuopn(flds) | |
267 | register char *flds[]; | |
268 | { | |
1a85e9d2 RC |
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; | |
01af9d69 | 275 | char nobrand[MAXPH], *line; |
1a85e9d2 RC |
276 | |
277 | exphone(flds[F_PHONE], phone); | |
01af9d69 JB |
278 | if (snccmp(flds[F_LINE], "LOCAL") == SAME) |
279 | line = "ACU"; | |
280 | else | |
281 | line = flds[F_LINE]; | |
1a85e9d2 | 282 | devSel[0] = '\0'; |
04503449 | 283 | nobrand[0] = '\0'; |
1a85e9d2 RC |
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 */ | |
01af9d69 JB |
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; | |
04503449 | 314 | strncpy(nobrand, dev.D_brand, sizeof nobrand); |
1a85e9d2 | 315 | } |
01af9d69 | 316 | } |
1a85e9d2 | 317 | |
438731a9 RA |
318 | if (acustatus < 1) |
319 | acustatus = 1; /* has been found */ | |
320 | ||
b72750d4 | 321 | if (mlock(dev.D_line) == FAIL) |
01af9d69 | 322 | continue; |
b72750d4 | 323 | |
1a85e9d2 | 324 | #ifdef DIALINOUT |
c8a90aca | 325 | #ifdef ALLACUINOUT |
01af9d69 | 326 | if (1) { |
c8a90aca | 327 | #else !ALLACUINOUT |
01af9d69 | 328 | if (snccmp("inout", dev.D_calldev) == SAME) { |
c8a90aca | 329 | #endif !ALLACUINOUT |
01af9d69 | 330 | if (disable(dev.D_line) == FAIL) { |
1a85e9d2 | 331 | delock(dev.D_line); |
01af9d69 | 332 | continue; |
1a85e9d2 | 333 | } |
01af9d69 JB |
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; | |
572555ee | 349 | } |
1a85e9d2 | 350 | fclose(dfp); |
04503449 JB |
351 | if (acustatus == 0) { |
352 | if (nobrand[0]) | |
353 | logent(nobrand, "unsupported ACU type"); | |
354 | else | |
355 | logent("L-devices", "No appropriate ACU"); | |
356 | } | |
1a85e9d2 RC |
357 | if (acustatus == 1) |
358 | logent("DEVICE", "NO"); | |
359 | return retval; | |
572555ee SL |
360 | } |
361 | ||
572555ee | 362 | /* |
c8a90aca | 363 | * intervaldelay: delay execution for numerator/denominator seconds. |
572555ee SL |
364 | */ |
365 | ||
366 | #ifdef INTERVALTIMER | |
62ba4a08 | 367 | #include <sys/time.h> |
c8a90aca JB |
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 | } | |
572555ee SL |
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) | |
1a85e9d2 | 383 | register int time; |
572555ee SL |
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) | |
572555ee SL |
396 | ftimedelay(n) |
397 | { | |
398 | static struct timeb loctime; | |
46b15d8a RC |
399 | register i = loctime.millitm; |
400 | ||
572555ee | 401 | ftime(&loctime); |
46b15d8a RC |
402 | while (abs((int)(loctime.millitm - i))<n) ftime(&loctime) |
403 | ; | |
572555ee SL |
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) | |
46b15d8a | 412 | { |
572555ee | 413 | DELAY(n); |
46b15d8a | 414 | } |
572555ee SL |
415 | #endif BUSYLOOP |
416 | ||
417 | slowrite(fd, str) | |
418 | register char *str; | |
419 | { | |
46b15d8a | 420 | DEBUG(6, "slowrite ", CNULL); |
572555ee SL |
421 | while (*str) { |
422 | DEBUG(6, "%c", *str); | |
2af814a5 | 423 | uucpdelay(1, 10); /* delay 1/10 second */ |
572555ee SL |
424 | write(fd, str, 1); |
425 | str++; | |
572555ee | 426 | } |
46b15d8a | 427 | DEBUG(6, "\n", CNULL); |
572555ee | 428 | } |
2af814a5 JB |
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 | ||
1a85e9d2 RC |
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; | |
1a85e9d2 RC |
509 | strcpy(enbdev, rdev); |
510 | return SUCCESS; | |
511 | } | |
512 | ||
513 | reenable() | |
514 | { | |
04503449 | 515 | if (enbdev[0] == '\0') |
1a85e9d2 RC |
516 | return; |
517 | DEBUG(4, "Reenable %s\n", enbdev); | |
518 | (void) enbcall("enable", enbdev); | |
1a85e9d2 RC |
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) { | |
c8a90aca | 553 | #ifdef BSD4_2 |
1a85e9d2 | 554 | setlinebuf(fil); |
c8a90aca | 555 | #endif BSD4_2 |
1a85e9d2 RC |
556 | while (fgets(buf, sizeof buf, fil) != NULL) { |
557 | p = buf + strlen(buf) - 1; | |
558 | if (*p == '\n') | |
559 | *p = '\0'; | |
b72750d4 | 560 | DEBUG(4, "ACUCNTRL: %s\n", buf); |
1a85e9d2 RC |
561 | } |
562 | } | |
563 | while(wait(&status) != pid) | |
564 | ; | |
565 | fclose(fil); | |
566 | return status ? FAIL : SUCCESS; | |
567 | } | |
568 | #endif DIALINOUT |