Fix bug in OS_Close() (when accept returns fds >8). ernst@wildape.com
[catagits/fcgi2.git] / cgi-fcgi / cgi-fcgi.c
index 32dfd83..4e03e4d 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * cgifcgi.c --
  *
  *     CGI to FastCGI bridge
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  *
  */
-
 #ifndef lint
-static const char rcsid[] = "$Id: cgi-fcgi.c,v 1.1 1997/09/16 15:36:25 stanleyg Exp $";
+static const char rcsid[] = "$Id: cgi-fcgi.c,v 1.10 1999/08/27 19:39:17 roberts Exp $";
 #endif /* not lint */
 
-#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <fcntl.h>
+#include "fcgi_config.h"
+
 #include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <ctype.h>
+
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+
+#ifdef _WIN32
+#include <stdlib.h>
+#else
+extern char **environ;
 #endif
+
 #ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h>
 #endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#if defined HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #include "fcgimisc.h"
 #include "fcgiapp.h"
 #include "fcgiappmisc.h"
 #include "fastcgi.h"
-#include "fcgi_config.h"
 #include "fcgios.h"
 
+
 static int wsReadPending = 0;
-static int wsWritePending = 0;
 static int fcgiReadPending = 0;
 static int fcgiWritePending = 0;
 
@@ -335,6 +346,18 @@ static int webServerReadHandlerEOF;
                          * the Web server. Used in main to prevent
                          * rescheduling WebServerReadHandler. */
 
+static void WriteStdinEof(void)
+{
+    static int stdin_eof_sent = 0;
+
+    if (stdin_eof_sent)
+       return;
+
+    *((FCGI_Header *)fromWS.stop) = MakeHeader(FCGI_STDIN, requestId, 0, 0);
+    fromWS.stop += sizeof(FCGI_Header);
+    stdin_eof_sent = 1;
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -362,6 +385,10 @@ static void WebServerReadHandler(ClientData clientData, int bytesRead)
     bytesToRead -= bytesRead;
     fromWS.stop = &fromWS.buff[sizeof(FCGI_Header) + bytesRead];
     webServerReadHandlerEOF = (bytesRead == 0);
+
+    if (bytesToRead <= 0)
+       WriteStdinEof();
+
     ScheduleIo();
 }
 \f
@@ -395,7 +422,7 @@ static void AppServerWriteHandler(ClientData clientData, int bytesWritten)
     }
 
     ScheduleIo();
