# 2.11BSD#431 - /usr/src/ucb/tftp/tftpsubs.c

##### Functions

    r_init            X
    read_ahead        X
    readit            X
    rw_init           X
    synchnet          X
    w_init            X
    write_behind      X
    writeit           X

##### Variables

    bfs               X
    newline           X
    prevchar          X

##### Macros

    BF_ALLOC          X
    BF_FREE           X
    PKTSIZE           X

##### struct's

    bf                X

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

#### Defined functions

r_init defined in line 64; used 2 times

- in /usr/src/ucb/tftp/tftp.c line 77, 86

read_ahead defined in line 105; used 2 times

- in line 95
- in /usr/src/ucb/tftp/tftp.c line 115

readit defined in line 83; used 1 times

- in /usr/src/ucb/tftp/tftp.c line 97

rw_init defined in line 66; used 3 times

- in line 61-64(3)

synchnet defined in line 231; used 2 times

- in /usr/src/ucb/tftp/tftp.c line 148, 247

w_init defined in line 63; used 2 times

- in /usr/src/ucb/tftp/tftp.c line 178, 187

write_behind defined in line 173; used 3 times

- in line 161
- in /usr/src/ucb/tftp/tftp.c line 214, 268

writeit defined in line 153; used 1 times

- in /usr/src/ucb/tftp/tftp.c line 257

#### Defined variables

bfs defined in line 47; used 11 times

- in line 72-76(3), 90-93(2), 115, 158-163(4), 185

current defined in line 55; used 11 times

- in line 73, 90-93(4), 158-163(6)

newline defined in line 58; used 4 times

- in line 70, 129-133(2), 141

nextone defined in line 54; used 7 times

- in line 75, 115-118(3), 185, 192(2)

prevchar defined in line 59; used 5 times

- in line 71, 130, 139, 204, 214

sccsid defined in line 21; never used

#### Defined struct's

bf defined in line 44; used 6 times

- in line 88(2), 112(2), 182(2)

#### Defined macros

BF_ALLOC defined in line 50; used 2 times

- in line 72, 162

BF_FREE defined in line 51; used 6 times

- in line 74, 90-94(2), 116, 160, 190

PKTSIZE defined in line 42; used 2 times

- in line 46, 236

Last modified: 1991-05-16 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1577 |