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