00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "defs.h"
00022 #include "setblock.h"
00023 #include "../c2/bufio.h"
00024
00025
00026
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
00052
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
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
00150 ec_null( stin = Bfdopen(STDIN_FILENO, "r") )
00151 while ((c = Bgetc(stin)) != -1)
00152
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)
00171 {
00172
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
00182 if (!cready())
00183 refresh();
00184 c = cget();
00185
00186 }
00187 #endif
00188
00189 #include <fcntl.h>
00190
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:
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:
00244 errno = 0;
00245 EC_FAIL
00246 }
00247
00248 EC_CLEANUP_BGN
00249 return false;
00250 EC_CLEANUP_END
00251 }
00252
00253
00254
00255
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);
00263 i = 0;
00264 while (true) {
00265 if (i >= nfds) {
00266 sleep(1);
00267 i = 0;
00268 }
00269 c = 0;
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
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;
00302 ec_neg1( read(fds[i], &c, 1) )
00303 *whichp = i;
00304 return c;
00305 }
00306 }
00307
00308 errno = 0;
00309 EC_FAIL
00310
00311 EC_CLEANUP_BGN
00312 return -1;
00313 EC_CLEANUP_END
00314 }
00315 #ifndef DARWIN
00316
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;
00339 ec_neg1( read(fdinfo[i].fd, &c, 1) )
00340 *whichp = i;
00341 return c;
00342 }
00343 }
00344
00345 errno = 0;
00346 EC_FAIL
00347
00348 EC_CLEANUP_BGN
00349 return -1;
00350 EC_CLEANUP_END
00351 }
00352
00353 #endif
00354
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
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
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
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
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
00499 }
00500
00501 }
00502
00503
00504
00505 readany_test2();
00506 exit(EXIT_SUCCESS);
00507
00508 while (1) {
00509 printf("Type (getln): ");
00510
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
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 }