Annotation of 43BSD/ucb/tftp/tftpsubs.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1985 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: static char sccsid[] = "@(#)tftpsubs.c 1.2 (Berkeley) 2/7/86";
        !             9: #endif not lint
        !            10: 
        !            11: /* Simple minded read-ahead/write-behind subroutines for tftp user and
        !            12:    server.  Written originally with multiple buffers in mind, but current
        !            13:    implementation has two buffer logic wired in.
        !            14: 
        !            15:    Todo:  add some sort of final error check so when the write-buffer
        !            16:    is finally flushed, the caller can detect if the disk filled up
        !            17:    (or had an i/o error) and return a nak to the other side.
        !            18: 
        !            19:                        Jim Guyton 10/85
        !            20:  */
        !            21: 
        !            22: #include <sys/types.h>
        !            23: #include <sys/socket.h>
        !            24: #include <sys/ioctl.h>
        !            25: #include <netinet/in.h>
        !            26: #include <arpa/tftp.h>
        !            27: #include <stdio.h>
        !            28: 
        !            29: #define PKTSIZE SEGSIZE+4       /* should be moved to tftp.h */
        !            30: 
        !            31: struct bf {
        !            32:        int counter;            /* size of data in buffer, or flag */
        !            33:        char buf[PKTSIZE];      /* room for data packet */
        !            34: } bfs[2];
        !            35: 
        !            36:                                /* Values for bf.counter  */
        !            37: #define BF_ALLOC -3             /* alloc'd but not yet filled */
        !            38: #define BF_FREE  -2             /* free */
        !            39: /* [-1 .. SEGSIZE] = size of data in the data buffer */
        !            40: 
        !            41: static int nextone;     /* index of next buffer to use */
        !            42: static int current;     /* index of buffer in use */
        !            43: 
        !            44:                        /* control flags for crlf conversions */
        !            45: int newline = 0;        /* fillbuf: in middle of newline expansion */
        !            46: int prevchar = -1;      /* putbuf: previous char (cr check) */
        !            47: 
        !            48: struct tftphdr *rw_init();
        !            49: 
        !            50: struct tftphdr *w_init() { return rw_init(0); }         /* write-behind */
        !            51: struct tftphdr *r_init() { return rw_init(1); }         /* read-ahead */
        !            52: 
        !            53: struct tftphdr *
        !            54: rw_init(x)              /* init for either read-ahead or write-behind */
        !            55: int x;                  /* zero for write-behind, one for read-head */
        !            56: {
        !            57:        newline = 0;            /* init crlf flag */
        !            58:        prevchar = -1;
        !            59:        bfs[0].counter =  BF_ALLOC;     /* pass out the first buffer */
        !            60:        current = 0;
        !            61:        bfs[1].counter = BF_FREE;
        !            62:        nextone = x;                    /* ahead or behind? */
        !            63:        return (struct tftphdr *)bfs[0].buf;
        !            64: }
        !            65: 
        !            66: 
        !            67: /* Have emptied current buffer by sending to net and getting ack.
        !            68:    Free it and return next buffer filled with data.
        !            69:  */
        !            70: readit(file, dpp, convert)
        !            71:        FILE *file;                     /* file opened for read */
        !            72:        struct tftphdr **dpp;
        !            73:        int convert;                    /* if true, convert to ascii */
        !            74: {
        !            75:        struct bf *b;
        !            76: 
        !            77:        bfs[current].counter = BF_FREE; /* free old one */
        !            78:        current = !current;             /* "incr" current */
        !            79: 
        !            80:        b = &bfs[current];              /* look at new buffer */
        !            81:        if (b->counter == BF_FREE)      /* if it's empty */
        !            82:                read_ahead(file, convert);      /* fill it */
        !            83: /*      assert(b->counter != BF_FREE);  /* check */
        !            84:        *dpp = (struct tftphdr *)b->buf;        /* set caller's ptr */
        !            85:        return b->counter;
        !            86: }
        !            87: 
        !            88: /*
        !            89:  * fill the input buffer, doing ascii conversions if requested
        !            90:  * conversions are  lf -> cr,lf  and cr -> cr, nul
        !            91:  */
        !            92: read_ahead(file, convert)
        !            93:        FILE *file;                     /* file opened for read */
        !            94:        int convert;                    /* if true, convert to ascii */
        !            95: {
        !            96:        register int i;
        !            97:        register char *p;
        !            98:        register int c;
        !            99:        struct bf *b;
        !           100:        struct tftphdr *dp;
        !           101: 
        !           102:        b = &bfs[nextone];              /* look at "next" buffer */
        !           103:        if (b->counter != BF_FREE)      /* nop if not free */
        !           104:                return;
        !           105:        nextone = !nextone;             /* "incr" next buffer ptr */
        !           106: 
        !           107:        dp = (struct tftphdr *)b->buf;
        !           108: 
        !           109:        if (convert == 0) {
        !           110:                b->counter = read(fileno(file), dp->th_data, SEGSIZE);
        !           111:                return;
        !           112:        }
        !           113: 
        !           114:        p = dp->th_data;
        !           115:        for (i = 0 ; i < SEGSIZE; i++) {
        !           116:                if (newline) {
        !           117:                        if (prevchar == '\n')
        !           118:                                c = '\n';       /* lf to cr,lf */
        !           119:                        else    c = '\0';       /* cr to cr,nul */
        !           120:                        newline = 0;
        !           121:                }
        !           122:                else {
        !           123:                        c = getc(file);
        !           124:                        if (c == EOF) break;
        !           125:                        if (c == '\n' || c == '\r') {
        !           126:                                prevchar = c;
        !           127:                                c = '\r';
        !           128:                                newline = 1;
        !           129:                        }
        !           130:                }
        !           131:               *p++ = c;
        !           132:        }
        !           133:        b->counter = (int)(p - dp->th_data);
        !           134: }
        !           135: 
        !           136: /* Update count associated with the buffer, get new buffer
        !           137:    from the queue.  Calls write_behind only if next buffer not
        !           138:    available.
        !           139:  */
        !           140: writeit(file, dpp, ct, convert)
        !           141:        FILE *file;
        !           142:        struct tftphdr **dpp;
        !           143:        int convert;
        !           144: {
        !           145:        bfs[current].counter = ct;      /* set size of data to write */
        !           146:        current = !current;             /* switch to other buffer */
        !           147:        if (bfs[current].counter != BF_FREE)     /* if not free */
        !           148:                write_behind(file, convert);     /* flush it */
        !           149:        bfs[current].counter = BF_ALLOC;        /* mark as alloc'd */
        !           150:        *dpp =  (struct tftphdr *)bfs[current].buf;
        !           151:        return ct;                      /* this is a lie of course */
        !           152: }
        !           153: 
        !           154: /*
        !           155:  * Output a buffer to a file, converting from netascii if requested.
        !           156:  * CR,NUL -> CR  and CR,LF => LF.
        !           157:  * Note spec is undefined if we get CR as last byte of file or a
        !           158:  * CR followed by anything else.  In this case we leave it alone.
        !           159:  */
        !           160: write_behind(file, convert)
        !           161:        FILE *file;
        !           162:        int convert;
        !           163: {
        !           164:        char *buf;
        !           165:        int count;
        !           166:        register int ct;
        !           167:        register char *p;
        !           168:        register int c;                 /* current character */
        !           169:        struct bf *b;
        !           170:        struct tftphdr *dp;
        !           171: 
        !           172:        b = &bfs[nextone];
        !           173:        if (b->counter < -1)            /* anything to flush? */
        !           174:                return 0;               /* just nop if nothing to do */
        !           175: 
        !           176:        count = b->counter;             /* remember byte count */
        !           177:        b->counter = BF_FREE;           /* reset flag */
        !           178:        dp = (struct tftphdr *)b->buf;
        !           179:        nextone = !nextone;             /* incr for next time */
        !           180:        buf = dp->th_data;
        !           181: 
        !           182:        if (count <= 0) return -1;      /* nak logic? */
        !           183: 
        !           184:        if (convert == 0)
        !           185:                return write(fileno(file), buf, count);
        !           186: 
        !           187:        p = buf;
        !           188:        ct = count;
        !           189:        while (ct--) {                  /* loop over the buffer */
        !           190:            c = *p++;                   /* pick up a character */
        !           191:            if (prevchar == '\r') {     /* if prev char was cr */
        !           192:                if (c == '\n')          /* if have cr,lf then just */
        !           193:                   fseek(file, -1, 1);  /* smash lf on top of the cr */
        !           194:                else
        !           195:                   if (c == '\0')       /* if have cr,nul then */
        !           196:                        goto skipit;    /* just skip over the putc */
        !           197:                /* else just fall through and allow it */
        !           198:            }
        !           199:            putc(c, file);
        !           200: skipit:
        !           201:            prevchar = c;
        !           202:        }
        !           203:        return count;
        !           204: }
        !           205: 
        !           206: 
        !           207: /* When an error has occurred, it is possible that the two sides
        !           208:  * are out of synch.  Ie: that what I think is the other side's
        !           209:  * response to packet N is really their response to packet N-1.
        !           210:  *
        !           211:  * So, to try to prevent that, we flush all the input queued up
        !           212:  * for us on the network connection on our host.
        !           213:  *
        !           214:  * We return the number of packets we flushed (mostly for reporting
        !           215:  * when trace is active).
        !           216:  */
        !           217: 
        !           218: int
        !           219: synchnet(f)
        !           220: int    f;              /* socket to flush */
        !           221: {
        !           222:        int i, j = 0;
        !           223:        char rbuf[PKTSIZE];
        !           224:        struct sockaddr_in from;
        !           225:        int fromlen;
        !           226: 
        !           227:        while (1) {
        !           228:                (void) ioctl(f, FIONREAD, &i);
        !           229:                if (i) {
        !           230:                        j++;
        !           231:                        fromlen = sizeof from;
        !           232:                        (void) recvfrom(f, rbuf, sizeof (rbuf), 0,
        !           233:                                (caddr_t)&from, &fromlen);
        !           234:                } else {
        !           235:                        return(j);
        !           236:                }
        !           237:        }
        !           238: }

unix.superglobalmegacorp.com

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