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

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)fio.c      5.5     (Berkeley) 4/5/88";
        !             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       4096    /* for X.25 interfaces: set equal to packet size,
        !            56:                                 * but see comment above
        !            57:                                 */
        !            58: 
        !            59: #define FOBUFSIZ       4096    /* 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: extern long Bytes_Sent, Bytes_Received;
        !            72: 
        !            73: static
        !            74: falarm()
        !            75: {
        !            76:        signal(SIGALRM, falarm);
        !            77:        longjmp(Ffailbuf, 1);
        !            78: }
        !            79: 
        !            80: static int (*fsig)();
        !            81: 
        !            82: #ifndef USG
        !            83: #define TCGETA TIOCGETP
        !            84: #define TCSETAF        TIOCSETP
        !            85: #define termio sgttyb
        !            86: #endif USG
        !            87: static struct  termio ttbuf;
        !            88: 
        !            89: fturnon()
        !            90: {
        !            91:        int ttbuf_flags;
        !            92: 
        !            93:        if (!IsTcpIp) {
        !            94:                ioctl(Ifn, TCGETA, &ttbuf);
        !            95: #ifdef USG
        !            96:                ttbuf_flags = ttbuf.c_iflag;
        !            97:                ttbuf.c_iflag = IXOFF|IXON|ISTRIP;
        !            98:                ttbuf.c_cc[VMIN] = FIBUFSIZ > 64 ? 64 : FIBUFSIZ;
        !            99:                ttbuf.c_cc[VTIME] = 5;
        !           100:                if (ioctl(Ifn, TCSETAF, &ttbuf) < 0) {
        !           101:                        syslog(LOG_ERR, "ioctl(TCSETAF) failed: %m");
        !           102:                        cleanup(FAIL);
        !           103:                }
        !           104:                ttbuf.c_iflag = ttbuf_flags;
        !           105: #else !USG
        !           106:                ttbuf_flags = ttbuf.sg_flags;
        !           107:                ttbuf.sg_flags = ANYP|CBREAK;
        !           108:                if (ioctl(Ifn, TCSETAF, &ttbuf) < 0) {
        !           109:                        syslog(LOG_ERR, "ioctl(TCSETAF) failed: %m");
        !           110:                        cleanup(FAIL);
        !           111:                }
        !           112:                /* this is two seperate ioctls to set the x.29 params */
        !           113:                ttbuf.sg_flags |= TANDEM;
        !           114:                if (ioctl(Ifn, TCSETAF, &ttbuf) < 0) {
        !           115:                        syslog(LOG_ERR, "ioctl(TCSETAF) failed: %m");
        !           116:                        cleanup(FAIL);
        !           117:                }
        !           118:                ttbuf.sg_flags = ttbuf_flags;
        !           119: #endif USG
        !           120:        }
        !           121:        fsig = signal(SIGALRM, falarm);
        !           122:        /* give the other side time to perform its ioctl;
        !           123:         * otherwise it may flush out the first data this
        !           124:         * side is about to send.
        !           125:         */
        !           126:        sleep(2);
        !           127:        return SUCCESS;
        !           128: }
        !           129: 
        !           130: fturnoff()
        !           131: {
        !           132:        if (!IsTcpIp)
        !           133:                ioctl(Ifn, TCSETAF, &ttbuf);
        !           134:        (void) signal(SIGALRM, fsig);
        !           135:        sleep(2);
        !           136:        return SUCCESS;
        !           137: }
        !           138: 
        !           139: fwrmsg(type, str, fn)
        !           140: register char *str;
        !           141: int fn;
        !           142: char type;
        !           143: {
        !           144:        register char *s;
        !           145:        char bufr[MAXMSGLEN];
        !           146: 
        !           147:        s = bufr;
        !           148:        *s++ = type;
        !           149:        while (*str)
        !           150:                *s++ = *str++;
        !           151:        if (*(s-1) == '\n')
        !           152:                s--;
        !           153:        *s++ = '\r';
        !           154:        *s = 0;
        !           155:        (void) write(fn, bufr, s - bufr);
        !           156:        return SUCCESS;
        !           157: }
        !           158: 
        !           159: frdmsg(str, fn)
        !           160: register char *str;
        !           161: register int fn;
        !           162: {
        !           163:        register char *smax;
        !           164: 
        !           165:        if (setjmp(Ffailbuf))
        !           166:                return FAIL;
        !           167:        smax = str + MAXMSGLEN - 1;
        !           168:        (void) alarm(2*MAXMSGTIME);
        !           169:        for (;;) {
        !           170:                if (read(fn, str, 1) <= 0)
        !           171:                        goto msgerr;
        !           172:                *str &= 0177;
        !           173:                if (*str == '\r')
        !           174:                        break;
        !           175:                if (*str < ' ') {
        !           176:                        continue;
        !           177:                }
        !           178:                if (str++ >= smax)
        !           179:                        goto msgerr;
        !           180:        }
        !           181:        *str = '\0';
        !           182:        (void) alarm(0);
        !           183:        return SUCCESS;
        !           184: msgerr:
        !           185:        (void) alarm(0);
        !           186:        return FAIL;
        !           187: }
        !           188: 
        !           189: fwrdata(fp1, fn)
        !           190: FILE *fp1;
        !           191: int fn;
        !           192: {
        !           193:        register int alen, ret;
        !           194:        char ack, ibuf[MAXMSGLEN];
        !           195:        int flen, mil, retries = 0;
        !           196:        long abytes, fbytes;
        !           197:        struct timeb t1, t2;
        !           198:        float ft;
        !           199: 
        !           200:        ret = FAIL;
        !           201: retry:
        !           202:        fchksum = 0xffff;
        !           203:        abytes = fbytes = 0L;
        !           204:        ack = '\0';
        !           205: #ifdef USG
        !           206:        time(&t1.time);
        !           207:        t1.millitm = 0;
        !           208: #else !USG
        !           209:        ftime(&t1);
        !           210: #endif !USG
        !           211:        do {
        !           212:                alen = fwrblk(fn, fp1, &flen);
        !           213:                fbytes += flen;
        !           214:                if (alen <= 0) {
        !           215:                        abytes -= alen;
        !           216:                        goto acct;
        !           217:                }
        !           218:                abytes += alen;
        !           219:        } while (!feof(fp1) && !ferror(fp1));
        !           220:        DEBUG(8, "\nchecksum: %04x\n", fchksum);
        !           221:        if (frdmsg(ibuf, fn) != FAIL) {
        !           222:                if ((ack = ibuf[0]) == 'G')
        !           223:                        ret = SUCCESS;
        !           224:                DEBUG(4, "ack - '%c'\n", ack);
        !           225:        }
        !           226: acct:
        !           227: #ifdef USG
        !           228:        time(&t2.time);
        !           229:        t2.millitm = 0;
        !           230: #else !USG
        !           231:        ftime(&t2);
        !           232: #endif !USG
        !           233:        Now = t2;
        !           234:        t2.time -= t1.time;
        !           235:        mil = t2.millitm - t1.millitm;
        !           236:        if (mil < 0) {
        !           237:                --t2.time;
        !           238:                mil += 1000;
        !           239:        }
        !           240:        ft = (float)t2.time + (float)mil/1000.;
        !           241:        sprintf(ibuf, "sent data %ld bytes %.2f secs %ld bps",
        !           242:                fbytes, ft, (long)((float)fbytes*8./ft));
        !           243:        sysacct(abytes, t2.time);
        !           244:        Bytes_Sent += fbytes;
        !           245:        if (retries > 0)
        !           246:                sprintf(&ibuf[strlen(ibuf)], ", %d retries", retries);
        !           247:        DEBUG(1, "%s\n", ibuf);
        !           248:        log_xferstats(ibuf);
        !           249:        if (ack == 'R') {
        !           250:                DEBUG(4, "RETRY:\n", 0);
        !           251:                fseek(fp1, 0L, 0);
        !           252:                retries++;
        !           253:                goto retry;
        !           254:        }
        !           255: #ifdef SYSACCT
        !           256:        if (ret == FAIL)
        !           257:                sysaccf(NULL);          /* force accounting */
        !           258: #endif SYSACCT
        !           259:        return ret;
        !           260: }
        !           261: 
        !           262: /* max. attempts to retransmit a file: */
        !           263: #define MAXRETRIES     (fbytes < 10000L ? 2 : 1)
        !           264: 
        !           265: frddata(fn, fp2)
        !           266: register int fn;
        !           267: register FILE *fp2;
        !           268: {
        !           269:        register int flen;
        !           270:        register char eof;
        !           271:        char ibuf[FIBUFSIZ];
        !           272:        int ret, mil, retries = 0;
        !           273:        long alen, abytes, fbytes;
        !           274:        struct timeb t1, t2;
        !           275:        float ft;
        !           276: 
        !           277:        ret = FAIL;
        !           278: retry:
        !           279:        fchksum = 0xffff;
        !           280:        abytes = fbytes = 0L;
        !           281: #ifdef USG
        !           282:        time(&t1.time);
        !           283:        t1.millitm = 0;
        !           284: #else !USG
        !           285:        ftime(&t1);
        !           286: #endif !USG
        !           287:        do {
        !           288:                flen = frdblk(ibuf, fn, &alen);
        !           289:                abytes += alen;
        !           290:                if (flen < 0)
        !           291:                        goto acct;
        !           292:                if (eof = flen > FIBUFSIZ)
        !           293:                        flen -= FIBUFSIZ + 1;
        !           294:                fbytes += flen;
        !           295:                if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
        !           296:                        goto acct;
        !           297:        } while (!eof);
        !           298:        ret = SUCCESS;
        !           299: acct:
        !           300: #ifdef USG
        !           301:        time(&t2.time);
        !           302:        t2.millitm = 0;
        !           303: #else !USG
        !           304:        ftime(&t2);
        !           305: #endif !USG
        !           306:        Now = t2;
        !           307:        t2.time -= t1.time;
        !           308:        mil = t2.millitm - t1.millitm;
        !           309:        if (mil < 0) {
        !           310:                --t2.time;
        !           311:                mil += 1000;
        !           312:        }
        !           313:        ft = (float)t2.time + (float)mil/1000.;
        !           314:        sprintf(ibuf, "received data %ld bytes %.2f secs %ld bps",
        !           315:                fbytes, ft, (long)((float)fbytes*8./ft));
        !           316:        if (retries > 0) 
        !           317:                sprintf(&ibuf[strlen(ibuf)]," %d retries", retries);
        !           318:        sysacct(abytes, t2.time);
        !           319:        Bytes_Received += fbytes;
        !           320:        DEBUG(1, "%s\n", ibuf);
        !           321:        log_xferstats(ibuf);
        !           322:        if (ret == FAIL) {
        !           323:                if (retries++ < MAXRETRIES) {
        !           324:                        DEBUG(8, "send ack: 'R'\n", 0);
        !           325:                        fwrmsg('R', "", fn);
        !           326:                        fseek(fp2, 0L, 0);
        !           327:                        DEBUG(4, "RETRY:\n", 0);
        !           328:                        goto retry;
        !           329:                }
        !           330:                DEBUG(8, "send ack: 'Q'\n", 0);
        !           331:                fwrmsg('Q', "", fn);
        !           332: #ifdef SYSACCT
        !           333:                sysaccf(NULL);          /* force accounting */
        !           334: #endif SYSACCT
        !           335:        }
        !           336:        else {
        !           337:                DEBUG(8, "send ack: 'G'\n", 0);
        !           338:                fwrmsg('G', "", fn);
        !           339:        }
        !           340:        return ret;
        !           341: }
        !           342: 
        !           343: static
        !           344: frdbuf(blk, len, fn)
        !           345: register char *blk;
        !           346: register int len;
        !           347: register int fn;
        !           348: {
        !           349:        static int ret = FIBUFSIZ / 2;
        !           350: 
        !           351:        if (setjmp(Ffailbuf))
        !           352:                return FAIL;
        !           353:        (void) alarm(MAXMSGTIME);
        !           354:        ret = read(fn, blk, len);
        !           355:        alarm(0);
        !           356:        return ret <= 0 ? FAIL : ret;
        !           357: }
        !           358: 
        !           359: #if !defined(BSD4_2) && !defined(USG)
        !           360: /* call ultouch every TC calls to either frdblk or fwrblk  */
        !           361: #define TC     20
        !           362: static int tc = TC;
        !           363: #endif !defined(BSD4_2) && !defined(USG)
        !           364: 
        !           365: /* Byte conversion:
        !           366:  *
        !           367:  *   from       pre       to
        !           368:  * 000-037      172     100-137
        !           369:  * 040-171              040-171
        !           370:  * 172-177      173     072-077
        !           371:  * 200-237      174     100-137
        !           372:  * 240-371      175     040-171
        !           373:  * 372-377      176     072-077
        !           374:  */
        !           375: 
        !           376: static
        !           377: fwrblk(fn, fp, lenp)
        !           378: int fn;
        !           379: register FILE *fp;
        !           380: int *lenp;
        !           381: {
        !           382:        register char *op;
        !           383:        register int c, sum, nl, len;
        !           384:        char obuf[FOBUFSIZ + 8];
        !           385:        int ret;
        !           386: 
        !           387: #if !defined(BSD4_2) && !defined(USG)
        !           388:        /* call ultouch occasionally */
        !           389:        if (--tc < 0) {
        !           390:                tc = TC;
        !           391:                ultouch();
        !           392:        }
        !           393: #endif !defined(BSD4_2) && !defined(USG)
        !           394:        op = obuf;
        !           395:        nl = 0;
        !           396:        len = 0;
        !           397:        sum = fchksum;
        !           398:        while ((c = getc(fp)) != EOF) {
        !           399:                len++;
        !           400:                if (sum & 0x8000) {
        !           401:                        sum <<= 1;
        !           402:                        sum++;
        !           403:                } else
        !           404:                        sum <<= 1;
        !           405:                sum += c;
        !           406:                sum &= 0xffff;
        !           407:                if (c & 0200) {
        !           408:                        c &= 0177;
        !           409:                        if (c < 040) {
        !           410:                                *op++ = '\174';
        !           411:                                *op++ = c + 0100;
        !           412:                        } else
        !           413:                        if (c <= 0171) {
        !           414:                                *op++ = '\175';
        !           415:                                *op++ = c;
        !           416:                        }
        !           417:                        else {
        !           418:                                *op++ = '\176';
        !           419:                                *op++ = c - 0100;
        !           420:                        }
        !           421:                        nl += 2;
        !           422:                } else {
        !           423:                        if (c < 040) {
        !           424:                                *op++ = '\172';
        !           425:                                *op++ = c + 0100;
        !           426:                                nl += 2;
        !           427:                        } else
        !           428:                        if (c <= 0171) {
        !           429:                                *op++ = c;
        !           430:                                nl++;
        !           431:                        } else {
        !           432:                                *op++ = '\173';
        !           433:                                *op++ = c - 0100;
        !           434:                                nl += 2;
        !           435:                        }
        !           436:                }
        !           437:                if (nl >= FOBUFSIZ - 1) {
        !           438:                        /*
        !           439:                         * peek at next char, see if it will fit
        !           440:                         */
        !           441:                        c = getc(fp);
        !           442:                        if (c == EOF)
        !           443:                                break;
        !           444:                        (void) ungetc(c, fp);
        !           445:                        if (nl >= FOBUFSIZ || c < 040 || c > 0171)
        !           446:                                goto writeit;
        !           447:                }
        !           448:        }
        !           449:        /*
        !           450:         * At EOF - append checksum, there is space for it...
        !           451:         */
        !           452:        sprintf(op, "\176\176%04x\r", sum);
        !           453:        nl += strlen(op);
        !           454: writeit:
        !           455:        *lenp = len;
        !           456:        fchksum = sum;
        !           457:        DEBUG(8, "%d/", len);
        !           458:        DEBUG(8, "%d,", nl);
        !           459:        ret = write(fn, obuf, nl);
        !           460:        return ret == nl ? nl : ret < 0 ? 0 : -ret;
        !           461: }
        !           462: 
        !           463: static
        !           464: frdblk(ip, fn, rlen)
        !           465: register char *ip;
        !           466: int fn;
        !           467: long *rlen;
        !           468: {
        !           469:        register char *op, c;
        !           470:        register int sum, len, nl;
        !           471:        char buf[5], *erbp = ip;
        !           472:        int i;
        !           473:        static char special = 0;
        !           474: 
        !           475: #if !defined(BSD4_2) && !defined(USG)
        !           476:        /* call ultouch occasionally */
        !           477:        if (--tc < 0) {
        !           478:                tc = TC;
        !           479:                ultouch();
        !           480:        }
        !           481: #endif !defined(BSD4_2) && !defined(USG)
        !           482:        if ((len = frdbuf(ip, FIBUFSIZ, fn)) == FAIL) {
        !           483:                *rlen = 0;
        !           484:                goto dcorr;
        !           485:        }
        !           486:        *rlen = len;
        !           487:        DEBUG(8, "%d/", len);
        !           488:        op = ip;
        !           489:        nl = 0;
        !           490:        sum = fchksum;
        !           491:        do {
        !           492:                if ((*ip &= 0177) >= '\172') {
        !           493:                        if (special) {
        !           494:                                DEBUG(8, "%d", nl);
        !           495:                                special = 0;
        !           496:                                op = buf;
        !           497:                                if (*ip++ != '\176' || (i = --len) > 5)
        !           498:                                        goto dcorr;
        !           499:                                while (i--)
        !           500:                                        *op++ = *ip++ & 0177;
        !           501:                                while (len < 5) {
        !           502:                                        i = frdbuf(&buf[len], 5 - len, fn);
        !           503:                                        if (i == FAIL) {
        !           504:                                                len = FAIL;
        !           505:                                                goto dcorr;
        !           506:                                        }
        !           507:                                        DEBUG(8, ",%d", i);
        !           508:                                        len += i;
        !           509:                                        *rlen += i;
        !           510:                                        while (i--)
        !           511:                                                *op++ &= 0177;
        !           512:                                }
        !           513:                                if (buf[4] != '\r')
        !           514:                                        goto dcorr;
        !           515:                                sscanf(buf, "%4x", &fchksum);
        !           516:                                DEBUG(8, "\nchecksum: %04x\n", sum);
        !           517:                                if (fchksum == sum)
        !           518:                                        return FIBUFSIZ + 1 + nl;
        !           519:                                else {
        !           520:                                        DEBUG(8, "\n", 0);
        !           521:                                        DEBUG(4, "Bad checksum\n", 0);
        !           522:                                        return FAIL;
        !           523:                                }
        !           524:                        }
        !           525:                        special = *ip++;
        !           526:                } else {
        !           527:                        if (*ip < '\040') {
        !           528:                                /* error: shouldn't get control chars */
        !           529:                                goto dcorr;
        !           530:                        }
        !           531:                        switch (special) {
        !           532:                        case 0:
        !           533:                                c = *ip++;
        !           534:                                break;
        !           535:                        case '\172':
        !           536:                                c = *ip++ - 0100;
        !           537:                                break;
        !           538:                        case '\173':
        !           539:                                c = *ip++ + 0100;
        !           540:                                break;
        !           541:                        case '\174':
        !           542:                                c = *ip++ + 0100;
        !           543:                                break;
        !           544:                        case '\175':
        !           545:                                c = *ip++ + 0200;
        !           546:                                break;
        !           547:                        case '\176':
        !           548:                                c = *ip++ + 0300;
        !           549:                                break;
        !           550:                        }
        !           551:                        *op++ = c;
        !           552:                        if (sum & 0x8000) {
        !           553:                                sum <<= 1;
        !           554:                                sum++;
        !           555:                        } else
        !           556:                                sum <<= 1;
        !           557:                        sum += c & 0377;
        !           558:                        sum &= 0xffff;
        !           559:                        special = 0;
        !           560:                        nl++;
        !           561:                }
        !           562:        } while (--len);
        !           563:        fchksum = sum;
        !           564:        DEBUG(8, "%d,", nl);
        !           565:        return nl;
        !           566: dcorr:
        !           567:        DEBUG(8, "\n", 0);
        !           568:        DEBUG(4, "Data corrupted\n", 0);
        !           569:        while (len != FAIL) {
        !           570:                if ((len = frdbuf(erbp, FIBUFSIZ, fn)) != FAIL)
        !           571:                        *rlen += len;
        !           572:        }
        !           573:        return FAIL;
        !           574: }
        !           575: 

unix.superglobalmegacorp.com

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