Annotation of 43BSD/usr.bin/uucp/fio.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.