+ case '-':
+ parse_opts_opt(cfg, argc, argv, i);
+ break;
+ default :
+ parse_opts_spec(cfg, argc, argv, i);
+ }
+ }
+}
+
+void
+opts_parse(Config *cfg, int argc, char *argv[])
+{
+ opts_parse_any(cfg, argc, argv, 1);
+
+ Fifo *last = cfg->fifos;
+ cfg->fifos = NULL;
+ for (Fifo *f = last; f; ) {
+ Fifo *next = f->next;
+ f->next = cfg->fifos;
+ cfg->fifos = f;
+ f = next;
+ }
+}
+
+void
+fifo_read_error(Fifo *f, char *buf)
+{
+ char *b;
+ int i;
+
+ b = buf + f->pos;
+ /* Copy as much of the error message as possible.
+ * EXCLUDING the reminating \0. */
+ for (i = 0; i < errlen && i < f->width; i++)
+ b[i] = errmsg[i];
+ /* Any remaining slots: */
+ for (; i < f->width; i++)
+ b[i] = '_';
+}
+
+void
+fifo_read_one(Fifo *f, char *buf)
+{
+ ssize_t current;
+ ssize_t total;
+ char *b;
+ char c;
+
+ current = 0;
+ total = 0;
+ c = '\0';
+ b = buf + f->pos;
+ while ((current = read(f->fd, &c, 1)) && c != '\n' && c != '\0' && total++ < f->width)
+ *b++ = c;
+ if (current == -1) {
+ error("Failed to read: \"%s\". Error: %s\n", f->name, strerror(errno));
+ fifo_read_error(f, buf);
+ } else {
+ while (total++ < f->width)
+ *b++ = ' ';
+ }
+ /* TODO Record timestamp read */
+ close(f->fd);
+ f->fd = -1;
+}
+
+void
+fifo_read_all(Config *cfg, char *buf)
+{
+ fd_set fds;
+ int maxfd = -1;
+ int ready;
+ struct stat st;
+
+ FD_ZERO(&fds);
+ for (Fifo *f = cfg->fifos; f; f = f->next) {
+ /* TODO: Create the FIFO if it doesn't already exist. */
+ if (lstat(f->name, &st) < 0) {
+ error("Cannot stat \"%s\". Error: %s\n", f->name, strerror(errno));
+ fifo_read_error(f, buf);
+ continue;
+ }
+ if (!(st.st_mode & S_IFIFO)) {
+ error("\"%s\" is not a FIFO\n", f->name);
+ fifo_read_error(f, buf);
+ continue;
+ }
+ debug("opening: %s\n", f->name);
+ if (f->fd < 0)
+ f->fd = open(f->name, O_RDONLY | O_NONBLOCK);
+ if (f->fd == -1) {
+ /* TODO: Consider backing off retries for failed fifos. */
+ error("Failed to open \"%s\"\n", f->name);
+ fifo_read_error(f, buf);
+ continue;
+ }
+ if (f->fd > maxfd)
+ maxfd = f->fd;
+ FD_SET(f->fd, &fds);
+ }
+ debug("selecting...\n");
+ ready = select(maxfd + 1, &fds, NULL, NULL, NULL);
+ debug("ready: %d\n", ready);
+ assert(ready != 0);
+ if (ready < 0)
+ fatal("%s", strerror(errno));
+ for (Fifo *f = cfg->fifos; f; f = f->next) {
+ if (FD_ISSET(f->fd, &fds)) {
+ debug("reading: %s\n", f->name);
+ fifo_read_one(f, buf);