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