simplify cgi function
Don't fork+execlp the script. There's no need to do so since on exec the new process will inherit our file descriptor table (and hence our stdout), so copying from its stdout to ours is just a waste of time. This allows to drop the ``proc'' pledge(2) promise and to (slightly) improve performance.
This commit is contained in:
parent
16a5ed7b30
commit
ee8569c6e6
2 changed files with 8 additions and 55 deletions
55
main.c
55
main.c
|
@ -99,8 +99,8 @@ drop_privileges(const char *user, const char *path)
|
|||
* write to stdio
|
||||
*/
|
||||
if (strlen(cgibin) > 0) {
|
||||
/* cgi need execlp() (exec) and fork() (proc) */
|
||||
epledge("stdio rpath exec proc", NULL);
|
||||
/* cgi need execlp() (exec) */
|
||||
epledge("stdio rpath exec", NULL);
|
||||
} else {
|
||||
epledge("stdio rpath", NULL);
|
||||
}
|
||||
|
@ -270,58 +270,11 @@ autoindex(const char *path)
|
|||
void
|
||||
cgi(const char *cgicmd)
|
||||
{
|
||||
|
||||
int pipedes[2] = {0};
|
||||
pid_t pid;
|
||||
|
||||
/* get a pipe to get stdout */
|
||||
if (pipe(pipedes) != 0) {
|
||||
status(42, "text/gemini");
|
||||
err(1, "pipe failed");
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
close(pipedes[0]);
|
||||
close(pipedes[1]);
|
||||
status(42, "text/gemini");
|
||||
err(1, "fork failed");
|
||||
}
|
||||
|
||||
if (pid > 0) { /* parent */
|
||||
char buf[3];
|
||||
size_t nread = 0;
|
||||
FILE *output = NULL;
|
||||
|
||||
close(pipedes[1]); /* make sure entry is closed so fread() gets EOF */
|
||||
|
||||
/* use fread/fwrite because are buffered */
|
||||
output = fdopen(pipedes[0], "r");
|
||||
if (output == NULL) {
|
||||
status(42, "text/gemini");
|
||||
err(1, "fdopen failed");
|
||||
}
|
||||
|
||||
/* read pipe output */
|
||||
while ((nread = fread(buf, 1, sizeof(buf), output)) != 0) {
|
||||
fwrite(buf, 1, nread, stdout);
|
||||
}
|
||||
close(pipedes[0]);
|
||||
fclose(output);
|
||||
|
||||
wait(NULL); /* wait for child to terminate */
|
||||
|
||||
exit(0);
|
||||
|
||||
} else if (pid == 0) { /* child */
|
||||
dup2(pipedes[1], STDOUT_FILENO); /* set pipe output equal to stdout */
|
||||
close(pipedes[1]); /* no need this file descriptor : it is now stdout */
|
||||
execlp(cgicmd, cgicmd, NULL);
|
||||
/* if execlp is ok, this will never be reached */
|
||||
status(42, "text/gemini");
|
||||
status(42, "Couldn't execute CGI script");
|
||||
errlog("error when trying to execlp %s", cgicmd);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -89,7 +89,7 @@ if ! [ $OUT = "fa065a67d1f7c973501d4a9e3ca2ea57" ] ; then echo "error" ; exit 1
|
|||
|
||||
# cgi with error
|
||||
OUT=$(printf "gemini://host.name/cgi-bin/nope\r\n" | ../vger -d var/gemini/ -c /cgi-bin | tee /dev/stderr | MD5)
|
||||
if ! [ $OUT = "2c88347cfac44450035283a8508a29cb" ] ; then echo "error" ; exit 1 ; fi
|
||||
if ! [ $OUT = "4156170c2aa8a6a8a0892ff5a61bf5f5" ] ; then echo "error" ; exit 1 ; fi
|
||||
|
||||
# remove ?.* if any
|
||||
OUT=$(printf "gemini://host.name/main.gmi?anything-here\r\n" | ../vger -d var/gemini/ | tee /dev/stderr | MD5)
|
||||
|
|
Loading…
Reference in a new issue