Fix a silly change I made back w/ the multi-thread changes
[catagits/fcgi2.git] / libfcgi / fcgiapp.c
index 9b65b15..d1bbe31 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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.
  */
@@ -59,7 +60,13 @@ static const char rcsid[] = "$Id: fcgiapp.c,v 1.3 1999/02/12 00:46:41 roberts Ex
 #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)
 {
@@ -71,7 +78,7 @@ 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;
@@ -183,9 +190,9 @@ char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream)
         if(c == EOF) {
             if(p == str)
                 return NULL;
-            else 
+            else
                 break;
-        } 
+        }
         *p++ = c;
         n--;
         if(c == '\n')
@@ -251,7 +258,7 @@ int FCGX_HasSeenEOF(FCGX_Stream *stream) {
  *
  * Results:
  *     The byte, or EOF (-1) if an error occurred.
- * 
+ *
  *----------------------------------------------------------------------
  */
 int FCGX_PutChar(int c, FCGX_Stream *stream)
@@ -279,7 +286,7 @@ 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)
@@ -325,7 +332,7 @@ 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)
@@ -344,7 +351,7 @@ 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, ...)
@@ -368,7 +375,7 @@ int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...)
  * Results:
  *      number of bytes written for normal return,
  *      EOF (-1) if an error occurred.
- * 
+ *
  *----------------------------------------------------------------------
  */
 
@@ -411,7 +418,7 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
     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;
@@ -564,10 +571,11 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                         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;
                        }
@@ -611,7 +619,7 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                } 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;
                    }
@@ -846,7 +854,7 @@ static void CopyAndAdvance(char **destPtr, char **srcPtr, int n)
  *
  * Results:
  *      EOF (-1) if an error occurred.
- * 
+ *
  *----------------------------------------------------------------------
  */
 int FCGX_FFlush(FCGX_Stream *stream)
@@ -871,7 +879,7 @@ int FCGX_FFlush(FCGX_Stream *stream)
  *
  * Results:
  *      EOF (-1) if an error occurred.
- * 
+ *
  *----------------------------------------------------------------------
  */
 int FCGX_FClose(FCGX_Stream *stream)
@@ -985,8 +993,8 @@ typedef Params *ParamsPtr;
 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;
@@ -1001,7 +1009,7 @@ static ParamsPtr NewParams(int length)
  *     Frees a Params structure and all the parameters it contains.
  *
  * Side effects:
- *      paramsPtr becomes invalid.
+ *      env becomes invalid.
  *
  *----------------------------------------------------------------------
  */
@@ -1030,11 +1038,11 @@ static void FreeParams(ParamsPtr *paramsPtrPtr)
  * Results:
  *      None.
  *
- * Side effects:  
+ * Side effects:
  *      Parameters structure updated.
  *
  *----------------------------------------------------------------------
- */  
+ */
 static void PutParam(ParamsPtr paramsPtr, char *nameValue)
 {
     int size;
@@ -1043,8 +1051,7 @@ static void PutParam(ParamsPtr paramsPtr, char *nameValue)
     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;
@@ -1130,7 +1137,7 @@ static int ReadParams(Params *paramsPtr, FCGX_Stream *stream)
          * 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);
