[BACK]Return to tftpsubs.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tftp

Diff for /src/usr.bin/tftp/tftpsubs.c between version 1.9 and 1.10

version 1.9, 2003/09/24 20:21:40 version 1.10, 2006/07/12 16:58:51
Line 34 
Line 34 
 #if 0  #if 0
 static char sccsid[] = "@(#)tftpsubs.c  8.1 (Berkeley) 6/6/93";  static char sccsid[] = "@(#)tftpsubs.c  8.1 (Berkeley) 6/6/93";
 #endif  #endif
 static const char rcsid[] = "$OpenBSD$";  static const char rcsid[] =
       "$OpenBSD$";
 #endif /* not lint */  #endif /* not lint */
   
 /* Simple minded read-ahead/write-behind subroutines for tftp user and  /*
    server.  Written originally with multiple buffers in mind, but current   * Simple minded read-ahead/write-behind subroutines for tftp user and
    implementation has two buffer logic wired in.   * server.  Written originally with multiple buffers in mind, but current
    * implementation has two buffer logic wired in.
    Todo:  add some sort of final error check so when the write-buffer   *
    is finally flushed, the caller can detect if the disk filled up   * Todo:  add some sort of final error check so when the write-buffer
    (or had an i/o error) and return a nak to the other side.   * is finally flushed, the caller can detect if the disk filled up
    * (or had an i/o error) and return a nak to the other side.
                         Jim Guyton 10/85   *
    *                      Jim Guyton 10/85
  */   */
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <sys/ioctl.h>  #include <sys/ioctl.h>
   
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <arpa/tftp.h>  #include <arpa/tftp.h>
   
