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 57GLOBAL unsigned int dk_timewait = DK_DEFWAIT; /* Caller to dkdial might modify */ 58 59static char Conn_Msg[] = "Can't connect to %s: %s\n"; 60static char Resp_Msg[] = "No response from Datakit"; 61 62static SIGRTN timout(); /* Alarm signal handler */ 63static void setalarm(), usralarm(); 64EXTERN int dkndial(); 65static int Elapsed; /* Alarm time elapsed during dial */ 66static int Timer; /* Current alarm setting */ 67static short TimeErr; /* Alarm clock rang */ 68 69extern char *getenv(); 70EXTERN int dk_verbose, dk_errno; 71 72GLOBAL int 73dkdial(dest) 74 char *dest; 75{ 76 return(dkndial(dest, atoi(getenv("DKINTF")))); 77} 78 79GLOBAL int 80dkndial(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 */ 172static SIGRTN 173timout(arg) 174int 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 184static void 185setalarm(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 197static void 198usralarm(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