chiark / gitweb /
mention bug
[userv.git] / overlord.c
index b18102fbf6a0edfdff37fa97b3ad5be6bbda1371..020fff09098fb36ad9d3c994a344214fe7270d2b 100644 (file)
@@ -2,7 +2,7 @@
  * userv - overlord.c
  * daemon main program, collects request and forks handlers
  *
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1997,1999 Ian Jackson
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <assert.h>
 #include <fnmatch.h>
 #include <sys/wait.h>
 #include <sys/types.h>
-#include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
+#include <time.h>
 #include <dirent.h>
 #include <sys/un.h>
 
@@ -43,7 +44,7 @@
 pid_t overlordpid;
 
 static pid_t checkpid= -1, detachpid= -1;
-static sig_atomic_t needcheck= 1;
+static sig_atomic_t needcheck= 1; /* 2 means we half-expect the server to be down */
 
 static void checkstalepipes(void) {
   /* There is an unimportant race here.  If there is a stale pipe but
@@ -81,7 +82,7 @@ static void checkstalepipes(void) {
 
 static void sighandler_chld(int x) {
   pid_t r;
-  int status, es, ar;
+  int status, es;
 
   es= errno;
   for (;;) {
@@ -117,8 +118,7 @@ static void sighandler_chld(int x) {
               (long)checkpid,status);
       }
       checkpid= -1;
-      ar= alarm(USERVD_MYSELF_CHECK);
-      if (ar<0) { syslog(LOG_CRIT,"set alarm for next check: %m"); exit(5); }
+      alarm(USERVD_MYSELF_CHECK);
     } else {
       if (WIFSIGNALED(status)) {
        syslog(LOG_ERR,"call pid %ld %s due to signal %s",
@@ -128,11 +128,14 @@ static void sighandler_chld(int x) {
       } else if (!WIFEXITED(status)) {
        syslog(LOG_ERR,"call pid %ld died due to unknown reason, code %d",
               (long)r,status);
+      } else if (WEXITSTATUS(status)==10) {
+       needcheck= 2;
       } else if (WEXITSTATUS(status)>12) {
        if (WEXITSTATUS(status)>24)
          syslog(LOG_ERR,"call pid %ld exited with status %d >24",
                 (long)r,WEXITSTATUS(status));
        checkstalepipes();
+       needcheck= 1;
       }
     }
   }
@@ -165,7 +168,7 @@ static void blocksignals(int how) {
   r= sigprocmask(how,&set,0); assert(!r);
 }
 
-static void NONRETURNING docheck(void) {
+static void NONRETURNING docheck(int needwanted) {
 #ifndef DEBUG
   /* This subprocess exits with status 0 if the parent should die,
    * 1 if it should not, and something else if it fails horribly.
@@ -197,13 +200,15 @@ static void NONRETURNING docheck(void) {
 
   r= connect(sfd,(struct sockaddr*)&ssockname,sizeof(ssockname));
   if (r) {
-    if (errno == ECONNREFUSED || errno == ENOENT)
-      { syslog(LOG_WARNING,"real uservd daemon is not running: %m"); exit(0); }
+    if (errno == ECONNREFUSED || errno == ENOENT) {
+      if (needwanted != 2)
+       syslog(LOG_WARNING,"real uservd daemon is not running: %m");
+      exit(0);
+    }
     syslog(LOG_ERR,"unable to connect to uservd daemon: %m"); exit(1);
   }
 
-  r= alarm(USERVD_MYSELF_TIMEOUT);
-  if (r<0) { syslog(LOG_ERR,"set alarm for read: %m"); exit(1); }
+  alarm(USERVD_MYSELF_TIMEOUT);
   remain= sizeof(opening_mbuf); p= (unsigned char*)&opening_mbuf;
   while (remain) {
     r= read(sfd,p,remain);
@@ -228,7 +233,7 @@ static void NONRETURNING docheck(void) {
   request_mbuf.clientpid= -1;
   request_mbuf.serviceuserlen= 0;
   request_mbuf.servicelen= 0;
-  request_mbuf.lognamelen= 0;
+  request_mbuf.loginnamelen= 0;
   request_mbuf.spoofed= 0;
   request_mbuf.cwdlen= 0;
   request_mbuf.overridelen= -1;
@@ -340,16 +345,14 @@ int main(int argc, char *const *argv) {
 
   for (;;) {
     if (needcheck) {
-      assert(checkpid==-1);
-      for (;;) {
+      while (checkpid==-1) {
        checkpid= fork();
        if (checkpid!=-1) {
-         if (!checkpid) docheck();
+         if (!checkpid) docheck(needcheck);
          break;
        } else if (errno==EAGAIN) {
          syslog(LOG_ERR,"fork for check - will wait and retry: %m");
-         r= alarm(USERVD_CHECKFORK_RETRY);
-         if (r<0) { syslog(LOG_CRIT,"set alarm for retry check: %m"); exit(5); }
+         alarm(USERVD_CHECKFORK_RETRY);
          break;
        } else if (errno!=EINTR) {
          syslog(LOG_CRIT,"fork for check: %m"); exit(5);