bump version to 0.82 and prepare for release
[catagits/fcgi2.git] / libfcgi / fcgiapp.c
index b9f2e04..7ddecae 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * fcgiapp.c --
  *
  *     FastCGI application library: request-at-a-time
@@ -6,50 +6,54 @@
  *
  * Copyright (c) 1996 Open Market, Inc.
  *
- * See the file "LICENSE.TERMS" for information on usage and redistribution
+ * See the file "LICENSE" for information on usage and redistribution
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  *
  */
-
 #ifndef lint
-static const char rcsid[] = "$Id: fcgiapp.c,v 1.1 1997/09/16 15:36:33 stanleyg Exp $";
+static const char rcsid[] = "$Id: fcgiapp.c,v 1.35 2003/06/22 00:16:43 robs Exp $";
 #endif /* not lint */
 
-#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>
+
+#include "fcgi_config.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 */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifdef _WIN32
+#define DLLAPI  __declspec(dllexport)
 #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 +63,18 @@ static const char rcsid[] = "$Id: fcgiapp.c,v 1.1 1997/09/16 15:36:33 stanleyg E
 #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;
+
+void FCGX_ShutdownPending(void)
+{
+    OS_ShutdownPending();
+}
 
 static void *Malloc(size_t size)
 {
@@ -71,13 +86,13 @@ 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;
 }
 
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -92,18 +107,24 @@ static char *StringCopy(char *str)
  */
 int FCGX_GetChar(FCGX_Stream *stream)
 {
-    if(stream->rdNext != stream->stop)
-        return *stream->rdNext++;
-    if(stream->isClosed || !stream->isReader)
+    if (stream->isClosed || ! stream->isReader)
         return EOF;
+
+    if (stream->rdNext != stream->stop)
+        return *stream->rdNext++;
+
     stream->fillBuffProc(stream);
+    if (stream->isClosed)
+        return EOF;
+
     stream->stopUnget = stream->rdNext;
-    if(stream->rdNext != stream->stop)
+    if (stream->rdNext != stream->stop)
         return *stream->rdNext++;
+
     ASSERT(stream->isClosed); /* bug in fillBufProc if not */
     return EOF;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -123,7 +144,7 @@ int FCGX_GetStr(char *str, int n, FCGX_Stream *stream)
 {
     int m, bytesMoved;
 
-    if(n <= 0) {
+    if (stream->isClosed || ! stream->isReader || n <= 0) {
         return 0;
     }
     /*
@@ -148,14 +169,17 @@ int FCGX_GetStr(char *str, int n, FCGX_Stream *stream)
             if(bytesMoved == n)
                 return bytesMoved;
             str += m;
-       }
+        }
         if(stream->isClosed || !stream->isReader)
             return bytesMoved;
         stream->fillBuffProc(stream);
+        if (stream->isClosed)
+            return bytesMoved;
+
         stream->stopUnget = stream->rdNext;
     }
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -177,16 +201,17 @@ char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream)
 {
     int c;
     char *p = str;
+
     n--;
     while (n > 0) {
         c = FCGX_GetChar(stream);
         if(c == EOF) {
             if(p == str)
                 return NULL;
-            else 
+            else
                 break;
-        } 
-        *p++ = c;
+        }
+        *p++ = (char) c;
         n--;
         if(c == '\n')
             break;
@@ -194,7 +219,7 @@ char *FCGX_GetLine(char *str, int n, FCGX_Stream *stream)
     *p = '\0';
     return str;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -216,7 +241,7 @@ int FCGX_UnGetChar(int c, FCGX_Stream *stream) {
             || stream->rdNext == stream->stopUnget)
         return EOF;
     --(stream->rdNext);
-    *stream->rdNext = c;
+    *stream->rdNext = (unsigned char) c;
     return c;
 }
 
@@ -241,7 +266,7 @@ int FCGX_UnGetChar(int c, FCGX_Stream *stream) {
 int FCGX_HasSeenEOF(FCGX_Stream *stream) {
     return (stream->isClosed) ? EOF : 0;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -251,22 +276,22 @@ int FCGX_HasSeenEOF(FCGX_Stream *stream) {
  *
  * Results:
  *     The byte, or EOF (-1) if an error occurred.
- * 
+ *
  *----------------------------------------------------------------------
  */
 int FCGX_PutChar(int c, FCGX_Stream *stream)
 {
     if(stream->wrNext != stream->stop)
-        return (*stream->wrNext++ = c);
+        return (*stream->wrNext++ = (unsigned char) c);
     if(stream->isClosed || stream->isReader)
         return EOF;
     stream->emptyBuffProc(stream, FALSE);
     if(stream->wrNext != stream->stop)
-        return (*stream->wrNext++ = c);
+        return (*stream->wrNext++ = (unsigned char) c);
     ASSERT(stream->isClosed); /* bug in emptyBuffProc if not */
     return EOF;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -279,7 +304,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)
@@ -314,7 +339,7 @@ int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream)
         stream->emptyBuffProc(stream, FALSE);
     }
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -325,14 +350,14 @@ 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)
 {
     return FCGX_PutStr(str, strlen(str), stream);
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -344,7 +369,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 +393,7 @@ int FCGX_FPrintF(FCGX_Stream *stream, const char *format, ...)
  * Results:
  *      number of bytes written for normal return,
  *      EOF (-1) if an error occurred.
- * 
+ *
  *----------------------------------------------------------------------
  */
 
@@ -386,8 +411,8 @@ static void CopyAndAdvance(char **destPtr, char **srcPtr, int n);
 int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
 {
     char *f, *fStop, *percentPtr, *p, *fmtBuffPtr, *buffPtr;
-    int op, performedOp, sizeModifier, buffCount, buffLen, specifierLength;
-    int fastPath, n, auxBuffLen, buffReqd, minWidth, precision, exp;
+    int op, performedOp, sizeModifier, buffCount = 0, buffLen, specifierLength;
+    int fastPath, n, auxBuffLen = 0, buffReqd, minWidth, precision, exp;
     char *auxBuffPtr = NULL;
     int streamCount = 0;
     char fmtBuff[FMT_BUFFLEN];
@@ -399,22 +424,23 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
     unsigned unsignedArg;
     unsigned long uLongArg;
     unsigned short uShortArg;
-    char *charPtrArg;
+    char *charPtrArg = NULL;
     void *voidPtrArg;
     int *intPtrArg;
     long *longPtrArg;
     short *shortPtrArg;
-    double doubleArg;
-    LONG_DOUBLE lDoubleArg;
+    double doubleArg = 0.0;
+    LONG_DOUBLE lDoubleArg = 0.0L;
 
     fmtBuff[0] = '%';
     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;
+            if(FCGX_PutStr(f, percentPtr - f, stream) < 0)
+                goto ErrorReturn;
             streamCount += percentPtr - f;
             f = percentPtr;
             if(f == fStop) break;
@@ -443,14 +469,14 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                     case 'h':
                         sizeModifier = op;
                         op = *(percentPtr + 2);
-                        fmtBuff[1] = sizeModifier;
-                        fmtBuff[2] = op;
+                        fmtBuff[1] = (char) sizeModifier;
+                        fmtBuff[2] = (char) op;
                         fmtBuff[3] = '\0';
                         specifierLength = 3;
                         break;
                    default:
                         sizeModifier = ' ';
-                        fmtBuff[1] = op;
+                        fmtBuff[1] = (char) op;
                         fmtBuff[2] = '\0';
                         specifierLength = 2;
                         break;
@@ -470,7 +496,8 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                  * Scan flags
                  */
                 n = strspn(p, "-0+ #");
-                if(n > 5) goto ErrorReturn;
+                if(n > 5)
+                    goto ErrorReturn;
                 CopyAndAdvance(&fmtBuffPtr, &p, n);
                 /*
                  * Scan minimum field width
@@ -479,7 +506,8 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                 if(n == 0) {
                     if(*p == '*') {
                         minWidth = va_arg(arg, int);
-                        if(abs(minWidth) > 999999) goto ErrorReturn;
+                        if(abs(minWidth) > 999999)
+                            goto ErrorReturn;
                        /*
                         * The following use of strlen rather than the
                         * value returned from sprintf is because SUNOS4
@@ -507,7 +535,8 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                         if(*p == '*') {
                             precision = va_arg(arg, int);
                             if(precision < 0) precision = 0;
-                            if(precision > 999999) goto ErrorReturn;
+                            if(precision > 999999)
+                                goto ErrorReturn;
                        /*
                         * The following use of strlen rather than the
                         * value returned from sprintf is because SUNOS4
@@ -564,10 +593,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;
                        }
@@ -576,11 +606,13 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                         switch(sizeModifier) {
                             case ' ':
                                 doubleArg = va_arg(arg, double);
-                               frexp(doubleArg, &exp);
+                                               frexp(doubleArg, &exp);
                                 break;
                             case 'L':
                                 lDoubleArg = va_arg(arg, LONG_DOUBLE);
-                               frexp(lDoubleArg, &exp);
+                                /* XXX Need to check for the presence of 
+                                 * frexpl() and use it if available */
+                                               frexp((double) lDoubleArg, &exp);
                                 break;
                             default:
                                 goto ErrorReturn;
@@ -611,9 +643,10 @@ 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;
+                        if(auxBuffPtr == NULL)
+                            goto ErrorReturn;
                    }
                     buffPtr = auxBuffPtr;
                    buffLen = auxBuffLen;
@@ -648,8 +681,8 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                             buffCount = strlen(buffPtr);
                             break;
                        case 'h':
-                            shortArg = va_arg(arg, short);
-                           sprintf(buffPtr, fmtBuff, shortArg);
+                            shortArg = (short) va_arg(arg, int);
+                            sprintf(buffPtr, fmtBuff, shortArg);
                             buffCount = strlen(buffPtr);
                             break;
                        default:
@@ -672,8 +705,8 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                             buffCount = strlen(buffPtr);
                             break;
                         case 'h':
-                            uShortArg = va_arg(arg, unsigned short);
-                           sprintf(buffPtr, fmtBuff, uShortArg);
+                            uShortArg = (unsigned short) va_arg(arg, int);
+                            sprintf(buffPtr, fmtBuff, uShortArg);
                             buffCount = strlen(buffPtr);
                             break;
                         default:
@@ -721,7 +754,8 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                     }
                     break;
                 case 'p':
