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);