userplex: Fixed missing-404 bug, finally.
authorFredrik Tolf <fredrik@dolda2000.com>
Sat, 29 Dec 2012 05:09:33 +0000 (06:09 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Sat, 29 Dec 2012 05:09:33 +0000 (06:09 +0100)
doc/userplex.doc
src/userplex.c

index e69cb5d..1269073 100644 (file)
@@ -41,8 +41,8 @@ argument. 'PUBDIR' defaults to `htpub` if no 'PROGRAM' was specified.
 
 If 'PUBDIR' was given (either by being specified explicitly, or
 implicitly if no 'PROGRAM' argument was given), it is checked for
-existence. If it does not exist, *userplex* should return a 404
-response to the client (but see BUGS below).
+existence. If it does not exist, *userplex* returns a 404 response to
+the client.
 
 If there exists a file named `~/.ashd/error` in the user's home
 directory, it will be opened in append mode and connected to the
@@ -126,12 +126,6 @@ its normal login procedure, and then *exec*(2) the *dirplex*(1)
 handler to serve files normally. Of course, the second line can be
 replaced by whatever other handler one might wish to use.
 
-BUGS
-----
-
-Currently, *userplex* does not, in fact, return a 404 response to the
-client if the 'PUBDIR' directory does not exist.
-
 AUTHOR
 ------
 Fredrik Tolf <fredrik@dolda2000.com>
index 357d791..c50a15c 100644 (file)
@@ -98,18 +98,35 @@ static void login(struct passwd *pwd)
     }
 }
 
-static void execchild(struct passwd *pwd)
+static void discardreq(int fromfd)
+{
+    struct hthead *req;
+    int fd;
+    
+    if((fd = recvreq(fromfd, &req)) >= 0) {
+       freehthead(req);
+       close(fd);
+    }
+}
+
+static void execchild(struct passwd *pwd, struct hthead *forreq, int reqfd)
 {
     if(!ignore)
        execl(".ashd/handler", ".ashd/handler", NULL);
     if(dirname != NULL) {
-       if(access(dirname, X_OK | R_OK))
+       if(access(dirname, X_OK | R_OK)) {
+           discardreq(0);
+           simpleerror(reqfd, 404, "Not Found", "No such resource could be found.");
            return;
+       }
     }
     execvp(childspec[0], childspec);
+    discardreq(0);
+    flog(LOG_ERR, "could not start request handler for user `%s': %s", pwd->pw_name, strerror(errno));
+    simpleerror(reqfd, 500, "User Error", "Could not start any request handler for that user.");
 }
 
-static int forkchild(char *usrnm)
+static int forkchild(char *usrnm, struct hthead *forreq, int reqfd)
 {
     struct passwd *pwd;
     pid_t pid;
@@ -131,7 +148,7 @@ static int forkchild(char *usrnm)
        close(fd[0]);
        close(fd[1]);
        login(pwd);
-       execchild(pwd);
+       execchild(pwd, forreq, reqfd);
        exit(127);
     }
     close(fd[0]);
@@ -142,19 +159,18 @@ static int forkchild(char *usrnm)
 static void serve2(struct user *usr, struct hthead *req, int fd)
 {
     if(usr->fd < 0)
-       usr->fd = forkchild(usr->name);
+       usr->fd = forkchild(usr->name, req, fd);
     if(sendreq(usr->fd, req, fd)) {
        if((errno == EPIPE) || (errno == ECONNRESET)) {
            /* Assume that the child has crashed and restart it. */
            close(usr->fd);
-           usr->fd = forkchild(usr->name);
+           usr->fd = forkchild(usr->name, req, fd);
            if(!sendreq(usr->fd, req, fd))
                return;
        }
        flog(LOG_ERR, "could not pass on request to user `%s': %s", usr->name, strerror(errno));
        close(usr->fd);
        usr->fd = -1;
-       simpleerror(fd, 500, "User Error", "The request handler for that user keeps crashing.");
     }
 }