1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1995 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * flow control protocol. 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * This protocol relies on flow control of the data stream. 34*7c478bd9Sstevel@tonic-gate * It is meant for working over links that can (almost) be 35*7c478bd9Sstevel@tonic-gate * guaranteed to be errorfree, specifically X.25/PAD links. 36*7c478bd9Sstevel@tonic-gate * A sumcheck is carried out over a whole file only. If a 37*7c478bd9Sstevel@tonic-gate * transport fails the receiver can request retransmission(s). 38*7c478bd9Sstevel@tonic-gate * This protocol uses a 7-bit datapath only, so it can be 39*7c478bd9Sstevel@tonic-gate * used on links that are not 8-bit transparent. 40*7c478bd9Sstevel@tonic-gate * 41*7c478bd9Sstevel@tonic-gate * When using this protocol with an X.25 PAD: 42*7c478bd9Sstevel@tonic-gate * Although this protocol uses no control chars except CR, 43*7c478bd9Sstevel@tonic-gate * control chars NULL and ^P are used before this protocol 44*7c478bd9Sstevel@tonic-gate * is started; since ^P is the default char for accessing 45*7c478bd9Sstevel@tonic-gate * PAD X.28 command mode, be sure to disable that access 46*7c478bd9Sstevel@tonic-gate * (PAD par 1). Also make sure both flow control pars 47*7c478bd9Sstevel@tonic-gate * (5 and 12) are set. The CR used in this proto is meant 48*7c478bd9Sstevel@tonic-gate * to trigger packet transmission, hence par 3 should be 49*7c478bd9Sstevel@tonic-gate * set to 2; a good value for the Idle Timer (par 4) is 10. 50*7c478bd9Sstevel@tonic-gate * All other pars should be set to 0. 51*7c478bd9Sstevel@tonic-gate * 52*7c478bd9Sstevel@tonic-gate * Normally a calling site will take care of setting the 53*7c478bd9Sstevel@tonic-gate * local PAD pars via an X.28 command and those of the remote 54*7c478bd9Sstevel@tonic-gate * PAD via an X.29 command, unless the remote site has a 55*7c478bd9Sstevel@tonic-gate * special channel assigned for this protocol with the proper 56*7c478bd9Sstevel@tonic-gate * par settings. 57*7c478bd9Sstevel@tonic-gate * 58*7c478bd9Sstevel@tonic-gate * Additional comments for hosts with direct X.25 access: 59*7c478bd9Sstevel@tonic-gate * - the global variable IsTcpIp, when set, excludes the ioctl's, 60*7c478bd9Sstevel@tonic-gate * so the same binary can run on X.25 and non-X.25 hosts; 61*7c478bd9Sstevel@tonic-gate * - reads are done in small chunks, which can be smaller than 62*7c478bd9Sstevel@tonic-gate * the packet size; your X.25 driver must support that. 63*7c478bd9Sstevel@tonic-gate * 64*7c478bd9Sstevel@tonic-gate * 65*7c478bd9Sstevel@tonic-gate * Author: 66*7c478bd9Sstevel@tonic-gate * Piet Beertema, CWI, Amsterdam, Sep 1984 67*7c478bd9Sstevel@tonic-gate * Modified for X.25 hosts: 68*7c478bd9Sstevel@tonic-gate * Robert Elz, Melbourne Univ, Mar 1985 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #include "uucp.h" 72*7c478bd9Sstevel@tonic-gate #ifdef F_PROTOCOL 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate extern unsigned msgtime; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* privates */ 77*7c478bd9Sstevel@tonic-gate static int frdblk(), fwrblk(); 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate #define FIBUFSIZ 4096 /* for X.25 interfaces: set equal to packet size, 80*7c478bd9Sstevel@tonic-gate * but see comment above 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate #define FOBUFSIZ 4096 /* for X.25 interfaces: set equal to packet size; 84*7c478bd9Sstevel@tonic-gate * otherwise make as large as feasible to reduce 85*7c478bd9Sstevel@tonic-gate * number of write system calls 86*7c478bd9Sstevel@tonic-gate */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate #ifndef MAXMSGLEN 89*7c478bd9Sstevel@tonic-gate #define MAXMSGLEN BUFSIZ 90*7c478bd9Sstevel@tonic-gate #endif MAXMSGLEN 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static int fchksum; 93*7c478bd9Sstevel@tonic-gate static jmp_buf Ffailbuf; 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 96*7c478bd9Sstevel@tonic-gate static void 97*7c478bd9Sstevel@tonic-gate falarm(sig) 98*7c478bd9Sstevel@tonic-gate int sig; 99*7c478bd9Sstevel@tonic-gate { 100*7c478bd9Sstevel@tonic-gate signal(SIGALRM, falarm); 101*7c478bd9Sstevel@tonic-gate longjmp(Ffailbuf, 1); 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate static void (*fsig)(); 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate static int ioctlok; 107*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY 108*7c478bd9Sstevel@tonic-gate static struct termio ttbuf; 109*7c478bd9Sstevel@tonic-gate #else 110*7c478bd9Sstevel@tonic-gate static struct sgttyb ttbuf; 111*7c478bd9Sstevel@tonic-gate #endif 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate fturnon() 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate int ret; 116*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY 117*7c478bd9Sstevel@tonic-gate struct termio save_ttbuf; 118*7c478bd9Sstevel@tonic-gate #else 119*7c478bd9Sstevel@tonic-gate struct sgttyb save_ttbuf; 120*7c478bd9Sstevel@tonic-gate #endif 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY 123*7c478bd9Sstevel@tonic-gate if (ioctl(Ifn, TCGETA, &ttbuf) >= 0) { 124*7c478bd9Sstevel@tonic-gate ioctlok = 1; 125*7c478bd9Sstevel@tonic-gate save_ttbuf = ttbuf; 126*7c478bd9Sstevel@tonic-gate ioctl(Ifn, TCGETA, &ttbuf); 127*7c478bd9Sstevel@tonic-gate ttbuf.c_iflag = IXOFF|IXON|ISTRIP; 128*7c478bd9Sstevel@tonic-gate ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ; 129*7c478bd9Sstevel@tonic-gate ttbuf.c_cc[VTIME] = 5; 130*7c478bd9Sstevel@tonic-gate ret = ioctl(Ifn, TCSETA, &ttbuf); 131*7c478bd9Sstevel@tonic-gate ASSERT(ret >= 0, "STTY FAILED", "", ret); 132*7c478bd9Sstevel@tonic-gate ttbuf = save_ttbuf; 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate #else /* !ATTSVTTY */ 135*7c478bd9Sstevel@tonic-gate if (ioctl(Ifn, TIOCGETP, &ttbuf) >= 0) { 136*7c478bd9Sstevel@tonic-gate ioctlok = 1; 137*7c478bd9Sstevel@tonic-gate save_ttbuf = ttbuf; 138*7c478bd9Sstevel@tonic-gate ttbuf.sg_flags = ANYP|CBREAK|TANDEM; 139*7c478bd9Sstevel@tonic-gate ret = ioctl(Ifn, TIOCSETP, &ttbuf); 140*7c478bd9Sstevel@tonic-gate ASSERT(ret >= 0, "STTY FAILED", "", ret); 141*7c478bd9Sstevel@tonic-gate ttbuf = save_ttbuf; 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate #endif /* ATTSVTTY */ 144*7c478bd9Sstevel@tonic-gate fsig = signal(SIGALRM, falarm); 145*7c478bd9Sstevel@tonic-gate /* give the other side time to perform its ioctl; 146*7c478bd9Sstevel@tonic-gate * otherwise it may flush out the first data this 147*7c478bd9Sstevel@tonic-gate * side is about to send. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate sleep(2); 150*7c478bd9Sstevel@tonic-gate return SUCCESS; 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate fturnoff() 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate if (ioctlok) { 156*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY 157*7c478bd9Sstevel@tonic-gate (void) ioctl(Ifn, TCSETA, &ttbuf); 158*7c478bd9Sstevel@tonic-gate #else 159*7c478bd9Sstevel@tonic-gate (void) ioctl(Ifn, TIOCSETP, &ttbuf); 160*7c478bd9Sstevel@tonic-gate #endif 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate (void) signal(SIGALRM, fsig); 163*7c478bd9Sstevel@tonic-gate sleep(2); 164*7c478bd9Sstevel@tonic-gate return SUCCESS; 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate fwrmsg(type, str, fn) 168*7c478bd9Sstevel@tonic-gate register char *str; 169*7c478bd9Sstevel@tonic-gate int fn; 170*7c478bd9Sstevel@tonic-gate char type; 171*7c478bd9Sstevel@tonic-gate { 172*7c478bd9Sstevel@tonic-gate register char *s; 173*7c478bd9Sstevel@tonic-gate char bufr[MAXMSGLEN]; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate s = bufr; 176*7c478bd9Sstevel@tonic-gate *s++ = type; 177*7c478bd9Sstevel@tonic-gate while (*str) 178*7c478bd9Sstevel@tonic-gate *s++ = *str++; 179*7c478bd9Sstevel@tonic-gate if (*(s-1) == '\n') 180*7c478bd9Sstevel@tonic-gate s--; 181*7c478bd9Sstevel@tonic-gate *s++ = '\r'; 182*7c478bd9Sstevel@tonic-gate *s = 0; 183*7c478bd9Sstevel@tonic-gate (void) write(fn, bufr, s - bufr); 184*7c478bd9Sstevel@tonic-gate return SUCCESS; 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate frdmsg(str, fn) 188*7c478bd9Sstevel@tonic-gate register char *str; 189*7c478bd9Sstevel@tonic-gate register int fn; 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate register char *smax; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate if (setjmp(Ffailbuf)) 194*7c478bd9Sstevel@tonic-gate return FAIL; 195*7c478bd9Sstevel@tonic-gate smax = str + MAXMSGLEN - 1; 196*7c478bd9Sstevel@tonic-gate (void) alarm(msgtime); 197*7c478bd9Sstevel@tonic-gate for (;;) { 198*7c478bd9Sstevel@tonic-gate if (read(fn, str, 1) <= 0) 199*7c478bd9Sstevel@tonic-gate goto msgerr; 200*7c478bd9Sstevel@tonic-gate *str &= 0177; 201*7c478bd9Sstevel@tonic-gate if (*str == '\r') 202*7c478bd9Sstevel@tonic-gate break; 203*7c478bd9Sstevel@tonic-gate if (*str < ' ') { 204*7c478bd9Sstevel@tonic-gate continue; 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate if (str++ >= smax) 207*7c478bd9Sstevel@tonic-gate goto msgerr; 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate *str = '\0'; 210*7c478bd9Sstevel@tonic-gate (void) alarm(0); 211*7c478bd9Sstevel@tonic-gate return SUCCESS; 212*7c478bd9Sstevel@tonic-gate msgerr: 213*7c478bd9Sstevel@tonic-gate (void) alarm(0); 214*7c478bd9Sstevel@tonic-gate return FAIL; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate fwrdata(fp1, fn) 218*7c478bd9Sstevel@tonic-gate FILE *fp1; 219*7c478bd9Sstevel@tonic-gate int fn; 220*7c478bd9Sstevel@tonic-gate { 221*7c478bd9Sstevel@tonic-gate register int alen, ret; 222*7c478bd9Sstevel@tonic-gate char ack, ibuf[MAXMSGLEN]; 223*7c478bd9Sstevel@tonic-gate int flen, retries = 0; 224*7c478bd9Sstevel@tonic-gate long fbytes; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate ret = FAIL; 227*7c478bd9Sstevel@tonic-gate retry: 228*7c478bd9Sstevel@tonic-gate fchksum = 0xffff; 229*7c478bd9Sstevel@tonic-gate fbytes = 0L; 230*7c478bd9Sstevel@tonic-gate ack = '\0'; 231*7c478bd9Sstevel@tonic-gate do { 232*7c478bd9Sstevel@tonic-gate alen = fwrblk(fn, fp1, &flen); 233*7c478bd9Sstevel@tonic-gate fbytes += flen; 234*7c478bd9Sstevel@tonic-gate if (alen <= 0) { 235*7c478bd9Sstevel@tonic-gate goto acct; 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate } while (!feof(fp1) && !ferror(fp1)); 238*7c478bd9Sstevel@tonic-gate DEBUG(8, "\nchecksum: %04x\n", fchksum); 239*7c478bd9Sstevel@tonic-gate if (frdmsg(ibuf, fn) != FAIL) { 240*7c478bd9Sstevel@tonic-gate if ((ack = ibuf[0]) == 'G') 241*7c478bd9Sstevel@tonic-gate ret = SUCCESS; 242*7c478bd9Sstevel@tonic-gate DEBUG(4, "ack - '%c'\n", ack); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate acct: 245*7c478bd9Sstevel@tonic-gate DEBUG(7, "%d retries\n", retries); 246*7c478bd9Sstevel@tonic-gate if (ack == 'R') { 247*7c478bd9Sstevel@tonic-gate DEBUG(4, "RETRY:\n", 0); 248*7c478bd9Sstevel@tonic-gate fseek(fp1, 0L, 0); 249*7c478bd9Sstevel@tonic-gate retries++; 250*7c478bd9Sstevel@tonic-gate goto retry; 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate return ret; 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* max. attempts to retransmit a file: */ 256*7c478bd9Sstevel@tonic-gate #define MAXRETRIES (fbytes < 10000L ? 2 : 1) 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate frddata(fn, fp2) 259*7c478bd9Sstevel@tonic-gate register int fn; 260*7c478bd9Sstevel@tonic-gate register FILE *fp2; 261*7c478bd9Sstevel@tonic-gate { 262*7c478bd9Sstevel@tonic-gate register int flen; 263*7c478bd9Sstevel@tonic-gate register char eof; 264*7c478bd9Sstevel@tonic-gate char ibuf[FIBUFSIZ]; 265*7c478bd9Sstevel@tonic-gate int ret, retries = 0; 266*7c478bd9Sstevel@tonic-gate long alen, fbytes; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate ret = FAIL; 269*7c478bd9Sstevel@tonic-gate retry: 270*7c478bd9Sstevel@tonic-gate fchksum = 0xffff; 271*7c478bd9Sstevel@tonic-gate fbytes = 0L; 272*7c478bd9Sstevel@tonic-gate do { 273*7c478bd9Sstevel@tonic-gate flen = frdblk(ibuf, fn, &alen); 274*7c478bd9Sstevel@tonic-gate if (flen < 0) 275*7c478bd9Sstevel@tonic-gate goto acct; 276*7c478bd9Sstevel@tonic-gate if (eof = flen > FIBUFSIZ) 277*7c478bd9Sstevel@tonic-gate flen -= FIBUFSIZ + 1; 278*7c478bd9Sstevel@tonic-gate fbytes += flen; 279*7c478bd9Sstevel@tonic-gate if (fwrite(ibuf, sizeof (char), flen, fp2) != flen) 280*7c478bd9Sstevel@tonic-gate goto acct; 281*7c478bd9Sstevel@tonic-gate } while (!eof); 282*7c478bd9Sstevel@tonic-gate ret = SUCCESS; 283*7c478bd9Sstevel@tonic-gate acct: 284*7c478bd9Sstevel@tonic-gate DEBUG(7, "%d retries\n", retries); 285*7c478bd9Sstevel@tonic-gate if (ret == FAIL) { 286*7c478bd9Sstevel@tonic-gate if (retries++ < MAXRETRIES) { 287*7c478bd9Sstevel@tonic-gate DEBUG(8, "send ack: 'R'\n", 0); 288*7c478bd9Sstevel@tonic-gate fwrmsg('R', "", fn); 289*7c478bd9Sstevel@tonic-gate fseek(fp2, 0L, 0); 290*7c478bd9Sstevel@tonic-gate DEBUG(4, "RETRY:\n", 0); 291*7c478bd9Sstevel@tonic-gate goto retry; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate DEBUG(8, "send ack: 'Q'\n", 0); 294*7c478bd9Sstevel@tonic-gate fwrmsg('Q', "", fn); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate else { 297*7c478bd9Sstevel@tonic-gate DEBUG(8, "send ack: 'G'\n", 0); 298*7c478bd9Sstevel@tonic-gate fwrmsg('G', "", fn); 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate return ret; 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate static 304*7c478bd9Sstevel@tonic-gate frdbuf(blk, len, fn) 305*7c478bd9Sstevel@tonic-gate register char *blk; 306*7c478bd9Sstevel@tonic-gate register int len; 307*7c478bd9Sstevel@tonic-gate register int fn; 308*7c478bd9Sstevel@tonic-gate { 309*7c478bd9Sstevel@tonic-gate static int ret = FIBUFSIZ / 2; 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate if (setjmp(Ffailbuf)) 312*7c478bd9Sstevel@tonic-gate return FAIL; 313*7c478bd9Sstevel@tonic-gate (void) alarm(msgtime); 314*7c478bd9Sstevel@tonic-gate ret = read(fn, blk, len); 315*7c478bd9Sstevel@tonic-gate alarm(0); 316*7c478bd9Sstevel@tonic-gate return ret <= 0 ? FAIL : ret; 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL) 320*7c478bd9Sstevel@tonic-gate /* call ultouch every TC calls to either frdblk or fwrblk */ 321*7c478bd9Sstevel@tonic-gate #define TC 20 322*7c478bd9Sstevel@tonic-gate static int tc = TC; 323*7c478bd9Sstevel@tonic-gate #endif !defined(ATTSVKILL) 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* Byte conversion: 326*7c478bd9Sstevel@tonic-gate * 327*7c478bd9Sstevel@tonic-gate * from pre to 328*7c478bd9Sstevel@tonic-gate * 000-037 172 100-137 329*7c478bd9Sstevel@tonic-gate * 040-171 040-171 330*7c478bd9Sstevel@tonic-gate * 172-177 173 072-077 331*7c478bd9Sstevel@tonic-gate * 200-237 174 100-137 332*7c478bd9Sstevel@tonic-gate * 240-371 175 040-171 333*7c478bd9Sstevel@tonic-gate * 372-377 176 072-077 334*7c478bd9Sstevel@tonic-gate */ 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate static 337*7c478bd9Sstevel@tonic-gate fwrblk(fn, fp, lenp) 338*7c478bd9Sstevel@tonic-gate int fn; 339*7c478bd9Sstevel@tonic-gate register FILE *fp; 340*7c478bd9Sstevel@tonic-gate int *lenp; 341*7c478bd9Sstevel@tonic-gate { 342*7c478bd9Sstevel@tonic-gate register char *op; 343*7c478bd9Sstevel@tonic-gate register int c, sum, nl, len; 344*7c478bd9Sstevel@tonic-gate char obuf[FOBUFSIZ + 8]; 345*7c478bd9Sstevel@tonic-gate int ret; 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL) 348*7c478bd9Sstevel@tonic-gate /* call ultouch occasionally */ 349*7c478bd9Sstevel@tonic-gate if (--tc < 0) { 350*7c478bd9Sstevel@tonic-gate tc = TC; 351*7c478bd9Sstevel@tonic-gate ultouch(); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate #endif /*!defined(ATTSVKILL)*/ 354*7c478bd9Sstevel@tonic-gate op = obuf; 355*7c478bd9Sstevel@tonic-gate nl = 0; 356*7c478bd9Sstevel@tonic-gate len = 0; 357*7c478bd9Sstevel@tonic-gate sum = fchksum; 358*7c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) { 359*7c478bd9Sstevel@tonic-gate len++; 360*7c478bd9Sstevel@tonic-gate if (sum & 0x8000) { 361*7c478bd9Sstevel@tonic-gate sum <<= 1; 362*7c478bd9Sstevel@tonic-gate sum++; 363*7c478bd9Sstevel@tonic-gate } else 364*7c478bd9Sstevel@tonic-gate sum <<= 1; 365*7c478bd9Sstevel@tonic-gate sum += c; 366*7c478bd9Sstevel@tonic-gate sum &= 0xffff; 367*7c478bd9Sstevel@tonic-gate if (c & 0200) { 368*7c478bd9Sstevel@tonic-gate c &= 0177; 369*7c478bd9Sstevel@tonic-gate if (c < 040) { 370*7c478bd9Sstevel@tonic-gate *op++ = '\174'; 371*7c478bd9Sstevel@tonic-gate *op++ = c + 0100; 372*7c478bd9Sstevel@tonic-gate } else 373*7c478bd9Sstevel@tonic-gate if (c <= 0171) { 374*7c478bd9Sstevel@tonic-gate *op++ = '\175'; 375*7c478bd9Sstevel@tonic-gate *op++ = c; 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate else { 378*7c478bd9Sstevel@tonic-gate *op++ = '\176'; 379*7c478bd9Sstevel@tonic-gate *op++ = c - 0100; 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate nl += 2; 382*7c478bd9Sstevel@tonic-gate } else { 383*7c478bd9Sstevel@tonic-gate if (c < 040) { 384*7c478bd9Sstevel@tonic-gate *op++ = '\172'; 385*7c478bd9Sstevel@tonic-gate *op++ = c + 0100; 386*7c478bd9Sstevel@tonic-gate nl += 2; 387*7c478bd9Sstevel@tonic-gate } else 388*7c478bd9Sstevel@tonic-gate if (c <= 0171) { 389*7c478bd9Sstevel@tonic-gate *op++ = c; 390*7c478bd9Sstevel@tonic-gate nl++; 391*7c478bd9Sstevel@tonic-gate } else { 392*7c478bd9Sstevel@tonic-gate *op++ = '\173'; 393*7c478bd9Sstevel@tonic-gate *op++ = c - 0100; 394*7c478bd9Sstevel@tonic-gate nl += 2; 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate if (nl >= FOBUFSIZ - 1) { 398*7c478bd9Sstevel@tonic-gate /* 399*7c478bd9Sstevel@tonic-gate * peek at next char, see if it will fit 400*7c478bd9Sstevel@tonic-gate */ 401*7c478bd9Sstevel@tonic-gate c = getc(fp); 402*7c478bd9Sstevel@tonic-gate if (c == EOF) 403*7c478bd9Sstevel@tonic-gate break; 404*7c478bd9Sstevel@tonic-gate (void) ungetc(c, fp); 405*7c478bd9Sstevel@tonic-gate if (nl >= FOBUFSIZ || c < 040 || c > 0171) 406*7c478bd9Sstevel@tonic-gate goto writeit; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate /* 410*7c478bd9Sstevel@tonic-gate * At EOF - append checksum, there is space for it... 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate sprintf(op, "\176\176%04x\r", sum); 413*7c478bd9Sstevel@tonic-gate nl += strlen(op); 414*7c478bd9Sstevel@tonic-gate writeit: 415*7c478bd9Sstevel@tonic-gate *lenp = len; 416*7c478bd9Sstevel@tonic-gate fchksum = sum; 417*7c478bd9Sstevel@tonic-gate DEBUG(8, "%d/", len); 418*7c478bd9Sstevel@tonic-gate DEBUG(8, "%d,", nl); 419*7c478bd9Sstevel@tonic-gate ret = write(fn, obuf, nl); 420*7c478bd9Sstevel@tonic-gate return ret == nl ? nl : ret < 0 ? 0 : -ret; 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate static 424*7c478bd9Sstevel@tonic-gate frdblk(ip, fn, rlen) 425*7c478bd9Sstevel@tonic-gate register char *ip; 426*7c478bd9Sstevel@tonic-gate int fn; 427*7c478bd9Sstevel@tonic-gate long *rlen; 428*7c478bd9Sstevel@tonic-gate { 429*7c478bd9Sstevel@tonic-gate register char *op, c; 430*7c478bd9Sstevel@tonic-gate register int sum, len, nl; 431*7c478bd9Sstevel@tonic-gate char buf[5], *erbp = ip; 432*7c478bd9Sstevel@tonic-gate int i; 433*7c478bd9Sstevel@tonic-gate static char special = 0; 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate #if !defined(ATTSVKILL) 436*7c478bd9Sstevel@tonic-gate /* call ultouch occasionally */ 437*7c478bd9Sstevel@tonic-gate if (--tc < 0) { 438*7c478bd9Sstevel@tonic-gate tc = TC; 439*7c478bd9Sstevel@tonic-gate ultouch(); 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate #endif /*!defined(ATTSVKILL)*/ 442*7c478bd9Sstevel@tonic-gate if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) { 443*7c478bd9Sstevel@tonic-gate *rlen = 0; 444*7c478bd9Sstevel@tonic-gate goto dcorr; 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate *rlen = len; 447*7c478bd9Sstevel@tonic-gate DEBUG(8, "%d/", len); 448*7c478bd9Sstevel@tonic-gate op = ip; 449*7c478bd9Sstevel@tonic-gate nl = 0; 450*7c478bd9Sstevel@tonic-gate sum = fchksum; 451*7c478bd9Sstevel@tonic-gate do { 452*7c478bd9Sstevel@tonic-gate if ((*ip &= 0177) >= '\172') { 453*7c478bd9Sstevel@tonic-gate if (special) { 454*7c478bd9Sstevel@tonic-gate DEBUG(8, "%d", nl); 455*7c478bd9Sstevel@tonic-gate special = 0; 456*7c478bd9Sstevel@tonic-gate op = buf; 457*7c478bd9Sstevel@tonic-gate if (*ip++ != '\176' || (i = --len) > 5) 458*7c478bd9Sstevel@tonic-gate goto dcorr; 459*7c478bd9Sstevel@tonic-gate while (i--) 460*7c478bd9Sstevel@tonic-gate *op++ = *ip++ & 0177; 461*7c478bd9Sstevel@tonic-gate while (len < 5) { 462*7c478bd9Sstevel@tonic-gate i = frdbuf(&buf[len], 5 - len, fn); 463*7c478bd9Sstevel@tonic-gate if (i == FAIL) { 464*7c478bd9Sstevel@tonic-gate len = FAIL; 465*7c478bd9Sstevel@tonic-gate goto dcorr; 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate DEBUG(8, ",%d", i); 468*7c478bd9Sstevel@tonic-gate len += i; 469*7c478bd9Sstevel@tonic-gate *rlen += i; 470*7c478bd9Sstevel@tonic-gate while (i--) 471*7c478bd9Sstevel@tonic-gate *op++ &= 0177; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate if (buf[4] != '\r') 474*7c478bd9Sstevel@tonic-gate goto dcorr; 475*7c478bd9Sstevel@tonic-gate sscanf(buf, "%4x", &fchksum); 476*7c478bd9Sstevel@tonic-gate DEBUG(8, "\nchecksum: %04x\n", sum); 477*7c478bd9Sstevel@tonic-gate if (fchksum == sum) 478*7c478bd9Sstevel@tonic-gate return FIBUFSIZ + 1 + nl; 479*7c478bd9Sstevel@tonic-gate else { 480*7c478bd9Sstevel@tonic-gate DEBUG(8, "\n", 0); 481*7c478bd9Sstevel@tonic-gate DEBUG(4, "Bad checksum\n", 0); 482*7c478bd9Sstevel@tonic-gate return FAIL; 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate special = *ip++; 486*7c478bd9Sstevel@tonic-gate } else { 487*7c478bd9Sstevel@tonic-gate if (*ip < '\040') { 488*7c478bd9Sstevel@tonic-gate /* error: shouldn't get control chars */ 489*7c478bd9Sstevel@tonic-gate goto dcorr; 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate switch (special) { 492*7c478bd9Sstevel@tonic-gate case 0: 493*7c478bd9Sstevel@tonic-gate c = *ip++; 494*7c478bd9Sstevel@tonic-gate break; 495*7c478bd9Sstevel@tonic-gate case '\172': 496*7c478bd9Sstevel@tonic-gate c = *ip++ - 0100; 497*7c478bd9Sstevel@tonic-gate break; 498*7c478bd9Sstevel@tonic-gate case '\173': 499*7c478bd9Sstevel@tonic-gate c = *ip++ + 0100; 500*7c478bd9Sstevel@tonic-gate break; 501*7c478bd9Sstevel@tonic-gate case '\174': 502*7c478bd9Sstevel@tonic-gate c = *ip++ + 0100; 503*7c478bd9Sstevel@tonic-gate break; 504*7c478bd9Sstevel@tonic-gate case '\175': 505*7c478bd9Sstevel@tonic-gate c = *ip++ + 0200; 506*7c478bd9Sstevel@tonic-gate break; 507*7c478bd9Sstevel@tonic-gate case '\176': 508*7c478bd9Sstevel@tonic-gate c = *ip++ + 0300; 509*7c478bd9Sstevel@tonic-gate break; 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate *op++ = c; 512*7c478bd9Sstevel@tonic-gate if (sum & 0x8000) { 513*7c478bd9Sstevel@tonic-gate sum <<= 1; 514*7c478bd9Sstevel@tonic-gate sum++; 515*7c478bd9Sstevel@tonic-gate } else 516*7c478bd9Sstevel@tonic-gate sum <<= 1; 517*7c478bd9Sstevel@tonic-gate sum += c & 0377; 518*7c478bd9Sstevel@tonic-gate sum &= 0xffff; 519*7c478bd9Sstevel@tonic-gate special = 0; 520*7c478bd9Sstevel@tonic-gate nl++; 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate } while (--len); 523*7c478bd9Sstevel@tonic-gate fchksum = sum; 524*7c478bd9Sstevel@tonic-gate DEBUG(8, "%d,", nl); 525*7c478bd9Sstevel@tonic-gate return nl; 526*7c478bd9Sstevel@tonic-gate dcorr: 527*7c478bd9Sstevel@tonic-gate DEBUG(8, "\n", 0); 528*7c478bd9Sstevel@tonic-gate DEBUG(4, "Data corrupted\n", 0); 529*7c478bd9Sstevel@tonic-gate while (len != FAIL) { 530*7c478bd9Sstevel@tonic-gate if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL) 531*7c478bd9Sstevel@tonic-gate *rlen += len; 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate return FAIL; 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate #endif /* F_PROTOCOL */ 536