static int run(const char * const who, const char * const file, const int upload_pipe_fd) { struct stat st; pid_t pid; if (script == NULL || *script == 0 || file == NULL || *file == 0 || lstat(file, &st) < 0 || !S_ISREG(st.st_mode)) { return -1; } pid = fork(); if (pid == (pid_t) 0) { /* Yes, there's already the cloexec flag on this fd, * but it's really important to close it. Be paranoid. */ if (close(upload_pipe_fd) < 0 || closedesc_all(1) < 0) { _exit(EXIT_FAILURE); } fillenv(who, &st); execl(script, script, file, (char *) NULL); _exit(EXIT_FAILURE); } else if (pid != (pid_t) -1) { #ifdef HAVE_WAITPID (void) waitpid(pid, NULL, 0); #else { pid_t foundpid; while ((foundpid = wait3(NULL, 0, NULL)) != (pid_t) -1 && foundpid != pid); } #endif } return 0; }
int cgihandle(response_t *resp) { /*************** BEGIN VARIABLE DECLARATIONS **************/ pid_t pid; int stdin_pipe[2]; int stdout_pipe[2]; char buf[BUF_SIZE]; int readret; char** envp; /*************** END VARIABLE DECLARATIONS **************/ logging("now in cgi handling routine\n"); /*************** BEGIN PIPE **************/ /* 0 can be read from, 1 can be written to */ if (pipe(stdin_pipe) < 0) { logging("Error piping for stdin.\n"); return -1; } if (pipe(stdout_pipe) < 0) { logging("Error piping for stdout.\n"); return -1; } /*************** END PIPE **************/ logging("start building the environment array\n"); buildEnvp(resp); logging("Start Filling envrionment array\n"); if ((envp = fillenv(resp)) == NULL) { return -1; } logging("Filling environment array successed!\n"); /*************** BEGIN FORK **************/ pid = fork(); /* not good */ if (pid < 0) { logging("Something really bad happened when forking.\n"); return -1; } /* child, setup environment, execve */ if (pid == 0) { /*************** BEGIN EXECVE ****************/ close(stdout_pipe[0]); close(stdin_pipe[1]); dup2(stdout_pipe[1], fileno(stdout)); dup2(stdin_pipe[0], fileno(stdin)); // dup2(getlogfd(), fileno(stderr)); /* pretty much no matter what, if it returns bad things happened... */ if (execve(_cgipath, ARGV, envp)) { execve_error_handler(); logging("Error executing execve syscall.\n"); exit(EXIT_FAILURE); } /*************** END EXECVE ****************/ } if (pid > 0) { logging("Parent: Heading to select() loop.\n"); close(stdout_pipe[1]); close(stdin_pipe[0]); int i = 0; for (i = 0; i < CGI_HEADER_LEN; ++i) { free(envp[i]); } if (resp->method == POST) { if (write(stdin_pipe[1], resp->postbody, resp->postlen) < 0) { logging( "Error writing to spawned CGI program.\n"); close(stdin_pipe[1]); return -1; } } close(stdin_pipe[1]); /* finished writing to spawn */ resp->cgiNode = malloc(sizeof(cgi_node)); resp->cgiNode->connfd = stdout_pipe[0]; resp->cgiNode->pid = pid; } /*************** END FORK **************/ return 0; }