-                    if(sizeModifier != ' ') goto ErrorReturn;
+                    if(sizeModifier != ' ')
+                        goto ErrorReturn;
                     voidPtrArg = va_arg(arg, void *);
                    sprintf(buffPtr, fmtBuff, voidPtrArg);
                     buffCount = strlen(buffPtr);
@@ -737,8 +771,8 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                             *longPtrArg = streamCount;
                             break;
                         case 'h':
-                            shortPtrArg = va_arg(arg, short *);
-                            *shortPtrArg = streamCount;
+                            shortPtrArg = (short *) va_arg(arg, short *);
+                            *shortPtrArg = (short) streamCount;
                             break;
                        default:
                             goto ErrorReturn;
@@ -795,7 +829,8 @@ int FCGX_VFPrintF(FCGX_Stream *stream, const char *format, va_list arg)
                     break;
             } /* switch(op) */
             if(performedOp) break;
-            if(!fastPath) goto ErrorReturn;
+            if(!fastPath)
+                goto ErrorReturn;
             fastPath = FALSE;
         } /* for (;;) */
         ASSERT(buffCount < buffLen);
@@ -830,7 +865,7 @@ static void CopyAndAdvance(char **destPtr, char **srcPtr, int n)
     *destPtr = dest;
     *srcPtr = src;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -846,7 +881,7 @@ static void CopyAndAdvance(char **destPtr, char **srcPtr, int n)
  *
  * Results:
  *      EOF (-1) if an error occurred.
