8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / bnu / callers.c
blob7e8f3fea2b26638f3f363b7fd24736b71cf34a9f
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include "uucp.h"
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
45 #include <libgen.h>
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)();
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
67 #ifdef DIAL801
68 EXTERN int dial801();
69 EXTERN int open801();
70 #endif
72 #ifdef DATAKIT
73 EXTERN int dkcall();
74 #endif /* DATAKIT */
76 #ifdef V8
77 int Dialout();
78 #endif
80 #ifdef TCP
81 int unetcall();
82 int tcpcall();
83 #endif /* TCP */
85 #ifdef SYTEK
86 int sytcall();
87 #endif /* SYTEK */
89 #ifdef TLI
90 EXTERN int tlicall();
91 #endif /* TLI */
93 static struct caller Caller[] = {
95 #ifdef DIAL801
96 {"801", dial801},
97 {"212", dial801},
98 #endif /* DIAL801 */
100 #ifdef V8
101 {"Dialout", Dialout}, /* ditto but using dialout(III) */
102 #endif
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 */
115 #ifdef DATAKIT
116 {"DK", dkcall}, /* standard AT&T DATAKIT VCS caller */
117 #endif /* DATAKIT */
119 #ifdef SYTEK
120 {"Sytek", sytcall}, /* untested but should work */
121 #endif /* SYTEK */
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 */
130 {NULL, NULL} /* this line must be last */
134 * exphone - expand phone number for given prefix and number
136 * return code - none
139 static void
140 exphone(in, out)
141 char *in, *out;
143 FILE *fn;
144 char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
145 char buf[BUFSIZ];
146 char *s1;
148 if (!isalpha(*in)) {
149 (void) strcpy(out, in);
150 return;
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;
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;
172 fclose(fn);
175 (void) strcpy(out, tpre);
176 (void) strcat(out, npart);
177 return;
181 * repphone - Replace \D and \T sequences in arg with phone
182 * expanding and translating as appropriate.
184 static char *
185 repphone(arg, phone, trstr)
186 char *arg, *phone, *trstr;
188 static char pbuf[2*(MAXPH+2)];
189 char *fp, *tp;
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++)
202 arg++;
203 break;
204 case 'D':
205 for(fp=phone; *tp = *fp++; tp++)
207 arg++;
208 break;
209 default:
210 *tp++ = *arg;
211 break;
215 *tp = '\0';
216 return(pbuf);
219 static u_int saved_mode;
220 static char saved_dcname[20];
223 * processdev - Process a line from the Devices file
225 * return codes:
226 * file descriptor - succeeded
227 * FAIL - failed
229 GLOBAL int
230 processdev(flds, dev)
231 char *flds[], *dev[];
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;
246 sdev = dev;
247 /* set up default "break" routine */
248 genbrk = ttygenbrk;
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]);
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";
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);
274 dev += 2; /* Skip to next CALLER and ARG */
275 break;
278 if (dcf == -1) {
279 /* Here if not a built-in caller function */
281 /* We do locking (file and advisory) after open */
284 * Open the line
286 if ( *dev[D_LINE] != '/' ) {
287 (void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
288 } else {
289 (void) strcpy(dcname, dev[D_LINE] );
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;
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;
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;
320 /* check locks BEFORE modifying the stream */
322 if ( fd_mklock(dcf) != SUCCESS ) {
323 DEBUG(1, "failed to lock device %s\n", dcname);
324 Uerror = SS_LOCKED_DEVICE;
325 goto bad;
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;
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;
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;
353 /* save initial state of line in case script fails */
354 ret_orig = ioctl(dcf, TCGETA, &tty_orig);
356 /* use sdev[] since dev[] is incremented for internal callers */
357 fixline(dcf, atoi(fdig(sdev[D_CLASS])), D_DIRECT);
360 * Now loop through the remaining callers and chat
361 * according to scripts in dialers file.
363 for (; dev[D_CALLER] != NULL; dev += 2) {
364 int w;
366 * Scan Dialers file to find an entry
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;
373 if (w <= 2) /* do nothing - no chat */
374 break;
376 * Translate the phone number
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";
384 phonecl = repphone(dev[D_ARG], flds[F_PHONE], args[1]);
385 exphone(phonecl, phoneex);
386 translate(args[1], phoneex);
388 * Chat
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;
397 * Success at last!
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);
409 /* restore vanilla unix interface */
410 (void)interface("UNIX");
411 return(FAIL);
415 * clear_hup() clear the hangup state of the given device
417 GLOBAL int
418 clear_hup(dcf)
419 int dcf;
421 int ndcf;
422 if ((ndcf = open(saved_dcname, saved_mode)) < 0) {
423 return (FAIL);
425 if (ndcf != dcf) {
426 close(ndcf);
428 return (SUCCESS);
433 * translate the pairs of characters present in the first
434 * string whenever the first of the pair appears in the second
435 * string.
437 static void
438 translate(ttab, str)
439 char *ttab, *str;
441 char *s;
443 for(;*ttab && *(ttab+1); ttab += 2)
444 for(s=str;*s;s++)
445 if(*ttab == *s)
446 *s = *(ttab+1);
447 return;
450 #define MAXLINE 512
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
462 static int
463 gdial(type, arps, narps)
464 char *type, *arps[];
465 int narps;
467 static char info[MAXLINE];
468 int na;
469 EXTERN void dialreset();
470 EXTERN char * currdial();
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);
487 DEBUG(1, "%s not found in Dialers file\n", type);
488 dialreset();
489 return(0);
493 #ifdef DATAKIT
496 * dkcall(flds, dev) make a DATAKIT VCS connection
497 * DATAKIT VCS is a trademark of AT&T
499 * return codes:
500 * >0 - file number - ok
501 * FAIL - failed
504 #include "dk.h"
505 EXTERN int dkdial();
507 /*ARGSUSED*/
508 GLOBAL int
509 dkcall(flds, dev)
510 char *flds[], *dev[];
512 int fd;
513 #ifdef V8
514 extern int cdkp_ld;
515 #endif
517 char dialstring[64];
518 EXTERN void dkbreak();
520 strcpy(dialstring, dev[D_ARG]);
521 DEBUG(4, "dkcall(%s)\n", dialstring);
524 #ifdef V8
525 if (setjmp(Sjbuf)) {
526 Uerror = SS_DIAL_FAILED;
527 return(FAIL);
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)
537 close(fd);
538 fd = -1;
540 (void) alarm(0);
541 #else
542 fd = dkdial(dialstring);
543 #endif
545 (void) strcpy(Dc, "DK");
546 if (fd < 0) {
547 Uerror = SS_DIAL_FAILED;
548 return(FAIL);
550 else {
551 genbrk = dkbreak;
552 return(fd);
556 #endif /* DATAKIT */
558 #ifdef TCP
561 * tcpcall(flds, dev) make ethernet/socket connection
563 * return codes:
564 * >0 - file number - ok
565 * FAIL - failed
568 #if !(defined(BSD4_2) || defined(ATTSVR4))
569 /*ARGSUSED*/
570 GLOBAL int
571 tcpcall(flds, dev)
572 char *flds[], *dev[];
574 Uerror = SS_NO_DEVICE;
575 return(FAIL);
577 #else /* BSD4_2 */
578 /*ARGSUSED*/
579 GLOBAL int
580 tcpcall(flds, dev)
581 char *flds[], *dev[];
583 int ret;
584 short port;
585 struct servent *sp;
586 struct hostent *hp;
587 struct sockaddr_in sin;
589 if (EQUALS(flds[F_CLASS], "-")) {
591 * Use standard UUCP port number.
593 sp = getservbyname("uucp", "tcp");
594 endservent();
595 ASSERT(sp != NULL, "No uucp service number", 0, 0);
596 port = sp->s_port;
597 } else {
599 * Systems file specifies a port number.
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);
610 } else
611 port = sp->s_port;
613 if (EQUALS(flds[F_PHONE], "-")) {
615 * Use UUCP name as host name.
617 hp = gethostbyname(flds[F_NAME]);
618 } else {
620 * Systems file specifies a host name different from the UUCP
621 * host name.
623 hp = gethostbyname(flds[F_PHONE]);
625 endhostent();
626 if (hp == NULL) {
627 logent("tcpopen", "no such host");
628 Uerror = SS_NO_DEVICE;
629 return(FAIL);
631 DEBUG(4, "tcpdial host %s, ", hp->h_name);
632 DEBUG(4, "port %d\n", ntohs(port));
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);
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);
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);
667 (void) signal(SIGPIPE, SIG_IGN); /* watch out for broken ipc link...*/
668 (void) alarm(0);
669 (void) strcpy(Dc, "IPC");
670 return(ret);
673 #endif /* BSD4_2 */
676 * unetcall(flds, dev) make ethernet connection
678 * return codes:
679 * >0 - file number - ok
680 * FAIL - failed
683 #ifndef UNET
684 /*ARGSUSED*/
685 GLOBAL int
686 unetcall(flds, dev)
687 char *flds[], *dev[];
689 Uerror = SS_NO_DEVICE;
690 return(FAIL);
692 #else /* UNET */
693 GLOBAL int
694 unetcall(flds, dev)
695 char *flds[], *dev[];
697 int ret;
698 int port;
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);
712 (void) strcpy(Dc, "UNET");
713 return(ret);
715 #endif /* UNET */
717 #endif /* TCP */
719 #ifdef SYTEK
722 * sytcall(flds, dev) make a sytek connection
724 * return codes:
725 * >0 - file number - ok
726 * FAIL - failed
729 /*ARGSUSED*/
730 GLOBAL int
731 sytcall(flds, dev)
732 char *flds[], *dev[];
734 int dcr, dcr2, nullfd, ret;
735 char dcname[20], command[BUFSIZ];
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);
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);
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);
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);
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);
790 #endif /* SYTEK */
792 #ifdef DIAL801
795 * dial801(flds, dev) dial remote machine on 801/801
796 * char *flds[], *dev[];
798 * return codes:
799 * file descriptor - succeeded
800 * FAIL - failed
802 * unfortunately, open801() is different for usg and non-usg
805 /*ARGSUSED*/
806 GLOBAL int
807 dial801(flds, dev)
808 char *flds[], *dev[];
810 char dcname[20], dnname[20], phone[MAXPH+2];
811 int dcf = -1, speed;
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 */
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);
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", "");
840 return(dcf);
844 #ifndef ATTSV
845 /*ARGSUSED*/
846 GLOBAL int
847 open801(dcname, dnname, phone, speed)
848 char *dcname, *dnname, *phone;
850 int nw, lt, dcf = -1, nullfd, dnf = -1;
851 pid_t w_ret, pid = -1;
852 unsigned timelim;
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);
859 DEBUG(5, "%s is open\n", dnname);
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);
872 Uerror = SS_DIAL_FAILED;
873 return(FAIL);
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);
886 DEBUG(4, "ACU write ok\n%s", "");
887 exit(0);
889 /* open line - will return on carrier */
890 dcf = open(dcname, O_RDWR);
892 DEBUG(4, "dcf is %d\n", dcf);
893 if (dcf < 0) { /* handle like a timeout */
894 (void) alarm(0);
895 longjmp(Sjbuf, 1);
898 /* modem is open */
899 while ((w_ret = wait(&lt)) != 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);
907 (void) alarm(0);
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);
916 return(dcf);
919 #else /* ATTSV */
921 GLOBAL int
922 open801(dcname, dnname, phone, speed)
923 char *dcname, *dnname, *phone;
925 int nw, lt, dcf = -1, nullfd, dnf = -1, ret;
926 unsigned timelim;
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);
937 (void) signal(SIGALRM, alarmtr);
938 timelim = 5 * strlen(phone);
939 (void) alarm(timelim < connecttime ? connecttime : timelim);
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);
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;
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);
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);
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", "");
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);
988 (void) fcntl(dcf,F_SETFL, fcntl(dcf, F_GETFL, 0) & ~O_NDELAY);
989 return(dcf);
991 #endif /* ATTSV */
993 #endif /* DIAL801 */
995 #ifdef V8
996 GLOBAL int
997 Dialout(flds)
998 char *flds[];
1000 int fd;
1001 char phone[MAXPH+2];
1003 exphone(flds[F_PHONE], phone);
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;
1015 (void) strcpy(Dc, "Dialout");
1017 return(fd);
1019 #endif /* V8 */
1021 #ifdef TLI
1024 * AT&T Transport Layer Interface
1026 * expected in Devices
1027 * TLI line1 - - TLI
1028 * or
1029 * TLIS line1 - - TLIS
1033 #include <sys/tiuser.h>
1035 EXTERN void tfaillog();
1037 char *t_alloc();
1038 int t_bind(), t_close(), t_connect(), t_free(), t_look(), t_open(), t_rcvdis();
1040 #define CONNECT_ATTEMPTS 3
1041 #define TFREE(p, type) if ((p)) t_free((char *)(p), (type))
1044 * returns fd to remote uucp daemon
1046 /*ARGSUSED*/
1047 GLOBAL int
1048 tlicall(flds, dev)
1049 char *flds[];
1050 char *dev[];
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;
1061 EXTERN struct netbuf *stoa();
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]);
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);
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);
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);
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);
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);
1120 DEBUG(5, "tlicall: bound to %s\n", bind_ret->addr.buf);
1123 * Prepare to connect.
1125 * If address begins with "\x", "\X", "\o", or "\O",
1126 * assume is hexadecimal or octal address and use stoa()
1127 * to convert it.
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.
1138 * The DEBUG must print the strecpy'd address (so that
1139 * non-printables will have been replaced with C escapes).
1142 DEBUG(5, "t_connect to addr \"%s\"\n",
1143 strecpy( addrbuf, dev[D_ARG], "\\" ) );
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);
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;
1165 else {
1166 addrbuf[j] = dev[D_ARG][i];
1169 sndcall->addr.buf = addrbuf;
1170 sndcall->addr.len = j;
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);
1183 (void) signal(SIGALRM, alarmtr);
1184 (void) alarm(connecttime);
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);
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);
1216 errno = t_errno = 0;
1217 (void) strcpy(Dc, dev[D_CALLER]);
1218 return(fd);
1220 #endif /* TLI */