-/*
+/*
* fcgiapp.c --
*
* FastCGI application library: request-at-a-time
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
-
#ifndef lint
-static const char rcsid[] = "$Id: fcgiapp.c,v 1.3 1999/02/12 00:46:41 roberts Exp $";
+static const char rcsid[] = "$Id: fcgiapp.c,v 1.12 1999/08/14 21:20:56 roberts Exp $";
#endif /* not lint */
+#include "fcgi_config.h"
+
#ifdef _WIN32
#define DLLAPI __declspec(dllexport)
#endif
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h> /* for fcntl */
+#include <math.h>
+#include <memory.h> /* for memchr() */
+#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h> /* for getpeername */
+#endif
+
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#include "fcgi_config.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <memory.h> /* for memchr() */
-#include <errno.h>
-#include <stdarg.h>
-#include <math.h>
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h> /* for getpeername */
-#endif
-#include <fcntl.h> /* for fcntl */
-
#include "fcgimisc.h"
-#include "fcgiapp.h"
#include "fcgiappmisc.h"
#include "fastcgi.h"
#include "fcgios.h"
+#include "fcgiapp.h"
/*
- * This is a workaround for one version of the HP C compiler
+ * This is a workaround for one version of the HP C compiler
* (c89 on HP-UX 9.04, also Stratus FTX), which will dump core
* if given 'long double' for varargs.
*/
#define LONG_DOUBLE long double
#endif
-static int osLibInitialized = 0;
+/*
+ * Globals
+ */
+static int libInitialized = 0;
+static int isFastCGI = -1;
+static char *webServerAddressList = NULL;
+static FCGX_Request the_request;
static void *Malloc(size_t size)
{
static char *StringCopy(char *str)
{
int strLen = strlen(str);
- char *newString = Malloc(strLen + 1);
+ char *newString = (char *)Malloc(strLen + 1);
memcpy(newString, str, strLen);
newString[strLen] = '\000';
return newString;
if(c == EOF) {
if(p == str)
return NULL;
- else
+ else
break;
- }
+ }
*p++ = c;
n--;
if(c == '\n')
*
* Results:
* The byte, or EOF (-1) if an error occurred.
- *
+ *
*----------------------------------------------------------------------
*/
int FCGX_PutChar(int c, FCGX_Stream *stream)
* Results:
* Number of bytes written (n) for normal return,
* EOF (-1) if an error occurred.
- *
+ *
*----------------------------------------------------------------------
*/
int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream)
* Results:
* number of bytes written for normal return,
* EOF (-1) if an error occurred.
- *
+ *
*----------------------------------------------------------------------
*/
int FCGX_PutS(const char *str, FCGX_Stream *stream)
* Results:
* number of bytes written for normal return,
* EOF (-1) if an error occurred.
- *
+ *
*----------------------------------------------------------------------
*/
int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...)
* Results:
* number of bytes written for normal return,
* EOF (-1) if an error occurred.
- *
+ *
*----------------------------------------------------------------------
*/
f = (char *) format;
fStop = f + strlen(f);
while (f != fStop) {
- percentPtr = memchr(f, '%', fStop - f);
+ percentPtr = (char *)memchr(f, '%', fStop - f);
if(percentPtr == NULL) percentPtr = fStop;
if(percentPtr != f) {
if(FCGX_PutStr(f, percentPtr - f, stream) < 0) goto ErrorReturn;
break;
case 's':
charPtrArg = va_arg(arg, char *);
+ if (!charPtrArg) charPtrArg = "(null)";
if(precision == -1) {
buffReqd = strlen(charPtrArg);
} else {
- p = memchr(charPtrArg, '\0', precision);
+ p = (char *)memchr(charPtrArg, '\0', precision);
buffReqd =
(p == NULL) ? precision : p - charPtrArg;
}
} else {
if(auxBuffPtr == NULL || buffReqd > auxBuffLen) {
if(auxBuffPtr != NULL) free(auxBuffPtr);
- auxBuffPtr = Malloc(buffReqd);
+ auxBuffPtr = (char *)Malloc(buffReqd);
auxBuffLen = buffReqd;
if(auxBuffPtr == NULL) goto ErrorReturn;
}
*
* Results:
* EOF (-1) if an error occurred.
- *
+ *
*----------------------------------------------------------------------
*/
int FCGX_FFlush(FCGX_Stream *stream)
*
* Results:
* EOF (-1) if an error occurred.
- *
+ *
*----------------------------------------------------------------------
*/
int FCGX_FClose(FCGX_Stream *stream)
static ParamsPtr NewParams(int length)
{
ParamsPtr result;
- result = Malloc(sizeof(Params));
- result->vec = (char **) Malloc(length * sizeof(char *));
+ result = (Params *)Malloc(sizeof(Params));
+ result->vec = (char **)Malloc(length * sizeof(char *));
result->length = length;
result->cur = result->vec;
*result->cur = NULL;
* Frees a Params structure and all the parameters it contains.
*
* Side effects:
- * paramsPtr becomes invalid.
+ * env becomes invalid.
*
*----------------------------------------------------------------------
*/
* Results:
* None.
*
- * Side effects:
+ * Side effects:
* Parameters structure updated.
*
*----------------------------------------------------------------------
- */
+ */
static void PutParam(ParamsPtr paramsPtr, char *nameValue)
{
int size;
size = paramsPtr->cur - paramsPtr->vec;
if(size >= paramsPtr->length) {
paramsPtr->length *= 2;
- paramsPtr->vec =
- realloc(paramsPtr->vec, paramsPtr->length * sizeof(char *));
+ paramsPtr->vec = (FCGX_ParamArray)realloc(paramsPtr->vec, paramsPtr->length * sizeof(char *));
paramsPtr->cur = paramsPtr->vec + size;
}
*paramsPtr->cur = NULL;
* nameLen and valueLen are now valid; read the name and value
* from stream and construct a standard environment entry.
*/
- nameValue = Malloc(nameLen + valueLen + 2);
+ nameValue = (char *)Malloc(nameLen + valueLen + 2);
if(FCGX_GetStr(nameValue, nameLen, stream) != nameLen) {
SetError(stream, FCGX_PARAMS_ERROR);
free(nameValue);
return p + u;
}
\f
-/*
- * State associated with a request
- */
-typedef struct ReqData {
- int ipcFd; /* < 0 means no connection */
- int isBeginProcessed; /* FCGI_BEGIN_REQUEST seen */
- int requestId; /* valid if isBeginProcessed */
- int keepConnection; /* don't close ipcFd at end of request */
- int role;
- int appStatus;
- int nWriters; /* number of open writers (0..2) */
- FCGX_Stream *inStream;
- FCGX_Stream *outStream;
- FCGX_Stream *errStream;
- ParamsPtr paramsPtr;
-} ReqData;
-
/*
* State associated with a stream
int paddingLen; /* reader: bytes of unread padding */
int isAnythingWritten; /* writer: data has been written to ipcFd */
int rawWrite; /* writer: write data without stream headers */
- ReqData *reqDataPtr; /* request data not specific to one stream */
+ FCGX_Request *reqDataPtr; /* request data not specific to one stream */
} FCGX_Stream_Data;
\f
/*
*/
static void WriteCloseRecords(struct FCGX_Stream *stream)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
/*
* Enter rawWrite mode so final records won't be encapsulated as
* stream data.
static int write_it_all(int fd, char *buf, int len)
{
int wrote;
-
+
while (len) {
wrote = OS_Write(fd, buf, len);
if (wrote < 0)
*/
static void EmptyBuffProc(struct FCGX_Stream *stream, int doClose)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
int cLen, eLen;
/*
* If the buffer contains stream data, fill in the header.
*/
static int ProcessManagementRecord(int type, FCGX_Stream *stream)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
ParamsPtr paramsPtr = NewParams(3);
char **pPtr;
char response[64]; /* 64 = 8 + 3*(1+1+14+1)* + padding */
*/
static int ProcessBeginRecord(int requestId, FCGX_Stream *stream)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
FCGI_BeginRequestBody body;
if(requestId == 0 || data->contentLen != sizeof(body)) {
return FCGX_PROTOCOL_ERROR;
*/
static int ProcessHeader(FCGI_Header header, FCGX_Stream *stream)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
int requestId;
if(header.version != FCGI_VERSION_1) {
return FCGX_UNSUPPORTED_VERSION;
*/
static void FillBuffProc(FCGX_Stream *stream)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
FCGI_Header header;
int headerLen = 0;
int status, count;
*----------------------------------------------------------------------
*/
static FCGX_Stream *NewStream(
- ReqData *reqDataPtr, int bufflen, int isReader, int streamType)
+ FCGX_Request *reqDataPtr, int bufflen, int isReader, int streamType)
{
/*
* XXX: It would be a lot cleaner to have a NewStream that only
* but also data->buff and data->buffStop. This has implications
* for procs that want to swap buffers, too.
*/
- FCGX_Stream *stream = Malloc(sizeof(FCGX_Stream));
- FCGX_Stream_Data *data = Malloc(sizeof(FCGX_Stream_Data));
+ FCGX_Stream *stream = (FCGX_Stream *)Malloc(sizeof(FCGX_Stream));
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)Malloc(sizeof(FCGX_Stream_Data));
data->reqDataPtr = reqDataPtr;
bufflen = AlignInt8(min(max(bufflen, 32), FCGI_MAX_LENGTH + 1));
data->bufflen = bufflen;
- data->mBuff = Malloc(bufflen);
+ data->mBuff = (unsigned char *)Malloc(bufflen);
data->buff = AlignPtr8(data->mBuff);
if(data->buff != data->mBuff) {
data->bufflen -= 8;
if(stream == NULL) {
return;
}
- data = stream->data;
+ data = (FCGX_Stream_Data *)stream->data;
data->reqDataPtr = NULL;
free(data->mBuff);
free(data);
*/
static FCGX_Stream *SetReaderType(FCGX_Stream *stream, int streamType)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
ASSERT(stream->isReader);
data->type = streamType;
data->eorStop = FALSE;
*
*----------------------------------------------------------------------
*/
-static FCGX_Stream *NewReader(ReqData *reqDataPtr, int bufflen, int streamType)
+static FCGX_Stream *NewReader(FCGX_Request *reqDataPtr, int bufflen, int streamType)
{
return NewStream(reqDataPtr, bufflen, TRUE, streamType);
}
*
*----------------------------------------------------------------------
*/
-static FCGX_Stream *NewWriter(ReqData *reqDataPtr, int bufflen, int streamType)
+static FCGX_Stream *NewWriter(FCGX_Request *reqDataPtr, int bufflen, int streamType)
{
return NewStream(reqDataPtr, bufflen, FALSE, streamType);
}
int bufflen,
int streamType)
{
- ReqData *reqDataPtr = Malloc(sizeof(ReqData));
+ FCGX_Request *reqDataPtr = (FCGX_Request *)Malloc(sizeof(FCGX_Request));
reqDataPtr->ipcFd = ipcFd;
reqDataPtr->requestId = requestId;
/*
*======================================================================
*/
-static int isCGI = -1;
-static int isFastCGI = -1;
-
/*
*----------------------------------------------------------------------
*
* Results:
* TRUE if the process is a CGI process, FALSE if FastCGI.
*
- * Side effects:
- * If this is a FastCGI process there's a chance that a connection
- * will be accepted while performing the test. If this occurs,
- * the connection is saved and used later by the FCGX_Accept logic.
- *
*----------------------------------------------------------------------
*/
int FCGX_IsCGI(void)
{
- /*
- * Already been here, no need to test again.
- */
- if(isCGI != -1) {
- return isCGI;
+ if (isFastCGI != -1) {
+ return !isFastCGI;
}
-
- if(!osLibInitialized) {
- if(OS_LibInit(NULL) == -1) {
- exit(OS_Errno);
- }
- osLibInitialized = 1;
+
+ if (!libInitialized) {
+ int rc = FCGX_Init();
+ if (rc) {
+ /* exit() isn't great, but hey */
+ exit((rc < 0) ? rc : -rc);
+ }
}
- isFastCGI = OS_IsFcgi();
- isCGI = !isFastCGI;
- return isCGI;
+ isFastCGI = OS_IsFcgi(FCGI_LISTENSOCK_FILENO);
+
+ return !isFastCGI;
}
\f
/*
*
*----------------------------------------------------------------------
*/
-static ReqData *reqDataPtr = NULL;
void FCGX_Finish(void)
{
- if(reqDataPtr != NULL && reqDataPtr->inStream != NULL) {
- /*
- * Complete the previous request.
- */
- int errStatus = FCGX_FClose(reqDataPtr->errStream);
- int outStatus = FCGX_FClose(reqDataPtr->outStream);
- int prevRequestFailed = (errStatus != 0)
- || (outStatus != 0)
- || (FCGX_GetError(reqDataPtr->inStream) != 0);
- ASSERT(reqDataPtr->nWriters == 0);
- FreeStream(&reqDataPtr->inStream);
- FreeStream(&reqDataPtr->outStream);
- FreeStream(&reqDataPtr->errStream);
- FreeParams(&reqDataPtr->paramsPtr);
- if(prevRequestFailed || !reqDataPtr->keepConnection) {
+ FCGX_Finish_r(&the_request);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FCGX_Finish_r --
+ *
+ * Finishes the current request from the HTTP server.
+ *
+ * Side effects:
+ *
+ * Finishes the request accepted by (and frees any
+ * storage allocated by) the previous call to FCGX_Accept.
+ *
+ * DO NOT retain pointers to the envp array or any strings
+ * contained in it (e.g. to the result of calling FCGX_GetParam),
+ * since these will be freed by the next call to FCGX_Finish
+ * or FCGX_Accept.
+ *
+ *----------------------------------------------------------------------
+ */
+void FCGX_Finish_r(FCGX_Request *reqDataPtr)
+{
+ if (reqDataPtr == NULL) {
+ return;
+ }
+
+ if (reqDataPtr->in) {
+ int errStatus = FCGX_FClose(reqDataPtr->err);
+ int outStatus = FCGX_FClose(reqDataPtr->out);
+
+ if (errStatus || outStatus
+ || FCGX_GetError(reqDataPtr->in)
+ || !reqDataPtr->keepConnection)
+ {
OS_IpcClose(reqDataPtr->ipcFd);
- reqDataPtr->ipcFd = -1;
}
+
+ ASSERT(reqDataPtr->nWriters == 0);
+
+ FreeStream(&reqDataPtr->in);
+ FreeStream(&reqDataPtr->out);
+ FreeStream(&reqDataPtr->err);
+
+ FreeParams(&reqDataPtr->paramsPtr);
+ }
+
+ if (!reqDataPtr->keepConnection) {
+ reqDataPtr->ipcFd = -1;
}
}
-\f
+
+int FCGX_OpenSocket(const char *path, int backlog)
+{
+ int rc = OS_CreateLocalIpcFd(path, backlog);
+ if (rc == FCGI_LISTENSOCK_FILENO && isFastCGI == 0) {
+ /* XXX probably need to call OS_LibInit() again for Win */
+ isFastCGI = 1;
+ }
+ return rc;
+}
+
+int FCGX_InitRequest(FCGX_Request *request, int sock, int flags)
+{
+ memset(request, 0, sizeof(FCGX_Request));
+
+ /* @@@ Should check that sock is open and listening */
+ request->listen_sock = sock;
+
+ /* @@@ Should validate against "known" flags */
+ request->flags = flags;
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FCGX_Init --
+ *
+ * Initilize the FCGX library. This is called by FCGX_Accept()
+ * but must be called by the user when using FCGX_Accept_r().
+ *
+ * Results:
+ * 0 for successful call.
+ *
+ *----------------------------------------------------------------------
+ */
+int FCGX_Init(void)
+{
+ char *p;
+
+ if (libInitialized) {
+ return 0;
+ }
+
+ /* If our compiler doesn't play by the ISO rules for struct layout, halt. */
+ ASSERT(sizeof(FCGI_Header) == FCGI_HEADER_LEN);
+
+ FCGX_InitRequest(&the_request, FCGI_LISTENSOCK_FILENO, 0);
+
+ if (OS_LibInit(NULL) == -1) {
+ return OS_Errno ? OS_Errno : -9997;
+ }
+
+ p = getenv("FCGI_WEB_SERVER_ADDRS");
+ webServerAddressList = p ? StringCopy(p) : NULL;
+
+ libInitialized = 1;
+ return 0;
+}
+
/*
*----------------------------------------------------------------------
*
*
*----------------------------------------------------------------------
*/
-static ReqData reqData;
-static char *webServerAddressList = NULL;
int FCGX_Accept(
FCGX_Stream **in,
FCGX_Stream **err,
FCGX_ParamArray *envp)
{
- /*
- * If our compiler doesn't play by the ISO rules for struct
- * layout, halt.
- */
- ASSERT(sizeof(FCGI_Header) == FCGI_HEADER_LEN);
+ int rc;
- if(!osLibInitialized) {
- if(OS_LibInit(NULL) == -1) {
- exit(OS_Errno);
- }
- osLibInitialized = 1;
+ if (!libInitialized) {
+ if ((rc = FCGX_Init())) {
+ return (rc < 0) ? rc : -rc;
+ }
}
- /*
- * If our compiler doesn't play by the ISO rules for struct
- * layout, halt.
- */
- ASSERT(sizeof(FCGI_Header) == FCGI_HEADER_LEN);
-
- if(reqDataPtr == NULL) {
- /*
- * Very first call, so capture FCGI_WEB_SERVER_ADDRS from
- * the initial environment, and initialize reqDataPtr
- * and parts of reqData.
- */
- char *p = getenv("FCGI_WEB_SERVER_ADDRS");
- if (p != NULL) {
- webServerAddressList = StringCopy(p);
- }
- reqDataPtr = &reqData;
- reqDataPtr->ipcFd = -1;
- reqDataPtr->inStream = NULL;
- reqDataPtr->outStream = NULL;
- reqDataPtr->errStream = NULL;
- } else {
- /*
- * Not the first call. Finish the current request, if any.
- */
- FCGX_Finish();
+ rc = FCGX_Accept_r(&the_request);
+
+ *in = the_request.in;
+ *out = the_request.out;
+ *err = the_request.err;
+ *envp = the_request.envp;
+
+ return rc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FCGX_Accept_r --
+ *
+ * Accepts a new request from the HTTP server.
+ *
+ * Results:
+ * 0 for successful call, -1 for error.
+ *
+ * Side effects:
+ *
+ * Finishes the request accepted by (and frees any
+ * storage allocated by) the previous call to FCGX_Accept.
+ * Creates input, output, and error streams and
+ * assigns them to *in, *out, and *err respectively.
+ * Creates a parameters data structure to be accessed
+ * via getenv(3) (if assigned to environ) or by FCGX_GetParam
+ * and assigns it to *envp.
+ *
+ * DO NOT retain pointers to the envp array or any strings
+ * contained in it (e.g. to the result of calling FCGX_GetParam),
+ * since these will be freed by the next call to FCGX_Finish
+ * or FCGX_Accept.
+ *
+ *----------------------------------------------------------------------
+ */
+int FCGX_Accept_r(FCGX_Request *reqDataPtr)
+{
+ if (!libInitialized) {
+ return -9998;
}
- for(;;) {
+
+ /* Finish the current request, if any. */
+ FCGX_Finish_r(reqDataPtr);
+
+ for (;;) {
/*
* If a connection isn't open, accept a new connection (blocking).
* If an OS error occurs in accepting the connection,
* return -1 to the caller, who should exit.
*/
- if(reqDataPtr->ipcFd < 0) {
- reqDataPtr->ipcFd = OS_FcgiIpcAccept(webServerAddressList);
- if(reqDataPtr->ipcFd < 0) {
- reqDataPtr = NULL;
- return (errno > 0) ? (0 - errno) : -9999;
- }
- }
+ if (reqDataPtr->ipcFd < 0) {
+ int fail_on_intr = reqDataPtr->flags & FCGI_FAIL_ACCEPT_ON_INTR;
+
+ reqDataPtr->ipcFd = OS_Accept(reqDataPtr->listen_sock, fail_on_intr, webServerAddressList);
+ if (reqDataPtr->ipcFd < 0) {
+ return (errno > 0) ? (0 - errno) : -9999;
+ }
+ }
/*
* A connection is open. Read from the connection in order to
* get the request's role and environment. If protocol or other
* errors occur, close the connection and try again.
*/
reqDataPtr->isBeginProcessed = FALSE;
- reqDataPtr->inStream = NewReader(reqDataPtr, 8192, 0);
- FillBuffProc(reqDataPtr->inStream);
+ reqDataPtr->in = NewReader(reqDataPtr, 8192, 0);
+ FillBuffProc(reqDataPtr->in);
if(!reqDataPtr->isBeginProcessed) {
goto TryAgain;
}
reqDataPtr->paramsPtr = NewParams(30);
PutParam(reqDataPtr->paramsPtr, StringCopy(roleStr));
}
- SetReaderType(reqDataPtr->inStream, FCGI_PARAMS);
- if(ReadParams(reqDataPtr->paramsPtr, reqDataPtr->inStream) >= 0) {
+ SetReaderType(reqDataPtr->in, FCGI_PARAMS);
+ if(ReadParams(reqDataPtr->paramsPtr, reqDataPtr->in) >= 0) {
/*
* Finished reading the environment. No errors occurred, so
* leave the connection-retry loop.
*/
TryAgain:
FreeParams(&reqDataPtr->paramsPtr);
- FreeStream(&reqDataPtr->inStream);
+ FreeStream(&reqDataPtr->in);
OS_Close(reqDataPtr->ipcFd);
reqDataPtr->ipcFd = -1;
} /* for (;;) */
* Build the remaining data structures representing the new
* request and return successfully to the caller.
*/
- SetReaderType(reqDataPtr->inStream, FCGI_STDIN);
- reqDataPtr->outStream = NewWriter(reqDataPtr, 8192, FCGI_STDOUT);
- reqDataPtr->errStream = NewWriter(reqDataPtr, 512, FCGI_STDERR);
+ SetReaderType(reqDataPtr->in, FCGI_STDIN);
+ reqDataPtr->out = NewWriter(reqDataPtr, 8192, FCGI_STDOUT);
+ reqDataPtr->err = NewWriter(reqDataPtr, 512, FCGI_STDERR);
reqDataPtr->nWriters = 2;
- *in = reqDataPtr->inStream;
- *out = reqDataPtr->outStream;
- *err = reqDataPtr->errStream;
- *envp = reqDataPtr->paramsPtr->vec;
+ reqDataPtr->envp = reqDataPtr->paramsPtr->vec;
return 0;
}
\f
* FCGX_CALL_SEQ_ERROR.
*
* Results:
- * 0 for a normal return, < 0 for error
+ * 0 for a normal return, < 0 for error
*
*----------------------------------------------------------------------
*/
int FCGX_StartFilterData(FCGX_Stream *stream)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
if(data->reqDataPtr->role != FCGI_FILTER
|| !stream->isReader
|| !stream->isClosed
SetError(stream, FCGX_CALL_SEQ_ERROR);
return -1;
}
- SetReaderType(reqDataPtr->inStream, FCGI_DATA);
+ SetReaderType(stream, FCGI_DATA);
return 0;
}
\f
void FCGX_SetExitStatus(int status, FCGX_Stream *stream)
{
- FCGX_Stream_Data *data = stream->data;
+ FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
data->reqDataPtr->appStatus = status;
}
+