123599Sbloom #ifndef lint 2*33563Srick static char sccsid[] = "@(#)fio.c 5.4 (Berkeley) 02/24/88"; 323599Sbloom #endif 423599Sbloom 523599Sbloom /* 623599Sbloom * flow control protocol. 723599Sbloom * 823599Sbloom * This protocol relies on flow control of the data stream. 923599Sbloom * It is meant for working over links that can (almost) be 1023599Sbloom * guaranteed to be errorfree, specifically X.25/PAD links. 1123599Sbloom * A sumcheck is carried out over a whole file only. If a 1223599Sbloom * transport fails the receiver can request retransmission(s). 1323599Sbloom * This protocol uses a 7-bit datapath only, so it can be 1423599Sbloom * used on links that are not 8-bit transparent. 1523599Sbloom * 1623599Sbloom * When using this protocol with an X.25 PAD: 1723599Sbloom * Although this protocol uses no control chars except CR, 1823599Sbloom * control chars NULL and ^P are used before this protocol 1923599Sbloom * is started; since ^P is the default char for accessing 2023599Sbloom * PAD X.28 command mode, be sure to disable that access 2123599Sbloom * (PAD par 1). Also make sure both flow control pars 2223599Sbloom * (5 and 12) are set. The CR used in this proto is meant 2323599Sbloom * to trigger packet transmission, hence par 3 should be 2423599Sbloom * set to 2; a good value for the Idle Timer (par 4) is 10. 2523599Sbloom * All other pars should be set to 0. 2625130Sbloom * 2723599Sbloom * Normally a calling site will take care of setting the 2823599Sbloom * local PAD pars via an X.28 command and those of the remote 2923599Sbloom * PAD via an X.29 command, unless the remote site has a 3023599Sbloom * special channel assigned for this protocol with the proper 3123599Sbloom * par settings. 3223599Sbloom * 3325130Sbloom * Additional comments for hosts with direct X.25 access: 3425130Sbloom * - the global variable IsTcpIp, when set, excludes the ioctl's, 3525130Sbloom * so the same binary can run on X.25 and non-X.25 hosts; 3625130Sbloom * - reads are done in small chunks, which can be smaller than 3725130Sbloom * the packet size; your X.25 driver must support that. 3825130Sbloom * 3925130Sbloom * 4025130Sbloom * Author: 4125130Sbloom * Piet Beertema, CWI, Amsterdam, Sep 1984 4225130Sbloom * Modified for X.25 hosts: 4325130Sbloom * Robert Elz, Melbourne Univ, Mar 1985 4423599Sbloom */ 4523599Sbloom 4625130Sbloom #include "uucp.h" 4723599Sbloom #include <signal.h> 4823599Sbloom #ifdef USG 4923599Sbloom #include <termio.h> 5023599Sbloom #else !USG 5123599Sbloom #include <sgtty.h> 5223599Sbloom #endif !USG 5323599Sbloom #include <setjmp.h> 5423599Sbloom 55*33563Srick #define FIBUFSIZ 4096 /* for X.25 interfaces: set equal to packet size, 5625130Sbloom * but see comment above 5725130Sbloom */ 5823599Sbloom 59*33563Srick #define FOBUFSIZ 4096 /* for X.25 interfaces: set equal to packet size; 6025130Sbloom * otherwise make as large as feasible to reduce 6125130Sbloom * number of write system calls 6225130Sbloom */ 6325130Sbloom 6423599Sbloom #ifndef MAXMSGLEN 6523599Sbloom #define MAXMSGLEN BUFSIZ 6623599Sbloom #endif MAXMSGLEN 6723599Sbloom 6823599Sbloom static int fchksum; 6923599Sbloom static jmp_buf Ffailbuf; 7023599Sbloom 71*33563Srick extern long Bytes_Sent, Bytes_Received; 72*33563Srick 7323599Sbloom static 7423599Sbloom falarm() 7523599Sbloom { 7623599Sbloom signal(SIGALRM, falarm); 7723599Sbloom longjmp(Ffailbuf, 1); 7823599Sbloom } 7923599Sbloom 8023599Sbloom static int (*fsig)(); 8123599Sbloom 8223599Sbloom #ifndef USG 8323599Sbloom #define TCGETA TIOCGETP 8423599Sbloom #define TCSETA TIOCSETP 8523599Sbloom #define termio sgttyb 8623599Sbloom #endif USG 87*33563Srick static struct termio ttbuf; 8823599Sbloom 8923599Sbloom fturnon() 9023599Sbloom { 9123599Sbloom int ret; 92*33563Srick int ttbuf_flags; 9323599Sbloom 9425130Sbloom if (!IsTcpIp) { 9525130Sbloom ioctl(Ifn, TCGETA, &ttbuf); 9623599Sbloom #ifdef USG 97*33563Srick ttbuf_flags = ttbuf.c_iflag; 9825130Sbloom ttbuf.c_iflag = IXOFF|IXON|ISTRIP; 9925130Sbloom ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ; 10025130Sbloom ttbuf.c_cc[VTIME] = 5; 101*33563Srick ret = ioctl(Ifn, TCSETA, &ttbuf); 102*33563Srick ASSERT(ret >= 0, "STTY FAILED", "", ret); 103*33563Srick ttbuf.c_iflag = ttbuf_flags; 10425130Sbloom #else !USG 105*33563Srick ttbuf_flags = ttbuf.sg_flags; 106*33563Srick ttbuf.sg_flags = ANYP|CBREAK; 10725130Sbloom ret = ioctl(Ifn, TCSETA, &ttbuf); 10825130Sbloom ASSERT(ret >= 0, "STTY FAILED", "", ret); 109*33563Srick /* this is two seperate ioctls to set the x.29 params */ 110*33563Srick ttbuf.sg_flags |= TANDEM; 111*33563Srick ret = ioctl(Ifn, TCSETA, &ttbuf); 112*33563Srick ASSERT(ret >= 0, "STTY FAILED", "", ret); 113*33563Srick ttbuf.sg_flags = ttbuf_flags; 114*33563Srick #endif USG 11525130Sbloom } 11623599Sbloom fsig = signal(SIGALRM, falarm); 11723599Sbloom /* give the other side time to perform its ioctl; 11823599Sbloom * otherwise it may flush out the first data this 11923599Sbloom * side is about to send. 12023599Sbloom */ 12123599Sbloom sleep(2); 12223599Sbloom return SUCCESS; 12323599Sbloom } 12423599Sbloom 12523599Sbloom fturnoff() 12623599Sbloom { 127*33563Srick if (!IsTcpIp) 128*33563Srick ioctl(Ifn, TCSETA, &ttbuf); 12923599Sbloom (void) signal(SIGALRM, fsig); 130*33563Srick sleep(2); 13123599Sbloom return SUCCESS; 13223599Sbloom } 13323599Sbloom 13423599Sbloom fwrmsg(type, str, fn) 13523599Sbloom register char *str; 13623599Sbloom int fn; 13723599Sbloom char type; 13823599Sbloom { 13923599Sbloom register char *s; 14023599Sbloom char bufr[MAXMSGLEN]; 14123599Sbloom 14223599Sbloom s = bufr; 14323599Sbloom *s++ = type; 14423599Sbloom while (*str) 14523599Sbloom *s++ = *str++; 14623599Sbloom if (*(s-1) == '\n') 14723599Sbloom s--; 14823599Sbloom *s++ = '\r'; 14925130Sbloom *s = 0; 15023599Sbloom (void) write(fn, bufr, s - bufr); 15123599Sbloom return SUCCESS; 15223599Sbloom } 15323599Sbloom 15423599Sbloom frdmsg(str, fn) 15523599Sbloom register char *str; 15623599Sbloom register int fn; 15723599Sbloom { 15823599Sbloom register char *smax; 15923599Sbloom 16023599Sbloom if (setjmp(Ffailbuf)) 16123599Sbloom return FAIL; 16223599Sbloom smax = str + MAXMSGLEN - 1; 16323599Sbloom (void) alarm(2*MAXMSGTIME); 16423599Sbloom for (;;) { 16523599Sbloom if (read(fn, str, 1) <= 0) 16623599Sbloom goto msgerr; 16725130Sbloom *str &= 0177; 16823599Sbloom if (*str == '\r') 16923599Sbloom break; 17025130Sbloom if (*str < ' ') { 17123599Sbloom continue; 17225130Sbloom } 17323599Sbloom if (str++ >= smax) 17423599Sbloom goto msgerr; 17523599Sbloom } 17623599Sbloom *str = '\0'; 17723599Sbloom (void) alarm(0); 17823599Sbloom return SUCCESS; 17923599Sbloom msgerr: 18023599Sbloom (void) alarm(0); 18123599Sbloom return FAIL; 18223599Sbloom } 18323599Sbloom 18423599Sbloom fwrdata(fp1, fn) 18523599Sbloom FILE *fp1; 18623599Sbloom int fn; 18723599Sbloom { 18825130Sbloom register int alen, ret; 18925130Sbloom char ack, ibuf[MAXMSGLEN]; 19025130Sbloom int flen, mil, retries = 0; 19123599Sbloom long abytes, fbytes; 19223599Sbloom struct timeb t1, t2; 193*33563Srick float ft; 19423599Sbloom 19523599Sbloom ret = FAIL; 19623599Sbloom retry: 19723599Sbloom fchksum = 0xffff; 19823599Sbloom abytes = fbytes = 0L; 19923599Sbloom ack = '\0'; 20023599Sbloom #ifdef USG 20123599Sbloom time(&t1.time); 20223599Sbloom t1.millitm = 0; 20323599Sbloom #else !USG 20423599Sbloom ftime(&t1); 20523599Sbloom #endif !USG 20625130Sbloom do { 20725130Sbloom alen = fwrblk(fn, fp1, &flen); 20825130Sbloom fbytes += flen; 20925130Sbloom if (alen <= 0) { 21025130Sbloom abytes -= alen; 21123599Sbloom goto acct; 21223599Sbloom } 21325130Sbloom abytes += alen; 21425130Sbloom } while (!feof(fp1) && !ferror(fp1)); 21525130Sbloom DEBUG(8, "\nchecksum: %04x\n", fchksum); 21625130Sbloom if (frdmsg(ibuf, fn) != FAIL) { 21725130Sbloom if ((ack = ibuf[0]) == 'G') 21825130Sbloom ret = SUCCESS; 21925130Sbloom DEBUG(4, "ack - '%c'\n", ack); 22023599Sbloom } 22123599Sbloom acct: 22223599Sbloom #ifdef USG 22323599Sbloom time(&t2.time); 22423599Sbloom t2.millitm = 0; 22523599Sbloom #else !USG 22623599Sbloom ftime(&t2); 22723599Sbloom #endif !USG 22823599Sbloom Now = t2; 22923599Sbloom t2.time -= t1.time; 23023599Sbloom mil = t2.millitm - t1.millitm; 23123599Sbloom if (mil < 0) { 23223599Sbloom --t2.time; 23323599Sbloom mil += 1000; 23423599Sbloom } 235*33563Srick ft = (float)t2.time + (float)mil/1000.; 236*33563Srick sprintf(ibuf, "sent data %ld bytes %.2f secs %ld bps", 237*33563Srick fbytes, ft, (long)((float)fbytes*8./ft)); 23825149Sbloom sysacct(abytes, t2.time); 239*33563Srick Bytes_Sent += fbytes; 24025130Sbloom if (retries > 0) 24125130Sbloom sprintf(&ibuf[strlen(ibuf)], ", %d retries", retries); 24223599Sbloom DEBUG(1, "%s\n", ibuf); 24323599Sbloom syslog(ibuf); 24425130Sbloom if (ack == 'R') { 24525130Sbloom DEBUG(4, "RETRY:\n", 0); 24625130Sbloom fseek(fp1, 0L, 0); 24725130Sbloom retries++; 24825130Sbloom goto retry; 24925130Sbloom } 25023599Sbloom #ifdef SYSACCT 25125130Sbloom if (ret == FAIL) 25223599Sbloom sysaccf(NULL); /* force accounting */ 25323599Sbloom #endif SYSACCT 25423599Sbloom return ret; 25523599Sbloom } 25623599Sbloom 25723599Sbloom /* max. attempts to retransmit a file: */ 25823599Sbloom #define MAXRETRIES (fbytes < 10000L ? 2 : 1) 25923599Sbloom 26023599Sbloom frddata(fn, fp2) 26123599Sbloom register int fn; 26223599Sbloom register FILE *fp2; 26323599Sbloom { 26423599Sbloom register int flen; 26523599Sbloom register char eof; 26625130Sbloom char ibuf[FIBUFSIZ]; 26725130Sbloom int ret, mil, retries = 0; 26823599Sbloom long alen, abytes, fbytes; 26923599Sbloom struct timeb t1, t2; 270*33563Srick float ft; 27123599Sbloom 27223599Sbloom ret = FAIL; 27323599Sbloom retry: 27423599Sbloom fchksum = 0xffff; 27523599Sbloom abytes = fbytes = 0L; 27623599Sbloom #ifdef USG 27723599Sbloom time(&t1.time); 27823599Sbloom t1.millitm = 0; 27923599Sbloom #else !USG 28023599Sbloom ftime(&t1); 28123599Sbloom #endif !USG 28223599Sbloom do { 28323599Sbloom flen = frdblk(ibuf, fn, &alen); 28423599Sbloom abytes += alen; 28523599Sbloom if (flen < 0) 28623599Sbloom goto acct; 28725130Sbloom if (eof = flen > FIBUFSIZ) 28825130Sbloom flen -= FIBUFSIZ + 1; 28923599Sbloom fbytes += flen; 29023599Sbloom if (fwrite(ibuf, sizeof (char), flen, fp2) != flen) 29123599Sbloom goto acct; 29223599Sbloom } while (!eof); 29325130Sbloom ret = SUCCESS; 29423599Sbloom acct: 29523599Sbloom #ifdef USG 29623599Sbloom time(&t2.time); 29723599Sbloom t2.millitm = 0; 29823599Sbloom #else !USG 29923599Sbloom ftime(&t2); 30023599Sbloom #endif !USG 30123599Sbloom Now = t2; 30223599Sbloom t2.time -= t1.time; 30323599Sbloom mil = t2.millitm - t1.millitm; 30423599Sbloom if (mil < 0) { 30523599Sbloom --t2.time; 30623599Sbloom mil += 1000; 30723599Sbloom } 308*33563Srick ft = (float)t2.time + (float)mil/1000.; 309*33563Srick sprintf(ibuf, "received data %ld bytes %.2f secs %ld bps", 310*33563Srick fbytes, ft, (long)((float)fbytes*8./ft)); 31125130Sbloom if (retries > 0) 31225130Sbloom sprintf(&ibuf[strlen(ibuf)]," %d retries", retries); 31325149Sbloom sysacct(abytes, t2.time); 314*33563Srick Bytes_Received += fbytes; 31523599Sbloom DEBUG(1, "%s\n", ibuf); 31623599Sbloom syslog(ibuf); 31725130Sbloom if (ret == FAIL) { 31825130Sbloom if (retries++ < MAXRETRIES) { 31925130Sbloom DEBUG(8, "send ack: 'R'\n", 0); 32025130Sbloom fwrmsg('R', "", fn); 32125130Sbloom fseek(fp2, 0L, 0); 32225130Sbloom DEBUG(4, "RETRY:\n", 0); 32325130Sbloom goto retry; 32425130Sbloom } 32525130Sbloom DEBUG(8, "send ack: 'Q'\n", 0); 32625130Sbloom fwrmsg('Q', "", fn); 32725130Sbloom #ifdef SYSACCT 32825130Sbloom sysaccf(NULL); /* force accounting */ 32925130Sbloom #endif SYSACCT 33025130Sbloom } 33125130Sbloom else { 33225130Sbloom DEBUG(8, "send ack: 'G'\n", 0); 33325130Sbloom fwrmsg('G', "", fn); 33425130Sbloom } 33523599Sbloom return ret; 33623599Sbloom } 33723599Sbloom 33823599Sbloom static 33923599Sbloom frdbuf(blk, len, fn) 34023599Sbloom register char *blk; 34123599Sbloom register int len; 34223599Sbloom register int fn; 34323599Sbloom { 34425130Sbloom static int ret = FIBUFSIZ / 2; 34523599Sbloom 34623599Sbloom if (setjmp(Ffailbuf)) 34723599Sbloom return FAIL; 34823599Sbloom (void) alarm(MAXMSGTIME); 34923599Sbloom ret = read(fn, blk, len); 35023599Sbloom alarm(0); 35123599Sbloom return ret <= 0 ? FAIL : ret; 35223599Sbloom } 35323599Sbloom 35425130Sbloom #if !defined(BSD4_2) && !defined(USG) 35523599Sbloom /* call ultouch every TC calls to either frdblk or fwrblk */ 35625130Sbloom #define TC 20 35725130Sbloom static int tc = TC; 35825130Sbloom #endif !defined(BSD4_2) && !defined(USG) 35923599Sbloom 36023599Sbloom /* Byte conversion: 36123599Sbloom * 36225130Sbloom * from pre to 36325130Sbloom * 000-037 172 100-137 36425130Sbloom * 040-171 040-171 36525130Sbloom * 172-177 173 072-077 36625130Sbloom * 200-237 174 100-137 36725130Sbloom * 240-371 175 040-171 36825130Sbloom * 372-377 176 072-077 36923599Sbloom */ 37023599Sbloom 37123599Sbloom static 37225130Sbloom fwrblk(fn, fp, lenp) 37323599Sbloom int fn; 37425130Sbloom register FILE *fp; 37525130Sbloom int *lenp; 37623599Sbloom { 37723599Sbloom register char *op; 37825130Sbloom register int c, sum, nl, len; 37925130Sbloom char obuf[FOBUFSIZ + 8]; 38023599Sbloom int ret; 38123599Sbloom 38225130Sbloom #if !defined(BSD4_2) && !defined(USG) 38323599Sbloom /* call ultouch occasionally */ 38423599Sbloom if (--tc < 0) { 38523599Sbloom tc = TC; 38623599Sbloom ultouch(); 38723599Sbloom } 38825130Sbloom #endif !defined(BSD4_2) && !defined(USG) 38923599Sbloom op = obuf; 39023599Sbloom nl = 0; 39125130Sbloom len = 0; 39223599Sbloom sum = fchksum; 39325130Sbloom while ((c = getc(fp)) != EOF) { 39425130Sbloom len++; 39523599Sbloom if (sum & 0x8000) { 39623599Sbloom sum <<= 1; 39723599Sbloom sum++; 39823599Sbloom } else 39923599Sbloom sum <<= 1; 40025130Sbloom sum += c; 40123599Sbloom sum &= 0xffff; 40225130Sbloom if (c & 0200) { 40325130Sbloom c &= 0177; 40425130Sbloom if (c < 040) { 40523599Sbloom *op++ = '\174'; 40625130Sbloom *op++ = c + 0100; 40723599Sbloom } else 40825130Sbloom if (c <= 0171) { 40923599Sbloom *op++ = '\175'; 41025130Sbloom *op++ = c; 41123599Sbloom } 41223599Sbloom else { 41323599Sbloom *op++ = '\176'; 41425130Sbloom *op++ = c - 0100; 41523599Sbloom } 41623599Sbloom nl += 2; 41723599Sbloom } else { 41825130Sbloom if (c < 040) { 41923599Sbloom *op++ = '\172'; 42025130Sbloom *op++ = c + 0100; 42123599Sbloom nl += 2; 42223599Sbloom } else 42325130Sbloom if (c <= 0171) { 42425130Sbloom *op++ = c; 42523599Sbloom nl++; 42623599Sbloom } else { 42723599Sbloom *op++ = '\173'; 42825130Sbloom *op++ = c - 0100; 42923599Sbloom nl += 2; 43023599Sbloom } 43123599Sbloom } 43225130Sbloom if (nl >= FOBUFSIZ - 1) { 43325130Sbloom /* 43425130Sbloom * peek at next char, see if it will fit 43525130Sbloom */ 43625130Sbloom c = getc(fp); 43725130Sbloom if (c == EOF) 43825130Sbloom break; 43925130Sbloom (void) ungetc(c, fp); 44025130Sbloom if (nl >= FOBUFSIZ || c < 040 || c > 0171) 44125130Sbloom goto writeit; 44225130Sbloom } 44325130Sbloom } 44425130Sbloom /* 44525130Sbloom * At EOF - append checksum, there is space for it... 44625130Sbloom */ 44725130Sbloom sprintf(op, "\176\176%04x\r", sum); 44825130Sbloom nl += strlen(op); 44925130Sbloom writeit: 45025130Sbloom *lenp = len; 45123599Sbloom fchksum = sum; 45225130Sbloom DEBUG(8, "%d/", len); 45323599Sbloom DEBUG(8, "%d,", nl); 45423599Sbloom ret = write(fn, obuf, nl); 45523599Sbloom return ret == nl ? nl : ret < 0 ? 0 : -ret; 45623599Sbloom } 45723599Sbloom 45823599Sbloom static 45923599Sbloom frdblk(ip, fn, rlen) 46023599Sbloom register char *ip; 46123599Sbloom int fn; 46223599Sbloom long *rlen; 46323599Sbloom { 46423599Sbloom register char *op, c; 46523599Sbloom register int sum, len, nl; 46623599Sbloom char buf[5], *erbp = ip; 46723599Sbloom int i; 46823599Sbloom static char special = 0; 46923599Sbloom 47025130Sbloom #if !defined(BSD4_2) && !defined(USG) 47123599Sbloom /* call ultouch occasionally */ 47223599Sbloom if (--tc < 0) { 47323599Sbloom tc = TC; 47423599Sbloom ultouch(); 47523599Sbloom } 47625130Sbloom #endif !defined(BSD4_2) && !defined(USG) 47725130Sbloom if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) { 47823599Sbloom *rlen = 0; 47923599Sbloom goto dcorr; 48023599Sbloom } 48123599Sbloom *rlen = len; 48223599Sbloom DEBUG(8, "%d/", len); 48323599Sbloom op = ip; 48423599Sbloom nl = 0; 48523599Sbloom sum = fchksum; 48623599Sbloom do { 48723599Sbloom if ((*ip &= 0177) >= '\172') { 48823599Sbloom if (special) { 48923599Sbloom DEBUG(8, "%d", nl); 49023599Sbloom special = 0; 49123599Sbloom op = buf; 49223599Sbloom if (*ip++ != '\176' || (i = --len) > 5) 49323599Sbloom goto dcorr; 49423599Sbloom while (i--) 49525130Sbloom *op++ = *ip++ & 0177; 49623599Sbloom while (len < 5) { 49723599Sbloom i = frdbuf(&buf[len], 5 - len, fn); 49823599Sbloom if (i == FAIL) { 49923599Sbloom len = FAIL; 50023599Sbloom goto dcorr; 50123599Sbloom } 50223599Sbloom DEBUG(8, ",%d", i); 50323599Sbloom len += i; 50423599Sbloom *rlen += i; 50525130Sbloom while (i--) 50625130Sbloom *op++ &= 0177; 50723599Sbloom } 50823599Sbloom if (buf[4] != '\r') 50923599Sbloom goto dcorr; 51023599Sbloom sscanf(buf, "%4x", &fchksum); 51123599Sbloom DEBUG(8, "\nchecksum: %04x\n", sum); 51223599Sbloom if (fchksum == sum) 51325130Sbloom return FIBUFSIZ + 1 + nl; 51423599Sbloom else { 51523599Sbloom DEBUG(8, "\n", 0); 51623599Sbloom DEBUG(4, "Bad checksum\n", 0); 51723599Sbloom return FAIL; 51823599Sbloom } 51923599Sbloom } 52023599Sbloom special = *ip++; 52123599Sbloom } else { 52223599Sbloom if (*ip < '\040') { 52323599Sbloom /* error: shouldn't get control chars */ 52423599Sbloom goto dcorr; 52523599Sbloom } 52623599Sbloom switch (special) { 52723599Sbloom case 0: 52823599Sbloom c = *ip++; 52923599Sbloom break; 53023599Sbloom case '\172': 53123599Sbloom c = *ip++ - 0100; 53223599Sbloom break; 53323599Sbloom case '\173': 53423599Sbloom c = *ip++ + 0100; 53523599Sbloom break; 53623599Sbloom case '\174': 53723599Sbloom c = *ip++ + 0100; 53823599Sbloom break; 53923599Sbloom case '\175': 54023599Sbloom c = *ip++ + 0200; 54123599Sbloom break; 54223599Sbloom case '\176': 54323599Sbloom c = *ip++ + 0300; 54423599Sbloom break; 54523599Sbloom } 54623599Sbloom *op++ = c; 54723599Sbloom if (sum & 0x8000) { 54823599Sbloom sum <<= 1; 54923599Sbloom sum++; 55023599Sbloom } else 55123599Sbloom sum <<= 1; 55223599Sbloom sum += c & 0377; 55323599Sbloom sum &= 0xffff; 55423599Sbloom special = 0; 55523599Sbloom nl++; 55623599Sbloom } 55723599Sbloom } while (--len); 55823599Sbloom fchksum = sum; 55923599Sbloom DEBUG(8, "%d,", nl); 56023599Sbloom return nl; 56123599Sbloom dcorr: 56223599Sbloom DEBUG(8, "\n", 0); 56323599Sbloom DEBUG(4, "Data corrupted\n", 0); 56423599Sbloom while (len != FAIL) { 56525130Sbloom if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL) 56623599Sbloom *rlen += len; 56723599Sbloom } 56823599Sbloom return FAIL; 56923599Sbloom } 57025130Sbloom 571