@@ -1249,23 +1256,6 @@ static unsigned char *AlignPtr8(unsigned char *p) {
     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
@@ -1286,7 +1276,7 @@ typedef struct FCGX_Stream_Data {
     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
 /*
@@ -1302,7 +1292,7 @@ typedef struct FCGX_Stream_Data {
  */
 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.
@@ -1339,7 +1329,7 @@ static void WriteCloseRecords(struct FCGX_Stream *stream)
 static int write_it_all(int fd, char *buf, int len)
 {
     int wrote;
-    
+
     while (len) {
         wrote = OS_Write(fd, buf, len);
         if (wrote < 0)
@@ -1362,7 +1352,7 @@ static int write_it_all(int fd, char *buf, int len)
  */
 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.
@@ -1430,7 +1420,7 @@ static void EmptyBuffProc(struct FCGX_Stream *stream, int doClose)
  */
 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 */
@@ -1503,7 +1493,7 @@ static int ProcessManagementRecord(int type, FCGX_Stream *stream)
  */
 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;
@@ -1564,7 +1554,7 @@ static int ProcessBeginRecord(int requestId, FCGX_Stream *stream)
  */
 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;
@@ -1600,7 +1590,7 @@ static int ProcessHeader(FCGI_Header header, FCGX_Stream *stream)
  */
 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;
@@ -1729,7 +1719,7 @@ static void FillBuffProc(FCGX_Stream *stream)
  *----------------------------------------------------------------------
  */
 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
@@ -1739,12 +1729,12 @@ static FCGX_Stream *NewStream(
      * 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;
@@ -1802,7 +1792,7 @@ void FreeStream(FCGX_Stream **streamPtr)
     if(stream == NULL) {
         return;
     }
-    data = stream->data;
+    data = (FCGX_Stream_Data *)stream->data;
     data->reqDataPtr = NULL;
     free(data->mBuff);
     free(data);
@@ -1821,7 +1811,7 @@ void FreeStream(FCGX_Stream **streamPtr)
  */
 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;
@@ -1843,7 +1833,7 @@ static FCGX_Stream *SetReaderType(FCGX_Stream *stream, int streamType)
  *
  *----------------------------------------------------------------------
  */
-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);
 }
@@ -1860,7 +1850,7 @@ static FCGX_Stream *NewReader(ReqData *reqDataPtr, int bufflen, int 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);
 }
@@ -1884,7 +1874,7 @@ FCGX_Stream *CreateWriter(
         int bufflen,
         int streamType)
 {
-    ReqData *reqDataPtr = Malloc(sizeof(ReqData));
+    FCGX_Request *reqDataPtr = (FCGX_Request *)Malloc(sizeof(FCGX_Request));
     reqDataPtr->ipcFd = ipcFd;
     reqDataPtr->requestId = requestId;
     /*
@@ -1900,9 +1890,6 @@ FCGX_Stream *CreateWriter(
  *======================================================================
  */
 
-static int isCGI = -1;
-static int isFastCGI = -1;
-
 /*
  *----------------------------------------------------------------------
  *
@@ -1916,32 +1903,25 @@ 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
 /*
@@ -1963,31 +1943,122 @@ int FCGX_IsCGI(void)
  *
  *----------------------------------------------------------------------
  */
-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;
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -2015,8 +2086,6 @@ void FCGX_Finish(void)
  *
  *----------------------------------------------------------------------
  */
-static ReqData reqData;
-static char *webServerAddressList = NULL;
 
 int FCGX_Accept(
         FCGX_Stream **in,
@@ -2024,67 +2093,82 @@ int FCGX_Accept(
         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;
         }
@@ -2106,8 +2190,8 @@ int FCGX_Accept(
             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.
@@ -2119,7 +2203,7 @@ int FCGX_Accept(
          */
       TryAgain:
         FreeParams(&reqDataPtr->paramsPtr);
-        FreeStream(&reqDataPtr->inStream);
+        FreeStream(&reqDataPtr->in);
         OS_Close(reqDataPtr->ipcFd);
         reqDataPtr->ipcFd = -1;
     } /* for (;;) */
@@ -2127,14 +2211,11 @@ int FCGX_Accept(
      * 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
@@ -2151,14 +2232,14 @@ int FCGX_Accept(
  *      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
@@ -2166,7 +2247,7 @@ int FCGX_StartFilterData(FCGX_Stream *stream)
         SetError(stream, FCGX_CALL_SEQ_ERROR);
         return -1;
     }
-    SetReaderType(reqDataPtr->inStream, FCGI_DATA);
+    SetReaderType(stream, FCGI_DATA);
     return 0;
 }
 \f
@@ -2186,6 +2267,7 @@ int FCGX_StartFilterData(FCGX_Stream *stream)
 
 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;
 }
+