X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=overlord.c;h=756c5ab67c9d4379340c5fda6b6779518432c2f4;hb=7adf2c71251abac86b93cbd21914acccac295575;hp=b18102fbf6a0edfdff37fa97b3ad5be6bbda1371;hpb=f7dd4f74d0a6b3399fe694f80911657aec351ffd;p=userv.git
diff --git a/overlord.c b/overlord.c
index b18102f..756c5ab 100644
--- a/overlord.c
+++ b/overlord.c
@@ -2,11 +2,12 @@
* userv - overlord.c
* daemon main program, collects request and forks handlers
*
- * Copyright (C)1996-1997 Ian Jackson
+ * userv is copyright Ian Jackson and other contributors.
+ * See README for full authorship information.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
@@ -15,8 +16,7 @@
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with userv; if not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with userv; if not, see .
*/
#include
@@ -25,14 +25,15 @@
#include
#include
#include
+#include
#include
#include
#include
#include
-#include
#include
#include
-#include
+#include
+#include
#include
#include
@@ -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
@@ -67,7 +68,7 @@ static void checkstalepipes(void) {
if (time(&now) == -1) { syslog(LOG_ERR,"get current time: %m"); return; }
dir= opendir(".");
if (!dir) { syslog(LOG_ERR,"open directory " VARDIR ": %m"); return; }
- while ((de= readdir(dir))) {
+ while ((errno=0, de= readdir(dir))) {
if (fnmatch(PIPEPATTERN,de->d_name,FNM_PATHNAME|FNM_PERIOD)) continue;
r= lstat(de->d_name,&stab); if (r && errno==ENOENT) continue;
if (r) { syslog(LOG_ERR,"could not stat `" VARDIR "/%s': %m",de->d_name); continue; }
@@ -76,12 +77,13 @@ static void checkstalepipes(void) {
if (unlink(de->d_name) && errno!=ENOENT)
syslog(LOG_ERR,"could not remove stale pipe `%s': %m",de->d_name);
}
+ if (errno) syslog(LOG_ERR,"read directory " VARDIR ": %m");
if (closedir(dir)) syslog(LOG_ERR,"close directory " VARDIR ": %m");
}
static void sighandler_chld(int x) {
pid_t r;
- int status, es, ar;
+ int status, es;
es= errno;
for (;;) {
@@ -117,8 +119,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 +129,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 +169,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 +201,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 +234,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;
@@ -241,7 +247,8 @@ static void NONRETURNING docheck(void) {
r= write(sfd,&request_mbuf,sizeof(request_mbuf));
if (r==sizeof(request_mbuf)) {
endmagic= REQUEST_END_MAGIC;
- write(sfd,&endmagic,sizeof(endmagic));
+ r= write(sfd,&endmagic,sizeof(endmagic));
+ (void)r;
}
syslog(LOG_NOTICE,"uservd[%ld] is running",(long)overlordpid);
#endif
@@ -257,7 +264,8 @@ static void NONRETURNING startupsyscallerr(const char *what) {
}
int main(int argc, char *const *argv) {
- int mfd, sfd, nfd, csocklen, e, r, becomedaemon;
+ int mfd, sfd, nfd, e, r, becomedaemon;
+ socklen_t csocklen;
struct sigaction sigact;
struct sockaddr_un ssockname, csockname;
pid_t child, parentpid, sid;
@@ -340,16 +348,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);