support new format of /etc/ttys (from rick@seismo)
[unix-history] / usr / src / usr.bin / uucp / uucico / condevs.c
CommitLineData
572555ee 1#ifndef lint
04503449 2static 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
29struct 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 106nulldev()
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 114nodev()
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
133diropn(flds)
134register 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
228dircls(fd)
229register 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
244char devSel[20]; /* used for later unlock() */
245
246Acuopn(flds)
247register 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)
348intervaldelay(num,denom)
349int 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. */
361nap (time)
1a85e9d2 362register 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
375ftimedelay(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); }
390busyloop(n)
46b15d8a 391{
572555ee 392 DELAY(n);
46b15d8a 393}
572555ee
SL
394#endif BUSYLOOP
395
396slowrite(fd, str)
397register 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
417char enbdev[16];
418
419disable(dev)
420register 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
446reenable()
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
456enbcall(type, dev)
457char *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