+/* Read from a fd and output to a log. This is a quick hack to
+ support logging stderr, and needs code adding to tidy up before it
+ can be used for anything else. */
+#define FDLOG_BUFSIZE 1024
+struct fdlog {
+ struct log_if *log;
+ int fd;
+ cstring_t prefix;
+ string_t buffer;
+ int i;
+ bool_t finished;
+};
+
+static int log_from_fd_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
+ int *timeout_io)
+{
+ struct fdlog *st=sst;
+ if (!st->finished) {
+ *nfds_io=1;
+ fds[0].fd=st->fd;
+ fds[0].events=POLLIN;
+ }
+ return 0;
+}
+
+static void log_from_fd_afterpoll(void *sst, struct pollfd *fds, int nfds)
+{
+ struct fdlog *st=sst;
+ int r,remain,i;
+
+ if (nfds==0) return;
+ if (fds[0].revents&POLLERR) {
+ st->finished=True;
+ }
+ if (fds[0].revents&POLLIN) {
+ remain=FDLOG_BUFSIZE-st->i-1;
+ if (remain<=0) {
+ st->buffer[FDLOG_BUFSIZE-1]=0;
+ st->log->log(st->log,M_WARNING,"%s: overlong line: %s",
+ st->prefix,st->buffer);
+ st->i=0;
+ remain=FDLOG_BUFSIZE-1;
+ }
+ r=read(st->fd,st->buffer+st->i,remain);
+ if (r>0) {
+ st->i+=r;
+ for (i=0; i<st->i; i++) {
+ if (st->buffer[i]=='\n') {
+ st->buffer[i]=0;
+ st->log->log(st->log->st,M_INFO,"%s: %s",
+ st->prefix,st->buffer);
+ i++;
+ memmove(st->buffer,st->buffer+i,st->i-i);
+ st->i-=i;
+ i=-1;
+ }
+ }
+ } else {
+ Message(M_WARNING,"log_from_fd: %s\n",strerror(errno));
+ st->finished=True;
+ }
+ }
+}
+
+void log_from_fd(int fd, cstring_t prefix, struct log_if *log)
+{
+ struct fdlog *st;
+
+ st=safe_malloc(sizeof(*st),"log_from_fd");
+ st->log=log;
+ st->fd=fd;
+ st->prefix=prefix;
+ st->buffer=safe_malloc(FDLOG_BUFSIZE,"log_from_fd");
+ st->i=0;
+ st->finished=False;
+
+ register_for_poll(st,log_from_fd_beforepoll,log_from_fd_afterpoll,1,
+ prefix);
+}
+