home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char sccsid[] = "@(#)fio.c 5.3 (Berkeley) 10/9/85";
- #endif
- #define TERMIO
- /*
- * flow control protocol.
- *
- * This protocol relies on flow control of the data stream.
- * It is meant for working over links that can (almost) be
- * guaranteed to be errorfree, specifically X.25/PAD links.
- * A sumcheck is carried out over a whole file only. If a
- * transport fails the receiver can request retransmission(s).
- * This protocol uses a 7-bit datapath only, so it can be
- * used on links that are not 8-bit transparent.
- *
- * When using this protocol with an X.25 PAD:
- * Although this protocol uses no control chars except CR,
- * control chars NULL and ^P are used before this protocol
- * is started; since ^P is the default char for accessing
- * PAD X.28 command mode, be sure to disable that access
- * (PAD par 1). Also make sure both flow control pars
- * (5 and 12) are set. The CR used in this proto is meant
- * to trigger packet transmission, hence par 3 should be
- * set to 2; a good value for the Idle Timer (par 4) is 10.
- * All other pars should be set to 0.
- *
- * Normally a calling site will take care of setting the
- * local PAD pars via an X.28 command and those of the remote
- * PAD via an X.29 command, unless the remote site has a
- * special channel assigned for this protocol with the proper
- * par settings.
- *
- * Additional comments for hosts with direct X.25 access:
- * - the global variable IsTcpIp, when set, excludes the ioctl's,
- * so the same binary can run on X.25 and non-X.25 hosts;
- * - reads are done in small chunks, which can be smaller than
- * the packet size; your X.25 driver must support that.
- *
- *
- * Author:
- * Piet Beertema, CWI, Amsterdam, Sep 1984
- * Modified for X.25 hosts:
- * Robert Elz, Melbourne Univ, Mar 1985
- */
-
- #include "uucp.h"
- #ifdef ALTOS
- #include <sys/timeb.h>
- #endif
- #ifdef ATTSV
- struct timeb {
- long time;
- int millitm;
- };
- #define USG
- #endif
-
- #ifdef X25
- #define FIBUFSIZ 128 /* for X.25 interfaces: set equal to packet size,
- * but see comment above
- */
-
- #define FOBUFSIZ 128 /* for X.25 interfaces: set equal to packet size;
- * otherwise make as large as feasible to reduce
- * number of write system calls
- */
- #else
- #define FIBUFSIZ 1024 /* for HST interfaces: set equal to packet size,
- * but see comment above
- */
-
- #define FOBUFSIZ 1024 /* for HST interfaces: set equal to packet size;
- * otherwise make as large as feasible to reduce*/
- #endif
-
- #ifndef MAXMSGLEN
- #define MAXMSGLEN BUFSIZ
- #endif
-
- static int fchksum;
- static jmp_buf Ffailbuf;
- int IsTcpIp = 0 ; /* KORN : no ioctl's */
-
- static
- falarm()
- {
- signal(SIGALRM, falarm);
- longjmp(Ffailbuf, 1);
- }
-
- static int (*fsig)();
-
- #ifdef SGTTY
- #define TCGETA TIOCGETP
- #define TCSETA TIOCSETP
- #define termio sgttyb
- #endif
-
- fturnon()
- {
- int ret;
- struct termio ttbuf;
-
- if ( !IsTcpIp ) {
- ioctl(Ifn, TCGETA, &ttbuf);
- #ifdef TERMIO
- ttbuf.c_iflag = IXOFF|IXON|ISTRIP;
- ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ;
- ttbuf.c_cc[VTIME] = 5;
- #else
- ttbuf.sg_flags = ANYP|CBREAK|TANDEM;
- #endif
- ret = ioctl(Ifn, TCSETA, &ttbuf);
- ASSERT(ret >= 0, "STTY FAILED", "", ret);
- }
- fsig=signal(SIGALRM, falarm);
- /* give the other side time to perform its ioctl;
- * otherwise it may flush out the first data this
- * side is about to send.
- */
- sleep(2);
- #ifdef ALTOS
- xstart(); /* KORN */
- #endif
- return SUCCESS;
- }
-
- fturnoff()
- {
- (void) signal(SIGALRM, fsig);
- #ifdef ALTOS
- xstop(); /* KORN */
- #endif
- return SUCCESS;
- }
-
- fwrmsg(type, str, fn)
- register char *str;
- int fn;
- char type;
- {
- register char *s;
- char bufr[MAXMSGLEN];
-
- s = bufr;
- *s++ = type;
- while (*str)
- *s++ = *str++;
- if (*(s-1) == '\n')
- s--;
- *s++ = '\r';
- *s = 0;
- DEBUG(5,"fwrmsg='%s'\n",bufr);
- /* (void) write(fn, bufr, s - bufr); KORN --- BULLSHIT !!! */
- (void) (*Write)(fn, bufr, s - bufr);
- return SUCCESS;
- }
-
- frdmsg(str, fn)
- register char *str;
- register int fn;
- {
- register char *smax;
-
- DEBUG(5,"frdmsg entered.\n",0);
- if (setjmp(Ffailbuf))
- return FAIL;
- smax = str + MAXMSGLEN - 1;
- (void) alarm(2*MAXMSGTIME);
- for (;;) {
- /* if (read(fn, str, 1) <= 0) KORN: SCHEISSE !!!!!!! */
- if ((*Read)(fn, str, 1) <= 0)
- goto msgerr;
- *str &= 0177;
- if (*str == '\r')
- break;
- if (*str < ' ') {
- continue;
- }
- if (str++ >= smax)
- goto msgerr;
- }
- *str = '\0';
- (void) alarm(0);
- DEBUG(5,"successful end of frdmsg.\n",0);
- return SUCCESS;
- msgerr:
- (void) alarm(0);
- DEBUG(5,"unsuccessful end of frdmsg.\n",0);
- return FAIL;
- }
-
- fwrdata(fp1, fn)
- FILE *fp1;
- int fn;
- {
- register int alen, ret;
- register char *obp;
- char ack, ibuf[MAXMSGLEN];
- int flen, mil, retries = 0;
- long abytes, fbytes;
- long t1;
-
- DEBUG(5,"fwrdata entered.\n",0);
- ret = FAIL;
- retry:
- fchksum = 0xffff;
- abytes = fbytes = 0L;
- ack = '\0';
- (void) millitick();
- do {
- alen = fwrblk(fn, fp1, &flen);
- if (FIBUFSIZ>2048) sleep(1);
- fbytes += flen;
- if (alen <= 0) {
- abytes -= alen;
- goto acct;
- }
- abytes += alen;
- } while (!feof(fp1) && !ferror(fp1));
- DEBUG(8, "\nchecksum: %04x\n", fchksum);
- if (frdmsg(ibuf, fn) != FAIL) {
- if ((ack = ibuf[0]) == 'G')
- ret = SUCCESS;
- DEBUG(4, "ack - '%c'\n", ack);
- }
- acct:
- t1=millitick();
-
- if (retries > 0)
- sprintf(ibuf, "-> (%dr)", retries);
- else
- strcpy (ibuf,"->");
-
- statlog(ibuf,fbytes,t1);
- if (ack == 'R') {
- DEBUG(4, "RETRY:\n", 0);
- fseek(fp1, 0L, 0);
- retries++;
- goto retry;
- }
- #ifdef SYSACCT
- if (ret == FAIL)
- sysaccf(NULL); /* force accounting */
- #endif
- return ret;
- }
-
- /* max. attempts to retransmit a file: */
- #define MAXRETRIES (fbytes < 10000L ? 3 : 2) /* KORN: was 2:1 */
-
- frddata(fn, fp2)
- register int fn;
- register FILE *fp2;
- {
- register int flen;
- register char eof;
- char ibuf[FIBUFSIZ];
- int ret, mil, retries = 0;
- long alen, abytes, fbytes;
- long t1;
-
- DEBUG(5,"frddata entered.\n",0);
- ret = FAIL;
- retry:
- fchksum = 0xffff;
- abytes = fbytes = 0L;
- (void) millitick();
- do {
- flen = frdblk(ibuf, fn, &alen);
- abytes += alen;
- if (flen < 0)
- goto acct;
- if (eof = flen > FIBUFSIZ)
- flen -= FIBUFSIZ + 1;
- fbytes += flen;
- if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
- goto acct;
- } while (!eof);
- ret = SUCCESS;
- acct:
- t1=millitick();
- if (retries > 0)
- sprintf(ibuf,"<- %d ret", retries);
- else
- strcpy (ibuf,"<-");
- statlog(ibuf,fbytes,t1);
- if (ret == FAIL) {
- if (retries++ < MAXRETRIES) {
- DEBUG(8, "send ack: 'R'\n", 0);
- fwrmsg('R', "", fn);
- fseek(fp2, 0L, 0);
- DEBUG(4, "RETRY:\n", 0);
- goto retry;
- }
- DEBUG(8, "send ack: 'Q'\n", 0);
- fwrmsg('Q', "", fn);
- #ifdef SYSACCT
- sysaccf(NULL); /* force accounting */
- #endif
- }
- else {
- DEBUG(8, "send ack: 'G'\n", 0);
- fwrmsg('G', "", fn);
- }
- return ret;
- }
-
- static
- frdbuf(blk, len, fn)
- register char *blk;
- register int len;
- register int fn;
- {
- static int ret = FIBUFSIZ / 2;
-
- DEBUG(9,"frdbuf (%d) entered.\n",len);
- if (setjmp(Ffailbuf))
- return FAIL;
- (void) alarm(MAXMSGTIME);
- /* ret = read(fn, blk, len); KORN grmbl... */
- ret = (*Read)(fn, blk, len);
- alarm(0);
- return ret <= 0 ? FAIL : ret;
- }
-
- #if !defined(BSD4_2) && !defined(USG)
- /* call ultouch every TC calls to either frdblk or fwrblk */
- #define TC 20
- static int tc = TC;
- #endif
-
- /* Byte conversion:
- *
- * from pre to
- * 000-037 172 100-137
- * 040-171 040-171
- * 172-177 173 072-077
- * 200-237 174 100-137
- * 240-371 175 040-171
- * 372-377 176 072-077
- */
-
- static
- fwrblk(fn, fp, lenp)
- int fn;
- register FILE *fp;
- int *lenp;
- {
- register char *op;
- register int c, sum, nl, len;
- char obuf[FOBUFSIZ + 8];
- int ret;
-
- DEBUG(9,"fwrblk entered.\n",0);
-
- #if !defined(BSD4_2) && !defined(USG)
- /* call ultouch occasionally */
- if (--tc < 0) {
- tc = TC;
- ultouch();
- }
- #endif
- op = obuf;
- nl = 0;
- len = 0;
- sum = fchksum;
- while ((c = getc(fp)) != EOF) {
- len++;
- if (sum & 0x8000) {
- sum <<= 1;
- sum++;
- } else
- sum <<= 1;
- sum += c;
- sum &= 0xffff;
- if (c & 0200) {
- c &= 0177;
- if (c < 040) {
- *op++ = '\174';
- *op++ = c + 0100;
- } else
- if (c <= 0171) {
- *op++ = '\175';
- *op++ = c;
- }
- else {
- *op++ = '\176';
- *op++ = c - 0100;
- }
- nl += 2;
- } else {
- if (c < 040) {
- *op++ = '\172';
- *op++ = c + 0100;
- nl += 2;
- } else
- if (c <= 0171) {
- *op++ = c;
- nl++;
- } else {
- *op++ = '\173';
- *op++ = c - 0100;
- nl += 2;
- }
- }
- if (nl >= FOBUFSIZ - 1) {
- /*
- * peek at next char, see if it will fit
- */
- c = getc(fp);
- if (c == EOF)
- break;
- (void) ungetc(c, fp);
- if (nl >= FOBUFSIZ || c < 040 || c > 0171)
- goto writeit;
- }
- }
- /*
- * At EOF - append checksum, there is space for it...
- */
- sprintf(op, "\176\176%04x\r", sum);
- nl += strlen(op);
- writeit:
- *lenp = len;
- fchksum = sum;
- DEBUG(8, "%d/", len);
- DEBUG(8, "%d,", nl);
- /* ret = write(fn, obuf, nl); KORN: grmbl.... */
- ret = (*Write)(fn, obuf, nl);
- return ret == nl ? nl : ret < 0 ? 0 : -ret;
- }
-
- static
- frdblk(ip, fn, rlen)
- register char *ip;
- int fn;
- long *rlen;
- {
- register char *op, c;
- register int sum, len, nl;
- char buf[5], *erbp = ip;
- int i;
- static char special = 0;
-
- DEBUG(9,"frdblk entered.\n",0);
-
- #if !defined(BSD4_2) && !defined(USG)
- /* call ultouch occasionally */
- if (--tc < 0) {
- tc = TC;
- ultouch();
- }
- #endif
- if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) {
- *rlen = 0;
- goto dcorr;
- }
- *rlen = len;
- DEBUG(8, "%d/", len);
- op = ip;
- nl = 0;
- sum = fchksum;
- do {
- if ((*ip &= 0177) >= '\172') {
- if (special) {
- DEBUG(8, "%d", nl);
- special = 0;
- op = buf;
- if (*ip++ != '\176' || (i = --len) > 5)
- goto dcorr;
- while (i--)
- *op++ = *ip++ & 0177;
- while (len < 5) {
- i = frdbuf(&buf[len], 5 - len, fn);
- if (i == FAIL) {
- len = FAIL;
- goto dcorr;
- }
- DEBUG(8, ",%d", i);
- len += i;
- *rlen += i;
- while (i--)
- *op++ &= 0177;
- }
- if (buf[4] != '\r')
- goto dcorr;
- sscanf(buf, "%4x", &fchksum);
- DEBUG(8, "\nchecksum: %04x\n", sum);
- if (fchksum == sum)
- return FIBUFSIZ + 1 + nl;
- else {
- DEBUG(8, "\n", 0);
- DEBUG(4, "Bad checksum\n", 0);
- return FAIL;
- }
- }
- special = *ip++;
- } else {
- if (*ip < '\040') {
- /* error: shouldn't get control chars */
- goto dcorr;
- }
- switch (special) {
- case 0:
- c = *ip++;
- break;
- case '\172':
- c = *ip++ - 0100;
- break;
- case '\173':
- c = *ip++ + 0100;
- break;
- case '\174':
- c = *ip++ + 0100;
- break;
- case '\175':
- c = *ip++ + 0200;
- break;
- case '\176':
- c = *ip++ + 0300;
- break;
- }
- *op++ = c;
- if (sum & 0x8000) {
- sum <<= 1;
- sum++;
- } else
- sum <<= 1;
- sum += c & 0377;
- sum &= 0xffff;
- special = 0;
- nl++;
- }
- } while (--len);
- fchksum = sum;
- DEBUG(8, "%d,", nl);
- return nl;
- dcorr:
- DEBUG(8, "\n", 0);
- DEBUG(4, "Data corrupted\n", 0);
- while (len != FAIL) {
- if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL)
- *rlen += len;
- }
- return FAIL;
- }
-
- /*KORN*/
- sysacct(){}
-