home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / ip / sized_io.shar.Z / sized_io.shar / sized_io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-28  |  3.7 KB  |  146 lines

  1. /* sized_io.c - Preserve message boundaries in stream io.
  2.  
  3. These two routines enable us to have use stream io, but still detect end of
  4. record marks.  Each call to sized_read() returns a complete buffer, that is
  5. what was written by one call to sized_write().
  6.  
  7. Notes:
  8.  
  9. The IPC system seems to be a confusing mess.  I.e. unusual conditions are
  10. handled in all different ways.  Specifically,
  11.  
  12. While we are reading, if the writer goes away, we sometimes get a read()
  13. == -1 && errno == ECONNRESET.  Sometimes we get a read() == 0.  Why the
  14. difference?
  15.  
  16. While we are writing, if the reader goes away, we get a signal (SIGPIPE).
  17.  
  18.  
  19. Don Libes
  20. National Institute of Standards and Technology
  21. (301) 975-3535
  22. libes@cme.nist.gov
  23. ...!uunet!cme-durer!libes
  24.  
  25. */
  26.  
  27. #include <stdio.h>
  28. #include <errno.h>
  29. extern int errno;
  30. #include <sys/types.h>        /* defines u_long */
  31. #include <netinet/in.h>        /* defines htonl(), etc */
  32.  
  33. /* read exactly this many bytes */
  34. /* We may be forced to loop doing reads, since occasionally reads return */
  35. /* only partial buffers.  Surprisingly, this happens even when reading */
  36. /* tiny (4-byte) buffers. */
  37. /* should probably make an exact_write() also */
  38. static exact_read(fd,buffer,size)
  39. int fd;
  40. char *buffer;
  41. int size;
  42. {
  43.     int rembytes = size;
  44.     int cc;
  45.  
  46.     while (rembytes) {
  47.         if (-1 == (cc = read(fd,buffer,rembytes))) {
  48.             fprintf(stderr,"sized_read(,,%d) = read(,,%d) = %d\n",
  49.                             size,rembytes,cc);
  50.             if (errno != ECONNRESET) perror("read");
  51.             return(-1);
  52.         }
  53.  
  54.         if (0 == cc) {    /* EOF - process died */
  55.             return(-1);
  56.         }
  57.  
  58. #ifdef DEBUG
  59.         if (rembytes != cc)
  60.             fprintf(stderr,"sized_read(,,%d) = read(,,%d) = %d\n",
  61.                             size,rembytes,cc);
  62. #endif
  63.         /* read() returned more bytes than requested!?!?!?! */
  64.         /* this can't happen, but appears to be anyway */
  65.         if (cc > rembytes) {
  66.             fprintf(stderr,"sized_read(,,%d) = read(,,%d) = %d!?!?!\n",
  67.                             size,rembytes,cc);
  68.             fprintf(stderr,"read() returned more chars than requested!  Aborting program.\n");
  69.             abort();
  70.         }
  71.         buffer += cc;
  72.         rembytes -= cc;
  73.     }
  74.     return(size);
  75. }
  76.  
  77.  
  78. int    /* returns number of bytes read or -1 if error (i.e. EOF) */
  79. sized_read(fd,buffer,maxbytes)
  80. int fd;
  81. char *buffer;
  82. int maxbytes;    /* unlike read(), this parameter is the maximum size of */
  83.         /* the buffer */
  84. {
  85.     int size;    /* size of incoming packet */
  86.     u_long netlong;    /* network byte ordered length */
  87.  
  88.     /* read header */
  89.     if (-1 == exact_read(fd,(char *)&netlong,sizeof(netlong))) return(-1);
  90.     size = ntohl(netlong);
  91.  
  92.     /* read data */
  93.     if (size == 0) return(0);
  94.     else if (size > maxbytes) {
  95.         fprintf(stderr,"sized_read: buffer too small.  ");
  96.         fprintf(stderr,"buffer size was %d  actual size was %d\n",
  97.             maxbytes,size);
  98.         return(-1);
  99.     }
  100.     return(exact_read(fd,buffer,size));
  101. }
  102.  
  103. int    /* returns number of data bytes written or -1 if error */
  104. sized_write(fd,buffer,nbytes)
  105. int fd;
  106. char *buffer;
  107. int nbytes;
  108. {
  109.     int cc;
  110.     int rembytes;
  111.     u_long netlong;    /* network byte ordered length */
  112.  
  113.     /* write header */
  114.     netlong = htonl(nbytes);
  115.     if (sizeof(nbytes) != (cc = write(fd,(char *)&netlong,
  116.                             sizeof(netlong)))) {
  117. #ifdef DEBUG
  118.         /* this can never happen (SIGPIPE will always occur first) */
  119.         fprintf(stderr,"sized_write: tried to write buffer size but only wrote %d chars\n",cc);
  120. #endif
  121.         if (cc == -1) perror("write");
  122.         return(-1);
  123.     }
  124.  
  125.     /* write data */
  126.     if (nbytes == 0) return(0);
  127.  
  128.     rembytes = nbytes;
  129.     while (rembytes) {
  130.         if (-1 == (cc = write(fd,buffer,rembytes))) {
  131.               fprintf(stderr,"sized_write(,,%d) = write(,,%d) = %d\n",
  132.                             nbytes,rembytes,cc);
  133.             perror("write");
  134.             return(-1);
  135.         }
  136. #ifdef DEBUG
  137.         if (rembytes != cc) 
  138.               fprintf(stderr,"sized_write(,,%d) = write(,,%d) = %d\n",
  139.                             nbytes,rembytes,cc);
  140. #endif
  141.         buffer += cc;
  142.         rembytes -= cc;
  143.     }
  144.     return(nbytes);
  145. }
  146.