- * 
+ *
  *----------------------------------------------------------------------
  */
 int FCGX_FFlush(FCGX_Stream *stream)
@@ -856,7 +891,7 @@ int FCGX_FFlush(FCGX_Stream *stream)
     stream->emptyBuffProc(stream, FALSE);
     return (stream->isClosed) ? -1 : 0;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -871,11 +906,13 @@ int FCGX_FFlush(FCGX_Stream *stream)
  *
  * Results:
  *      EOF (-1) if an error occurred.
- * 
+ *
  *----------------------------------------------------------------------
  */
 int FCGX_FClose(FCGX_Stream *stream)
 {
+    if (stream == NULL) return 0;
+
     if(!stream->wasFCloseCalled) {
         if(!stream->isReader) {
             stream->emptyBuffProc(stream, TRUE);
@@ -890,7 +927,7 @@ int FCGX_FClose(FCGX_Stream *stream)
     }
     return (stream->FCGI_errno == 0) ? 0 : EOF;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -909,8 +946,9 @@ static void SetError(FCGX_Stream *stream, int FCGI_errno)
      */
     if(stream->FCGI_errno == 0) {
         stream->FCGI_errno = FCGI_errno;
-        stream->isClosed = TRUE;
     }
+  
+    stream->isClosed = TRUE;
 }
 
 /*
@@ -950,7 +988,7 @@ void FCGX_ClearError(FCGX_Stream *stream) {
      * of the stream that are now all lumped under isClosed.
      */
 }
