/* Wrappers. Can protect from possible implementation of FastCGI API as preprocessor macros. Reduces potential for #include conflicts in the generated *.c file. Also useful to decouple prototypes as defined in fcgiapp.h and fcgi_stdio.h from these declared on the Lisp side (e.g. bool/int or short/long) -- rather hypothetical. */ int fcgi_is_cgi_wrapper() { return FCGX_IsCGI(); }
void printHeaders(const char* status) { FCGI_fprintf(FCGI_stdout, "X-FCGI: %d\n", !FCGX_IsCGI()); FCGI_fprintf(FCGI_stdout, "Content-Type: application/json\n%s\n\n", status); }
void printHeaders() { FCGI_fprintf(FCGI_stdout, "X-FCGI: %d\n", !FCGX_IsCGI()); FCGI_fputs("Content-Type: application/json\n\n", FCGI_stdout); }
foreign_t fcgi_param(term_t name, term_t value, control_t h) { fcgi_context *ctxt; char **env, **cgi_environ; char *s, *v, *sep; ctxt = pthread_getspecific(key); if ( FCGX_IsCGI() ) { cgi_environ = environ; } else { cgi_environ = ctxt->env; } if ( !PL_is_variable(name) ) { if ( !PL_get_atom_chars(name, &s) ) { return PL_type_error("atom", name); } v = FCGX_GetParam(s, cgi_environ); if ( !v ) { return FALSE; } return PL_unify_chars(value, PL_ATOM|REP_UTF8, -1, v); } switch ( PL_foreign_control(h) ) { case PL_FIRST_CALL: { env = cgi_environ; break; } case PL_REDO: { env = PL_foreign_context_address(h); break; } case PL_PRUNED: default: { return TRUE; } } for ( ; *env; env++ ) { s = strdup(*env); sep = index(s, '='); sep[0] = '\0'; if ( !PL_unify_chars(name, PL_ATOM|REP_UTF8, -1, s) ) { free(s); return FALSE; } if ( !PL_unify_chars(value, PL_ATOM|REP_UTF8, -1, sep+1) ) { free(s); return FALSE; } free(s); PL_retry_address(env+1); } return FALSE; }
foreign_t fcgi_is_cgi(void) { return FCGX_IsCGI(); }
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); }