123599Sbloom #ifndef lint 2*46879Sbostic static char sccsid[] = "@(#)fio.c 5.7 (Berkeley) 03/02/91"; 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 5533563Srick #define FIBUFSIZ 4096 /* for X.25 interfaces: set equal to packet size, 5625130Sbloom * but see comment above 5725130Sbloom */ 5823599Sbloom 5933563Srick #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 7133563Srick extern long Bytes_Sent, Bytes_Received; 7233563Srick 73*46879Sbostic static void 7423599Sbloom falarm() 7523599Sbloom { 7623599Sbloom signal(SIGALRM, falarm); 7723599Sbloom longjmp(Ffailbuf, 1); 7823599Sbloom } 7923599Sbloom 8044710Strent static void (*fsig)(); 8123599Sbloom 8223599Sbloom #ifndef USG 8323599Sbloom #define TCGETA TIOCGETP 8433969Srick #define TCSETAF TIOCSETP 8523599Sbloom #define termio sgttyb 8623599Sbloom #endif USG 8733563Srick static struct termio ttbuf; 8823599Sbloom 8923599Sbloom fturnon() 9023599Sbloom { 9133563Srick int ttbuf_flags; 9223599Sbloom 9325130Sbloom if (!IsTcpIp) { 9425130Sbloom ioctl(Ifn, TCGETA, &ttbuf); 9523599Sbloom #ifdef USG 9633563Srick ttbuf_flags = ttbuf.c_iflag; 9725130Sbloom ttbuf.c_iflag = IXOFF|IXON|ISTRIP; 9825130Sbloom ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ; 9925130Sbloom ttbuf.c_cc[VTIME] = 5; 10033969Srick if (ioctl(Ifn, TCSETAF, &ttbuf) < 0) { 10133969Srick syslog(LOG_ERR, "ioctl(TCSETAF) failed: %m"); 10233969Srick cleanup(FAIL); 10333969Srick } 10433563Srick ttbuf.c_iflag = ttbuf_flags; 10525130Sbloom #else !USG 10633563Srick ttbuf_flags = ttbuf.sg_flags; 10733563Srick ttbuf.sg_flags = ANYP|CBREAK; 10833969Srick if (ioctl(Ifn, TCSETAF, &ttbuf) < 0) { 10933969Srick syslog(LOG_ERR, "ioctl(TCSETAF) failed: %m"); 11033969Srick cleanup(FAIL); 11133969Srick } 11233563Srick /* this is two seperate ioctls to set the x.29 params */ 11333563Srick ttbuf.sg_flags |= TANDEM; 11433969Srick if (ioctl(Ifn, TCSETAF, &ttbuf) < 0) { 11533969Srick syslog(LOG_ERR, "ioctl(TCSETAF) failed: %m"); 11633969Srick cleanup(FAIL); 11733969Srick } 11833563Srick ttbuf.sg_flags = ttbuf_flags; 11933563Srick #endif USG 12025130Sbloom } 12123599Sbloom fsig = signal(SIGALRM, falarm); 12223599Sbloom /* give the other side time to perform its ioctl; 12323599Sbloom * otherwise it may flush out the first data this 12423599Sbloom * side is about to send. 12523599Sbloom */ 12623599Sbloom sleep(2); 12723599Sbloom return SUCCESS; 12823599Sbloom } 12923599Sbloom 13023599Sbloom fturnoff() 13123599Sbloom { 13233563Srick if (!IsTcpIp) 13333969Srick ioctl(Ifn, TCSETAF, &ttbuf); 13423599Sbloom (void) signal(SIGALRM, fsig); 13533563Srick sleep(2); 13623599Sbloom return SUCCESS; 13723599Sbloom } 13823599Sbloom 13923599Sbloom fwrmsg(type, str, fn) 14023599Sbloom register char *str; 14123599Sbloom int fn; 14223599Sbloom char type; 14323599Sbloom { 14423599Sbloom register char *s; 14523599Sbloom char bufr[MAXMSGLEN]; 14623599Sbloom 14723599Sbloom s = bufr; 14823599Sbloom *s++ = type; 14923599Sbloom while (*str) 15023599Sbloom *s++ = *str++; 15123599Sbloom if (*(s-1) == '\n') 15223599Sbloom s--; 15323599Sbloom *s++ = '\r'; 15425130Sbloom *s = 0; 15523599Sbloom (void) write(fn, bufr, s - bufr); 15623599Sbloom return SUCCESS; 15723599Sbloom } 15823599Sbloom 15923599Sbloom frdmsg(str, fn) 16023599Sbloom register char *str; 16123599Sbloom register int fn; 16223599Sbloom { 16323599Sbloom register char *smax; 16423599Sbloom 16523599Sbloom if (setjmp(Ffailbuf)) 16623599Sbloom return FAIL; 16723599Sbloom smax = str + MAXMSGLEN - 1; 16823599Sbloom (void) alarm(2*MAXMSGTIME); 16923599Sbloom for (;;) { 17023599Sbloom if (read(fn, str, 1) <= 0) 17123599Sbloom goto msgerr; 17225130Sbloom *str &= 0177; 17323599Sbloom if (*str == '\r') 17423599Sbloom break; 17525130Sbloom if (*str < ' ') { 17623599Sbloom continue; 17725130Sbloom } 17823599Sbloom if (str++ >= smax) 17923599Sbloom goto msgerr; 18023599Sbloom } 18123599Sbloom *str = '\0'; 18223599Sbloom (void) alarm(0); 18323599Sbloom return SUCCESS; 18423599Sbloom msgerr: 18523599Sbloom (void) alarm(0); 18623599Sbloom return FAIL; 18723599Sbloom } 18823599Sbloom 18923599Sbloom fwrdata(fp1, fn) 19023599Sbloom FILE *fp1; 19123599Sbloom int fn; 19223599Sbloom { 19325130Sbloom register int alen, ret; 19425130Sbloom char ack, ibuf[MAXMSGLEN]; 19525130Sbloom int flen, mil, retries = 0; 19623599Sbloom long abytes, fbytes; 19723599Sbloom struct timeb t1, t2; 19833563Srick float ft; 199*46879Sbostic static int fwrblk(); 20023599Sbloom 20123599Sbloom ret = FAIL; 20223599Sbloom retry: 20323599Sbloom fchksum = 0xffff; 20423599Sbloom abytes = fbytes = 0L; 20523599Sbloom ack = '\0'; 20623599Sbloom #ifdef USG 20723599Sbloom time(&t1.time); 20823599Sbloom t1.millitm = 0; 20923599Sbloom #else !USG 21023599Sbloom ftime(&t1); 21123599Sbloom #endif !USG 21225130Sbloom do { 21325130Sbloom alen = fwrblk(fn, fp1, &flen); 21425130Sbloom fbytes += flen; 21525130Sbloom if (alen <= 0) { 21625130Sbloom abytes -= alen; 21723599Sbloom goto acct; 21823599Sbloom } 21925130Sbloom abytes += alen; 22025130Sbloom } while (!feof(fp1) && !ferror(fp1)); 22125130Sbloom DEBUG(8, "\nchecksum: %04x\n", fchksum); 22225130Sbloom if (frdmsg(ibuf, fn) != FAIL) { 22325130Sbloom if ((ack = ibuf[0]) == 'G') 22425130Sbloom ret = SUCCESS; 22525130Sbloom DEBUG(4, "ack - '%c'\n", ack); 22623599Sbloom } 22723599Sbloom acct: 22823599Sbloom #ifdef USG 22923599Sbloom time(&t2.time); 23023599Sbloom t2.millitm = 0; 23123599Sbloom #else !USG 23223599Sbloom ftime(&t2); 23323599Sbloom #endif !USG 23423599Sbloom Now = t2; 23523599Sbloom t2.time -= t1.time; 23623599Sbloom mil = t2.millitm - t1.millitm; 23723599Sbloom if (mil < 0) { 23823599Sbloom --t2.time; 23923599Sbloom mil += 1000; 24023599Sbloom } 24133563Srick ft = (float)t2.time + (float)mil/1000.; 24233563Srick sprintf(ibuf, "sent data %ld bytes %.2f secs %ld bps", 24333563Srick fbytes, ft, (long)((float)fbytes*8./ft)); 24425149Sbloom sysacct(abytes, t2.time); 24533563Srick Bytes_Sent += fbytes; 24625130Sbloom if (retries > 0) 24725130Sbloom sprintf(&ibuf[strlen(ibuf)], ", %d retries", retries); 24823599Sbloom DEBUG(1, "%s\n", ibuf); 24933969Srick log_xferstats(ibuf); 25025130Sbloom if (ack == 'R') { 25125130Sbloom DEBUG(4, "RETRY:\n", 0); 25225130Sbloom fseek(fp1, 0L, 0); 25325130Sbloom retries++; 25425130Sbloom goto retry; 25525130Sbloom } 25623599Sbloom #ifdef SYSACCT 25725130Sbloom if (ret == FAIL) 25823599Sbloom sysaccf(NULL); /* force accounting */ 25923599Sbloom #endif SYSACCT 26023599Sbloom return ret; 26123599Sbloom } 26223599Sbloom 26323599Sbloom /* max. attempts to retransmit a file: */ 26423599Sbloom #define MAXRETRIES (fbytes < 10000L ? 2 : 1) 26523599Sbloom 26623599Sbloom frddata(fn, fp2) 26723599Sbloom register int fn; 26823599Sbloom register FILE *fp2; 26923599Sbloom { 27023599Sbloom register int flen; 27123599Sbloom register char eof; 27225130Sbloom char ibuf[FIBUFSIZ]; 27325130Sbloom int ret, mil, retries = 0; 27423599Sbloom long alen, abytes, fbytes; 27523599Sbloom struct timeb t1, t2; 27633563Srick float ft; 277*46879Sbostic static int frdblk(); 27823599Sbloom 27923599Sbloom ret = FAIL; 28023599Sbloom retry: 28123599Sbloom fchksum = 0xffff; 28223599Sbloom abytes = fbytes = 0L; 28323599Sbloom #ifdef USG 28423599Sbloom time(&t1.time); 28523599Sbloom t1.millitm = 0; 28623599Sbloom #else !USG 28723599Sbloom ftime(&t1); 28823599Sbloom #endif !USG 28923599Sbloom do { 29023599Sbloom flen = frdblk(ibuf, fn, &alen); 29123599Sbloom abytes += alen; 29223599Sbloom if (flen < 0) 29323599Sbloom goto acct; 29425130Sbloom if (eof = flen > FIBUFSIZ) 29525130Sbloom flen -= FIBUFSIZ + 1; 29623599Sbloom fbytes += flen; 29723599Sbloom if (fwrite(ibuf, sizeof (char), flen, fp2) != flen) 29823599Sbloom goto acct; 29923599Sbloom } while (!eof); 30025130Sbloom ret = SUCCESS; 30123599Sbloom acct: 30223599Sbloom #ifdef USG 30323599Sbloom time(&t2.time); 30423599Sbloom t2.millitm = 0; 30523599Sbloom #else !USG 30623599Sbloom ftime(&t2); 30723599Sbloom #endif !USG 30823599Sbloom Now = t2; 30923599Sbloom t2.time -= t1.time; 31023599Sbloom mil = t2.millitm - t1.millitm; 31123599Sbloom if (mil < 0) { 31223599Sbloom --t2.time; 31323599Sbloom mil += 1000; 31423599Sbloom } 31533563Srick ft = (float)t2.time + (float)mil/1000.; 31633563Srick sprintf(ibuf, "received data %ld bytes %.2f secs %ld bps", 31733563Srick fbytes, ft, (long)((float)fbytes*8./ft)); 31825130Sbloom if (retries > 0) 31925130Sbloom sprintf(&ibuf[strlen(ibuf)]," %d retries", retries); 32025149Sbloom sysacct(abytes, t2.time); 32133563Srick Bytes_Received += fbytes; 32223599Sbloom DEBUG(1, "%s\n", ibuf); 32333969Srick log_xferstats(ibuf); 32425130Sbloom if (ret == FAIL) { 32525130Sbloom if (retries++ < MAXRETRIES) { 32625130Sbloom DEBUG(8, "send ack: 'R'\n", 0); 32725130Sbloom fwrmsg('R', "", fn); 32825130Sbloom fseek(fp2, 0L, 0); 32925130Sbloom DEBUG(4, "RETRY:\n", 0); 33025130Sbloom goto retry; 33125130Sbloom } 33225130Sbloom DEBUG(8, "send ack: 'Q'\n", 0); 33325130Sbloom fwrmsg('Q', "", fn); 33425130Sbloom #ifdef SYSACCT 33525130Sbloom sysaccf(NULL); /* force accounting */ 33625130Sbloom #endif SYSACCT 33725130Sbloom } 33825130Sbloom else { 33925130Sbloom DEBUG(8, "send ack: 'G'\n", 0); 34025130Sbloom fwrmsg('G', "", fn); 34125130Sbloom } 34223599Sbloom return ret; 34323599Sbloom } 34423599Sbloom 34523599Sbloom static 34623599Sbloom frdbuf(blk, len, fn) 34723599Sbloom register char *blk; 34823599Sbloom register int len; 34923599Sbloom register int fn; 35023599Sbloom { 35125130Sbloom static int ret = FIBUFSIZ / 2; 35223599Sbloom 35323599Sbloom if (setjmp(Ffailbuf)) 35423599Sbloom return FAIL; 35523599Sbloom (void) alarm(MAXMSGTIME); 35623599Sbloom ret = read(fn, blk, len); 35723599Sbloom alarm(0); 35823599Sbloom return ret <= 0 ? FAIL : ret; 35923599Sbloom } 36023599Sbloom 36125130Sbloom #if !defined(BSD4_2) && !defined(USG) 36223599Sbloom /* call ultouch every TC calls to either frdblk or fwrblk */ 36325130Sbloom #define TC 20 36425130Sbloom static int tc = TC; 36525130Sbloom #endif !defined(BSD4_2) && !defined(USG) 36623599Sbloom 36723599Sbloom /* Byte conversion: 36823599Sbloom * 36925130Sbloom * from pre to 37025130Sbloom * 000-037 172 100-137 37125130Sbloom * 040-171 040-171 37225130Sbloom * 172-177 173 072-077 37325130Sbloom * 200-237 174 100-137 37425130Sbloom * 240-371 175 040-171 37525130Sbloom * 372-377 176 072-077 37623599Sbloom */ 37723599Sbloom 37823599Sbloom static 37925130Sbloom fwrblk(fn, fp, lenp) 38023599Sbloom int fn; 38125130Sbloom register FILE *fp; 38225130Sbloom int *lenp; 38323599Sbloom { 38423599Sbloom register char *op; 38525130Sbloom register int c, sum, nl, len; 38625130Sbloom char obuf[FOBUFSIZ + 8]; 38723599Sbloom int ret; 38823599Sbloom 38925130Sbloom #if !defined(BSD4_2) && !defined(USG) 39023599Sbloom /* call ultouch occasionally */ 39123599Sbloom if (--tc < 0) { 39223599Sbloom tc = TC; 39323599Sbloom ultouch(); 39423599Sbloom } 39525130Sbloom #endif !defined(BSD4_2) && !defined(USG) 39623599Sbloom op = obuf; 39723599Sbloom nl = 0; 39825130Sbloom len = 0; 39923599Sbloom sum = fchksum; 40025130Sbloom while ((c = getc(fp)) != EOF) { 40125130Sbloom len++; 40223599Sbloom if (sum & 0x8000) { 40323599Sbloom sum <<= 1; 40423599Sbloom sum++; 40523599Sbloom } else 40623599Sbloom sum <<= 1; 40725130Sbloom sum += c; 40823599Sbloom sum &= 0xffff; 40925130Sbloom if (c & 0200) { 41025130Sbloom c &= 0177; 41125130Sbloom if (c < 040) { 41223599Sbloom *op++ = '\174'; 41325130Sbloom *op++ = c + 0100; 41423599Sbloom } else 41525130Sbloom if (c <= 0171) { 41623599Sbloom *op++ = '\175'; 41725130Sbloom *op++ = c; 41823599Sbloom } 41923599Sbloom else { 42023599Sbloom *op++ = '\176'; 42125130Sbloom *op++ = c - 0100; 42223599Sbloom } 42323599Sbloom nl += 2; 42423599Sbloom } else { 42525130Sbloom if (c < 040) { 42623599Sbloom *op++ = '\172'; 42725130Sbloom *op++ = c + 0100; 42823599Sbloom nl += 2; 42923599Sbloom } else 43025130Sbloom if (c <= 0171) { 43125130Sbloom *op++ = c; 43223599Sbloom nl++; 43323599Sbloom } else { 43423599Sbloom *op++ = '\173'; 43525130Sbloom *op++ = c - 0100; 43623599Sbloom nl += 2; 43723599Sbloom } 43823599Sbloom } 43925130Sbloom if (nl >= FOBUFSIZ - 1) { 44025130Sbloom /* 44125130Sbloom * peek at next char, see if it will fit 44225130Sbloom */ 44325130Sbloom c = getc(fp); 44425130Sbloom if (c == EOF) 44525130Sbloom break; 44625130Sbloom (void) ungetc(c, fp); 44725130Sbloom if (nl >= FOBUFSIZ || c < 040 || c > 0171) 44825130Sbloom goto writeit; 44925130Sbloom } 45025130Sbloom } 45125130Sbloom /* 45225130Sbloom * At EOF - append checksum, there is space for it... 45325130Sbloom */ 45425130Sbloom sprintf(op, "\176\176%04x\r", sum); 45525130Sbloom nl += strlen(op); 45625130Sbloom writeit: 45725130Sbloom *lenp = len; 45823599Sbloom fchksum = sum; 45925130Sbloom DEBUG(8, "%d/", len); 46023599Sbloom DEBUG(8, "%d,", nl); 46123599Sbloom ret = write(fn, obuf, nl); 46223599Sbloom return ret == nl ? nl : ret < 0 ? 0 : -ret; 46323599Sbloom } 46423599Sbloom 46523599Sbloom static 46623599Sbloom frdblk(ip, fn, rlen) 46723599Sbloom register char *ip; 46823599Sbloom int fn; 46923599Sbloom long *rlen; 47023599Sbloom { 47123599Sbloom register char *op, c; 47223599Sbloom register int sum, len, nl; 47323599Sbloom char buf[5], *erbp = ip; 47423599Sbloom int i; 47523599Sbloom static char special = 0; 47623599Sbloom 47725130Sbloom #if !defined(BSD4_2) && !defined(USG) 47823599Sbloom /* call ultouch occasionally */ 47923599Sbloom if (--tc < 0) { 48023599Sbloom tc = TC; 48123599Sbloom ultouch(); 48223599Sbloom } 48325130Sbloom #endif !defined(BSD4_2) && !defined(USG) 48425130Sbloom if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) { 48523599Sbloom *rlen = 0; 48623599Sbloom goto dcorr; 48723599Sbloom } 48823599Sbloom *rlen = len; 48923599Sbloom DEBUG(8, "%d/", len); 49023599Sbloom op = ip; 49123599Sbloom nl = 0; 49223599Sbloom sum = fchksum; 49323599Sbloom do { 49423599Sbloom if ((*ip &= 0177) >= '\172') { 49523599Sbloom if (special) { 49623599Sbloom DEBUG(8, "%d", nl); 49723599Sbloom special = 0; 49823599Sbloom op = buf; 49923599Sbloom if (*ip++ != '\176' || (i = --len) > 5) 50023599Sbloom goto dcorr; 50123599Sbloom while (i--) 50225130Sbloom *op++ = *ip++ & 0177; 50323599Sbloom while (len < 5) { 50423599Sbloom i = frdbuf(&buf[len], 5 - len, fn); 50523599Sbloom if (i == FAIL) { 50623599Sbloom len = FAIL; 50723599Sbloom goto dcorr; 50823599Sbloom } 50923599Sbloom DEBUG(8, ",%d", i); 51023599Sbloom len += i; 51123599Sbloom *rlen += i; 51225130Sbloom while (i--) 51325130Sbloom *op++ &= 0177; 51423599Sbloom } 51523599Sbloom if (buf[4] != '\r') 51623599Sbloom goto dcorr; 51723599Sbloom sscanf(buf, "%4x", &fchksum); 51823599Sbloom DEBUG(8, "\nchecksum: %04x\n", sum); 51923599Sbloom if (fchksum == sum) 52025130Sbloom return FIBUFSIZ + 1 + nl; 52123599Sbloom else { 52223599Sbloom DEBUG(8, "\n", 0); 52323599Sbloom DEBUG(4, "Bad checksum\n", 0); 52423599Sbloom return FAIL; 52523599Sbloom } 52623599Sbloom } 52723599Sbloom special = *ip++; 52823599Sbloom } else { 52923599Sbloom if (*ip < '\040') { 53023599Sbloom /* error: shouldn't get control chars */ 53123599Sbloom goto dcorr; 53223599Sbloom } 53323599Sbloom switch (special) { 53423599Sbloom case 0: 53523599Sbloom c = *ip++; 53623599Sbloom break; 53723599Sbloom case '\172': 53823599Sbloom c = *ip++ - 0100; 53923599Sbloom break; 54023599Sbloom case '\173': 54123599Sbloom c = *ip++ + 0100; 54223599Sbloom break; 54323599Sbloom case '\174': 54423599Sbloom c = *ip++ + 0100; 54523599Sbloom break; 54623599Sbloom case '\175': 54723599Sbloom c = *ip++ + 0200; 54823599Sbloom break; 54923599Sbloom case '\176': 55023599Sbloom c = *ip++ + 0300; 55123599Sbloom break; 55223599Sbloom } 55323599Sbloom *op++ = c; 55423599Sbloom if (sum & 0x8000) { 55523599Sbloom sum <<= 1; 55623599Sbloom sum++; 55723599Sbloom } else 55823599Sbloom sum <<= 1; 55923599Sbloom sum += c & 0377; 56023599Sbloom sum &= 0xffff; 56123599Sbloom special = 0; 56223599Sbloom nl++; 56323599Sbloom } 56423599Sbloom } while (--len); 56523599Sbloom fchksum = sum; 56623599Sbloom DEBUG(8, "%d,", nl); 56723599Sbloom return nl; 56823599Sbloom dcorr: 56923599Sbloom DEBUG(8, "\n", 0); 57023599Sbloom DEBUG(4, "Data corrupted\n", 0); 57123599Sbloom while (len != FAIL) { 57225130Sbloom if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL) 57323599Sbloom *rlen += len; 57423599Sbloom } 57523599Sbloom return FAIL; 57623599Sbloom } 57725130Sbloom 578