Annotation of 43BSDReno/usr.bin/uucp/fio.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)fio.c      5.6     (Berkeley) 6/29/90";
                      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 void (*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.