userplex: Corrected opening of /dev/null.
[ashd.git] / src / userplex.c
index 77f79d7..357d791 100644 (file)
@@ -43,15 +43,17 @@ struct user {
 
 static int ignore = 0;
 static char *mgroup = NULL;
-static char *dirname = "htpub";
+static char *dirname = NULL;
 static char **childspec;
 static uid_t minuid = 0;
+static int usesyslog = 0;
 static struct user *users = NULL;
 
 static void login(struct passwd *pwd)
 {
     int fd;
     
+    setsid();
     if(getuid() == 0) {
        if(initgroups(pwd->pw_name, pwd->pw_gid)) {
            flog(LOG_ERR, "could not init group list for %s: %s", pwd->pw_name, strerror(errno));
@@ -73,6 +75,10 @@ static void login(struct passwd *pwd)
        flog(LOG_ERR, "could not change to home directory for %s: %s", pwd->pw_name, strerror(errno));
        exit(1);
     }
+    if(usesyslog)
+       putenv("ASHD_USESYSLOG=1");
+    else
+       unsetenv("ASHD_USESYSLOG");
     putenv(sprintf2("HOME=%s", pwd->pw_dir));
     putenv(sprintf2("SHELL=%s", pwd->pw_shell));
     putenv(sprintf2("USER=%s", pwd->pw_name));
@@ -81,12 +87,12 @@ static void login(struct passwd *pwd)
      * getting Kerberos credentials, running PAM session modules, and
      * who knows what. I'll add them along as I find them useful. */
     if(((fd = open(".ashd/output", O_WRONLY | O_APPEND)) >= 0) ||
-       ((fd = open("/dev/null", 0)) >= 0)) {
+       ((fd = open("/dev/null", O_WRONLY)) >= 0)) {
        dup2(fd, 1);
        close(fd);
     }
     if(((fd = open(".ashd/error", O_WRONLY | O_APPEND)) >= 0) ||
-       ((fd = open("/dev/null", 0)) >= 0)) {
+       ((fd = open("/dev/null", O_WRONLY)) >= 0)) {
        dup2(fd, 2);
        close(fd);
     }
@@ -107,7 +113,7 @@ static int forkchild(char *usrnm)
 {
     struct passwd *pwd;
     pid_t pid;
-    int i, fd[2];
+    int fd[2];
     
     /* XXX: There should be a way for the child to report errors (like
      * 404 when htpub doesn't exist), but for now I don't bother with
@@ -121,17 +127,15 @@ static int forkchild(char *usrnm)
     if((pid = fork()) < 0)
        return(-1);
     if(pid == 0) {
-       for(i = 3; i < FD_SETSIZE; i++) {
-           if(i != fd[0])
-               close(i);
-       }
        dup2(fd[0], 0);
        close(fd[0]);
+       close(fd[1]);
        login(pwd);
        execchild(pwd);
        exit(127);
     }
     close(fd[0]);
+    fcntl(fd[1], F_SETFD, FD_CLOEXEC);
     return(fd[1]);
 }
 
@@ -140,7 +144,7 @@ static void serve2(struct user *usr, struct hthead *req, int fd)
     if(usr->fd < 0)
        usr->fd = forkchild(usr->name);
     if(sendreq(usr->fd, req, fd)) {
-       if(errno == EPIPE) {
+       if((errno == EPIPE) || (errno == ECONNRESET)) {
            /* Assume that the child has crashed and restart it. */
            close(usr->fd);
            usr->fd = forkchild(usr->name);
@@ -230,9 +234,13 @@ out:
     free(usrnm);
 }
 
+static void sighandler(int sig)
+{
+}
+
 static void usage(FILE *out)
 {
-    fprintf(out, "usage: userplex [-hI] [-g GROUP] [-m MIN-UID] [-d PUB-DIR] [PROGRAM ARGS...]\n");
+    fprintf(out, "usage: userplex [-hIs] [-g GROUP] [-m MIN-UID] [-d PUB-DIR] [PROGRAM ARGS...]\n");
 }
 
 int main(int argc, char **argv)
@@ -242,11 +250,14 @@ int main(int argc, char **argv)
     int fd;
     struct charvbuf csbuf;
     
-    while((c = getopt(argc, argv, "+hIg:m:d:")) >= 0) {
+    while((c = getopt(argc, argv, "+hIsg:m:d:")) >= 0) {
        switch(c) {
        case 'I':
            ignore = 1;
            break;
+       case 's':
+           usesyslog = 1;
+           break;
        case 'm':
            if((minuid = atoi(optarg)) < 1) {
                fprintf(stderr, "userplex: argument to -m must be greater than 0\n");
@@ -269,8 +280,9 @@ int main(int argc, char **argv)
     }
     if(optind < argc) {
        childspec = argv + optind;
-       dirname = NULL;
     } else {
+       if(dirname == NULL)
+           dirname = "htpub";
        bufinit(csbuf);
        bufadd(csbuf, "dirplex");
        bufadd(csbuf, dirname);
@@ -278,6 +290,7 @@ int main(int argc, char **argv)
        childspec = csbuf.b;
     }
     signal(SIGCHLD, SIG_IGN);
+    signal(SIGPIPE, sighandler);
     while(1) {
        if((fd = recvreq(0, &req)) < 0) {
            if(errno != 0)