check for error on socket()
[unix-history] / usr / src / usr.bin / uucp / uucico / condevs.c
CommitLineData
572555ee 1#ifndef lint
01af9d69 2static char sccsid[] = "@(#)condevs.c 5.12 (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 },
01af9d69 53 { "WATS", "hayestone", Acuopn, hystopn, hyscls },
572555ee
SL
54#endif HAYES
55#ifdef HAYESQ /* a version of hayes that doesn't use result codes */
c8a90aca
JB
56 { "ACU", "hayesq", Acuopn, hysqpopn, hysqcls },
57 { "ACU", "hayesqpulse", Acuopn, hysqpopn, hysqcls },
58 { "ACU", "hayesqtone", Acuopn, hysqtopn, hysqcls },
59#endif HAYESQ
46b15d8a
RC
60#ifdef NOVATION
61 { "ACU", "novation", Acuopn, novopn, novcls},
62#endif NOVATION
572555ee 63#ifdef DF02
46b15d8a
RC
64 { "ACU", "DF02", Acuopn, df2opn, df2cls },
65#endif DF02
1a85e9d2
RC
66#ifdef DF112
67 { "ACU", "DF112P", Acuopn, df12popn, df12cls },
68 { "ACU", "DF112T", Acuopn, df12topn, df12cls },
69#endif DF112
572555ee 70#ifdef VENTEL
46b15d8a 71 { "ACU", "ventel", Acuopn, ventopn, ventcls },
572555ee 72#endif VENTEL
1a85e9d2
RC
73#ifdef PENRIL
74 { "ACU", "penril", Acuopn, penopn, pencls },
75#endif PENRIL
572555ee 76#ifdef VADIC
46b15d8a 77 { "ACU", "vadic", Acuopn, vadopn, vadcls },
572555ee 78#endif VADIC
46b15d8a
RC
79#ifdef VA212
80 { "ACU", "va212", Acuopn, va212opn, va212cls },
81#endif VA212
82#ifdef VA811S
83 { "ACU", "va811s", Acuopn, va811opn, va811cls },
84#endif VA811S
85#ifdef VA820
86 { "ACU", "va820", Acuopn, va820opn, va820cls },
87 { "WATS", "va820", Acuopn, va820opn, va820cls },
46b15d8a 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;
01af9d69 255 char nobrand[MAXPH], *line;
1a85e9d2
RC
256
257 exphone(flds[F_PHONE], phone);
01af9d69
JB
258 if (snccmp(flds[F_LINE], "LOCAL") == SAME)
259 line = "ACU";
260 else
261 line = flds[F_LINE];
1a85e9d2 262 devSel[0] = '\0';
04503449 263 nobrand[0] = '\0';
1a85e9d2
RC
264 DEBUG(4, "Dialing %s\n", phone);
265 dfp = fopen(DEVFILE, "r");
266 ASSERT(dfp != NULL, "Can't open", DEVFILE, 0);
267
268 acustatus = 0; /* none found, none locked */
01af9d69
JB
269 while (rddev(dfp, &dev) != FAIL) {
270 /*
271 * for each ACU L.sys line, try at most twice
272 * (TRYCALLS) to establish carrier. The old way tried every
273 * available dialer, which on big sites takes forever!
274 * Sites with a single auto-dialer get one try.
275 * Sites with multiple dialers get a try on each of two
276 * different dialers.
277 * To try 'harder' to connect to a remote site,
278 * use multiple L.sys entries.
279 */
280 if (acustatus > TRYCALLS)
281 break;
282 if (strcmp(flds[F_CLASS], dev.D_class) != SAME)
283 continue;
284 if (snccmp(line, dev.D_type) != SAME)
285 continue;
286 if (dev.D_brand[0] == '\0') {
287 logent("Acuopn","No 'brand' name on ACU");
288 continue;
289 }
290 for(cd = condevs; cd->CU_meth != NULL; cd++) {
291 if (snccmp(line, cd->CU_meth) == SAME) {
292 if (snccmp(dev.D_brand, cd->CU_brand) == SAME)
293 break;
04503449 294 strncpy(nobrand, dev.D_brand, sizeof nobrand);
1a85e9d2 295 }
01af9d69 296 }
1a85e9d2 297
01af9d69
JB
298 if (mlock(dev.D_line) == FAIL) {
299 acustatus++;
300 continue;
301 }
302 if (acustatus < 1)
303 acustatus = 1; /* has been found */
1a85e9d2 304#ifdef DIALINOUT
c8a90aca 305#ifdef ALLACUINOUT
01af9d69 306 if (1) {
c8a90aca 307#else !ALLACUINOUT
01af9d69 308 if (snccmp("inout", dev.D_calldev) == SAME) {
c8a90aca 309#endif !ALLACUINOUT
01af9d69 310 if (disable(dev.D_line) == FAIL) {
1a85e9d2 311 delock(dev.D_line);
01af9d69 312 continue;
1a85e9d2 313 }
01af9d69
JB
314 } else
315 reenable();
316#endif DIALINOUT
317
318 DEBUG(4, "Using %s\n", cd->CU_brand);
319 acustatus++;
320 fd = (*(cd->CU_open))(phone, flds, &dev);
321 if (fd > 0) {
322 CU_end = cd->CU_clos; /* point CU_end at close func */
323 fclose(dfp);
324 strcpy(devSel, dev.D_line); /* save for later unlock() */
325 return fd;
326 } else
327 delock(dev.D_line);
328 retval = CF_DIAL;
572555ee 329 }
1a85e9d2 330 fclose(dfp);
04503449
JB
331 if (acustatus == 0) {
332 if (nobrand[0])
333 logent(nobrand, "unsupported ACU type");
334 else
335 logent("L-devices", "No appropriate ACU");
336 }
1a85e9d2
RC
337 if (acustatus == 1)
338 logent("DEVICE", "NO");
339 return retval;
572555ee
SL
340}
341
1a85e9d2 342#if defined(VENTEL) || defined(NOVATION) || defined(DF112)
572555ee 343/*
c8a90aca 344 * intervaldelay: delay execution for numerator/denominator seconds.
572555ee
SL
345 */
346
347#ifdef INTERVALTIMER
62ba4a08 348#include <sys/time.h>
c8a90aca
JB
349#define uucpdelay(num,denom) intervaldelay(num,denom)
350intervaldelay(num,denom)
351int num, denom;
352{
353 struct timeval tv;
354 tv.tv_sec = num / denom;
355 tv.tv_usec = (num * 1000000L / denom ) % 1000000L;
356 (void) select (0, (int *)0, (int *)0, (int *)0, &tv);
357}
572555ee
SL
358#endif INTERVALTIMER
359
360#ifdef FASTTIMER
361#define uucpdelay(num,denom) nap(60*num/denom)
362/* Sleep in increments of 60ths of second. */
363nap (time)
1a85e9d2 364register int time;
572555ee
SL
365{
366 static int fd;
367
368 if (fd == 0)
369 fd = open (FASTTIMER, 0);
370
371 read (fd, 0, time);
372}
373#endif FASTTIMER
374
375#ifdef FTIME
376#define uucpdelay(num,denom) ftimedelay(1000*num/denom)
572555ee
SL
377ftimedelay(n)
378{
379 static struct timeb loctime;
46b15d8a
RC
380 register i = loctime.millitm;
381
572555ee 382 ftime(&loctime);
46b15d8a
RC
383 while (abs((int)(loctime.millitm - i))<n) ftime(&loctime)
384 ;
572555ee
SL
385}
386#endif FTIME
387
388#ifdef BUSYLOOP
389#define uucpdelay(num,denom) busyloop(CPUSPEED*num/denom)
390#define CPUSPEED 1000000 /* VAX 780 is 1MIPS */
391#define DELAY(n) { register long N = (n); while (--N > 0); }
392busyloop(n)
46b15d8a 393{
572555ee 394 DELAY(n);
46b15d8a 395}
572555ee
SL
396#endif BUSYLOOP
397
398slowrite(fd, str)
399register char *str;
400{
46b15d8a 401 DEBUG(6, "slowrite ", CNULL);
572555ee
SL
402 while (*str) {
403 DEBUG(6, "%c", *str);
404 uucpdelay(1,10); /* delay 1/10 second */
405 write(fd, str, 1);
406 str++;
572555ee 407 }
46b15d8a 408 DEBUG(6, "\n", CNULL);
572555ee 409}
1a85e9d2
RC
410#endif VENTEL || NOVATION || DF112
411
412#ifdef DIALINOUT
413/* DIALIN/OUT CODE (WLS) */
414/*
415 * disable and reenable: allow a single line to be use for dialin/dialout
416 *
417 */
418
419char enbdev[16];
420
421disable(dev)
422register char *dev;
423{
424 register char *rdev;
425
426 /* strip off directory prefixes */
427 rdev = dev;
428 while (*rdev)
429 rdev++;
430 while (--rdev >= dev && *rdev != '/')
431 ;
432 rdev++;
433
434 if (enbdev[0]) {
435 if (strcmp(enbdev, rdev) == SAME)
436 return SUCCESS; /* already disabled */
437 delock(enbdev);
438 reenable(); /* else, reenable the old one */
439 }
440 DEBUG(4, "Disable %s\n", rdev);
441 if (enbcall("disable", rdev) == FAIL)
442 return FAIL;
1a85e9d2
RC
443 strcpy(enbdev, rdev);
444 return SUCCESS;
445}
446
447reenable()
448{
04503449 449 if (enbdev[0] == '\0')
1a85e9d2
RC
450 return;
451 DEBUG(4, "Reenable %s\n", enbdev);
452 (void) enbcall("enable", enbdev);
1a85e9d2
RC
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