xref: /titanic_44/usr/src/cmd/bnu/callers.c (revision b7f45089ccbe01bab3d7c7377b49d80d2ae18a69)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1996 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 
34 #include "uucp.h"
35 
36 #if defined(BSD4_2) || defined(ATTSVR4)
37 #include <netdb.h>
38 #include <netinet/in.h>
39 #include <sys/socket.h>
40 #endif
41 #ifdef UNET
42 #include  "UNET/unetio.h"
43 #include  "UNET/tcp.h"
44 #endif
45 
46 
47 EXTERN void alarmtr();
48 EXTERN jmp_buf Sjbuf;
49 EXTERN char *fdig(), *strecpy();
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
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 *
185 repphone(arg, phone, trstr)
186 register char *arg, *phone, *trstr;
187 {
188 	static char pbuf[2*(MAXPH+2)];
189 	register 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
230 processdev(flds, dev)
231 register char *flds[], *dev[];
232 {
233 	int dcf = -1;
234 	register struct caller	*ca;
235 	char *args[D_MAX+1], dcname[20];
236 	register char **sdev;
237 	EXTERN int pop_push();
238 	EXTERN void  setdevcfg();
239 	register 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 		register 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
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
438 translate(ttab, str)
439 register char *ttab, *str;
440 {
441 	register 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
463 gdial(type, arps, narps)
464 register char *type, *arps[];
465 register int narps;
466 {
467 	static char info[MAXLINE];
468 	register 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
509 dkcall(flds, dev)
510 char *flds[], *dev[];
511 {
512 	register 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
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
580 tcpcall(flds, dev)
581 char *flds[], *dev[];
582 {
583 	int ret;
584 	short port;
585 	extern int sys_nerr;
586 	extern char *sys_errlist[];
587 	struct servent *sp;
588 	struct hostent *hp;
589 	struct sockaddr_in sin;
590 
591 	if (EQUALS(flds[F_CLASS], "-")) {
592 		/*
593 		 * Use standard UUCP port number.
594 		 */
595 		sp = getservbyname("uucp", "tcp");
596 		endservent();
597 		ASSERT(sp != NULL, "No uucp service number", 0, 0);
598 		port = sp->s_port;
599 	} else {
600 		/*
601 		 * Systems file specifies a port number.
602 		 */
603 		sp = getservbyname(flds[F_CLASS], "tcp");
604 		endservent();
605 		if (sp == NULL) {
606 			port = htons(atoi(flds[F_CLASS]));
607 			if (port == 0) {
608 				logent("tcpopen", "unknown port number");
609 				Uerror = SS_NO_DEVICE;
610 				return(FAIL);
611 			}
612 		} else
613 			port = sp->s_port;
614 	}
615 	if (EQUALS(flds[F_PHONE], "-")) {
616 		/*
617 		 * Use UUCP name as host name.
618 		 */
619 		hp = gethostbyname(flds[F_NAME]);
620 	} else {
621 		/*
622 		 * Systems file specifies a host name different from the UUCP
623 		 * host name.
624 		 */
625 		hp = gethostbyname(flds[F_PHONE]);
626 	}
627 	endhostent();
628 	if (hp == NULL) {
629 		logent("tcpopen", "no such host");
630 		Uerror = SS_NO_DEVICE;
631 		return(FAIL);
632 	}
633 	DEBUG(4, "tcpdial host %s, ", hp->h_name);
634 	DEBUG(4, "port %d\n", ntohs(port));
635 
636 	ret = socket(AF_INET, SOCK_STREAM, 0);
637 	if (ret < 0) {
638 		if (errno < sys_nerr) {
639 			DEBUG(5, "no socket: %s\n", sys_errlist[errno]);
640 			logent("no socket", sys_errlist[errno]);
641 		}
642 		else {
643 			DEBUG(5, "no socket, errno %d\n", errno);
644 			logent("tcpopen", "NO SOCKET");
645 		}
646 		Uerror = SS_NO_DEVICE;
647 		return(FAIL);
648 	}
649 	sin.sin_family = hp->h_addrtype;
650 #ifdef BSD4_2
651 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
652 #else
653 	memcpy((caddr_t)&sin.sin_addr, hp->h_addr, hp->h_length);
654 #endif
655 	sin.sin_port = port;
656 	if (setjmp(Sjbuf)) {
657 		DEBUG(4, "timeout tcpopen\n%s", "");
658 		logent("tcpopen", "TIMEOUT");
659 		Uerror = SS_NO_DEVICE;
660 		return(FAIL);
661 	}
662 	(void) signal(SIGALRM, alarmtr);
663 	(void) alarm(connecttime);
664 	DEBUG(7, "family: %d\n", sin.sin_family);
665 	DEBUG(7, "port: %d\n", sin.sin_port);
666 	DEBUG(7, "addr: %08x\n",*((int *) &sin.sin_addr));
667 	if (connect(ret, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
668 		(void) alarm(0);
669 		(void) close(ret);
670 		if (errno < sys_nerr) {
671 			DEBUG(5, "connect failed: %s\n", sys_errlist[errno]);
672 			logent("connect failed", sys_errlist[errno]);
673 		}
674 		else {
675 			DEBUG(5, "connect failed, errno %d\n", errno);
676 			logent("tcpopen", "CONNECT FAILED");
677 		}
678 		Uerror = SS_NO_DEVICE;
679 		return(FAIL);
680 	}
681 	(void) signal(SIGPIPE, SIG_IGN);  /* watch out for broken ipc link...*/
682 	(void) alarm(0);
683 	(void) strcpy(Dc, "IPC");
684 	return(ret);
685 }
686 
687 #endif /* BSD4_2 */
688 
689 /*
690  *	unetcall(flds, dev)	make ethernet connection
691  *
692  *	return codes:
693  *		>0 - file number - ok
694  *		FAIL - failed
695  */
696 
697 #ifndef UNET
698 /*ARGSUSED*/
699 GLOBAL int
700 unetcall(flds, dev)
701 char	*flds[], *dev[];
702 {
703 	Uerror = SS_NO_DEVICE;
704 	return(FAIL);
705 }
706 #else /* UNET */
707 GLOBAL int
708 unetcall(flds, dev)
709 char *flds[], *dev[];
710 {
711 	int ret;
712 	int port;
713 
714 	port = atoi(dev[D_ARG]);
715 	DEBUG(4, "unetdial host %s, ", flds[F_PHONE]);
716 	DEBUG(4, "port %d\n", port);
717 	(void) alarm(connecttime);
718 	ret = tcpopen(flds[F_PHONE], port, 0, TO_ACTIVE, "rw");
719 	(void) alarm(0);
720 	endhnent();
721 	if (ret < 0) {
722 		DEBUG(5, "tcpopen failed: errno %d\n", errno);
723 		Uerror = SS_DIAL_FAILED;
724 		return(FAIL);
725 	}
726 	(void) strcpy(Dc, "UNET");
727 	return(ret);
728 }
729 #endif /* UNET */
730 
731 #endif /* TCP */
732 
733 #ifdef SYTEK
734 
735 /*
736  *	sytcall(flds, dev)	make a sytek connection
737  *
738  *	return codes:
739  *		>0 - file number - ok
740  *		FAIL - failed
741  */
742 
743 /*ARGSUSED*/
744 GLOBAL int
745 sytcall(flds, dev)
746 char *flds[], *dev[];
747 {
748 	int dcr, dcr2, nullfd, ret;
749 	char dcname[20], command[BUFSIZ];
750 
751 	(void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
752 	DEBUG(4, "dc - %s, ", dcname);
753 	dcr = open(dcname, O_WRONLY|O_NDELAY);
754 	if (dcr < 0) {
755 		Uerror = SS_DIAL_FAILED;
756 		DEBUG(4, "OPEN FAILED %s\n", dcname);
757 		return(FAIL);
758 	}
759 	if ( fd_mklock(dcr) != SUCCESS ) {
760 		(void)close(dcr);
761 		DEBUG(1, "failed to lock device %s\n", dcname);
762 		Uerror = SS_LOCKED_DEVICE;
763 		return(FAIL);
764 	}
765 
766 	sytfixline(dcr, atoi(fdig(dev[D_CLASS])), D_DIRECT);
767 	(void) sleep(2);
768 	DEBUG(4, "Calling Sytek unit %s\n", dev[D_ARG]);
769 	(void) sprintf(command,"\r\rcall %s\r", dev[D_ARG]);
770 	ret = (*Write)(dcr, command, strlen(command));
771 	(void) sleep(1);
772 	DEBUG(4, "COM1 return = %d\n", ret);
773 	sytfix2line(dcr);
774 	(void) close(nullfd = open("/", O_RDONLY));
775 	(void) signal(SIGALRM, alarmtr);
776 	if (setjmp(Sjbuf)) {
777 		DEBUG(4, "timeout sytek open\n%s", "");
778 		(void) close(nullfd);
779 		(void) close(dcr2);
780 		fd_rmlock(dcr);
781 		(void) close(dcr);
782 		Uerror = SS_DIAL_FAILED;
783 		return(FAIL);
784 	}
785 	(void) alarm(10);
786 	dcr2 = open(dcname,O_RDWR);
787 	(void) alarm(0);
788 	fd_rmlock(dcr);
789 	(void) close(dcr);
790 	if (dcr2 < 0) {
791 		DEBUG(4, "OPEN 2 FAILED %s\n", dcname);
792 		Uerror = SS_DIAL_FAILED;
793 		(void) close(nullfd);	/* kernel might think dc2 is open */
794 		return(FAIL);
795 	}
796 	if ( fd_mklock(dcr2) != SUCCESS ) {
797 		(void)close(dcr2);
798 		DEBUG(1, "failed to lock device %s\n", dcname);
799 		Uerror = SS_LOCKED_DEVICE;
800 		return(FAIL);
801 	return(dcr2);
802 }
803 
804 #endif /* SYTEK */
805 
806 #ifdef DIAL801
807 
808 /*
809  *	dial801(flds, dev)	dial remote machine on 801/801
810  *	char *flds[], *dev[];
811  *
812  *	return codes:
813  *		file descriptor  -  succeeded
814  *		FAIL  -  failed
815  *
816  *	unfortunately, open801() is different for usg and non-usg
817  */
818 
819 /*ARGSUSED*/
820 GLOBAL int
821 dial801(flds, dev)
822 char *flds[], *dev[];
823 {
824 	char dcname[20], dnname[20], phone[MAXPH+2];
825 	int dcf = -1, speed;
826 
827 	(void) sprintf(dnname, "/dev/%s", dev[D_CALLDEV]);
828 	(void) sprintf(phone, "%s%s", dev[D_ARG]   , ACULAST);
829 	(void) sprintf(dcname, "/dev/%s", dev[D_LINE]);
830 	CDEBUG(1, "Use Port %s, ", dcname);
831 	DEBUG(4, "acu - %s, ", dnname);
832 	VERBOSE("Trying modem - %s, ", dcname);	/* for cu */
833 	VERBOSE("acu - %s, ", dnname);	/* for cu */
834 	if(getuid()==0 || GRPCHK(getgid())) {
835 		CDEBUG(1, "Phone Number  %s\n", phone);
836 		/* In cu, only give out the phone number to trusted people. */
837 		VERBOSE("calling  %s:  ", phone);	/* for cu */
838 	}
839 	speed = atoi(fdig(dev[D_CLASS]));
840 	dcf = open801(dcname, dnname, phone, speed);
841 	if (dcf >= 0) {
842 	        if ( fd_mklock(dcf) != SUCCESS ) {
843 			(void) close(dcf);
844 			DEBUG(5, "fd_mklock line %s failed\n", dev[D_LINE]);
845 			Uerror = SS_LOCKED_DEVICE;
846 			return(FAIL);
847 		}
848 		fixline(dcf, speed, D_ACU);
849 		(void) strcpy(Dc, dev[D_LINE]);	/* for later unlock() */
850 		VERBOSE("SUCCEEDED\n%s", "");
851 	} else {
852 		VERBOSE("FAILED\n%s", "");
853 	}
854 	return(dcf);
855 }
856 
857 
858 #ifndef ATTSV
859 /*ARGSUSED*/
860 GLOBAL int
861 open801(dcname, dnname, phone, speed)
862 char *dcname, *dnname, *phone;
863 {
864 	int nw, lt, dcf = -1, nullfd, dnf = -1;
865 	pid_t w_ret, pid = -1;
866 	unsigned timelim;
867 
868 	if ((dnf = open(dnname, O_WRONLY)) < 0) {
869 		DEBUG(5, "can't open %s\n", dnname);
870 		Uerror = SS_CANT_ACCESS_DEVICE;
871 		return(FAIL);
872 	}
873 	DEBUG(5, "%s is open\n", dnname);
874 
875 	(void) close(nullfd = open("/dev/null", O_RDONLY));/* partial open hack */
876 	if (setjmp(Sjbuf)) {
877 		DEBUG(4, "timeout modem open\n%s", "");
878 		(void) close(nullfd);
879 		(void) close(dcf);
880 		(void) close(dnf);
881 		logent("801 open", "TIMEOUT");
882 		if (pid > 0) {
883 			kill(pid, 9);
884 			wait((int *) 0);
885 		}
886 		Uerror = SS_DIAL_FAILED;
887 		return(FAIL);
888 	}
889 	(void) signal(SIGALRM, alarmtr);
890 	timelim = 5 * strlen(phone);
891 	(void) alarm(timelim < connecttime ? connecttime : timelim);
892 	if ((pid = fork()) == 0) {
893 		sleep(2);
894 		nw = (*Write)(dnf, phone, lt = strlen(phone));
895 		if (nw != lt) {
896 			DEBUG(4, "ACU write error %d\n", errno);
897 			logent("ACU write", "FAILED");
898 			exit(1);
899 		}
900 		DEBUG(4, "ACU write ok\n%s", "");
901 		exit(0);
902 	}
903 	/*  open line - will return on carrier */
904 	dcf = open(dcname, O_RDWR);
905 
906 	DEBUG(4, "dcf is %d\n", dcf);
907 	if (dcf < 0) {	/* handle like a timeout */
908 		(void) alarm(0);
909 		longjmp(Sjbuf, 1);
910 	}
911 
912 	/* modem is open */
913 	while ((w_ret = wait(&lt)) != pid)
914 		if (w_ret == -1 && errno != EINTR) {
915 			DEBUG(4, "Wait failed errno=%d\n", errno);
916 			(void) close(dcf);
917 			(void) close(dnf);
918 			Uerror = SS_DIAL_FAILED;
919 			return(FAIL);
920 		}
921 	(void) alarm(0);
922 
923 	(void) close(dnf);	/* no reason to keep the 801 open */
924 	if (lt != 0) {
925 		DEBUG(4, "Fork Stat %o\n", lt);
926 		(void) close(dcf);
927 		Uerror = SS_DIAL_FAILED;
928 		return(FAIL);
929 	}
930 	return(dcf);
931 }
932 
933 #else /* ATTSV */
934 
935 GLOBAL int
936 open801(dcname, dnname, phone, speed)
937 char *dcname, *dnname, *phone;
938 {
939 	int nw, lt, dcf = -1, nullfd, dnf = -1, ret;
940 	unsigned timelim;
941 
942 	(void) close(nullfd = open("/", O_RDONLY));	/* partial open hack */
943 	if (setjmp(Sjbuf)) {
944 		DEBUG(4, "DN write %s\n", "timeout");
945 		(void) close(dnf);
946 		(void) close(dcf);
947 		(void) close(nullfd);
948 		Uerror = SS_DIAL_FAILED;
949 		return(FAIL);
950 	}
951 	(void) signal(SIGALRM, alarmtr);
952 	timelim = 5 * strlen(phone);
953 	(void) alarm(timelim < connecttime ? connecttime : timelim);
954 
955 	if ((dnf = open(dnname, O_WRONLY)) < 0 ) {
956 		DEBUG(5, "can't open %s\n", dnname);
957 		Uerror = SS_CANT_ACCESS_DEVICE;
958 		return(FAIL);
959 	}
960 	DEBUG(5, "%s is open\n", dnname);
961 	if ( fd_mklock(dnf) != SUCCESS ) {
962 		(void)close(dnf);
963 		DEBUG(1, "failed to lock device %s\n", dnname);
964 		Uerror = SS_LOCKED_DEVICE;
965 	}
966 	if (  (dcf = open(dcname, O_RDWR | O_NDELAY)) < 0 ) {
967 		DEBUG(5, "can't open %s\n", dcname);
968 		Uerror = SS_CANT_ACCESS_DEVICE;
969 		return(FAIL);
970 	}
971 	if ( fd_mklock(dcf) != SUCCESS ) {
972 		(void)close(dcf);
973 		DEBUG(1, "failed to lock device %s\n", dcname);
974 		Uerror = SS_LOCKED_DEVICE;
975 		return(FAIL);
976 	}
977 
978 	DEBUG(4, "dcf is %d\n", dcf);
979 	fixline(dcf, speed, D_ACU);
980 	nw = (*Write)(dnf, phone, lt = strlen(phone));
981 	if (nw != lt) {
982 		(void) alarm(0);
983 		DEBUG(4, "ACU write error %d\n", errno);
984 		(void) close(dnf);
985 		(void) close(dcf);
986 		Uerror = SS_DIAL_FAILED;
987 		return(FAIL);
988 	} else
989 		DEBUG(4, "ACU write ok\n%s", "");
990 
991 	(void) close(dnf);
992 	(void) close(nullfd = open("/", O_RDONLY));	/* partial open hack */
993 	ret = open(dcname, O_RDWR);  /* wait for carrier  */
994 	(void) alarm(0);
995 	(void) close(ret);	/* close 2nd modem open() */
996 	if (ret < 0) {		/* open() interrupted by alarm */
997 		DEBUG(4, "Line open %s\n", "failed");
998 		Uerror = SS_DIAL_FAILED;
999 		(void) close(nullfd);		/* close partially opened modem */
1000 		return(FAIL);
1001 	}
1002 	(void) fcntl(dcf,F_SETFL, fcntl(dcf, F_GETFL, 0) & ~O_NDELAY);
1003 	return(dcf);
1004 }
1005 #endif /* ATTSV */
1006 
1007 #endif /* DIAL801 */
1008 
1009 #ifdef V8
1010 GLOBAL int
1011 Dialout(flds)
1012 char *flds[];
1013 {
1014     int fd;
1015     char phone[MAXPH+2];
1016 
1017     exphone(flds[F_PHONE], phone);
1018 
1019     DEBUG(4, "call dialout(%s", phone);
1020     DEBUG(4, ", %s)\n", dev[D_CLASS]);
1021     fd = dialout(phone, dev[D_CLASS]);
1022     if (fd == -1)
1023 	Uerror = SS_NO_DEVICE;
1024     if (fd == -3)
1025 	Uerror = SS_DIAL_FAILED;
1026     if (fd == -9)
1027 	Uerror = SS_DEVICE_FAILED;
1028 
1029     (void) strcpy(Dc, "Dialout");
1030 
1031     return(fd);
1032 }
1033 #endif /* V8 */
1034 
1035 #ifdef TLI
1036 /*
1037  *
1038  * AT&T Transport Layer Interface
1039  *
1040  * expected in Devices
1041  *	TLI line1 - - TLI
1042  * or
1043  *	TLIS line1 - - TLIS
1044  *
1045  */
1046 
1047 #include <sys/tiuser.h>
1048 
1049 EXTERN void tfaillog();
1050 
1051 char *t_alloc();
1052 int t_bind(), t_close(), t_connect(), t_free(), t_look(), t_open(), t_rcvdis();
1053 
1054 #define	CONNECT_ATTEMPTS	3
1055 #define	TFREE(p, type)	if ((p)) t_free((char *)(p), (type))
1056 
1057 /*
1058  * returns fd to remote uucp daemon
1059  */
1060 /*ARGSUSED*/
1061 GLOBAL int
1062 tlicall(flds, dev)
1063 char *flds[];
1064 char *dev[];
1065 {
1066 	char		addrbuf[ BUFSIZ ];
1067 	char		devname[MAXNAMESIZE];
1068 	int		fd;
1069 	register int	i, j;
1070 	struct t_bind	*bind_ret = 0;
1071 	struct t_info	tinfo;
1072 	struct t_call	*sndcall = 0, *rcvcall = 0;
1073 	extern int	t_errno;
1074 
1075 	EXTERN struct netbuf	*stoa();
1076 
1077 	if ( dev[D_LINE][0] != '/' ) {
1078 		/*	dev holds device name relative to /dev	*/
1079 		sprintf(devname, "/dev/%s", dev[D_LINE]);
1080 	} else {
1081 		/*	dev holds full path name of device	*/
1082 		strcpy(devname, dev[D_LINE]);
1083 	}
1084 	/* gimme local transport endpoint */
1085 	errno = t_errno = 0;
1086 	if (setjmp(Sjbuf)) {
1087 		DEBUG(1, "t_open timeout\n%s", "");
1088 		logent("t_open", "TIMEOUT");
1089 		Uerror = SS_NO_DEVICE;
1090 		return(FAIL);
1091 	}
1092 	(void) signal(SIGALRM, alarmtr);
1093 	(void) alarm(5);
1094 	fd = t_open(devname, O_RDWR, &tinfo);
1095 	(void) alarm(0);
1096 	if (fd < 0) {
1097 		tfaillog(fd, "t_open" );
1098 		Uerror = SS_NO_DEVICE;
1099 		return(FAIL);
1100 	}
1101 	if ( fd_mklock(fd) != SUCCESS ) {
1102 		(void)t_close(fd);
1103 		DEBUG(1, "tlicall: failed to lock device %s\n", devname);
1104 		Uerror = SS_LOCKED_DEVICE;
1105 		return(FAIL);
1106 	}
1107 
1108 	/* allocate tli structures	*/
1109 	errno = t_errno = 0;
1110 	if ( (bind_ret = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL)) ==
1111 	    (struct t_bind *)NULL
1112 	|| (sndcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) ==
1113 	    (struct t_call *)NULL
1114 	|| (rcvcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL)) ==
1115 	    (struct t_call *)NULL ) {
1116 		tfaillog(fd, "t_alloc" );
1117 		TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1118 		TFREE(rcvcall, T_CALL);
1119 		Uerror = SS_NO_DEVICE;
1120 		return(FAIL);
1121 	}
1122 
1123 	/* bind */
1124 	errno = t_errno = 0;
1125 	if (t_bind(fd, (struct t_bind *) 0, bind_ret ) < 0) {
1126 		tfaillog(fd, "t_bind" );
1127 		TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1128 		TFREE(rcvcall, T_CALL);
1129 		Uerror = SS_NO_DEVICE;
1130 		fd_rmlock(fd);
1131 		(void) t_close(fd);
1132 		return(FAIL);
1133 	}
1134 	DEBUG(5, "tlicall: bound to %s\n", bind_ret->addr.buf);
1135 
1136 	/*
1137 	 * Prepare to connect.
1138 	 *
1139 	 * If address begins with "\x", "\X", "\o", or "\O",
1140 	 * assume is hexadecimal or octal address and use stoa()
1141 	 * to convert it.
1142 	 *
1143 	 * Else is usual uucico address -- only \N's left to process.
1144 	 * Walk thru connection address, changing \N's to NULLCHARs.
1145 	 * Note:  If a NULLCHAR must be part of the connection address,
1146 	 * it must be overtly included in the address.  One recommended
1147 	 * way is to do it in the Devices file, thusly:
1148 	 *		Netname /dev/netport - - TLI \D\000
1149 	 * bsfix() turns \000 into \N and then the loop below makes it a
1150 	 * real, included-in-the-length null-byte.
1151 	 *
1152 	 * The DEBUG must print the strecpy'd address (so that
1153 	 * non-printables will have been replaced with C escapes).
1154 	 */
1155 
1156 	DEBUG(5, "t_connect to addr \"%s\"\n",
1157 		strecpy( addrbuf, dev[D_ARG], "\\" ) );
1158 
1159 	if ( dev[D_ARG][0] == '\\' &&
1160 	( dev[D_ARG][1] == 'x' || dev[D_ARG][1] == 'X'
1161 	|| dev[D_ARG][1] == 'o' || dev[D_ARG][1] == 'O' ) ) {
1162 		if ( stoa(dev[D_ARG], &(sndcall->addr)) == (struct netbuf *)NULL ) {
1163 			DEBUG(5, "tlicall: stoa failed\n%s", "");
1164 			logent("tlicall", "string-to-address failed");
1165 			TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1166 			TFREE(rcvcall, T_CALL);
1167 			Uerror = SS_NO_DEVICE;
1168 			fd_rmlock(fd);
1169 			(void) t_close(fd);
1170 			return(FAIL);
1171 		}
1172 	} else {
1173 		for( i = j = 0; i < BUFSIZ && dev[D_ARG][i] != NULLCHAR;
1174 		++i, ++j ) {
1175 			if( dev[D_ARG][i] == '\\'  &&  dev[D_ARG][i+1] == 'N' ) {
1176 				addrbuf[j] = NULLCHAR;
1177 				++i;
1178 			}
1179 			else {
1180 				addrbuf[j] = dev[D_ARG][i];
1181 			}
1182 		}
1183 		sndcall->addr.buf = addrbuf;
1184 		sndcall->addr.len = j;
1185 	}
1186 
1187 	if (setjmp(Sjbuf)) {
1188 		DEBUG(4, "timeout tlicall\n%s", "");
1189 		logent("tlicall", "TIMEOUT");
1190 		TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1191 		TFREE(rcvcall, T_CALL);
1192 		Uerror = SS_NO_DEVICE;
1193 		fd_rmlock(fd);
1194 		(void) t_close(fd);
1195 		return(FAIL);
1196 	}
1197 	(void) signal(SIGALRM, alarmtr);
1198 	(void) alarm(connecttime);
1199 
1200 	/* connect to the service -- some listeners can't handle */
1201 	/* multiple connect requests, so try it a few times */
1202 	errno = t_errno = 0;
1203 	for ( i = 0; i < CONNECT_ATTEMPTS; ++i ) {
1204 		if (t_connect(fd, sndcall, rcvcall) == 0)
1205 			break;
1206 		if ( (t_errno == TLOOK) && (t_look(fd) == T_DISCONNECT)) {
1207 			t_rcvdis(fd,NULL);
1208 			(void) alarm(0);
1209 		} else {
1210 			(void) alarm(0);
1211 			tfaillog(fd, "t_connect");
1212 			TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1213 			TFREE(rcvcall, T_CALL);
1214 			Uerror = SS_DIAL_FAILED;
1215 			fd_rmlock(fd);
1216 			(void) t_close(fd);
1217 			return(FAIL);
1218 		}
1219 	}
1220 	(void) alarm(0);
1221 	TFREE(bind_ret, T_BIND);TFREE(sndcall, T_CALL);
1222 	TFREE(rcvcall, T_CALL);
1223 	if ( i == CONNECT_ATTEMPTS ) {
1224 		tfaillog(fd, "t_connect");
1225 		Uerror = SS_DIAL_FAILED;
1226 		fd_rmlock(fd);
1227 		(void) t_close(fd);
1228 		return(FAIL);
1229 	}
1230 	errno = t_errno = 0;
1231 	(void) strcpy(Dc, dev[D_CALLER]);
1232 	return(fd);
1233 }
1234 #endif /* TLI */
1235