home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / tftp / tftpsubs.c < prev   
Encoding:
C/C++ Source or Header  |  1993-12-17  |  8.3 KB  |  267 lines

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