diff --git a/vger.c b/vger.c index 11d8254..79bf09e 100644 --- a/vger.c +++ b/vger.c @@ -159,7 +159,7 @@ drop_privileges(const char *user, const char *chroot_dir, const char *cgi_dir) /* promise permissions */ if (*cgi_dir) - epledge("stdio rpath exec", NULL); + epledge("stdio rpath exec proc", NULL); else epledge("stdio rpath", NULL); #endif @@ -313,15 +313,41 @@ autoindex(const char *path) void cgi(const char *cgicmd) { - /* TODO? cgi currently return the wrong data size unless we switch from execl to popen */ + int fildes[2] = {0}; + int retcode = 0; + pid_t pid = 0; + FILE *output = NULL; - /* run cgicmd replacing current process */ - _datasiz = -1; /* bytes sent by cgi are unknown */ - execl(cgicmd, cgicmd, NULL); + if (pipe(fildes) != 0) + goto cgierr; + + if ((pid = fork()) < 0) + goto cgierr; + + if (pid > 0) { /* parent */ + close(fildes[1]); /* make sure entry is closed to get EOF */ + if ((output = fdopen(fildes[0], "r")) == NULL) + goto cgierr; + + _datasiz += print_file(output); + close(fildes[0]); + fclose(output); + waitpid(pid, &retcode, 0); + stop(EXIT_SUCCESS, "cgi ran with exit code %d", status); + + } else { /* child */ + /* set pipe output equal to stdout & stderr */ + dup2(fildes[1], STDOUT_FILENO); + close(fildes[1]); /* no longer required */ + execl(cgicmd, cgicmd, NULL); + } + + cgierr: /* if execl is ok, this will never be reached */ + close(fildes[0]); + close(fildes[1]); status(42, "error when trying run cgi"); stop(EXIT_FAILURE, "error when trying to execl %s", cgicmd); - } char *