Line 59 
Line 62 
   
 #include "tftpsubs.h"  #include "tftpsubs.h"
   
 #define PKTSIZE SEGSIZE+4       /* should be moved to tftp.h */  #define PKTSIZE         SEGSIZE + 4     /* should be moved to tftp.h */
                                           /* values for bf.counter */
   #define BF_ALLOC        -3              /* alloc'd but not yet filled */
   #define BF_FREE         -2              /* free */
   /* [-1 .. SEGSIZE] = size of data in the data buffer */
   
   static struct tftphdr   *rw_init(int);
   
 struct bf {  struct bf {
         int counter;            /* size of data in buffer, or flag */          int     counter;        /* size of data in buffer, or flag */
         char buf[PKTSIZE];      /* room for data packet */          char    buf[PKTSIZE];   /* room for data packet */
 } bfs[2];  } bfs[2];
   
                                 /* Values for bf.counter  */  static int      nextone;        /* index of next buffer to use */
 #define BF_ALLOC -3             /* alloc'd but not yet filled */  static int      current;        /* index of buffer in use */
 #define BF_FREE  -2             /* free */  
 /* [-1 .. SEGSIZE] = size of data in the data buffer */  
   
 static int nextone;             /* index of next buffer to use */  
 static int current;             /* index of buffer in use */  
   
                                 /* control flags for crlf conversions */                                  /* control flags for crlf conversions */
 int newline = 0;                /* fillbuf: in middle of newline expansion */  int             newline = 0;    /* fillbuf: in middle of newline expansion */
 int prevchar = -1;              /* putbuf: previous char (cr check) */  int             prevchar = -1;  /* putbuf: previous char (cr check) */
   
 static struct tftphdr *rw_init(int);  
   
 struct tftphdr *  struct tftphdr *
 w_init(void)  w_init(void)
 {  {
         return rw_init(0);      /* write-behind */          return (rw_init(0));    /* write-behind */
 }  }
   
 struct tftphdr *  struct tftphdr *
 r_init(void)  r_init(void)
 {  {
         return rw_init(1);      /* read-ahead */          return (rw_init(1));    /* read-ahead */
 }  }
   
 /* init for either read-ahead or write-behind */  /*
 /* zero for write-behind, one for read-head */   * Init for either read-ahead or write-behind.
    * Zero for write-behind, one for read-head.
    */
 static struct tftphdr *  static struct tftphdr *
 rw_init(int x)  rw_init(int x)
 {  {
         newline = 0;            /* init crlf flag */          newline = 0;                    /* init crlf flag */
         prevchar = -1;          prevchar = -1;
         bfs[0].counter =  BF_ALLOC;     /* pass out the first buffer */          bfs[0].counter =  BF_ALLOC;     /* pass out the first buffer */
         current = 0;          current = 0;
         bfs[1].counter = BF_FREE;          bfs[1].counter = BF_FREE;
         nextone = x;                    /* ahead or behind? */          nextone = x;                    /* ahead or behind? */
         return (struct tftphdr *)bfs[0].buf;  
           return ((struct tftphdr *)bfs[0].buf);
 }  }
   
   /*
 /* Have emptied current buffer by sending to net and getting ack.   * Have emptied current buffer by sending to net and getting ack.
    Free it and return next buffer filled with data.   * Free it and return next buffer filled with data.
  */   */
 int  int
 readit(FILE *file, struct tftphdr **dpp, int convert)  readit(FILE *file, struct tftphdr **dpp, int convert)
 {  {
         struct bf *b;          struct bf       *b;
   
         bfs[current].counter = BF_FREE; /* free old one */          bfs[current].counter = BF_FREE;         /* free old one */
         current = !current;             /* "incr" current */          current = !current;                     /* "incr" current */
   
         b = &bfs[current];              /* look at new buffer */          b = &bfs[current];                      /* look at new buffer */
         if (b->counter == BF_FREE)      /* if it's empty */          if (b->counter == BF_FREE)              /* if it's empty */
                 read_ahead(file, convert);      /* fill it */                  read_ahead(file, convert);      /* fill it */
 /*      assert(b->counter != BF_FREE);*//* check */          /* assert(b->counter != BF_FREE); */    /* check */
         *dpp = (struct tftphdr *)b->buf;        /* set caller's ptr */          *dpp = (struct tftphdr *)b->buf;        /* set caller's ptr */
         return b->counter;  
           return (b->counter);
 }  }
   
 /*  /*
  * fill the input buffer, doing ascii conversions if requested   * Fill the input buffer, doing ascii conversions if requested.
  * conversions are  lf -> cr,lf  and cr -> cr, nul   * Conversions are lf -> cr, lf and cr -> cr, nul.
  */   */
 void  void
 read_ahead(FILE *file, int convert)  read_ahead(FILE *file, int convert)
 {  {
         int i;          int              i;
         char *p;          char            *p;
         int c;          int              c;
         struct bf *b;          struct bf       *b;
         struct tftphdr *dp;          struct tftphdr  *dp;
   
         b = &bfs[nextone];              /* look at "next" buffer */          b = &bfs[nextone];                      /* look at "next" buffer */
         if (b->counter != BF_FREE)      /* nop if not free */          if (b->counter != BF_FREE)              /* nop if not free */
                 return;                  return;
         nextone = !nextone;             /* "incr" next buffer ptr */          nextone = !nextone;                     /* "incr" next buffer ptr */
   
         dp = (struct tftphdr *)b->buf;          dp = (struct tftphdr *)b->buf;
   
Line 152 
Line 157 
         }          }
   
         p = dp->th_data;          p = dp->th_data;
         for (i = 0 ; i < SEGSIZE; i++) {          for (i = 0; i < SEGSIZE; i++) {
                 if (newline) {                  if (newline) {
                         if (prevchar == '\n')                          if (prevchar == '\n')
                                 c = '\n';       /* lf to cr,lf */                                  c = '\n';       /* lf to cr, lf */
                         else                          else
                                 c = '\0';       /* cr to cr,nul */                                  c = '\0';       /* cr to cr, nul */
                         newline = 0;                          newline = 0;
                 } else {                  } else {
                         c = getc(file);                          c = getc(file);
                         if (c == EOF) break;                          if (c == EOF)
                                   break;
                         if (c == '\n' || c == '\r') {                          if (c == '\n' || c == '\r') {
                                 prevchar = c;                                  prevchar = c;
                                 c = '\r';                                  c = '\r';
Line 173 
Line 179 
         b->counter = (int)(p - dp->th_data);          b->counter = (int)(p - dp->th_data);
 }  }
   
 /* Update count associated with the buffer, get new buffer  /*
    from the queue.  Calls write_behind only if next buffer not   * Update count associated with the buffer, get new buffer
    available.   * from the queue.  Calls write_behind only if next buffer not
    * available.
  */   */
 int  int
 writeit(FILE *file, struct tftphdr **dpp, int ct, int convert)  writeit(FILE *file, struct tftphdr **dpp, int ct, int convert)
 {  {
         bfs[current].counter = ct;      /* set size of data to write */          bfs[current].counter = ct;              /* set size of data to write */
         current = !current;             /* switch to other buffer */          current = !current;                     /* switch to other buffer */
         if (bfs[current].counter != BF_FREE)     /* if not free */          if (bfs[current].counter != BF_FREE)    /* if not free */
                 (void)write_behind(file, convert); /* flush it */                  /* flush it */
         bfs[current].counter = BF_ALLOC;        /* mark as alloc'd */                  (void)write_behind(file, convert);
           bfs[current].counter = BF_ALLOC;        /* mark as alloc'd */
         *dpp =  (struct tftphdr *)bfs[current].buf;          *dpp =  (struct tftphdr *)bfs[current].buf;
         return ct;                      /* this is a lie of course */  
           return (ct);                            /* this is a lie of course */
 }  }
   
 /*  /*
  * Output a buffer to a file, converting from netascii if requested.   * Output a buffer to a file, converting from netascii if requested.
  * CR,NUL -> CR  and CR,LF => LF.   * CR, NUL -> CR and CR, LF -> LF.
  * Note spec is undefined if we get CR as last byte of file or a   * Note spec is undefined if we get CR as last byte of file or a
  * CR followed by anything else.  In this case we leave it alone.   * CR followed by anything else.  In this case we leave it alone.
 n */   */
 int  int
 write_behind(FILE *file, int convert)  write_behind(FILE *file, int convert)
 {  {
         char *buf;          char            *buf;
         int count;          int              count;
         int ct;          int              ct;
         char *p;          char            *p;
         int c;                          /* current character */          int              c; /* current character */
         struct bf *b;          struct bf       *b;
         struct tftphdr *dp;          struct tftphdr  *dp;
   
         b = &bfs[nextone];          b = &bfs[nextone];
         if (b->counter < -1)            /* anything to flush? */          if (b->counter < -1)            /* anything to flush? */
                 return 0;               /* just nop if nothing to do */                  return (0);             /* just nop if nothing to do */
   
         count = b->counter;             /* remember byte count */          count = b->counter;             /* remember byte count */
         b->counter = BF_FREE;           /* reset flag */          b->counter = BF_FREE;           /* reset flag */
         dp = (struct tftphdr *)b->buf;          dp = (struct tftphdr *)b->buf;
         nextone = !nextone;             /* incr for next time */          nextone = !nextone;             /* incr for next time */
         buf = dp->th_data;          buf = dp->th_data;
   
         if (count <= 0) return -1;      /* nak logic? */          if (count <= 0)                 /* nak logic? */
                   return (-1);
   
         if (convert == 0)          if (convert == 0)
                 return write(fileno(file), buf, count);                  return (write(fileno(file), buf, count));
   
         p = buf;          p = buf;
         ct = count;          ct = count;
         while (ct--) {                  /* loop over the buffer */          while (ct--) {                          /* loop over the buffer */
                 c = *p++;                   /* pick up a character */                  c = *p++;                       /* pick up a character */
                 if (prevchar == '\r') {     /* if prev char was cr */                  if (prevchar == '\r') {         /* if prev char was cr */
                         if (c == '\n')          /* if have cr,lf then just */                          if (c == '\n')          /* if have cr,lf then just */
                                 fseek(file, -1, 1);  /* smash lf on top of the cr */                                  /* smash lf on top of the cr */
                         else if (c == '\0')       /* if have cr,nul then */                                  fseek(file, -1, 1);
                                 goto skipit;    /* just skip over the putc */                          else if (c == '\0')     /* if have cr,nul then */
                         /* else just fall through and allow it */                                  goto skipit;    /* just skip over the putc */
                           /* FALLTHROUGH */
                 }                  }
                 putc(c, file);                  putc(c, file);
 skipit:  skipit:
                 prevchar = c;                  prevchar = c;
         }          }
         return count;  
           return (count);
 }  }
   
   /*
 /* When an error has occurred, it is possible that the two sides   * When an error has occurred, it is possible that the two sides
  * are out of synch.  Ie: that what I think is the other side's   * are out of synch.  Ie: that what I think is the other side's
  * response to packet N is really their response to packet N-1.   * response to packet N is really their response to packet N-1.
  *   *
Line 250 
Line 262 
  * We return the number of packets we flushed (mostly for reporting   * We return the number of packets we flushed (mostly for reporting
  * when trace is active).   * when trace is active).
  */   */
   
 int  int
 synchnet(int f)  synchnet(int f)
 {  {
         int i, j = 0;          int                     i, j = 0;
         char rbuf[PKTSIZE];          char                    rbuf[PKTSIZE];
         struct sockaddr_in from;          struct sockaddr_in      from;
         socklen_t fromlen;          socklen_t               fromlen;
   
         while (1) {          for (;;) {
                 (void) ioctl(f, FIONREAD, &i);                  (void)ioctl(f, FIONREAD, &i);
                 if (i) {                  if (i) {
                         j++;                          j++;
                         fromlen = sizeof from;                          fromlen = sizeof(from);
                         (void) recvfrom(f, rbuf, sizeof (rbuf), 0,                          (void)recvfrom(f, rbuf, sizeof(rbuf), 0,
                             (struct sockaddr *)&from, &fromlen);                              (struct sockaddr *)&from, &fromlen);
                 } else {                  } else
                         return(j);                          return (j);
                 }  
         }          }
 }  }

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10