/* *---------------------------------------------------------------------- * * WriteCloseRecords -- * * Writes an EOF record for the stream content if necessary. * If this is the last writer to close, writes an FCGI_END_REQUEST * record. * *---------------------------------------------------------------------- */ static void WriteCloseRecords(struct FCGX_Stream *stream) { FCGX_Stream_Data *data = (FCGX_Stream_Data *) stream->data; /* * Enter rawWrite mode so final records won't be encapsulated as * stream data. */ data->rawWrite = TRUE; /* * Generate EOF for stream content if needed. */ if (!(data->type == FCGI_STDERR && stream->wrNext == data->buff && !data->isAnythingWritten)) { FCGI_Header header; header = MakeHeader(data->type, data->reqDataPtr->requestId, 0, 0); FCGX_PutStr((char *)&header, sizeof(header), stream); }; /* * Generate FCGI_END_REQUEST record if needed. */ if (data->reqDataPtr->nWriters == 1) { FCGI_EndRequestRecord endRequestRecord; endRequestRecord.header = MakeHeader(FCGI_END_REQUEST, data->reqDataPtr->requestId, sizeof(endRequestRecord.body), 0); endRequestRecord.body = MakeEndRequestBody(data->reqDataPtr->appStatus, FCGI_REQUEST_COMPLETE); FCGX_PutStr((char *)&endRequestRecord, sizeof(endRequestRecord), stream); } data->reqDataPtr->nWriters--; }
static int flush_bufs(void) { int r; r = obuf.ptr - obuf.buf; if (r) { FCGX_PutStr(obuf.buf, r, out); /*FCGI_fwrite(obuf.buf, 1, r, FCGI_stdout);*/ obuf.ptr = obuf.buf; } r = ebuf.ptr - ebuf.buf; if (r) { FCGX_PutStr(ebuf.buf, r, err); /*FCGI_fwrite(ebuf.buf, 1, r, FCGI_stderr);*/ ebuf.ptr = ebuf.buf; } /*r = FCGX_FFlush(out);*/ /*r = FCGI_fflush(FCGI_stdout);*/ /*FCGX_FFlush(err);*/ /*FCGI_fflush(FCGI_stderr);*/ return r; }
/* * send response to server */ static void sendResponse(HTTPResponse *resp) { String *resphdrs; #ifndef PROFILE FCGX_FPrintF(out,"Status: %d %s" CRLF,resp->status,resp->statusMsg); #endif resphdrs = resp_packageHeaders(resp); #ifndef PROFILE FCGX_PutS(resphdrs->text,out); #endif str_free(resphdrs); #ifndef PROFILE FCGX_PutS(CRLF, out); #endif #ifndef PROFILE /* resp->content_valid will be 0 for HEAD requests and empty responses */ if (resp->content_valid) { while (resp->content_read < resp->content_length) { //fwrite(resp->content,sizeof(char),resp->content_valid,stdout); FCGX_PutStr(resp->content, resp->content_valid, out); if (resp_getResponseContent(resp, 1) == -1) { break; } } //fwrite(resp->content,sizeof(char),resp->content_valid,stdout); FCGX_PutStr(resp->content, resp->content_valid, out); } FCGX_FFlush(out); #endif return; }
/* static int tohex(char c) { if (c>='0' && c<='9') return c-'0'; if (c>='a' && c<='f') return c-'a'+10; if (c>='A' && c<='F') return c-'A'+10; return c; } */ static int handle_ctrl(FCGX_Request *request, char *bfr, int sz) { struct netv_lua_widget *w; enum lua_cmd cmd; cmd = *bfr; bfr++; sz--; w = (struct netv_lua_widget *)bfr; bfr += sizeof(*w); sz -= sizeof(*w); if (sz < 0) { FCGX_FPrintF(request->out, "Content-Type: text/html\r\n" "Status: 500\r\n" "\r\n" "Not enough data to handle ctrl interface\r\n"); return 0; } FCGX_FPrintF(request->out, "Content-Type: text/html\r\n" "X-Handle: %d\r\n" "X-%s: x=%d&y=%d&w=%d&h=%d&c1=%d&c2=%d&t=%d\r\n" "\r\n", w->id+HANDLE_OFFSET, (cmd==LC_INPUT || cmd==LC_NEWINPUT)?"Input":"Output", w->x, w->y, w->width, w->height, w->color1, w->color2, w->type); if (cmd == LC_OUTPUT) FCGX_PutStr(bfr, sz, request->out); return 0; }
static void output(sl_vm_t* vm, char* buff, size_t len) { slash_context_t* ctx = vm->data; flush_headers(ctx); FCGX_PutStr(buff, (int)len, ctx->request.out); }
static void io_fcgi_write_headers(void *context, const char * const *headers, int num_headers) { FCGX_Request *request = (FCGX_Request *)context; for(int i = 0; i < num_headers; i++) { FCGX_FPrintF(request->out, "%s\r\n", headers[i]); } FCGX_PutStr("\r\n", 2, request->out); }
size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp) { int n; if(fp->stdio_stream) return fwrite(ptr, size, nmemb, fp->stdio_stream); else if(fp->fcgx_stream) { n = FCGX_PutStr((char *) ptr, size * nmemb, fp->fcgx_stream); return (n/size); } return EOF; }
static ssize_t fcgi_stream_write(void *handle, char *buf, size_t size) { FCGX_Stream *s; ssize_t bytes_written; s = handle; bytes_written = FCGX_PutStr(buf, size, s); return bytes_written; }
static VALUE fcgi_stream_write(VALUE self, VALUE str) { FCGX_Stream *stream; int len; rb_secure(4); Data_Get_Struct(self, FCGX_Stream, stream); str = rb_obj_as_string(str); len = FCGX_PutStr(RSTRING_PTR(str), RSTRING_LEN(str), stream); if (len == EOF) CHECK_STREAM_ERROR(stream); return INT2NUM(len); }
size_t FCGI_fwrite(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp) { int n; if(fp->stdio_stream) return fwrite(ptr, size, nmemb, fp->stdio_stream); else if(fp->fcgx_stream) { if((size * nmemb) == 0) { return 0; } ASSERT(size * nmemb < (size_t)INT_MAX); n = (size_t)FCGX_PutStr((char *) ptr, (int)(size * nmemb), fp->fcgx_stream); ASSERT(n >= 0); return ((size_t)n/size); } return (size_t)EOF; }
int FastcgiRequest::write(const char *buf, int size) { int num = FCGX_PutStr(buf, size, fcgiRequest_.out); if (-1 == num) { std::stringstream str; int error = FCGX_GetError(fcgiRequest_.out); if (error > 0) { char buffer[256]; str << "Cannot write data to fastcgi socket: " << strerror_r(error, buffer, sizeof(buffer)) << ". "; } else { str << "FastCGI error. "; } generateRequestInfo(request_.get(), str); throw std::runtime_error(str.str()); } return num; }
static int request_write_(CONTAINER_REQUEST *me, const char *buf, size_t buflen) { int r; if(!me->headers_sent) { cw_request_headers_send(&(me->headers), request_write_header_, me); FCGX_PutChar('\n', me->out); me->wbytes++; me->headers_sent = 1; } r = FCGX_PutStr(buf, buflen, me->out); if(r > 0) { me->wbytes += r; } return r; }
/* r:puts(string) */ int L_req_puts(lua_State *L) { request_t* r = NULL; const char* s = NULL; size_t l = 0; if (lua_gettop(L) >= 2) { r = luaL_checkrequest(L, 1); s = luaL_checklstring(L, 2, &l); if (r->buffering) { /* add to output buffer */ buffer_add(&r->body, s, l); } else { /* make sure headers are sent before any data */ if(!r->headers_sent) send_header(r); FCGX_PutStr(s, l, r->fcgi.out); } } return 0; }
static PyObject * fcgi_Stream_write(fcgi_Stream *self, PyObject *args) { int wrote; FCGX_Stream *s; int len; char *data; fcgi_Stream_Check(); s = *(self->s); if (!PyArg_ParseTuple(args, "s#", &data, &len)) return NULL; if (len == 0) { Py_RETURN_NONE; } Py_BEGIN_ALLOW_THREADS wrote = FCGX_PutStr(data, len, s); Py_END_ALLOW_THREADS if (wrote < len) { if (wrote < 0) { PyErr_SetString(PyExc_IOError, "Write failed"); } else { char msgbuf[256]; PyOS_snprintf(msgbuf, sizeof(msgbuf), "Write failed, wrote %d of %d bytes", wrote, len); PyErr_SetString(PyExc_IOError, msgbuf); } return NULL; } Py_RETURN_NONE; }
std::size_t fastcgi::write(char const *buffer, std::size_t size) { assert(accepted()); return static_cast<std::size_t>(FCGX_PutStr(buffer, size, req_.get()->out)); }
/* This is a hacked version of Python's fileobject.c:file_writelines(). */ static PyObject * fcgi_Stream_writelines(fcgi_Stream *self, PyObject *seq) { #define CHUNKSIZE 1000 FCGX_Stream *s; PyObject *list, *line; PyObject *it; /* iter(seq) */ PyObject *result; int i, j, index, len, nwritten, islist; fcgi_Stream_Check(); s = *(self->s); result = NULL; list = NULL; islist = PyList_Check(seq); if (islist) it = NULL; else { it = PyObject_GetIter(seq); if (it == NULL) { PyErr_SetString(PyExc_TypeError, "writelines() requires an iterable argument"); return NULL; } /* From here on, fail by going to error, to reclaim "it". */ list = PyList_New(CHUNKSIZE); if (list == NULL) goto error; } /* Strategy: slurp CHUNKSIZE lines into a private list, checking that they are all strings, then write that list without holding the interpreter lock, then come back for more. */ for (index = 0; ; index += CHUNKSIZE) { if (islist) { Py_XDECREF(list); list = PyList_GetSlice(seq, index, index+CHUNKSIZE); if (list == NULL) goto error; j = PyList_GET_SIZE(list); } else { for (j = 0; j < CHUNKSIZE; j++) { line = PyIter_Next(it); if (line == NULL) { if (PyErr_Occurred()) goto error; break; } PyList_SetItem(list, j, line); } } if (j == 0) break; /* Check that all entries are indeed strings. If not, apply the same rules as for file.write() and convert the results to strings. This is slow, but seems to be the only way since all conversion APIs could potentially execute Python code. */ for (i = 0; i < j; i++) { PyObject *v = PyList_GET_ITEM(list, i); if (!PyString_Check(v)) { const char *buffer; int len; if (PyObject_AsReadBuffer(v, (const void**)&buffer, &len) || PyObject_AsCharBuffer(v, &buffer, &len)) { PyErr_SetString(PyExc_TypeError, "writelines() argument must be a sequence of strings"); goto error; } line = PyString_FromStringAndSize(buffer, len); if (line == NULL) goto error; Py_DECREF(v); PyList_SET_ITEM(list, i, line); } } /* Since we are releasing the global lock, the following code may *not* execute Python code. */ Py_BEGIN_ALLOW_THREADS errno = 0; for (i = 0; i < j; i++) { line = PyList_GET_ITEM(list, i); len = PyString_GET_SIZE(line); nwritten = FCGX_PutStr(PyString_AS_STRING(line), len, s); if (nwritten != len) { Py_BLOCK_THREADS if (nwritten < 0) { PyErr_SetString(PyExc_IOError, "Write failed"); } else { char msgbuf[256]; PyOS_snprintf(msgbuf, sizeof(msgbuf), "Write failed, wrote %d of %d bytes", nwritten, len); PyErr_SetString(PyExc_IOError, msgbuf); } goto error; } } Py_END_ALLOW_THREADS if (j < CHUNKSIZE) break; }
int lsp::io_def_write(void* ctx,const char* s,size_t len) { REQBAG *bag = (REQBAG*)ctx; output_headers(bag); return FCGX_PutStr(s, len, bag->out); }
static int nlua_webio(FCGX_Request *request, char *arg, int id) { char *method = FCGX_GetParam("REQUEST_METHOD", request->envp); /* If it's a POST, then write to Lua's stdin */ if (!strcmp(method, "POST")) { char bfr[8192]; int bytes_read, bytes_written; int timeout = DEFAULT_WEBIO_TIMEOUT; if (*arg) { timeout = strtoul(arg, NULL, 0); if (timeout < 0 || timeout > MAX_WEBIO_TIMEOUT) timeout = DEFAULT_WEBIO_TIMEOUT; } FCGX_FPrintF(request->out, "Content-Type: text/html\r\n\r\n"); while ( (bytes_read = FCGX_GetStr(bfr, sizeof(bfr), request->in)) > 0) { char *left = bfr; /* if (enc && (!strcmp(enc, "hex") || !strcmp(enc, "hexecho"))) { char *s = bfr; int input=0, output=0; while (input < bytes_read) { s[output] = (tohex(s[input++])<<4)&0xf0; if (s[input]) s[output] |= tohex(s[input++])&0x0f; output++; } s[output] = '\0'; bytes_read /= 2; } if (!strcmp(enc, "hexecho") || !strcmp(enc, "echo")) FCGX_PutStr(bfr, bytes_read, request->out); */ while (bytes_read > 0) { bytes_written = write(nlua_states[id].in_fd, left, bytes_read); if (bytes_written < 0) { perror("Unable to write file"); return make_error(request, "Unable to write file", errno); } left += bytes_written; bytes_read -= bytes_written; } } } /* If it's not a POST, then read from stdout / stderr */ else if (!strcmp(method, "GET")) { fd_set s; struct timeval t = {DEFAULT_WEBIO_TIMEOUT, 20000}; int i; int read_fd, handle_id; int max; FD_ZERO(&s); FD_SET(nlua_states[id].out_fd, &s); max = nlua_states[id].out_fd; FD_SET(nlua_states[id].err_fd, &s); if (max < nlua_states[id].err_fd) max = nlua_states[id].err_fd; FD_SET(nlua_states[id].out_ctrl, &s); if (max < nlua_states[id].out_ctrl) max = nlua_states[id].out_ctrl; i = select(max+1, &s, NULL, NULL, &t); if (i > 0) { char bfr[16384]; if (FD_ISSET(nlua_states[id].out_fd, &s)) { read_fd = nlua_states[id].out_fd; handle_id = 1; } else if (FD_ISSET(nlua_states[id].err_fd, &s)) { read_fd = nlua_states[id].err_fd; handle_id = 2; } else { read_fd = nlua_states[id].out_ctrl; handle_id = 3; } i = read(read_fd, bfr, sizeof(bfr)); if (i == -1 && (errno == EINTR || errno == EAGAIN)) { /* Interrupted, but try again */ FCGX_FPrintF(request->out, "Content-Type: text/html\r\n" "X-Handle: %d\r\n" "\r\n", handle_id); return 0; } else if (i == -1) { /* Unrecoverable error */ kill(nlua_states[id].pid, SIGKILL); kill(nlua_states[id].pid, SIGTERM); close(nlua_states[id].out_fd); close(nlua_states[id].err_fd); close(nlua_states[id].out_ctrl); nlua_states[id].out_fd = -1; nlua_states[id].err_fd = -1; nlua_states[id].out_ctrl = -1; nlua_pool_status[id] = 0; return make_error(request, "Unable to read from handle", errno); } /* The handle control fd requires special care */ else if (handle_id == 3) return handle_ctrl(request, bfr, i); else if (i == 0) { /* Connection closed */ close(nlua_states[id].out_fd); close(nlua_states[id].err_fd); close(nlua_states[id].out_ctrl); nlua_states[id].out_fd = -1; nlua_states[id].err_fd = -1; nlua_states[id].out_ctrl = -1; nlua_pool_status[id] = 0; FCGX_FPrintF(request->out, "Content-Type: text/plain\r\n" "Status: 204\r\n" "X-Handle: %d\r\n" "\r\n", handle_id); } else { FCGX_FPrintF(request->out, "Content-Type: text/plain\r\n" "X-Handle: %d\r\n" "\r\n", handle_id); FCGX_PutStr(bfr, i, request->out); } } else if (!i || (i == -1 && (errno == EINTR || errno == EAGAIN))) { /* No data to read */ FCGX_FPrintF(request->out, "Content-Type: text/html\r\n\r\n"); } else { /* Error occurred */ kill(nlua_states[id].pid, SIGKILL); kill(nlua_states[id].pid, SIGTERM); close(nlua_states[id].out_fd); close(nlua_states[id].err_fd); close(nlua_states[id].out_ctrl); nlua_states[id].out_fd = -1; nlua_states[id].err_fd = -1; nlua_states[id].out_ctrl = -1; nlua_pool_status[id] = 0; return make_error(request, "Unable to read from stdout", errno); } } else { return make_error(request, "Unrecognized http method", 0); } return 0; }
/* *---------------------------------------------------------------------- * * FCGX_PutS -- * * Writes a character string to the output stream. * * Results: * number of bytes written for normal return, * EOF (-1) if an error occurred. * *---------------------------------------------------------------------- */ int FCGX_PutS(const char *str, FCGX_Stream * stream) { return FCGX_PutStr(str, strlen(str), stream); }
Q_LONG FastCgiDevice::writeBlock( const char *data, Q_ULONG len ) { return FCGX_PutStr( data, len, m_stream ); }
static int io_fcgi_write(void *context, const void *buffer, int size) { FCGX_Request *request = (FCGX_Request *)context; return FCGX_PutStr((const char *)buffer, size, request->out); }
size_t HttpResponseX::WriteByte(const void *buf, size_t buf_size){ if(!m_header_sended){ SendHeader(); } return FCGX_PutStr((const char *)buf, (int)buf_size, request_->GetFCGX_Request()->out ); }
int main(int argc, char **argv, char **envp) { int count; FCGX_Stream *paramsStream; fd_set readFdSet, writeFdSet; int numFDs, selectStatus; unsigned char headerBuff[8]; int headerLen, valueLen; char *equalPtr; FCGI_BeginRequestRecord beginRecord; int doBind, doStart, nServers; char appPath[MAXPATHLEN], bindPath[MAXPATHLEN]; if(ParseArgs(argc, argv, &doBind, &doStart, (char *) &bindPath, (char *) &appPath, &nServers)) { fprintf(stderr, "Usage:\n" " cgi-fcgi -f <cmdPath> , or\n" " cgi-fcgi -connect <connName> <appPath> [<nServers>] , or\n" " cgi-fcgi -start -connect <connName> <appPath> [<nServers>] , or\n" " cgi-fcgi -bind -connect <connName> ,\n" "where <connName> is either the pathname of a UNIX domain socket\n" "or (if -bind is given) a hostName:portNumber specification\n" "or (if -start is given) a :portNumber specification (uses local host).\n"); exit(1); } if(doBind) { appServerSock = OS_FcgiConnect(bindPath); } if(doStart && (!doBind || appServerSock < 0)) { FCGI_Start(bindPath, appPath, nServers); if(!doBind) { exit(0); } else { appServerSock = OS_FcgiConnect(bindPath); } } if(appServerSock < 0) { fprintf(stderr, "Could not connect to %s\n", bindPath); exit(errno); } /* * Set an arbitrary non-null FCGI RequestId */ requestId = 1; /* * XXX: Send FCGI_GET_VALUES */ /* * XXX: Receive FCGI_GET_VALUES_RESULT */ /* * Send FCGI_BEGIN_REQUEST (XXX: hack, separate write) */ beginRecord.header = MakeHeader(FCGI_BEGIN_REQUEST, requestId, sizeof(beginRecord.body), 0); beginRecord.body = MakeBeginRequestBody(FCGI_RESPONDER, TRUE); count = write(appServerSock, &beginRecord, sizeof(beginRecord)); if(count != sizeof(beginRecord)) { exit(errno); } /* * Send environment to the FCGI application server */ paramsStream = CreateWriter(appServerSock, requestId, 8192, FCGI_PARAMS); for( ; *envp != NULL; envp++) { equalPtr = strchr(*envp, '='); if(equalPtr == NULL) { exit(1000); } valueLen = strlen(equalPtr + 1); FCGIUtil_BuildNameValueHeader( equalPtr - *envp, valueLen, &headerBuff[0], &headerLen); if(FCGX_PutStr((char *) &headerBuff[0], headerLen, paramsStream) < 0 || FCGX_PutStr(*envp, equalPtr - *envp, paramsStream) < 0 || FCGX_PutStr(equalPtr + 1, valueLen, paramsStream) < 0) { exit(FCGX_GetError(paramsStream)); } } FCGX_FClose(paramsStream); FreeStream(¶msStream); /* * Perform the event loop until AppServerReadHander sees FCGI_END_REQUEST */ fromWS.stop = fromWS.next = &fromWS.buff[0]; webServerReadHandlerEOF = FALSE; FD_ZERO(&readFdSet); FD_ZERO(&writeFdSet); numFDs = max(appServerSock, STDIN_FILENO) + 1; SetFlags(appServerSock, O_NONBLOCK); for(;;) { if((fromWS.stop == fromWS.next) && !webServerReadHandlerEOF) { FD_SET(STDIN_FILENO, &readFdSet); } else { FD_CLR(STDIN_FILENO, &readFdSet); } if(fromWS.stop != fromWS.next) { FD_SET(appServerSock, &writeFdSet); } else { FD_CLR(appServerSock, &writeFdSet); } FD_SET(appServerSock, &readFdSet); selectStatus = select(numFDs, &readFdSet, &writeFdSet, NULL, NULL); if(selectStatus < 0) { exit(errno); } if(selectStatus == 0) { /* * Should not happen, no select timeout. */ continue; } if(FD_ISSET(STDIN_FILENO, &readFdSet)) { WebServerReadHandler(); } if(FD_ISSET(appServerSock, &writeFdSet)) { AppServerWriteHandler(); } if(FD_ISSET(appServerSock, &readFdSet)) { AppServerReadHandler(); } if(exitStatusSet) { exit(exitStatus); } } }