-}      
+}
 
 \f
 /*
@@ -409,7 +436,7 @@ static void AppServerWriteHandler(ClientData clientData, int bytesWritten)
  *
  * Side effects:
  *      This routine will signal the ioEvent upon completion.
- * 
+ *
  */
 static void ScheduleIo(void)
 {
@@ -436,7 +463,7 @@ static void ScheduleIo(void)
     if(!fcgiReadPending && appServerSock != -1) {
        fromAS.next = &fromAS.buff[0];
 
-       if(OS_AsyncRead(appServerSock, 0, fromAS.next, BUFFLEN, 
+       if(OS_AsyncRead(appServerSock, 0, fromAS.next, BUFFLEN,
                        AppServerReadHandler,
                        (ClientData)appServerSock) == -1) {
            FCGIexit(OS_Errno);
@@ -452,7 +479,7 @@ static void ScheduleIo(void)
        !fcgiWritePending &&
        fromWS.next == &fromWS.buff[0]) {
        if(OS_AsyncReadStdin(fromWS.next + sizeof(FCGI_Header),
-                            BUFFLEN - sizeof(FCGI_Header), 
+                            BUFFLEN - sizeof(FCGI_Header),
                             WebServerReadHandler, STDIN_FILENO)== -1) {
            FCGIexit(OS_Errno);
        } else {
@@ -476,12 +503,12 @@ static void ScheduleIo(void)
 static void FCGI_Start(char *bindPath, char *appPath, int nServers)
 {
     int listenFd, i;
-    int            tcp = FALSE;
 
-    if((listenFd = OS_CreateLocalIpcFd(bindPath)) == -1) {
+    /* @@@ Should be able to pick up the backlog as an arg */
+    if((listenFd = OS_CreateLocalIpcFd(bindPath, 5)) == -1) {
         exit(OS_Errno);
     }
-    
+
     if(access(appPath, X_OK) == -1) {
        fprintf(stderr, "%s is not executable\n", appPath);
        exit(1);
@@ -514,8 +541,6 @@ static void FCGI_Start(char *bindPath, char *appPath, int nServers)
  *
  *----------------------------------------------------------------------
  */
-static buildNameValueHeaderCalls = 0; /* XXX: for testing */
-
 static void FCGIUtil_BuildNameValueHeader(
         int nameLen,
         int valueLen,
@@ -524,7 +549,7 @@ static void FCGIUtil_BuildNameValueHeader(
     unsigned char *startHeaderBuffPtr = headerBuffPtr;
 
     ASSERT(nameLen >= 0);
-    if(nameLen < 0x80 && (buildNameValueHeaderCalls & 1) == 0) {
+    if (nameLen < 0x80) {
         *headerBuffPtr++ = nameLen;
     } else {
         *headerBuffPtr++ = (nameLen >> 24) | 0x80;
@@ -533,7 +558,7 @@ static void FCGIUtil_BuildNameValueHeader(
         *headerBuffPtr++ = nameLen;
     }
     ASSERT(valueLen >= 0);
-    if(valueLen < 0x80 && (buildNameValueHeaderCalls & 2) == 0) {
+    if (valueLen < 0x80) {
         *headerBuffPtr++ = valueLen;
     } else {
         *headerBuffPtr++ = (valueLen >> 24) | 0x80;
@@ -542,7 +567,6 @@ static void FCGIUtil_BuildNameValueHeader(
         *headerBuffPtr++ = valueLen;
     }
     *headerLenPtr = headerBuffPtr - startHeaderBuffPtr;
-    buildNameValueHeaderCalls++;
 }
 \f
 
@@ -605,7 +629,7 @@ static int ParseArgs(int argc, char *argv[],
                                     "%d is max from a file\n", MAXARGS);
                                exit(-1);
                        }
-                       if((av[ac] = malloc(strlen(tp1)+1)) == NULL) {
+                       if((av[ac] = (char *)malloc(strlen(tp1)+1)) == NULL) {
                            fprintf(stderr, "Cannot allocate %d bytes\n",
                                    strlen(tp1)+1);
                            exit(-1);
@@ -645,7 +669,7 @@ static int ParseArgs(int argc, char *argv[],
            }
        } else if(*appPathPtr == '\0') {
             strcpy(appPathPtr, argv[i]);
-        } else if(isdigit(argv[i][0]) && *nServersPtr == 0) {
+        } else if(isdigit((int)argv[i][0]) && *nServersPtr == 0) {
             *nServersPtr = atoi(argv[i]);
             if(*nServersPtr <= 0) {
                 fprintf(stderr, "Number of servers must be greater than 0\n");
@@ -669,7 +693,7 @@ static int ParseArgs(int argc, char *argv[],
         This hack lets me test the ability to create a local process listening
        to a TCP/IP port for connections and subsequently connect to the app
        like we do for Unix domain and named pipes.
-       
+
         if(*doStartPtr && *doBindPtr) {
            fprintf(stderr,
                     "<connName> of form hostName:portNumber "
@@ -684,8 +708,9 @@ static int ParseArgs(int argc, char *argv[],
     return err;
 }
 \f
-void main(int argc, char **argv, char **envp)
+int main(int argc, char **argv)
 {
+    char **envp = environ;
     int count;
     FCGX_Stream *paramsStream;
     int numFDs;
@@ -721,7 +746,7 @@ void main(int argc, char **argv, char **envp)
     } else {
         bytesToRead = 0;
     }
-    
+
     if(doBind) {
         appServerSock = OS_FcgiConnect(bindPath);
     }
@@ -793,7 +818,11 @@ void main(int argc, char **argv, char **envp)
     numFDs = max(appServerSock, STDIN_FILENO) + 1;
     OS_SetFlags(appServerSock, O_NONBLOCK);
 
+    if (bytesToRead <= 0)
+       WriteStdinEof();
+
     ScheduleIo();
+
     while(!exitStatusSet) {
         /*
         * NULL = wait forever (or at least until there's something
@@ -806,4 +835,6 @@ void main(int argc, char **argv, char **envp)
     } else {
         FCGIexit(999);
     }
+
+    return 0;
 }