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 73 dkdial(dest) 74 char *dest; 75 { 76 return(dkndial(dest, atoi(getenv("DKINTF")))); 77 } 78 79 GLOBAL int 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 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 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 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