1 /* $OpenBSD: biz31.c,v 1.10 2006/03/17 19:17:13 moritz Exp $ */ 2 /* $NetBSD: biz31.c,v 1.5 1997/02/11 09:24:14 mrg Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)biz31.c 8.1 (Berkeley) 6/6/93"; 39 static char rcsid[] = "$OpenBSD: biz31.c,v 1.10 2006/03/17 19:17:13 moritz Exp $"; 40 #endif 41 #endif /* not lint */ 42 43 #include "tip.h" 44 45 #define MAXRETRY 3 /* sync up retry count */ 46 #define DISCONNECT_CMD "\21\25\11\24" /* disconnection string */ 47 48 static int biz_dialer(char *, char *); 49 static int bizsync(int); 50 static int echo(char *); 51 static void sigALRM(int); 52 static int detect(char *); 53 static int flush(char *); 54 static int bizsync(int); 55 56 static int timeout = 0; 57 static jmp_buf timeoutbuf; 58 59 /* 60 * Dial up on a BIZCOMP Model 1031 with either 61 * tone dialing (mod = "f") 62 * pulse dialing (mod = "w") 63 */ 64 static int 65 biz_dialer(char *num, char *mod) 66 { 67 int connected = 0; 68 69 if (!bizsync(FD)) { 70 logent(value(HOST), "", "biz", "out of sync"); 71 printf("bizcomp out of sync\n"); 72 delock(uucplock); 73 exit(0); 74 } 75 if (boolean(value(VERBOSE))) 76 printf("\nstarting call..."); 77 echo("#\rk$\r$\n"); /* disable auto-answer */ 78 echo("$>$.$ #\r"); /* tone/pulse dialing */ 79 echo(mod); 80 echo("$\r$\n"); 81 echo("$>$.$ #\re$ "); /* disconnection sequence */ 82 echo(DISCONNECT_CMD); 83 echo("\r$\n$\r$\n"); 84 echo("$>$.$ #\rr$ "); /* repeat dial */ 85 echo(num); 86 echo("\r$\n"); 87 if (boolean(value(VERBOSE))) 88 printf("ringing..."); 89 /* 90 * The reply from the BIZCOMP should be: 91 * `^G NO CONNECTION\r\n^G\r\n' failure 92 * ` CONNECTION\r\n^G' success 93 */ 94 connected = detect(" "); 95 #ifdef ACULOG 96 if (timeout) { 97 char line[80]; 98 99 (void)snprintf(line, sizeof line, "%ld second dial timeout", 100 number(value(DIALTIMEOUT))); 101 logent(value(HOST), num, "biz", line); 102 } 103 #endif 104 if (!connected) 105 flush(" NO CONNECTION\r\n\07\r\n"); 106 else 107 flush("CONNECTION\r\n\07"); 108 if (timeout) 109 biz31_disconnect(); /* insurance */ 110 return (connected); 111 } 112 113 int 114 biz31w_dialer(char *num, char *acu) 115 { 116 return (biz_dialer(num, "w")); 117 } 118 119 int 120 biz31f_dialer(char *num, char *acu) 121 { 122 return (biz_dialer(num, "f")); 123 } 124 125 void 126 biz31_disconnect(void) 127 { 128 write(FD, DISCONNECT_CMD, sizeof(DISCONNECT_CMD)-1); 129 sleep(2); 130 tcflush(FD, TCIOFLUSH); 131 } 132 133 void 134 biz31_abort(void) 135 { 136 write(FD, "\33", 1); 137 } 138 139 static int 140 echo(char *s) 141 { 142 char c; 143 144 while (c = *s++) switch (c) { 145 146 case '$': 147 read(FD, &c, 1); 148 s++; 149 break; 150 151 case '#': 152 c = *s++; 153 write(FD, &c, 1); 154 break; 155 156 default: 157 write(FD, &c, 1); 158 read(FD, &c, 1); 159 } 160 } 161 162 /*ARGSUSED*/ 163 static void 164 sigALRM(int signo) 165 { 166 timeout = 1; 167 longjmp(timeoutbuf, 1); 168 } 169 170 static int 171 detect(char *s) 172 { 173 sig_t f; 174 char c; 175 176 f = signal(SIGALRM, sigALRM); 177 timeout = 0; 178 while (*s) { 179 if (setjmp(timeoutbuf)) { 180 printf("\07timeout waiting for reply\n"); 181 biz31_abort(); 182 break; 183 } 184 alarm(number(value(DIALTIMEOUT))); 185 read(FD, &c, 1); 186 alarm(0); 187 if (c != *s++) 188 break; 189 } 190 signal(SIGALRM, f); 191 return (timeout == 0); 192 } 193 194 static int 195 flush(char *s) 196 { 197 sig_t f; 198 char c; 199 200 f = signal(SIGALRM, sigALRM); 201 while (*s++) { 202 if (setjmp(timeoutbuf)) 203 break; 204 alarm(10); 205 read(FD, &c, 1); 206 alarm(0); 207 } 208 signal(SIGALRM, f); 209 timeout = 0; /* guard against disconnection */ 210 } 211 212 /* 213 * This convoluted piece of code attempts to get 214 * the bizcomp in sync. If you don't have the capacity or nread 215 * call there are gory ways to simulate this. 216 */ 217 static int 218 bizsync(int fd) 219 { 220 #ifdef FIOCAPACITY 221 struct capacity b; 222 # define chars(b) ((b).cp_nbytes) 223 # define IOCTL FIOCAPACITY 224 #endif 225 #ifdef FIONREAD 226 long b; 227 # define chars(b) (b) 228 # define IOCTL FIONREAD 229 #endif 230 int already = 0; 231 char buf[10]; 232 233 retry: 234 if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0 && chars(b) > 0) 235 tcflush(FD, TCIOFLUSH); 236 write(fd, "\rp>\r", 4); 237 sleep(1); 238 if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0) { 239 if (chars(b) != 10) { 240 nono: 241 if (already > MAXRETRY) 242 return (0); 243 write(fd, DISCONNECT_CMD, 4); 244 sleep(2); 245 already++; 246 goto retry; 247 } else { 248 read(fd, buf, 10); 249 if (strncmp(buf, "p >\r\n\r\n>", 8)) 250 goto nono; 251 } 252 } 253 return (1); 254 } 255