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