©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  

c4/x4.c

Go to the documentation of this file.
00001 /*
00002     Miscellaneous examples for Chap. 4
00003     AUP2, Chap. 4
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 */
00021 #include "defs.h"
00022 #include "setblock.h"
00023 #include "../c2/bufio.h"
00024 
00025 /* read line from terminal */
00026 /*[getln]*/
00027 bool getln(char *s, ssize_t max, bool *iseof)
00028 {
00029     ssize_t nread;
00030 
00031     switch (nread = read(STDIN_FILENO, s, max - 1)) {
00032     case -1:
00033         EC_FAIL
00034     case 0:
00035         *iseof = true;
00036         return true;
00037     default:
00038         if (s[nread - 1] == '\n')
00039             nread--;
00040         s[nread] = '\0';
00041         *iseof = false;
00042         return true;
00043     }
00044 
00045 EC_CLEANUP_BGN
00046     return false;
00047 EC_CLEANUP_END
00048 }
00049 /*[]*/
00050 
00051 /* read line from anywhere */
00052 /*[getln2]*/
00053 bool getln2(char *s, ssize_t max, bool *iseof)
00054 {
00055     ssize_t n;
00056     char c;
00057 
00058     n = 0;
00059     while (true)
00060         switch (read(STDIN_FILENO, &c, 1)) {
00061         case -1:
00062             EC_FAIL
00063         case 0:
00064             s[n] = '\0';
00065             *iseof = true;
00066             return true;
00067         default:
00068             if (c == '\n') {
00069                 s[n] = '\0';
00070                 *iseof = false;
00071                 return true;
00072             }
00073             if (n >= max - 1) {
00074                 errno = E2BIG;
00075                 EC_FAIL
00076             }
00077             s[n++] = c;
00078         }
00079 
00080 EC_CLEANUP_BGN
00081     return false;
00082 EC_CLEANUP_END
00083 }
00084 /*[test_setblock]*/
00085 static void test_setblock(void)
00086 {
00087     char s[100];
00088     ssize_t n;
00089     time_t tstart, tnow;
00090 
00091     ec_neg1( tstart = time(NULL) )
00092     ec_false( setblock(STDIN_FILENO, false) )
00093     while (true) {
00094         ec_neg1( tnow = time(NULL) )
00095         printf("Waiting for input (%.0f sec.) ...\n",
00096           difftime(tnow, tstart));
00097         switch(n = read(STDIN_FILENO, s, sizeof(s) - 1)) {
00098         case 0:
00099             printf("EOF\n");
00100             break;
00101         case -1:
00102             if (errno == EAGAIN) {
00103                 sleep(5);
00104                 continue;
00105             }
00106             EC_FAIL
00107         default:
00108             if (s[n - 1] == '\n')
00109                 n--;
00110             s[n] = '\0';
00111             printf("Read \"%s\"\n", s);
00112             continue;
00113         }
00114         break;
00115     }
00116     return;
00117 
00118 EC_CLEANUP_BGN
00119     EC_FLUSH("test_setblock")
00120 EC_CLEANUP_END
00121 }
00122 /*[]*/
00123 static void test_setblock2(void)
00124 {
00125     char s[100];
00126     bool iseof;
00127 
00128     ec_false( setblock(STDIN_FILENO, true) )
00129     while (true) {
00130         ec_false( getln(s, sizeof(s), &iseof) )
00131         if (iseof) {
00132             printf("EOF\n");
00133             break;
00134         }
00135         else
00136             printf("Read \"%s\"\n", s);
00137     }
00138     return;
00139 
00140 EC_CLEANUP_BGN
00141     EC_FLUSH("test_setblock2")
00142 EC_CLEANUP_END
00143 }
00144 /*[]*/
00145 static void test_Bfdopen(void)
00146 {
00147     BUFIO *stin;
00148     int c;
00149 /*[Bfdopen-test]*/
00150     ec_null( stin = Bfdopen(STDIN_FILENO, "r") )
00151     while ((c = Bgetc(stin)) != -1)
00152         /* process character */
00153 /*[]*/
00154         putchar(c);
00155     if (errno != 0)
00156         EC_FAIL
00157     printf("Got EOF\n");
00158     ec_false( Bclose(stin) )
00159     return;
00160 
00161 EC_CLEANUP_BGN
00162     (void)Bclose(stin);
00163     EC_FLUSH("test_Bfdopen")
00164 EC_CLEANUP_END
00165 }
00166 #if 0
00167 #define Sfdopen Sopen
00168 #define refresh exit
00169 
00170 void junk(void) /* don't call! */
00171 {
00172 /*4-3*/
00173     STREAM *stin;
00174     char c;
00175 
00176     if ((stin = Sfdopen(STDIN_FILENO, "r")) == NULL)
00177         syserr("Sfdopen");
00178     c = Sgetc(stin);
00179 /**/
00180 
00181 /*4-5*/
00182     if (!cready())
00183         refresh();
00184     c = cget();
00185 /**/
00186 }
00187 #endif
00188 
00189 #include <fcntl.h>
00190 /*[cready-cget]*/
00191 #define EMPTY '\0'
00192 static unsigned char cbuf = EMPTY;
00193 typedef enum {CR_READY, CR_NOTREADY, CR_EOF} CR_STATUS;
00194 
00195 bool cready(CR_STATUS *statusp)
00196 {
00197     if (cbuf != EMPTY) {
00198         *statusp = CR_READY;
00199         return true;
00200     }
00201     setblock(STDIN_FILENO, false);
00202     switch (read(STDIN_FILENO, &cbuf, 1)) {
00203     case -1:
00204         if (errno == EAGAIN) {
00205             *statusp = CR_NOTREADY;
00206             return true;
00207         }
00208         EC_FAIL
00209     case 0:
00210         *statusp = CR_EOF;
00211         return true;
00212     case 1:
00213         return true;
00214     default: /* "impossible" case */
00215         errno = 0;
00216         EC_FAIL
00217     }
00218 
00219 EC_CLEANUP_BGN
00220     return false;
00221 EC_CLEANUP_END
00222 }
00223 
00224 bool cget(CR_STATUS *statusp, int *cp)
00225 {
00226     if (cbuf != EMPTY) {
00227         *cp = cbuf;
00228         cbuf = EMPTY;
00229         *statusp = CR_READY;
00230         return true;
00231     }
00232     setblock(0, true);
00233     switch (read(STDIN_FILENO, cp, 1)) {
00234     case -1:
00235         EC_FAIL
00236     case 0:
00237         *cp = 0;
00238         *statusp = CR_EOF;
00239         return true;
00240     case 1:
00241         *statusp = CR_READY;
00242         return true;
00243     default: /* "impossible" case */
00244         errno = 0;
00245         EC_FAIL
00246     }
00247 
00248 EC_CLEANUP_BGN
00249     return false;
00250 EC_CLEANUP_END
00251 }
00252 /*[]*/
00253 
00254 
00255 /*[readany]*/
00256 int readany(int fds[], int nfds, int *whichp)
00257 {
00258     int i;
00259     unsigned char c;
00260 
00261     for (i = 0; i < nfds; i++)
00262         setblock(fds[i], false); /* inefficient to do this every time */
00263     i = 0;
00264     while (true) {
00265         if (i >= nfds) {
00266             sleep(1);
00267             i = 0;
00268         }
00269         c = 0; /* return value for EOF */
00270         if (read(fds[i], &c, 1) == -1) {
00271             if (errno == EAGAIN) {
00272                 i++;
00273                 continue;
00274             }
00275             EC_FAIL
00276         }
00277         *whichp = i;
00278         return c;
00279     }
00280 
00281 EC_CLEANUP_BGN
00282     return -1;
00283 EC_CLEANUP_END
00284 }
00285 /*[readany2]*/
00286 int readany2(int fds[], int nfds, int *whichp)
00287 {
00288     fd_set set_read;
00289     int i, maxfd = 0;
00290     unsigned char c;
00291 
00292     FD_ZERO(&set_read);
00293     for (i = 0; i < nfds; i++) {
00294         FD_SET(fds[i], &set_read);
00295         if (fds[i] > maxfd)
00296             maxfd = fds[i];
00297     }
00298     ec_neg1( select(maxfd + 1, &set_read, NULL, NULL, NULL) )
00299     for (i = 0; i < nfds; i++) {
00300         if (FD_ISSET(fds[i], &set_read)) {
00301             c = 0; /* return value for EOF */
00302             ec_neg1( read(fds[i], &c, 1) )
00303             *whichp = i;
00304             return c;
00305         }
00306     }
00307     /* "impossible" to get here */
00308     errno = 0;
00309     EC_FAIL
00310 
00311 EC_CLEANUP_BGN
00312     return -1;
00313 EC_CLEANUP_END
00314 }
00315 #ifndef DARWIN
00316 /*[readany3]*/
00317 #include <poll.h>
00318 
00319 #define MAXFDS 100
00320 
00321 int readany3(int fds[], int nfds, int *whichp)
00322 {
00323     struct pollfd fdinfo[MAXFDS] = { { 0 } };
00324     int i;
00325     unsigned char c;
00326 
00327     if (nfds > MAXFDS) {
00328         errno = E2BIG;
00329         EC_FAIL
00330     }
00331     for (i = 0; i < nfds; i++) {
00332         fdinfo[i].fd = fds[i];
00333         fdinfo[i].events = POLLIN | POLLPRI;
00334     }
00335     ec_neg1( poll(fdinfo, nfds, -1) )
00336     for (i = 0; i < nfds; i++) {
00337         if (fdinfo[i].revents & (POLLIN | POLLPRI)) {
00338             c = 0; /* return value for EOF */
00339             ec_neg1( read(fdinfo[i].fd, &c, 1) )
00340             *whichp = i;
00341             return c;
00342         }
00343     }
00344     /* "impossible" to get here */
00345     errno = 0;
00346     EC_FAIL
00347 
00348 EC_CLEANUP_BGN
00349     return -1;
00350 EC_CLEANUP_END
00351 }
00352 /*[]*/
00353 #endif /* DARWIN */
00354 /*[readany_test]*/
00355 static void readany_test(void)
00356 {
00357     int fds[2] = {-1, -1}, which;
00358     int c;
00359     bool ok = false;
00360 
00361     ec_neg1( fds[0] = open("/dev/tty", O_RDWR) )
00362     ec_neg1( fds[1] = open("/dev/pts/3", O_RDWR) )
00363     while ((c = readany(fds, 2, &which)) > 0)
00364         printf("Got %c from terminal %d\n", isprint(c) ? c : '?', which);
00365     ec_neg1( c )
00366     ok = true;
00367     EC_CLEANUP
00368 
00369 EC_CLEANUP_BGN
00370     if (fds[0] != -1)
00371         (void)close(fds[0]);
00372     if (fds[1] != -1)
00373         (void)close(fds[1]);
00374     if (!ok)
00375         EC_FLUSH("readany_test1")
00376 EC_CLEANUP_END
00377 }
00378 /*[]*/
00379 static void readany_test2(void)
00380 {
00381     int fds[2] = {-1, -1}, which;
00382     int c;
00383     bool ok = false;
00384 
00385     ec_neg1( fds[0] = open("/dev/tty", O_RDWR) )
00386     ec_neg1( fds[1] = open("/dev/pts/3", O_RDWR) )
00387     while ((c = readany2(fds, 2, &which)) > 0)
00388         printf("Got %c from terminal %d\n", isprint(c) ? c : '?', which);
00389     ec_neg1( c )
00390     ok = true;
00391     EC_CLEANUP
00392 
00393 EC_CLEANUP_BGN
00394     if (fds[0] != -1)
00395         (void)close(fds[0]);
00396     if (fds[1] != -1)
00397         (void)close(fds[1]);
00398     if (!ok)
00399         EC_FLUSH("readany_test2")
00400 EC_CLEANUP_END
00401 }
00402 #ifndef DARWIN
00403 static void readany_test3(void)
00404 {
00405     int fds[2] = {-1, -1}, which;
00406     int c;
00407     bool ok = false;
00408 
00409     ec_neg1( fds[0] = open("/dev/tty", O_RDWR) )
00410     ec_neg1( fds[1] = open("/dev/pts/3", O_RDWR) )
00411     while ((c = readany3(fds, 2, &which)) > 0)
00412         printf("Got %c from terminal %d\n", isprint(c) ? c : '?', which);
00413     ec_neg1( c )
00414     ok = true;
00415     EC_CLEANUP
00416 
00417 EC_CLEANUP_BGN
00418     if (fds[0] != -1)
00419         (void)close(fds[0]);
00420     if (fds[1] != -1)
00421         (void)close(fds[1]);
00422     if (!ok)
00423         EC_FLUSH("readany_test3")
00424 EC_CLEANUP_END
00425 }
00426 #endif /* DARWIN */
00427 int main(void)
00428 {
00429     char s[100];
00430 #if 1
00431     int c;
00432     CR_STATUS status;
00433     int count = 0;
00434     while (true) {
00435         ec_false( cready(&status) )
00436         switch (status) {
00437         case CR_READY:
00438             ec_false( cget(&status, &c) )
00439             if (status == CR_EOF) {
00440                 printf("EOF from cget\n");
00441                 setblock(STDIN_FILENO, true);
00442                 exit(EXIT_SUCCESS);
00443             }
00444             printf("After %d cready() calls, got %c\n", count, c);
00445             count = 0;
00446         case CR_NOTREADY:
00447             count++;
00448             continue;
00449         case CR_EOF:
00450             printf("EOF from cready\n");
00451             setblock(STDIN_FILENO, true);
00452             exit(EXIT_SUCCESS);
00453         }
00454     }
00455 #if 0 /* AUP1 -- not sure what this is doing */
00456         if (cready())
00457             printf("READY\n");
00458         else
00459             printf("NOT READY\n");
00460         if ((c = cget()) == -1) {
00461             printf("EOF\n");
00462             exit(EXIT_SUCCESS);
00463         }
00464         if (c == 1) {
00465             setblock(0, true);
00466             exit(EXIT_SUCCESS);
00467         }
00468         printf("%c", c);
00469 #endif
00470 
00471 #endif
00472 
00473 /*[refresh-example]*/
00474 ec_false( cready(&status) )
00475 if (status == CR_NOTREADY)
00476     refresh();
00477 ec_false( cget(&status, &c) )
00478 /*[]*/
00479 
00480 
00481 
00482 #if 0
00483 {
00484     bool iseof;
00485 
00486     setbuf(stdout, NULL);
00487 
00488 {
00489     int fd1 = 1, fd2 = 4;
00490 
00491 /*[fd_set-example]*/
00492 fd_set set;
00493 
00494 FD_ZERO(&set);
00495 FD_SET(fd1, &set);
00496 FD_SET(fd2, &set);
00497 if (FD_ISSET(fd1, &set)) {
00498     /* do something with fd1, depending on which set */
00499 }
00500 /*[]*/
00501 }
00502     //test_Bfdopen();
00503     //test_setblock();
00504     //test_setblock2();
00505     readany_test2();
00506 exit(EXIT_SUCCESS);
00507 
00508     while (1) {
00509         printf("Type (getln): ");
00510 /*[getln-test]*/
00511 ec_false( getln(s, sizeof(s), &iseof) )
00512 if (iseof)
00513     printf("EOF\n");
00514 else
00515     printf("Read: %s\n", s);
00516 /*[]*/
00517         if (strcmp(s, "quit") == 0)
00518             break;
00519         printf("Type (getln2): ");
00520 /*[getln2-test]*/
00521 ec_false( getln2(s, sizeof(s), &iseof) )
00522 if (iseof)
00523     printf("EOF: %s\n", s);
00524 else
00525     printf("Read: %s\n", s);
00526 /*[]*/
00527         if (strcmp(s, "quit") == 0)
00528             break;
00529     }
00530     exit(EXIT_SUCCESS);
00531 
00532 }
00533 #endif
00534 EC_CLEANUP_BGN
00535     setblock(STDIN_FILENO, true);
00536     exit(EXIT_FAILURE);
00537 EC_CLEANUP_END
00538 }

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