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