Annotation of 43BSD/usr.bin/uucp/fio.c, revision 1.1.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.