xref: /illumos-gate/usr/src/cmd/bnu/dkdial.c (revision 47387219d1864755feb9c63e33d507b2874eaa72)
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 1994 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 /*
32  *	create a Datakit connection to a remote destination
33  */
34 #ifndef DIAL
35 	static char	SCCSID[] = "@(#)dkdial.c	2.7+BNU DKHOST 87/03/09";
36 #endif
37 /*
38  *	COMMKIT(TM) Software - Datakit(R) VCS Interface Release 2.0 V1
39  */
40 
41 #include <fcntl.h>
42 #include "dk.h"
43 #include <stdio.h>
44 #include <signal.h>
45 #define	SIGRTN	void
46 #include <setjmp.h>
47 #include <sysexits.h>
48 #include <errno.h>
49 
50 
51 #define DK_DEFWAIT	89	/* default time to wait for dial return */
52 #define	DK_MAXWAIT	600	/* maximum wait to allow the caller - 10 min */
53 
54 
55 GLOBAL unsigned int	dk_timewait = DK_DEFWAIT; /* Caller to dkdial might modify */
56 
57 static char	Conn_Msg[] = "Can't connect to %s: %s\n";
58 static char	Resp_Msg[] = "No response from Datakit";
59 
60 static SIGRTN	timout();	/* Alarm signal handler */
61 static void	setalarm(), usralarm();
62 EXTERN int	dkndial();
63 static int	Elapsed;	/* Alarm time elapsed during dial */
64 static int	Timer;		/* Current alarm setting */
65 static short	TimeErr;	/* Alarm clock rang */
66 
67 extern char	*getenv();
68 EXTERN int	dk_verbose, dk_errno;
69 
70 GLOBAL int
71 dkdial(dest)
72 	char *dest;
73 {
74 	return(dkndial(dest, atoi(getenv("DKINTF"))));
75 }
76 
77 GLOBAL int
78 dkndial(dest, intf)
79 	char *dest;
80 {
81 	short		fd;		/* Channel Descriptor	*/
82 	SIGRTN		(*SigWas)();	/* Caller's alarm handler */
83 	unsigned int	TimWas;		/* Caller's alarm clock */
84 	char		*key;
85 	struct diocdial {
86 			struct	diocreq iocb;
87 			char	dialstring[128];
88 		}	ioreq;
89 	char		dial_dev[32];
90 
91 
92 	sprintf(dial_dev, "/dev/dk/dial%d", intf);
93 
94 	/*
95 	** Clear our elapsed time and save caller's alarm stuff.
96 	*/
97 
98 	Timer = Elapsed = 0;
99 	SigWas = signal(SIGALRM, timout);
100 	TimWas = alarm(0);
101 
102 	/*
103 	** If requested timeout interval is unreasonable, use the default.
104 	*/
105 
106 	if ((dk_timewait == 0)  || (dk_timewait > DK_MAXWAIT))
107 		dk_timewait = DK_DEFWAIT;
108 
109 	/*
110 	** Do an alarm protected open of the dial device
111 	*/
112 
113 	setalarm(dk_timewait);
114 
115 	if ((fd = open(dial_dev, O_RDWR)) < 0) {
116 		setalarm(0);
117 		if (dk_verbose)
118 			fprintf(stderr, "dkdial: Can't open %s\n", dial_dev);
119 		usralarm(TimWas, SigWas);
120 		if (errno == EBUSY)
121 			return(dk_errno = -EX_TEMPFAIL);
122 		else
123 			return(dk_errno = -EX_OSFILE);
124 	}
125 
126 	/*
127 	** If the caller has a DKKEY, use it.
128 	*/
129 
130 	if((key = getenv("DKKEY")) != NULL && getuid() == geteuid())
131 		sprintf(ioreq.dialstring, "%s\n%s", dest, key);
132 	else
133 		strcpy(ioreq.dialstring, dest);
134 
135 	ioreq.iocb.req_traffic = 0;
136 	ioreq.iocb.req_1param = 0;
137 	ioreq.iocb.req_2param = 0;
138 
139 	/*
140 	** Try to dial the call.  If the alarm expires during the ioctl,
141 	** the ioctl will return in error.
142 	*/
143 
144 	if (ioctl(fd, DKIODIAL, &ioreq) < 0) {
145 		setalarm(0);
146 		if (dk_verbose)
147 		if (TimeErr)
148 			fprintf(stderr, Conn_Msg, Resp_Msg, ioreq.dialstring);
149 		else
150 			fprintf(stderr, Conn_Msg, ioreq.dialstring, dkerr(ioreq.iocb.req_error));
151 
152 		setalarm(2);		/* Don't wait forever on close */
153 		close(fd);
154 		usralarm(TimWas, SigWas);
155 		if (errno == EBUSY)
156 			return(-dkerrmap(dk_errno = -EX_TEMPFAIL));
157 		else
158 			return(-dkerrmap(dk_errno = ioreq.iocb.req_error));
159 	}
160 	usralarm(TimWas, SigWas);
161 	return (fd);
162 }
163 
164 /*
165 ** timout() is the alarm clock signal handling routine.  It is called
166 ** whenever the alarm clock expires during dial processing.
167 */
168 
169 /* ARGSUSED */
170 static SIGRTN
171 timout(arg)
172 int arg;
173 {
174 	TimeErr++;
175 }
176 
177 /*
178 ** setalarm() is called to request an alarm at a future time.  The residual
179 ** from the previous alarm (if any) is added to the elapsed time counter.
180 */
181 
182 static void
183 setalarm(Seconds)
184 {
185 	TimeErr = 0;
186 	(void) signal(SIGALRM, timout);
187 	Elapsed += Timer - alarm(Seconds);
188 	Timer = Seconds;
189 }
190 
191 /*
192 ** usralarm() is used to restore the alarm service for the caller.
193 */
194 
195 static void
196 usralarm(TimWas, SigWas)
197 	int		TimWas;		/* Caller's alarm clock */
198 	SIGRTN		(*SigWas)();	/* Caller's alarm handler */
199 {
200 	Elapsed += Timer - alarm(0);
201 	(void) signal(SIGALRM, SigWas);
202 	if (TimWas > 0) {
203 		TimWas -= Elapsed;
204 		if (TimWas < 2)
205 			TimWas = 2;
206 	}
207 	alarm(TimWas);
208 }
209