1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31
32
33 #include "uucp.h"
34
35 #if defined(BSD4_2) || defined(ATTSVR4)
36 #include <netdb.h>
37 #include <netinet/in.h>
38 #include <sys/socket.h>
39 #endif
40 #ifdef UNET
41 #include "UNET/unetio.h"
42 #include "UNET/tcp.h"
43 #endif
44
45 #include <libgen.h>
46
47 EXTERN void alarmtr();
48 EXTERN jmp_buf Sjbuf;
49 EXTERN char *fdig();
50 EXTERN int interface();
51 EXTERN int fd_mklock(), fd_cklock(), chat(), getdialline();
52 EXTERN void fixline(), fd_rmlock();
53 static void translate();
54 static int gdial();
55 EXTERN int Modemctrl;
56 EXTERN unsigned connecttime;
57 EXTERN int (*Setup)();
58
59 /*
60 * to add a new caller:
61 * declare the function that knows how to call on the device,
62 * add a line to the callers table giving the name of the device
63 * (from Devices file) and the name of the function
64 * add the function to the end of this file
65 */
66
67 #ifdef DIAL801
68 EXTERN int dial801();
69 EXTERN int open801();
70 #endif
71
72 #ifdef DATAKIT
73 EXTERN int dkcall();
74 #endif /* DATAKIT */
75
76 #ifdef V8
77 int Dialout();
78 #endif
79
80 #ifdef TCP
81 int unetcall();
82 int tcpcall();
83 #endif /* TCP */
84
85 #ifdef SYTEK
86 int sytcall();
87 #endif /* SYTEK */
88
89 #ifdef TLI
90 EXTERN int tlicall();
91 #endif /* TLI */
92
93 static struct caller Caller[] = {
94
95 #ifdef DIAL801
96 {"801", dial801},
97 {"212", dial801},
98 #endif /* DIAL801 */
99
100 #ifdef V8
101 {"Dialout", Dialout}, /* ditto but using dialout(III) */
102 #endif
103
104 #ifdef TCP
105 #if defined(BSD4_2) || defined(ATTSVR4)
106 {"TCP", tcpcall}, /* 4.2BSD sockets */
107 #else /* !BSD4_2 */
108 #ifdef UNET
109 {"TCP", unetcall}, /* 3com implementation of tcp */
110 {"Unetserver", unetcall},
111 #endif /* UNET */
112 #endif /* BSD4_2 || ATTSVR4 */
113 #endif /* TCP */
114
115 #ifdef DATAKIT
116 {"DK", dkcall}, /* standard AT&T DATAKIT VCS caller */
117 #endif /* DATAKIT */
118
119 #ifdef SYTEK
120 {"Sytek", sytcall}, /* untested but should work */
121 #endif /* SYTEK */
122
123 #ifdef TLI
124 {"TLI", tlicall}, /* AT&T Transport Layer Interface */
125 #ifdef TLIS
126 {"TLIS", tlicall}, /* AT&T Transport Layer Interface */
127 #endif /* TLIS */
128 #endif /* TLI */
129
130 {NULL, NULL} /* this line must be last */
131 };
132
133 /*
134 * exphone - expand phone number for given prefix and number
135 *
136 * return code - none
137 */
138
139 static void
exphone(in,out)140 exphone(in, out)
141 char *in, *out;
142 {
143 FILE *fn;
144 char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
145 char buf[BUFSIZ];
146 char *s1;
147
148 if (!isalpha(*in)) {
149 (void) strcpy(out, in);
150 return;
151 }
152
153 s1=pre;
154 while (isalpha(*in))
155 *s1++ = *in++;
156 *s1 = NULLCHAR;
157 s1 = npart;
158 while (*in != NULLCHAR)
159 *s1++ = *in++;
160 *s1 = NULLCHAR;
161
162 tpre[0] = NULLCHAR;
163 fn = fopen(DIALCODES, "r");
164 if (fn != NULL) {
165 while (fgets(buf, BUFSIZ, fn)) {
166 if ( sscanf(buf, "%s%s", p, tpre) < 1)
167 continue;
168 if (EQUALS(p, pre))
169 break;
170 tpre[0] = NULLCHAR;
171 }
172 fclose(fn);
173 }
174
175 (void) strcpy(out, tpre);
176 (void) strcat(out, npart);
177 return;
178 }
179
180 /*
181 * repphone - Replace \D and \T sequences in arg with phone
182 * expanding and translating as appropriate.
183 */
184 static char *
repphone(arg,phone,trstr)185 repphone(arg, phone, trstr)
186 char *arg, *phone, *trstr;
187 {
188 static char pbuf[2*(MAXPH+2)];
189 char *fp, *tp;
190
191 for (tp=pbuf; *arg; arg++) {
192 if (*arg != '\\') {
193 *tp++ = *arg;
194 continue;
195 } else {
196 switch (*(arg+1)) {
197 case 'T':
198 exphone(phone, tp);
199 translate(trstr, tp);
200 for(; *tp; tp++)
201 ;
202 arg++;
203 break;
204 case 'D':
205 for(fp=phone; *tp = *fp++; tp++)
206 ;
207 arg++;
208 break;
209 default:
210 *tp++ = *arg;
211 break;
212 }
213 }
214 }
215 *tp = '\0';
216 return(pbuf);
217 }
218
219 static u_int saved_mode;
220 static char saved_dcname[20];
221
222 /*
223 * processdev - Process a line from the Devices file
224 *
225 * return codes:
226 * file descriptor - succeeded
227 * FAIL - failed
228 */
229 GLOBAL int
processdev(flds,dev)230 processdev(flds, dev)
231 char *flds[], *dev[];
232 {
233 int dcf = -1;
234 struct caller *ca;
235 char *args[D_MAX+1], dcname[20];
236 char **sdev;
237 EXTERN int pop_push();
238 EXTERN void setdevcfg();
239 int nullfd;
240 char *phonecl; /* clear phone string */
241 char phoneex[2*(MAXPH+2)]; /* expanded phone string */
242 EXTERN void ttygenbrk();
243 struct termio tty_orig;
244 int ret_orig = -1;
245
246 sdev = dev;
247 /* set up default "break" routine */
248 genbrk = ttygenbrk;
249
250 /* initialize Devconfig info */
251 DEBUG(5, "processdev: calling setdevcfg(%s, ", Progname);
252 DEBUG(5, "%s)\n", flds[F_TYPE]);
253 setdevcfg(Progname, flds[F_TYPE]);
254
255 for (ca = Caller; ca->CA_type != NULL; ca++) {
256 /* This will find built-in caller functions */
257 if (EQUALS(ca->CA_type, dev[D_CALLER])) {
258 DEBUG(5, "Internal caller type %s\n", dev[D_CALLER]);
259 if (dev[D_ARG] == NULL) {
260 /* if NULL - assume translate */
261 dev[D_ARG+1] = NULL; /* needed for for loop later to mark the end */
262 dev[D_ARG] = "\\T";
263 }
264 dev[D_ARG] = repphone(dev[D_ARG], flds[F_PHONE], "");
265 if ((dcf = (*(ca->CA_caller))(flds, dev)) < 0)
266 return(dcf) ;
267 if ( interface( ca->CA_type ) ) {
268 DEBUG(5, "interface(%s) failed", ca->CA_type);
269 Uerror = SS_DEVICE_FAILED;
270 /* restore vanilla unix interface */
271 (void)interface("UNIX");
272 return(FAIL);
273 }
274 dev += 2; /* Skip to next CALLER and ARG */
275 break;
276 }
277 }
278 if (dcf == -1) {
279 /* Here if not a built-in caller function */
280
281 /* We do locking (file and advisory) after open */
282
283 /*
284 * Open the line
285 */
286 if ( *dev[D_LINE] != '/' ) {
287 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
288 } else {
289 (void) strcpy(dcname, dev[D_LINE] );
290 }
291 /* take care of the possible partial open fd */
292 (void) close(nullfd = open("/", O_RDONLY));
293 if (setjmp(Sjbuf)) {
294 (void) close(nullfd);
295 DEBUG(1, "generic open timeout\n%s", "");
296 logent("generic open", "TIMEOUT");
297 Uerror = SS_CANT_ACCESS_DEVICE;
298 goto bad;
299 }
300 (void) signal(SIGALRM, alarmtr);
301 (void) alarm(10);
302 if ( Modemctrl ) {
303 DEBUG(7, "opening with O_NDELAY set\n%s", "");
304 dcf = open(dcname, (O_RDWR | O_NDELAY) );
305 saved_mode = O_RDWR | O_NDELAY;
306 } else {
307 dcf = open(dcname, O_RDWR );
308 saved_mode = O_RDWR;
309 }
310 strcpy(saved_dcname, dcname);
311 (void) alarm(0);
312 if (dcf < 0) {
313 DEBUG(1, "generic open failed, errno = %d\n", errno);
314 (void) close(nullfd);
315 logent("generic open", "FAILED");
316 Uerror = SS_CANT_ACCESS_DEVICE;
317 goto bad;
318 }
319
320 /* check locks BEFORE modifying the stream */
321
322 if ( fd_mklock(dcf) != SUCCESS ) {
323 DEBUG(1, "failed to lock device %s\n", dcname);
324 Uerror = SS_LOCKED_DEVICE;
325 goto bad;
326 }
327
328 if ( Modemctrl ) {
329 DEBUG(7, "clear O_NDELAY\n%s", "");
330 if ( fcntl(dcf, F_SETFL,
331 (fcntl(dcf, F_GETFL, 0) & ~O_NDELAY)) < 0 ) {
332 DEBUG( 7, "clear O_NDELAY failed, errno %d\n", errno);
333 Uerror = SS_DEVICE_FAILED;
334 goto bad;
335 }
336 }
337 }
338
339 if ( (*Setup)( MASTER, &dcf, &dcf ) ) {
340 /* any device|system lock files we should remove? */
341 DEBUG(5, "MASTER Setup failed%s", "");
342 Uerror = SS_DEVICE_FAILED;
343 goto bad;
344 }
345
346 /* configure any requested streams modules */
347 if ( !pop_push(dcf) ) {
348 DEBUG(5, "STREAMS module configuration failed%s\n","");
349 Uerror = SS_DEVICE_FAILED;
350 goto bad;
351 }
352
353 /* save initial state of line in case script fails */
354 ret_orig = ioctl(dcf, TCGETA, &tty_orig);
355
356 /* use sdev[] since dev[] is incremented for internal callers */
357 fixline(dcf, atoi(fdig(sdev[D_CLASS])), D_DIRECT);
358
359 /*
360 * Now loop through the remaining callers and chat
361 * according to scripts in dialers file.
362 */
363 for (; dev[D_CALLER] != NULL; dev += 2) {
364 int w;
365 /*
366 * Scan Dialers file to find an entry
367 */
368 if ((w = gdial(dev[D_CALLER], args, D_MAX)) < 1) {
369 logent("generic call to gdial", "FAILED");
370 Uerror = SS_CANT_ACCESS_DEVICE;
371 goto bad;
372 }
373 if (w <= 2) /* do nothing - no chat */
374 break;
375 /*
376 * Translate the phone number
377 */
378 if (dev[D_ARG] == NULL) {
379 /* if NULL - assume no translation */
380 dev[D_ARG+1] = NULL; /* needed for for loop to mark the end */
381 dev[D_ARG] = "\\D";
382 }
383
384 phonecl = repphone(dev[D_ARG], flds[F_PHONE], args[1]);
385 exphone(phonecl, phoneex);
386 translate(args[1], phoneex);
387 /*
388 * Chat
389 */
390 if (chat(w-2, &args[2], dcf, phonecl, phoneex) != SUCCESS) {
391 CDEBUG(5, "\nCHAT gdial(%s) FAILED\n", dev[D_CALLER]);
392 Uerror = SS_CHAT_FAILED;
393 goto bad;
394 }
395 }
396 /*
397 * Success at last!
398 */
399 strcpy(Dc, sdev[D_LINE]);
400 return(dcf);
401 bad:
402 if ( dcf >= 0 ) {
403 /* reset line settings if we got them in the beginning */
404 if ( ret_orig == 0 )
405 (void) ioctl(dcf, TCSETAW, &tty_orig);
406 fd_rmlock(dcf);
407 (void)close(dcf);
408 }
409 /* restore vanilla unix interface */
410 (void)interface("UNIX");
411 return(FAIL);
412 }
413
414 /*
415 * clear_hup() clear the hangup state of the given device
416 */
417 GLOBAL int
clear_hup(dcf)418 clear_hup(dcf)
419 int dcf;
420 {
421 int ndcf;
422 if ((ndcf = open(saved_dcname, saved_mode)) < 0) {
423 return (FAIL);
424 }
425 if (ndcf != dcf) {
426 close(ndcf);
427 }
428 return (SUCCESS);
429 }
430
431
432 /*
433 * translate the pairs of characters present in the first
434 * string whenever the first of the pair appears in the second
435 * string.
436 */
437 static void
translate(ttab,str)438 translate(ttab, str)
439 char *ttab, *str;
440 {
441 char *s;
442
443 for(;*ttab && *(ttab+1); ttab += 2)
444 for(s=str;*s;s++)
445 if(*ttab == *s)
446 *s = *(ttab+1);
447 return;
448 }
449
450 #define MAXLINE 512
451 /*
452 * Get the information about the dialer.
453 * gdial(type, arps, narps)
454 * type -> type of dialer (e.g., penril)
455 * arps -> array of pointers returned by gdial
456 * narps -> number of elements in array returned by gdial
457 * Return value:
458 * -1 -> Can't open DIALERFILE
459 * 0 -> requested type not found
460 * >0 -> success - number of fields filled in
461 */
462 static int
gdial(type,arps,narps)463 gdial(type, arps, narps)
464 char *type, *arps[];
465 int narps;
466 {
467 static char info[MAXLINE];
468 int na;
469 EXTERN void dialreset();
470 EXTERN char * currdial();
471
472 DEBUG(2, "gdial(%s) called\n", type);
473 while (getdialline(info, sizeof(info))) {
474 if ((info[0] == '#') || (info[0] == ' ') ||
475 (info[0] == '\t') || (info[0] == '\n'))
476 continue;
477 if ((na = getargs(info, arps, narps)) == 0)
478 continue;
479 if (EQUALS(arps[0], type)) {
480 DEBUG(5, "Trying caller script '%s'", type);
481 DEBUG(5, " from '%s'.\n", currdial());
482 dialreset();
483 bsfix(arps);
484 return(na);
485 }
486 }
487 DEBUG(1, "%s not found in Dialers file\n", type);
488 dialreset();
489 return(0);
490 }
491
492
493 #ifdef DATAKIT
494
495 /*
496 * dkcall(flds, dev) make a DATAKIT VCS connection
497 * DATAKIT VCS is a trademark of AT&T
498 *
499 * return codes:
500 * >0 - file number - ok
501 * FAIL - failed
502 */
503
504 #include "dk.h"
505 EXTERN int dkdial();
506
507 /*ARGSUSED*/
508 GLOBAL int
dkcall(flds,dev)509 dkcall(flds, dev)
510 char *flds[], *dev[];
511 {
512 int fd;
513 #ifdef V8
514 extern int cdkp_ld;
515 #endif
516
517 char dialstring[64];
518 EXTERN void dkbreak();
519
520 strcpy(dialstring, dev[D_ARG]);
521 DEBUG(4, "dkcall(%s)\n", dialstring);
522
523
524 #ifdef V8
525 if (setjmp(Sjbuf)) {
526 Uerror = SS_DIAL_FAILED;
527 return(FAIL);
528 }
529
530 (void) signal(SIGALRM, alarmtr);
531 (void) alarm(connecttime);
532 DEBUG(4, "tdkdial(%s", flds[F_PHONE]);
533 DEBUG(4, ", %d)\n", atoi(dev[D_CLASS]));
534 if ((fd = tdkdial(flds[F_PHONE], atoi(dev[D_CLASS]))) >= 0)
535 if (dkproto(fd, cdkp_ld) < 0)
536 {
537 close(fd);
538 fd = -1;
539 }
540 (void) alarm(0);
541 #else
542 fd = dkdial(dialstring);
543 #endif
544
545 (void) strcpy(Dc, "DK");
546 if (fd < 0) {
547 Uerror = SS_DIAL_FAILED;
548 return(FAIL);
549 }
550 else {
551 genbrk = dkbreak;
552 return(fd);
553 }
554 }
555
556 #endif /* DATAKIT */
557
558 #ifdef TCP
559
560 /*
561 * tcpcall(flds, dev) make ethernet/socket connection
562 *
563 * return codes:
564 * >0 - file number - ok
565 * FAIL - failed
566 */
567
568 #if !(defined(BSD4_2) || defined(ATTSVR4))
569 /*ARGSUSED*/
570 GLOBAL int
tcpcall(flds,dev)571 tcpcall(flds, dev)
572 char *flds[], *dev[];
573 {
574 Uerror = SS_NO_DEVICE;
575 return(FAIL);
576 }
577 #else /* BSD4_2 */
578 /*ARGSUSED*/
579 GLOBAL int
tcpcall(flds,dev)580 tcpcall(flds, dev)
581 char *flds[], *dev[];
582 {
583 int ret;
584 short port;
585 struct servent *sp;
586 struct hostent *hp;
587 struct sockaddr_in sin;
588
589 if (EQUALS(flds[F_CLASS], "-")) {
590 /*
591 * Use standard UUCP port number.
592 */
593 sp = getservbyname("uucp", "tcp");
594 endservent();
595 ASSERT(sp != NULL, "No uucp service number", 0, 0);
596 port = sp->s_port;
597 } else {
598 /*
599 * Systems file specifies a port number.
600 */
601 sp = getservbyname(flds[F_CLASS], "tcp");
602 endservent();
603 if (sp == NULL) {
604 port = htons(atoi(flds[F_CLASS]));
605 if (port == 0) {
606 logent("tcpopen", "unknown port number");
607 Uerror = SS_NO_DEVICE;
608 return(FAIL);
609 }
610 } else
611 port = sp->s_port;
612 }
613 if (EQUALS(flds[F_PHONE], "-")) {
614 /*
615 * Use UUCP name as host name.
616 */
617 hp = gethostbyname(flds[F_NAME]);
618 } else {
619 /*
620 * Systems file specifies a host name different from the UUCP
621 * host name.
622 */
623 hp = gethostbyname(flds[F_PHONE]);
624 }
625 endhostent();
626 if (hp == NULL) {
627 logent("tcpopen", "no such host");
628 Uerror = SS_NO_DEVICE;
629 return(FAIL);
630 }
631 DEBUG(4, "tcpdial host %s, ", hp->h_name);
632 DEBUG(4, "port %d\n", ntohs(port));
633
634 ret = socket(AF_INET, SOCK_STREAM, 0);
635 if (ret < 0) {
636 DEBUG(5, "no socket: %s\n", strerror(errno));
637 logent("no socket", strerror(errno));
638 Uerror = SS_NO_DEVICE;
639 return(FAIL);
640 }
641 sin.sin_family = hp->h_addrtype;
642 #ifdef BSD4_2
643 bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
644 #else
645 memcpy((caddr_t)&sin.sin_addr, hp->h_addr, hp->h_length);
646 #endif
647 sin.sin_port = port;
648 if (setjmp(Sjbuf)) {
649 DEBUG(4, "timeout tcpopen\n%s", "");
650 logent("tcpopen", "TIMEOUT");
651 Uerror = SS_NO_DEVICE;
652 return(FAIL);
653 }
654 (void) signal(SIGALRM, alarmtr);
655 (void) alarm(connecttime);
656 DEBUG(7, "family: %d\n", sin.sin_family);
657 DEBUG(7, "port: %d\n", sin.sin_port);
658 DEBUG(7, "addr: %08x\n",*((int *) &sin.sin_addr));
659 if (connect(ret, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
660 (void) alarm(0);
661 (void) close(ret);
662 DEBUG(5, "connect failed: %s\n", strerror(errno));
663 logent("connect failed", strerror(errno));
664 Uerror = SS_NO_DEVICE;
665 return(FAIL);
666 }
667 (void) signal(SIGPIPE, SIG_IGN); /* watch out for broken ipc link...*/
668 (void) alarm(0);
669 (void) strcpy(Dc, "IPC");
670 return(ret);
671 }
672
673 #endif /* BSD4_2 */
674
675 /*
676 * unetcall(flds, dev) make ethernet connection
677 *
678 * return codes:
679 * >0 - file number - ok
680 * FAIL - failed
681 */
682
683 #ifndef UNET
684 /*ARGSUSED*/
685 GLOBAL int
unetcall(flds,dev)686 unetcall(flds, dev)
687 char *flds[], *dev[];
688 {
689 Uerror = SS_NO_DEVICE;
690 return(FAIL);
691 }
692 #else /* UNET */
693 GLOBAL int
unetcall(flds,dev)694 unetcall(flds, dev)
695 char *flds[], *dev[];
696 {
697 int ret;
698 int port;
699
700 port = atoi(dev[D_ARG]);
701 DEBUG(4, "unetdial host %s, ", flds[F_PHONE]);
702 DEBUG(4, "port %d\n", port);
703 (void) alarm(connecttime);
704 ret = tcpopen(flds[F_PHONE], port, 0, TO_ACTIVE, "rw");
705 (void) alarm(0);
706 endhnent();
707 if (ret < 0) {
708 DEBUG(5, "tcpopen failed: errno %d\n", errno);
709 Uerror = SS_DIAL_FAILED;
710 return(FAIL);
711 }
712 (void) strcpy(Dc, "UNET");
713 return(ret);
714 }
715 #endif /* UNET */
716
717 #endif /* TCP */
718
719 #ifdef SYTEK
720
721 /*
722 * sytcall(flds, dev) make a sytek connection
723 *
724 * return codes:
725 * >0 - file number - ok
726 * FAIL - failed
727 */
728
729 /*ARGSUSED*/
730 GLOBAL int
sytcall(flds,dev)731 sytcall(flds, dev)
732 char *flds[], *dev[];
733 {
734 int dcr, dcr2, nullfd, ret;
735 char dcname[20], command[BUFSIZ];
736
737 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
738 DEBUG(4, "dc - %s, ", dcname);
739 dcr = open(dcname, O_WRONLY|O_NDELAY);
740 if (dcr < 0) {
741 Uerror = SS_DIAL_FAILED;
742 DEBUG(4, "OPEN FAILED %s\n", dcname);
743 return(FAIL);
744 }
745 if ( fd_mklock(dcr) != SUCCESS ) {
746 (void)close(dcr);
747 DEBUG(1, "failed to lock device %s\n", dcname);
748 Uerror = SS_LOCKED_DEVICE;
749 return(FAIL);
750 }
751
752 sytfixline(dcr, atoi(fdig(dev[D_CLASS])), D_DIRECT);
753 (void) sleep(2);
754 DEBUG(4, "Calling Sytek unit %s\n", dev[D_ARG]);
755 (void) sprintf(command,"\r\rcall %s\r", dev[D_ARG]);
756 ret = (*Write)(dcr, command, strlen(command));
757 (void) sleep(1);
758 DEBUG(4, "COM1 return = %d\n", ret);
759 sytfix2line(dcr);
760 (void) close(nullfd = open("/", O_RDONLY));
761 (void) signal(SIGALRM, alarmtr);
762 if (setjmp(Sjbuf)) {
763 DEBUG(4, "timeout sytek open\n%s", "");
764 (void) close(nullfd);
765 (void) close(dcr2);
766 fd_rmlock(dcr);
767 (void) close(dcr);
768 Uerror = SS_DIAL_FAILED;
769 return(FAIL);
770 }
771 (void) alarm(10);
772 dcr2 = open(dcname,O_RDWR);
773 (void) alarm(0);
774 fd_rmlock(dcr);
775 (void) close(dcr);
776 if (dcr2 < 0) {
777 DEBUG(4, "OPEN 2 FAILED %s\n", dcname);
778 Uerror = SS_DIAL_FAILED;
779 (void) close(nullfd); /* kernel might think dc2 is open */
780 return(FAIL);
781 }
782 if ( fd_mklock(dcr2) != SUCCESS ) {
783 (void)close(dcr2);
784 DEBUG(1, "failed to lock device %s\n", dcname);
785 Uerror = SS_LOCKED_DEVICE;
786 return(FAIL);
787 return(dcr2);
788 }
789
790 #endif /* SYTEK */
791
792 #ifdef DIAL801
793
794 /*
795 * dial801(flds, dev) dial remote machine on 801/801
796 * char *flds[], *dev[];
797 *
798 * return codes:
799 * file descriptor - succeeded
800 * FAIL - failed
801 *
802 * unfortunately, open801() is different for usg and non-usg
803 */
804
805 /*ARGSUSED*/
806 GLOBAL int
807 dial801(flds, dev)
808 char *flds[], *dev[];
809 {
810 char dcname[20], dnname[20], phone[MAXPH+2];
811 int dcf = -1, speed;
812
813 (void) sprintf(dnname, "/dev/%s", dev[D_CALLDEV]);
814 (void) sprintf(phone, "%s%s", dev[D_ARG] , ACULAST);
815 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
816 CDEBUG(1, "Use Port %s, ", dcname);
817 DEBUG(4, "acu - %s, ", dnname);
818 VERBOSE("Trying modem - %s, ", dcname); /* for cu */
819 VERBOSE("acu - %s, ", dnname); /* for cu */
820 if(getuid()==0 || GRPCHK(getgid())) {
821 CDEBUG(1, "Phone Number %s\n", phone);
822 /* In cu, only give out the phone number to trusted people. */
823 VERBOSE("calling %s: ", phone); /* for cu */
824 }
825 speed = atoi(fdig(dev[D_CLASS]));
826 dcf = open801(dcname, dnname, phone, speed);
827 if (dcf >= 0) {
828 if ( fd_mklock(dcf) != SUCCESS ) {
829 (void) close(dcf);
830 DEBUG(5, "fd_mklock line %s failed\n", dev[D_LINE]);
831 Uerror = SS_LOCKED_DEVICE;
832 return(FAIL);
833 }
834 fixline(dcf, speed, D_ACU);
835 (void) strcpy(Dc, dev[D_LINE]); /* for later unlock() */
836 VERBOSE("SUCCEEDED\n%s", "");
837 } else {
838 VERBOSE("FAILED\n%s", "");
839 }
840 return(dcf);
841 }
842
843
844 #ifndef ATTSV
845 /*ARGSUSED*/
846 GLOBAL int
847 open801(dcname, dnname, phone, speed)
848 char *dcname, *dnname, *phone;
849 {
850 int nw, lt, dcf = -1, nullfd, dnf = -1;
851 pid_t w_ret, pid = -1;
852 unsigned timelim;
853
854 if ((dnf = open(dnname, O_WRONLY)) < 0) {
855 DEBUG(5, "can't open %s\n", dnname);
856 Uerror = SS_CANT_ACCESS_DEVICE;
857 return(FAIL);
858 }
859 DEBUG(5, "%s is open\n", dnname);
860
861 (void) close(nullfd = open("/dev/null", O_RDONLY));/* partial open hack */
862 if (setjmp(Sjbuf)) {
863 DEBUG(4, "timeout modem open\n%s", "");
864 (void) close(nullfd);
865 (void) close(dcf);
866 (void) close(dnf);
867 logent("801 open", "TIMEOUT");
868 if (pid > 0) {
869 kill(pid, 9);
870 wait((int *) 0);
871 }
872 Uerror = SS_DIAL_FAILED;
873 return(FAIL);
874 }
875 (void) signal(SIGALRM, alarmtr);
876 timelim = 5 * strlen(phone);
877 (void) alarm(timelim < connecttime ? connecttime : timelim);
878 if ((pid = fork()) == 0) {
879 sleep(2);
880 nw = (*Write)(dnf, phone, lt = strlen(phone));
881 if (nw != lt) {
882 DEBUG(4, "ACU write error %d\n", errno);
883 logent("ACU write", "FAILED");
884 exit(1);
885 }
886 DEBUG(4, "ACU write ok\n%s", "");
887 exit(0);
888 }
889 /* open line - will return on carrier */
890 dcf = open(dcname, O_RDWR);
891
892 DEBUG(4, "dcf is %d\n", dcf);
893 if (dcf < 0) { /* handle like a timeout */
894 (void) alarm(0);
895 longjmp(Sjbuf, 1);
896 }
897
898 /* modem is open */
899 while ((w_ret = wait(<)) != pid)
900 if (w_ret == -1 && errno != EINTR) {
901 DEBUG(4, "Wait failed errno=%d\n", errno);
902 (void) close(dcf);
903 (void) close(dnf);
904 Uerror = SS_DIAL_FAILED;
905 return(FAIL);
906 }
907 (void) alarm(0);
908
909 (void) close(dnf); /* no reason to keep the 801 open */
910 if (lt != 0) {
911 DEBUG(4, "Fork Stat %o\n", lt);
912 (void) close(dcf);
913 Uerror = SS_DIAL_FAILED;
914 return(FAIL);
915 }
916 return(dcf);
917 }
918
919 #else /* ATTSV */
920
921 GLOBAL int
922 open801(dcname, dnname, phone, speed)
923 char *dcname, *dnname, *phone;
924 {
925 int nw, lt, dcf = -1, nullfd, dnf = -1, ret;
926 unsigned timelim;
927
928 (void) close(nullfd = open("/", O_RDONLY)); /* partial open hack */
929 if (setjmp(Sjbuf)) {
930 DEBUG(4, "DN write %s\n", "timeout");
931 (void) close(dnf);
932 (void) close(dcf);
933 (void) close(nullfd);
934 Uerror = SS_DIAL_FAILED;
935 return(FAIL);
936 }
937 (void) signal(SIGALRM, alarmtr);
938 timelim = 5 * strlen(phone);
939 (void) alarm(timelim < connecttime ? connecttime : timelim);
940
941 if ((dnf = open(dnname, O_WRONLY)) < 0 ) {
942 DEBUG(5, "can't open %s\n", dnname);
943 Uerror = SS_CANT_ACCESS_DEVICE;
944 return(FAIL);
945 }
946 DEBUG(5, "%s is open\n", dnname);
947 if ( fd_mklock(dnf) != SUCCESS ) {
948 (void)close(dnf);
949 DEBUG(1, "failed to lock device %s\n", dnname);
950 Uerror = SS_LOCKED_DEVICE;
951 }
952 if ( (dcf = open(dcname, O_RDWR | O_NDELAY)) < 0 ) {
953 DEBUG(5, "can't open %s\n", dcname);
954 Uerror = SS_CANT_ACCESS_DEVICE;
955 return(FAIL);
956 }
957 if ( fd_mklock(dcf) != SUCCESS ) {
958 (void)close(dcf);
959 DEBUG(1, "failed to lock device %s\n", dcname);
960 Uerror = SS_LOCKED_DEVICE;
961 return(FAIL);
962 }
963
964 DEBUG(4, "dcf is %d\n", dcf);
965 fixline(dcf, speed, D_ACU);
966 nw = (*Write)(dnf, phone, lt = strlen(phone));
967 if (nw != lt) {
968 (void) alarm(0);
969 DEBUG(4, "ACU write error %d\n", errno);
970 (void) close(dnf);
971 (void) close(dcf);
972 Uerror = SS_DIAL_FAILED;
973 return(FAIL);
974 } else
975 DEBUG(4, "ACU write ok\n%s", "");
976
977 (void) close(dnf);
978 (void) close(nullfd = open("/", O_RDONLY)); /* partial open hack */
979 ret = open(dcname, O_RDWR); /* wait for carrier */
980 (void) alarm(0);
981 (void) close(ret); /* close 2nd modem open() */
982 if (ret < 0) { /* open() interrupted by alarm */
983 DEBUG(4, "Line open %s\n", "failed");
984 Uerror = SS_DIAL_FAILED;
985 (void) close(nullfd); /* close partially opened modem */
986 return(FAIL);
987 }
988 (void) fcntl(dcf,F_SETFL, fcntl(dcf, F_GETFL, 0) & ~O_NDELAY);
989 return(dcf);
990 }
991 #endif /* ATTSV */
992
993 #endif /* DIAL801 */
994
995 #ifdef V8
996 GLOBAL int
997 Dialout(flds)
998 char *flds[];
999 {
1000 int fd;
1001 char phone[MAXPH+2];
1002
1003 exphone(flds[F_PHONE], phone);
1004
1005 DEBUG(4, "call dialout(%s", phone);
1006 DEBUG(4, ", %s)\n", dev[D_CLASS]);
1007 fd = dialout(phone, dev[D_CLASS]);
1008 if (fd == -1)
1009 Uerror = SS_NO_DEVICE;
1010 if (fd == -3)
1011 Uerror = SS_DIAL_FAILED;
1012 if (fd == -9)
1013 Uerror = SS_DEVICE_FAILED;
1014
1015 (void) strcpy(Dc, "Dialout");
1016
1017 return(fd);
1018 }
1019 #endif /* V8 */
1020
1021 #ifdef TLI
1022 /*
1023 *
1024 * AT&T Transport Layer Interface
1025 *
1026 * expected in Devices
1027 * TLI line1 - - TLI
1028 * or
1029 * TLIS line1 - - TLIS
1030 *
1031 */
1032
1033 #include <sys/tiuser.h>
1034
1035 EXTERN void tfaillog();
1036
1037 char *t_alloc();
1038 int t_bind(), t_close(), t_connect(), t_free(), t_look(), t_open(), t_rcvdis();
1039
1040 #define CONNECT_ATTEMPTS 3
1041 #define TFREE(p, type) if ((p)) t_free((char *)(p), (type))
1042
1043 /*
1044 * returns fd to remote uucp daemon
1045 */
1046 /*ARGSUSED*/
1047 GLOBAL int
1048 tlicall(flds, dev)
1049 char *flds[];
1050 char *dev[];
1051 {
1052 char addrbuf[ BUFSIZ ];
1053 char devname[MAXNAMESIZE];
1054 int fd;
1055 int i, j;
1056 struct t_bind *bind_ret = 0;
1057 struct t_info tinfo;
1058 struct t_call *sndcall = 0, *rcvcall = 0;
1059 extern int t_errno;
1060
1061 EXTERN struct netbuf *stoa();
1062
1063 if ( dev[D_LINE][0] != '/' ) {
1064 /* dev holds device name relative to /dev */
1065 sprintf(devname, "/dev/%s", dev[D_LINE]);
1066 } else {
1067 /* dev holds full path name of device */
1068 strcpy(devname, dev[D_LINE]);
1069 }
1070 /* gimme local transport endpoint */
1071 errno = t_errno = 0;
1072 if (setjmp(Sjbuf)) {
1073 DEBUG(1, "t_open timeout\n%s", "");
1074 logent("t_open", "TIMEOUT");
1075 Uerror = SS_NO_DEVICE;
1076 return(FAIL);
1077 }
1078 (void) signal(SIGALRM, alarmtr);
1079 (void) alarm(5);
1080 fd = t_open(devname, O_RDWR, &tinfo);
1081 (void) alarm(0);
1082 if (fd < 0) {
1083 tfaillog(fd, "t_open" );
1084 Uerror = SS_NO_DEVICE;
1085 return(FAIL);
1086 }
1087 if ( fd_mklock(fd) != SUCCESS ) {
1088 (void)t_close(fd);
1089 DEBUG(1, "tlicall: failed to lock device %s\n", devname);
1090 Uerror = SS_LOCKED_DEVICE;
1091 return(FAIL);
1092 }
1093
1094 /* allocate tli structures */
1095 errno = t_errno = 0;
1096 if ( (bind_ret = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL)) ==
1097 (struct t_bind *)NULL
1098 || (sndcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) ==
1099 (struct t_call *)NULL
1100 || (rcvcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) ==
1101 (struct t_call *)NULL ) {
1102 tfaillog(fd, "t_alloc" );
1103 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1104 TFREE(rcvcall, T_CALL);
1105 Uerror = SS_NO_DEVICE;
1106 return(FAIL);
1107 }
1108
1109 /* bind */
1110 errno = t_errno = 0;
1111 if (t_bind(fd, (struct t_bind *) 0, bind_ret ) < 0) {
1112 tfaillog(fd, "t_bind" );
1113 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1114 TFREE(rcvcall, T_CALL);
1115 Uerror = SS_NO_DEVICE;
1116 fd_rmlock(fd);
1117 (void) t_close(fd);
1118 return(FAIL);
1119 }
1120 DEBUG(5, "tlicall: bound to %s\n", bind_ret->addr.buf);
1121
1122 /*
1123 * Prepare to connect.
1124 *
1125 * If address begins with "\x", "\X", "\o", or "\O",
1126 * assume is hexadecimal or octal address and use stoa()
1127 * to convert it.
1128 *
1129 * Else is usual uucico address -- only \N's left to process.
1130 * Walk thru connection address, changing \N's to NULLCHARs.
1131 * Note: If a NULLCHAR must be part of the connection address,
1132 * it must be overtly included in the address. One recommended
1133 * way is to do it in the Devices file, thusly:
1134 * Netname /dev/netport - - TLI \D\000
1135 * bsfix() turns \000 into \N and then the loop below makes it a
1136 * real, included-in-the-length null-byte.
1137 *
1138 * The DEBUG must print the strecpy'd address (so that
1139 * non-printables will have been replaced with C escapes).
1140 */
1141
1142 DEBUG(5, "t_connect to addr \"%s\"\n",
1143 strecpy( addrbuf, dev[D_ARG], "\\" ) );
1144
1145 if ( dev[D_ARG][0] == '\\' &&
1146 ( dev[D_ARG][1] == 'x' || dev[D_ARG][1] == 'X'
1147 || dev[D_ARG][1] == 'o' || dev[D_ARG][1] == 'O' ) ) {
1148 if ( stoa(dev[D_ARG], &(sndcall->addr)) == (struct netbuf *)NULL ) {
1149 DEBUG(5, "tlicall: stoa failed\n%s", "");
1150 logent("tlicall", "string-to-address failed");
1151 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1152 TFREE(rcvcall, T_CALL);
1153 Uerror = SS_NO_DEVICE;
1154 fd_rmlock(fd);
1155 (void) t_close(fd);
1156 return(FAIL);
1157 }
1158 } else {
1159 for( i = j = 0; i < BUFSIZ && dev[D_ARG][i] != NULLCHAR;
1160 ++i, ++j ) {
1161 if( dev[D_ARG][i] == '\\' && dev[D_ARG][i+1] == 'N' ) {
1162 addrbuf[j] = NULLCHAR;
1163 ++i;
1164 }
1165 else {
1166 addrbuf[j] = dev[D_ARG][i];
1167 }
1168 }
1169 sndcall->addr.buf = addrbuf;
1170 sndcall->addr.len = j;
1171 }
1172
1173 if (setjmp(Sjbuf)) {
1174 DEBUG(4, "timeout tlicall\n%s", "");
1175 logent("tlicall", "TIMEOUT");
1176 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1177 TFREE(rcvcall, T_CALL);
1178 Uerror = SS_NO_DEVICE;
1179 fd_rmlock(fd);
1180 (void) t_close(fd);
1181 return(FAIL);
1182 }
1183 (void) signal(SIGALRM, alarmtr);
1184 (void) alarm(connecttime);
1185
1186 /* connect to the service -- some listeners can't handle */
1187 /* multiple connect requests, so try it a few times */
1188 errno = t_errno = 0;
1189 for ( i = 0; i < CONNECT_ATTEMPTS; ++i ) {
1190 if (t_connect(fd, sndcall, rcvcall) == 0)
1191 break;
1192 if ( (t_errno == TLOOK) && (t_look(fd) == T_DISCONNECT)) {
1193 t_rcvdis(fd,NULL);
1194 (void) alarm(0);
1195 } else {
1196 (void) alarm(0);
1197 tfaillog(fd, "t_connect");
1198 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1199 TFREE(rcvcall, T_CALL);
1200 Uerror = SS_DIAL_FAILED;
1201 fd_rmlock(fd);
1202 (void) t_close(fd);
1203 return(FAIL);
1204 }
1205 }
1206 (void) alarm(0);
1207 TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1208 TFREE(rcvcall, T_CALL);
1209 if ( i == CONNECT_ATTEMPTS ) {
1210 tfaillog(fd, "t_connect");
1211 Uerror = SS_DIAL_FAILED;
1212 fd_rmlock(fd);
1213 (void) t_close(fd);
1214 return(FAIL);
1215 }
1216 errno = t_errno = 0;
1217 (void) strcpy(Dc, dev[D_CALLER]);
1218 return(fd);
1219 }
1220 #endif /* TLI */
1221