static void fcgi_pass(struct fcgi_context *fc) { char buf[FCGI_BUF_SIZE]; fd_set rset; int maxfd = 1 + max_va(fc->fd_stdout, fc->fd_stderr, MAX_VA_SENTINEL); int nready; const char *err; if (!fcgi_pass_request(fc)) return; /* now pass CGI reply back */ while (fc->fd_stdout >= 0 || fc->fd_stderr >= 0) { FD_ZERO(&rset); if (fc->fd_stdout >= 0) FD_SET(fc->fd_stdout, &rset); if (fc->fd_stderr >= 0) FD_SET(fc->fd_stderr, &rset); nready = select(maxfd, &rset, NULL, NULL, NULL); if (nready < 0) { if (errno == EAGAIN) continue; fcgi_finish(fc, "waiting for CGI reply"); return; } if (fc->fd_stdout >= 0 && FD_ISSET(fc->fd_stdout, &rset)) { err = fcgi_pass_fd(fc, &fc->fd_stdout, FCGI_stdout, buf, sizeof(buf)); if (err) { fcgi_finish(fc, err); return; } } if (fc->fd_stderr >= 0 && FD_ISSET(fc->fd_stderr, &rset)) { if (stderr_to_fastcgi) err = fcgi_pass_fd(fc, &fc->fd_stderr, FCGI_stderr, buf, sizeof(buf)); else err = fcgi_pass_raw_fd(&fc->fd_stderr, 2, buf, sizeof(buf)); if (err) { fcgi_finish(fc, err); return; } } } fc->cgi_pid = 0; fcgi_finish(fc, "reading CGI reply (no response received)"); }
static bool fcgi_pass_request(struct fcgi_context *fc) { char buf[FCGI_BUF_SIZE]; ssize_t nread; /* eat the whole request and pass it to CGI */ while ((nread = FCGI_fread(buf, 1, sizeof(buf), FCGI_stdin)) > 0) { if (write_all(fc->fd_stdin, buf, nread) <= 0) { fcgi_finish(fc, "reading the request"); return false; } } close(fc->fd_stdin); fc->fd_stdin = -1; return true; }
foreign_t fcgi_accept(control_t h) { FCGX_Request *req; fd_set fds; fcgi_context *ctxt; int status; FCGI_debug("fcgi_accept()"); if ( FCGX_IsCGI() ) { return TRUE; } ctxt = pthread_getspecific(key); if ( !ctxt ) { ctxt = malloc(sizeof(*ctxt)); memset(ctxt, 0, sizeof(*ctxt)); } if ( ctxt->req ) { fcgi_finish(); } req = malloc(sizeof(*req)); memset(req, 0, sizeof(*req)); status = FCGX_InitRequest(req, 0, 0); if ( status != FCGI_SUCCESS ) { return fcgi_raise_error(status, "FCGX_InitRequest() failed"); } FD_ZERO(&fds); FD_SET(req->listen_sock, &fds); if ( select(req->listen_sock+1, &fds, NULL, NULL, NULL) < 1 ) { return FALSE; } status = FCGX_Accept_r(req); if ( status != FCGI_SUCCESS ) { return fcgi_raise_error(status, "FCGX_Accept_r() failed"); } FCGI_debug("REMOTE_ADDR: %s, REQUEST_METHOD: %s, REQUEST_URI: %s", FCGX_GetParam("REMOTE_ADDR", req->envp), FCGX_GetParam("REQUEST_METHOD", req->envp), FCGX_GetParam("REQUEST_URI", req->envp)); if ( !ctxt ) { ctxt = malloc(sizeof(*ctxt)); memset(ctxt, 0, sizeof(*ctxt)); } ctxt->req = req; ctxt->pl_in = Suser_input; ctxt->h_in = Suser_input->handle; ctxt->fn_in = Suser_input->functions; ctxt->fcgi_in = req->in; ctxt->pl_out = Suser_output; ctxt->h_out = Suser_output->handle; ctxt->fn_out = Suser_output->functions; ctxt->fcgi_out = req->out; ctxt->pl_err = Suser_error; ctxt->h_err = Suser_error->handle; ctxt->fn_err = Suser_error->functions; ctxt->fcgi_err = req->err; ctxt->env = req->envp; pthread_setspecific(key, ctxt); Suser_input->handle = req->in; Suser_input->functions = &fcgi_functions; Suser_output->handle = req->out; Suser_output->functions = &fcgi_functions; Suser_error->handle = req->err; Suser_error->functions = &fcgi_functions; PL_retry(0); }