fifolog.c (2515B)
1 /* 2 * Copyright (C) Raymond Cole <rc@wolog.xyz> 3 * License: GPL-3.0-or-later 4 */ 5 #include <errno.h> 6 #include <fcntl.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <poll.h> 11 #include <unistd.h> 12 13 #include "util.h" 14 15 static size_t 16 getlines(char **linesptr, size_t *siz, int fd) 17 { 18 char *lines = *linesptr; 19 size_t len = 0; 20 char buf[256]; 21 ssize_t n; 22 struct pollfd fds[1]; 23 24 while ((n = read(fd, buf, sizeof(buf))) != 0) { 25 if (n < 0) { 26 if (errno != EAGAIN) 27 die("read:"); 28 } else { 29 if (len + n >= *siz && !(lines = realloc(lines, len + n + 1))) 30 die("realloc:"); 31 memcpy(lines + len, buf, n); 32 lines[len += n] = '\0'; 33 if (lines[len - 1] == '\n') 34 break; 35 } 36 fds->fd = fd; 37 fds->events = POLLIN; 38 while (poll(fds, 1, 1000) < 0) 39 ; 40 } 41 *linesptr = lines; 42 return len; 43 } 44 45 int 46 main(int argc, char **argv) 47 { 48 char **fns, **bns; 49 struct pollfd *fds; 50 int nfds; 51 char *p, *q; 52 int i, ready; 53 char *lines = NULL; 54 size_t siz = 0; 55 56 progname = argv[0]; 57 nfds = argc > 1 ? argc - 1 : 1; 58 if (!(fns = malloc(nfds * sizeof(*fns))) 59 || !(bns = malloc(nfds * sizeof(*bns))) 60 || !(fds = malloc(nfds * sizeof(*fds)))) 61 die("malloc:"); 62 if (argc < 2) 63 fns[0] = "-"; 64 else 65 for (i = 1; i < argc; ++i) 66 fns[i - 1] = argv[i]; 67 for (i = 0; i < nfds; ++i) { 68 if (!strcmp(fns[i], "-")) { 69 fds[i].fd = 0; 70 if (fcntl(0, F_SETFL, O_NONBLOCK) < 0) 71 die("fcntl:"); 72 bns[i] = fns[i]; 73 } else { 74 if ((fds[i].fd = open(fns[i], O_RDONLY|O_NONBLOCK)) < 0) 75 die("open `%s':", fns[i]); 76 bns[i] = (p = strrchr(fns[i], '/')) ? p + 1 : fns[i]; 77 } 78 fds[i].events = POLLIN; 79 } 80 setvbuf(stdout, NULL, _IOLBF, 0); 81 for (;;) { 82 if ((ready = poll(fds, nfds, -1)) < 0) 83 die("poll:"); 84 for (i = 0; i < nfds; ++i) { 85 if (fds[i].revents & (POLLNVAL|POLLERR)) 86 die("error on pipe `%s'", bns[i]); 87 if (fds[i].revents & POLLIN) { 88 if (getlines(&lines, &siz, fds[i].fd)) { 89 for (p = lines; (q = strchr(p, '\n')); p = q + 1) { 90 *q = '\0'; 91 printf("%s %s\n", bns[i], p); 92 } 93 } else { 94 fds[i].revents |= POLLHUP; 95 } 96 } 97 if (fds[i].revents & POLLHUP) { 98 if (fds[i].fd == 0) 99 goto done; 100 close(fds[i].fd); 101 printf("! %s\n", bns[i]); 102 if ((fds[i].fd = open(fns[i], O_RDONLY|O_NONBLOCK)) < 0) 103 die("open `%s':", fns[i]); 104 } 105 if (ferror(stdout)) 106 die("cannot write to stdout"); 107 } 108 } 109 done: 110 free(lines); 111 for (i = 0; i < nfds; ++i) 112 if (fds[i].fd > 0) 113 close(fds[i].fd); 114 free(fns); 115 free(bns); 116 free(fds); 117 return 0; 118 }