©2004 by Marc J. Rochkind. All rights reserved. Portions marked "Open Source" may be copied under license.

 

Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

c2/bufio.c

Go to the documentation of this file.
00001 /*
00002     Functions for User Buffering
00003     AUP2, Sec. 2.12.2
00004 
00005     Copyright 2003 by Marc J. Rochkind. All rights reserved.
00006     May be copied only for purposes and under conditions described
00007     on the Web page www.basepath.com/aup/copyright.htm.
00008 
00009     The Example Files are provided "as is," without any warranty;
00010     without even the implied warranty of merchantability or fitness
00011     for a particular purpose. The author and his publisher are not
00012     responsible for any damages, direct or incidental, resulting
00013     from the use or non-use of these Example Files.
00014 
00015     The Example Files may contain defects, and some contain deliberate
00016     coding mistakes that were included for educational reasons.
00017     You are responsible for determining if and how the Example Files
00018     are to be used.
00019 */
00020 #include "defs.h"
00021 #include "bufio.h"
00022 
00023 static BUFIO *Bopen_internal(int fd, const char *path, const char *dir)
00024 {
00025     BUFIO *b = NULL;
00026     int flags;
00027 
00028     switch (dir[0]) {
00029     case 'r':
00030         flags = O_RDONLY;
00031         break;
00032     case 'w':
00033         flags = O_WRONLY | O_CREAT | O_TRUNC;
00034         break;
00035     default:
00036         errno = EINVAL;
00037         EC_FAIL
00038     }
00039     ec_null( b = calloc(1, sizeof(BUFIO)) )
00040     b->fdopen = path == NULL;
00041     if (b->fdopen)
00042         b->fd = fd;
00043     else
00044         b->fd = open(path, flags, PERM_FILE);
00045     ec_neg1( b->fd )
00046     b->dir = dir[0];
00047     return b;
00048 
00049 EC_CLEANUP_BGN
00050     free(b);
00051     return NULL;
00052 EC_CLEANUP_END
00053 }
00054 
00055 BUFIO *Bfdopen(int fd, const char *dir)
00056 {
00057     return Bopen_internal(fd, NULL, dir);
00058 }
00059 
00060 /*[bufio.c]*/
00061 #if 0 /* non-Bfdopen version, as appeared in Chap. 2 of book */
00062 BUFIO *Bopen(const char *path, const char *dir)
00063 {
00064     BUFIO *b = NULL;
00065     int flags;
00066 
00067     switch (dir[0]) {
00068     case 'r':
00069         flags = O_RDONLY;
00070         break;
00071     case 'w':
00072         flags = O_WRONLY | O_CREAT | O_TRUNC;
00073         break;
00074     default:
00075         errno = EINVAL;
00076         EC_FAIL
00077     }
00078     ec_null( b = calloc(1, sizeof(BUFIO)) )
00079     ec_neg1( b->fd = open(path, flags, PERM_FILE) )
00080     b->dir = dir[0];
00081     return b;
00082 
00083 EC_CLEANUP_BGN
00084     free(b);
00085     return NULL;
00086 EC_CLEANUP_END
00087 }
00088 #else
00089 BUFIO *Bopen(const char *path, const char *dir)
00090 {
00091     return Bopen_internal(-1, path, dir);
00092 }
00093 #endif
00094 
00095 static bool readbuf(BUFIO *b)
00096 {
00097     if (b->timeout.tv_sec != 0 || b->timeout.tv_usec != 0) {
00098         fd_set set;
00099 
00100         FD_ZERO(&set);
00101         FD_SET(b->fd, &set);
00102         ec_neg1( select(b->fd + 1, &set, NULL, NULL, &b->timeout) )
00103         if (!FD_ISSET(b->fd, &set)) {
00104             errno = ETIMEDOUT;
00105             return false;
00106         }
00107     }
00108     ec_neg1( b->total = read(b->fd, b->buf, sizeof(b->buf)) )
00109     if (b->total == 0) {
00110         errno = 0;
00111         return false;
00112     }
00113     b->next = 0;
00114     return true;
00115 
00116 EC_CLEANUP_BGN
00117     return false;
00118 EC_CLEANUP_END
00119 }
00120 
00121 static bool writebuf(BUFIO *b)  /* flush buffer */
00122 {
00123     ssize_t n, total;
00124 
00125     total = 0;
00126     while (total < b->next) {
00127         ec_neg1( n = write(b->fd, &b->buf[total], b->next - total) )
00128         total += n;
00129     }
00130     b->next = 0;
00131     return true;
00132 
00133 EC_CLEANUP_BGN
00134     return false;
00135 EC_CLEANUP_END
00136 }
00137 
00138 int Bgetc(BUFIO *b)
00139 {
00140     if (b->next >= b->total)
00141         if (!readbuf(b)) {
00142             if (errno == 0)
00143                 return -1;
00144             EC_FAIL
00145         }
00146     return b->buf[b->next++];
00147 
00148 EC_CLEANUP_BGN
00149     return -1;
00150 EC_CLEANUP_END
00151 }
00152 
00153 bool Bputc(BUFIO *b, int c)
00154 {
00155     b->buf[b->next++] = c;
00156     if (b->next >= sizeof(b->buf))
00157         ec_false( writebuf(b) )
00158     return true;
00159 
00160 EC_CLEANUP_BGN
00161     return false;
00162 EC_CLEANUP_END
00163 }
00164 
00165 bool Bclose(BUFIO *b)
00166 {
00167     if (b != NULL) {
00168         if (b->dir == 'w')
00169             ec_false( writebuf(b) )
00170         if (!b->fdopen) /* this line not in book */
00171             ec_neg1( close(b->fd) )
00172         free(b);
00173     }
00174     return true;
00175 
00176 EC_CLEANUP_BGN
00177     return false;
00178 EC_CLEANUP_END
00179 }
00180 /*[]*/
00181 
00182 /*
00183     Rest of functions not in book.
00184 */
00185 bool Bgets(BUFIO *b, char *s, size_t smax)
00186 {
00187     int c, i;
00188     bool ok = true;
00189 
00190     for (i = 0; i < smax - 1; i++) {
00191         switch (c = Bgetc(b)) {
00192         case '\n':
00193             break;
00194         case -1:
00195             ok = i > 0;
00196             break;
00197         default:
00198             s[i] = (char)c;
00199             continue;
00200         }
00201         break;
00202     }
00203     s[i] = '\0';
00204     return ok;
00205 }
00206 
00207 void Bsettimeout(BUFIO *b, struct timeval *timeout)
00208 {
00209     b->timeout = *timeout;
00210 }

Generated on Fri Apr 23 10:56:54 2004 for AUP2 Example Source by doxygen 1.3.1