select

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

commit 33db3341a40340d0b9e0f0872131380cbb84cfcb
Author: Antoine Amarilli <a3nm@a3nm.net>
Date:   Sat, 15 Dec 2012 19:34:13 +0100

initial commit

Diffstat:
select.c | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+), 0 deletions(-)

diff --git a/select.c b/select.c @@ -0,0 +1,121 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/select.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <argp.h> // TODO +#include <string.h> + +// TODO +#define MAXFDS 242 +#define BUFSIZE 1024 + +#define E_SELECT 2 +#define E_READ 4 + +int fds[MAXFDS]; +fd_set rfds; +int nfds; + +int initfds() { + int i, max = -1; + for (i = 0; i < nfds; i++) { + if (fds[i] < 0) + continue; + FD_SET(fds[i], &rfds); + if (fds[i] > max) + max = fds[i]; + } + return max; +} + +int main(int argc, char **argv) { + int i, j, ret, max = 0; + int ready; + char buf[1024]; + char separator[] = "\t"; + + setvbuf(stdout, NULL, _IONBF, 0); + + nfds = argc; + fds[0] = -1; + // TODO + //if (argc == 1) + //FD_SET(0, &fds); + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-")) { + fds[i] = 0; + continue; + } + fds[i] = open(argv[i], O_RDONLY | O_NONBLOCK); + //printf("opened %s pos %d to %d\n", argv[i], i, fds[i]); + if (fds[i] < 0) { + perror(argv[i]); // TODO better + // TODO exit? + continue; + } + } + + max = initfds(); + + // TODO timeout? + // TODO signals? + while (max >= 0) { + //printf("\n\nabout to select max %d nfds %d\n", max+1, nfds); + ret = select(max+1, &rfds, NULL, NULL, NULL); + //printf("done selecting\n"); + // ignore signals? + // if (r == -1 && errno == EINTR + // continue; + if (ret < 0) { + perror("select"); + exit(E_SELECT); + } + for (i = 1; i < argc; i++) { + if (fds[i] < 0) continue; + if (!FD_ISSET(fds[i], &rfds)) continue; + ready = 1; + while (ready) { + ret = read(fds[i], buf, BUFSIZE); + //printf("%s%s/read %d", argv[i], separator, ret); // TODO + if (ret < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + //printf("\n%s%s/wouldblock", argv[i], separator); // TODO + break; + } + // TODO signals? + // TODO accept errors here? + perror(argv[i]); // TODO better reporting? + exit(E_READ); + } + if (!ret) { + //printf("%s%s/closed", argv[i], separator); // TODO + FD_CLR(fds[i], &rfds); + close(fds[i]); + // TODO try to reopen? + fds[i] = -1; + break; + } + printf("%s%s", argv[i], separator); + // TODO is this really safe or might lines get cut? + for (j = 0; j < ret; j++) { + putchar(buf[j]); + if (buf[j] == '\n' && j != ret-1) { + printf("%s%s", argv[i], separator); + } + } + if (buf[ret-1] != '\n') + putchar('\n'); + } + //printf("\n%s%s/doneread nfds%d", argv[i], separator, nfds); // TODO + max = initfds(); + } + } + for (i = 1; i < argc; i++) + if (fds[i] > 0) + close(fds[i]); + return 0; +} +