select

shell binding for select(2)
git clone https://a3nm.net/git/select/
Log | Files | Refs

select.c (2814B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <unistd.h>
      4 #include <sys/select.h>
      5 #include <sys/types.h>
      6 #include <sys/stat.h>
      7 #include <fcntl.h>
      8 #include <argp.h> // TODO
      9 #include <string.h>
     10 
     11 // TODO
     12 #define MAXFDS 242
     13 #define BUFSIZE 1024
     14 
     15 #define E_SELECT 2
     16 #define E_READ 4
     17 
     18 int fds[MAXFDS];
     19 fd_set rfds;
     20 int nfds;
     21 
     22 int initfds() {
     23   int i, max = -1;
     24   for (i = 0; i < nfds; i++) {
     25     if (fds[i] < 0)
     26       continue;
     27     FD_SET(fds[i], &rfds);
     28     if (fds[i] > max)
     29       max = fds[i];
     30   }
     31   return max;
     32 }
     33 
     34 int main(int argc, char **argv) {
     35   int i, j, ret, max = 0;
     36   int ready;
     37   char buf[1024];
     38   char separator[] = "\t";
     39 
     40   setvbuf(stdout, NULL, _IONBF, 0);
     41 
     42   nfds = argc;
     43   fds[0] = -1;
     44   // TODO
     45   //if (argc == 1)
     46     //FD_SET(0, &fds);
     47   for (i = 1; i < argc; i++) {
     48     if (!strcmp(argv[i], "-")) {
     49       fds[i] = 0;
     50       continue;
     51     }
     52     fds[i] = open(argv[i], O_RDONLY | O_NONBLOCK);
     53     //printf("opened %s pos %d to %d\n", argv[i], i, fds[i]);
     54     if (fds[i] < 0) {
     55       perror(argv[i]); // TODO better
     56       // TODO exit?
     57       continue;
     58     }
     59   }
     60 
     61   max = initfds();
     62 
     63   // TODO timeout?
     64   // TODO signals?
     65   while (max >= 0) {
     66     //printf("\n\nabout to select max %d nfds %d\n", max+1, nfds);
     67     ret = select(max+1, &rfds, NULL, NULL, NULL);
     68     //printf("done selecting\n");
     69     // ignore signals?
     70     // if (r == -1 && errno == EINTR
     71     //   continue;
     72     if (ret < 0) {
     73       perror("select");
     74       exit(E_SELECT);
     75     }
     76     for (i = 1; i < argc; i++) {
     77       if (fds[i] < 0) continue;
     78       if (!FD_ISSET(fds[i], &rfds)) continue;
     79       ready = 1;
     80       while (ready) {
     81         ret = read(fds[i], buf, BUFSIZE);
     82         //printf("%s%s/read %d", argv[i], separator, ret); // TODO
     83         if (ret < 0) {
     84           if (errno == EAGAIN || errno == EWOULDBLOCK) {
     85             //printf("\n%s%s/wouldblock", argv[i], separator); // TODO
     86             break;
     87           }
     88           // TODO signals?
     89           // TODO accept errors here?
     90           perror(argv[i]); // TODO better reporting?
     91           exit(E_READ);
     92         }
     93         if (!ret) {
     94           //printf("%s%s/closed", argv[i], separator); // TODO
     95           FD_CLR(fds[i], &rfds);
     96           close(fds[i]);
     97           // TODO try to reopen?
     98           fds[i] = -1;
     99           break;
    100         }
    101         printf("%s%s", argv[i], separator);
    102         // TODO is this really safe or might lines get cut?
    103         for (j = 0; j < ret; j++) {
    104           putchar(buf[j]);
    105           if (buf[j] == '\n' && j != ret-1) {
    106             printf("%s%s", argv[i], separator);
    107           }
    108         }
    109         if (buf[ret-1] != '\n')
    110           putchar('\n');
    111       }
    112       //printf("\n%s%s/doneread nfds%d", argv[i], separator, nfds); // TODO
    113       max = initfds();
    114     }
    115   }
    116   for (i = 1; i < argc; i++)
    117     if (fds[i] > 0)
    118       close(fds[i]);
    119   return 0;
    120 }
    121