-\f
+
 /*
  *======================================================================
  * Parameters
@@ -969,7 +1007,7 @@ typedef struct Params {
     char **cur;                    /* current item in vec; *cur == NULL */
 } Params;
 typedef Params *ParamsPtr;
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -985,14 +1023,14 @@ 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;
     return result;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1001,7 +1039,7 @@ static ParamsPtr NewParams(int length)
  *     Frees a Params structure and all the parameters it contains.
  *
  * Side effects:
- *      paramsPtr becomes invalid.
+ *      env becomes invalid.
  *
  *----------------------------------------------------------------------
  */
@@ -1019,7 +1057,7 @@ static void FreeParams(ParamsPtr *paramsPtrPtr)
     free(paramsPtr);
     *paramsPtrPtr = NULL;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1030,11 +1068,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,13 +1081,12 @@ 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;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1067,16 +1104,19 @@ char *FCGX_GetParam(const char *name, FCGX_ParamArray envp)
 {
     int len;
     char **p;
+
+       if (name == NULL || envp == NULL) return NULL;
+
     len = strlen(name);
-    if(len == 0) return NULL;
-    for (p = envp; *p != NULL; p++) {
+
+    for (p = envp; *p; ++p) {
         if((strncmp(name, *p, len) == 0) && ((*p)[len] == '=')) {
             return *p+len+1;
         }
     }
     return NULL;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1084,7 +1124,7 @@ char *FCGX_GetParam(const char *name, FCGX_ParamArray envp)
  *
  *----------------------------------------------------------------------
  */
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1130,7 +1170,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);
@@ -1148,7 +1188,7 @@ static int ReadParams(Params *paramsPtr, FCGX_Stream *stream)
     }
     return 0;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1168,16 +1208,16 @@ static FCGI_Header MakeHeader(
     ASSERT(contentLength >= 0 && contentLength <= FCGI_MAX_LENGTH);
     ASSERT(paddingLength >= 0 && paddingLength <= 0xff);
     header.version = FCGI_VERSION_1;
-    header.type             =  type;
-    header.requestIdB1      = (requestId      >> 8) & 0xff;
-    header.requestIdB0      = (requestId          ) & 0xff;
-    header.contentLengthB1  = (contentLength  >> 8) & 0xff;
-    header.contentLengthB0  = (contentLength      ) & 0xff;
-    header.paddingLength    =  paddingLength;
+    header.type             = (unsigned char) type;
+    header.requestIdB1      = (unsigned char) ((requestId     >> 8) & 0xff);
+    header.requestIdB0      = (unsigned char) ((requestId         ) & 0xff);
+    header.contentLengthB1  = (unsigned char) ((contentLength >> 8) & 0xff);
+    header.contentLengthB0  = (unsigned char) ((contentLength     ) & 0xff);
+    header.paddingLength    = (unsigned char) paddingLength;
     header.reserved         =  0;
     return header;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1192,15 +1232,15 @@ static FCGI_EndRequestBody MakeEndRequestBody(
         int protocolStatus)
 {
     FCGI_EndRequestBody body;
-    body.appStatusB3 = (appStatus >> 24) & 0xff;
-    body.appStatusB2 = (appStatus >> 16) & 0xff;
-    body.appStatusB1 = (appStatus >>  8) & 0xff;
-    body.appStatusB0 = (appStatus      ) & 0xff;
-    body.protocolStatus = protocolStatus;
+    body.appStatusB3    = (unsigned char) ((appStatus >> 24) & 0xff);
+    body.appStatusB2    = (unsigned char) ((appStatus >> 16) & 0xff);
+    body.appStatusB1    = (unsigned char) ((appStatus >>  8) & 0xff);
+    body.appStatusB0    = (unsigned char) ((appStatus      ) & 0xff);
+    body.protocolStatus = (unsigned char) protocolStatus;
     memset(body.reserved, 0, sizeof(body.reserved));
     return body;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1214,11 +1254,11 @@ static FCGI_UnknownTypeBody MakeUnknownTypeBody(
         int type)
 {
     FCGI_UnknownTypeBody body;
-    body.type = type;
+    body.type = (unsigned char) type;
     memset(body.reserved, 0, sizeof(body.reserved));
     return body;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1248,23 +1288,6 @@ static unsigned char *AlignPtr8(unsigned char *p) {
     u = ((u + 7) & (ULONG_MAX - 7)) - u;
     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;
 
 
 /*
@@ -1286,9 +1309,9 @@ 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 +1325,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.
@@ -1333,7 +1356,23 @@ static void WriteCloseRecords(struct FCGX_Stream *stream)
     }
     data->reqDataPtr->nWriters--;
 }
-\f
+
+
+
+static int write_it_all(int fd, char *buf, int len)
+{
+    int wrote;
+
+    while (len) {
+        wrote = OS_Write(fd, buf, len);
+        if (wrote < 0)
+            return wrote;
+        len -= wrote;
+        buf += wrote;
+    }
+    return len;
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1346,7 +1385,7 @@ static void WriteCloseRecords(struct FCGX_Stream *stream)
  */
 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.
@@ -1374,10 +1413,9 @@ static void EmptyBuffProc(struct FCGX_Stream *stream, int doClose)
     if(doClose) {
         WriteCloseRecords(stream);
     };
-    if(stream->wrNext != data->buff) {
+    if (stream->wrNext != data->buff) {
         data->isAnythingWritten = TRUE;
-        if(OS_Write(data->reqDataPtr->ipcFd, (char *)data->buff,
-                stream->wrNext - data->buff) < 0) {
+        if (write_it_all(data->reqDataPtr->ipcFd, (char *)data->buff, stream->wrNext - data->buff) < 0) {
             SetError(stream, OS_Errno);
             return;
         }
@@ -1390,7 +1428,7 @@ static void EmptyBuffProc(struct FCGX_Stream *stream, int doClose)
         stream->wrNext += sizeof(FCGI_Header);
     }
 }
-\f
+
 /*
  * Return codes for Process* functions
  */
@@ -1415,14 +1453,15 @@ static void EmptyBuffProc(struct FCGX_Stream *stream, int doClose)
  */
 static int ProcessManagementRecord(int type, FCGX_Stream *stream)
 {
-    FCGX_Stream_Data *data = stream->data;
-    ParamsPtr paramsPtr = NewParams(3);
+    FCGX_Stream_Data *data = (FCGX_Stream_Data *)stream->data;
+    ParamsPtr paramsPtr;
     char **pPtr;
     char response[64]; /* 64 = 8 + 3*(1+1+14+1)* + padding */
     char *responseP = &response[FCGI_HEADER_LEN];
-    char *name, value;
+    char *name, value = '\0';
     int len, paddedLen;
     if(type == FCGI_GET_VALUES) {
+        paramsPtr = NewParams(3);
         ReadParams(paramsPtr, stream);
         if((FCGX_GetError(stream) != 0) || (data->contentLen != 0)) {
             FreeParams(&paramsPtr);
@@ -1460,14 +1499,14 @@ static int ProcessManagementRecord(int type, FCGX_Stream *stream)
         ((FCGI_UnknownTypeRecord *) response)->body
             = MakeUnknownTypeBody(type);
     }
-    if(OS_Write(data->reqDataPtr->ipcFd,
-            response, FCGI_HEADER_LEN + paddedLen) < 0) {
+    if (write_it_all(data->reqDataPtr->ipcFd, response, FCGI_HEADER_LEN + paddedLen) < 0) {
         SetError(stream, OS_Errno);
         return -1;
     }
+
     return MGMT_RECORD;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1488,7 +1527,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;
@@ -1504,11 +1543,11 @@ static int ProcessBeginRecord(int requestId, FCGX_Stream *stream)
                 requestId, sizeof(endRequestRecord.body), 0);
         endRequestRecord.body
                 = MakeEndRequestBody(0, FCGI_CANT_MPX_CONN);
-        if(OS_Write(data->reqDataPtr->ipcFd, (char *) &endRequestRecord,
-                sizeof(endRequestRecord)) < 0) {
+        if (write_it_all(data->reqDataPtr->ipcFd, (char *)&endRequestRecord, sizeof(endRequestRecord)) < 0) {
             SetError(stream, OS_Errno);
             return -1;
         }
+
         return SKIP;
     }
     /*
@@ -1524,7 +1563,7 @@ static int ProcessBeginRecord(int requestId, FCGX_Stream *stream)
     data->reqDataPtr->isBeginProcessed = TRUE;
     return BEGIN_RECORD;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1549,7 +1588,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;
@@ -1573,7 +1612,7 @@ static int ProcessHeader(FCGI_Header header, FCGX_Stream *stream)
     }
     return STREAM_RECORD;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1585,7 +1624,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;
@@ -1702,7 +1741,7 @@ static void FillBuffProc(FCGX_Stream *stream)
        }
     }
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1714,7 +1753,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
@@ -1724,12 +1763,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;
@@ -1769,32 +1808,32 @@ static FCGX_Stream *NewStream(
     }
     return stream;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
- * FreeStream --
+ * FCGX_FreeStream --
  *
  *      Frees all storage allocated when *streamPtr was created,
  *      and nulls out *streamPtr.
  *
  *----------------------------------------------------------------------
  */
-void FreeStream(FCGX_Stream **streamPtr)
+void FCGX_FreeStream(FCGX_Stream **streamPtr)
 {
     FCGX_Stream *stream = *streamPtr;
     FCGX_Stream_Data *data;
     if(stream == NULL) {
         return;
     }
-    data = stream->data;
+    data = (FCGX_Stream_Data *)stream->data;
     data->reqDataPtr = NULL;
     free(data->mBuff);
     free(data);
     free(stream);
     *streamPtr = NULL;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1806,7 +1845,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;
@@ -1817,7 +1856,7 @@ static FCGX_Stream *SetReaderType(FCGX_Stream *stream, int streamType)
     stream->isClosed = FALSE;
     return stream;
 }
-\f
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1828,12 +1867,11 @@ 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);
 }
 
-
 /*
  *----------------------------------------------------------------------
  *
@@ -1845,16 +1883,15 @@ 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);
 }
 
-
 /*
  *----------------------------------------------------------------------
  *
- * CreateWriter --
+ * FCGX_CreateWriter --
  *
  *      Creates a stream to write streamType FastCGI records, using
  *      the given ipcFd and request Id.  This function is provided
@@ -1863,13 +1900,13 @@ static FCGX_Stream *NewWriter(ReqData *reqDataPtr, int bufflen, int streamType)
  *
  *----------------------------------------------------------------------
  */
-FCGX_Stream *CreateWriter(
+FCGX_Stream *FCGX_CreateWriter(
         int ipcFd,
         int requestId,
         int bufflen,
         int streamType)
 {
-    ReqData *reqDataPtr = Malloc(sizeof(ReqData));
+    FCGX_Request *reqDataPtr = (FCGX_Request *)Malloc(sizeof(FCGX_Request));
     reqDataPtr->ipcFd = ipcFd;
     reqDataPtr->requestId = requestId;
     /*
@@ -1878,16 +1915,13 @@ FCGX_Stream *CreateWriter(
     reqDataPtr->nWriters = 2;
     return NewWriter(reqDataPtr, bufflen, streamType);
 }
-\f
+
 /*
  *======================================================================
  * Control
  *======================================================================
  */
 
-static int isCGI = -1;
-static int isFastCGI = -1;
-
 /*
  *----------------------------------------------------------------------
  *
@@ -1901,34 +1935,27 @@ 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
+
 /*
  *----------------------------------------------------------------------
  *
@@ -1948,31 +1975,139 @@ 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) {
-            OS_IpcClose(reqDataPtr->ipcFd);
-            reqDataPtr->ipcFd = -1;
+    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)
+{
+    int close;
+
+    if (reqDataPtr == NULL) {
+        return;
+    }
+
+    close = !reqDataPtr->keepConnection;
+
+    /* This should probably use a 'status' member instead of 'in' */
+    if (reqDataPtr->in) {
+        close |= FCGX_FClose(reqDataPtr->err);
+        close |= FCGX_FClose(reqDataPtr->out);
+        close |= FCGX_GetError(reqDataPtr->in);
+
+        /* discard any remaining data in input stream on persistent connections */
+        if (!close && !reqDataPtr->in->isClosed && reqDataPtr->keepConnection) {
+            FCGX_Stream *stream = reqDataPtr->in;
+
+            do {
+                stream->rdNext = stream->stop;
+                stream->fillBuffProc(stream);
+            } while (!stream->isClosed);
+
+            close |= FCGX_GetError(stream);
         }
     }
+
+    FCGX_Free(reqDataPtr, close);
+}
+
+void FCGX_Free(FCGX_Request * request, int close)
+{
+    if (request == NULL) 
+        return;
+
+    FCGX_FreeStream(&request->in);
+    FCGX_FreeStream(&request->out);
+    FCGX_FreeStream(&request->err);
+    FreeParams(&request->paramsPtr);
+
+    if (close) {
+        OS_IpcClose(request->ipcFd, ! request->detached);
+        request->ipcFd = -1;
+        request->detached = 0;
+    }
+}
+
+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;
+
+    request->ipcFd = -1;
+
+    return 0;
 }
-\f
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+    }
+
+    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;
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -2000,8 +2135,6 @@ void FCGX_Finish(void)
  *
  *----------------------------------------------------------------------
  */
-static ReqData reqData;
-static char *webServerAddressList = NULL;
 
 int FCGX_Accept(
         FCGX_Stream **in,
@@ -2009,67 +2142,83 @@ 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) {
+        rc = FCGX_Init();
+        if (rc) {
+            return 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 -1;
-           }
-       }
+        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;
         }
@@ -2091,38 +2240,34 @@ 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.
              */
             break;
         }
+
         /*
          * Close the connection and try again.
          */
-      TryAgain:
-        FreeParams(&reqDataPtr->paramsPtr);
-        FreeStream(&reqDataPtr->inStream);
-        OS_Close(reqDataPtr->ipcFd);
-        reqDataPtr->ipcFd = -1;
+TryAgain:
+        FCGX_Free(reqDataPtr, 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
+
 /*
  *----------------------------------------------------------------------
  *
@@ -2136,14 +2281,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
@@ -2151,10 +2296,10 @@ 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
+
 /*
  *----------------------------------------------------------------------
  *
@@ -2171,6 +2316,27 @@ 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;
 }
+
+
+int 
+FCGX_Attach(FCGX_Request * r)
+{
+    r->detached = FALSE;
+    return 0;
+}
+
+
+int 
+FCGX_Detach(FCGX_Request * r)
+{
+    if (r->ipcFd <= 0)
+    {
+        return -1;
+    }
+
+    r->detached = TRUE;
+    return 0;
+}