+
+static void start_logging(void) {
+ int r;
+
+ openlog(script, LOG_NOWAIT|LOG_PID, LOG_USER);
+ logging = 1;
+ r = dup2(1,2);
+ if (r!=2) diee("dup2 stdout to stderr");
+}
+
+static void errpipe_readable(void) {
+ static char buf[1024];
+ static int pending;
+
+ /* %: does not contain newlines
+ * _: empty (garbage)
+ */
+
+ /* %%%%%%%%%%%__________________ */
+ /* ^ pending */
+
+ for (;;) {
+ int avail = sizeof(buf) - pending;
+ ssize_t got = read(errpipe, buf+pending, avail);
+ if (got==-1) {
+ if (errno==EINTR) continue;
+ else if (errno==EWOULDBLOCK || errno==EAGAIN) return;
+ else diee("(stage2) errpipe read");
+ got = 0;
+ } else if (got==0) {
+ warning("program closed its stderr fd");
+ errpipe = -1;
+ return;
+ }
+ int scanned = pending;
+ pending += got;
+ int eaten = 0;
+ for (;;) {
+ const char *newline = memchr(buf+scanned, '\n', pending-scanned);
+ int printupto, eat;
+ if (newline) {
+ printupto = newline-buf;
+ eat = printupto + 1;
+ } else if (!eaten && pending==sizeof(buf)) { /* overflow */
+ printupto = pending;
+ eat = printupto;
+ } else {
+ break;
+ }
+ syslog(LOG_ERR,"stderr: %.*s", printupto-eaten, buf+eaten);
+ eaten += eat;
+ scanned = eaten;
+ }
+ pending -= eaten;
+ memmove(buf, buf+eaten, pending);
+ }
+}
+
+static void await_something(void) {
+ int r;
+ sigset_t mask;
+ sigemptyset(&mask);
+
+ for (;;) {
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ if (errpipe >= 0)
+ FD_SET(errpipe, &rfds);
+ r = pselect(errpipe+1, &rfds,0,0, 0, &mask);
+ if (r==-1) {
+ if (errno != EINTR) diee("(stage2) sigsuspend");
+ continue;
+ }
+ assert(r>0);
+ assert(FD_ISSET(errpipe, &rfds));
+ errpipe_readable();
+ }
+}