-/*
+/*
* cgifcgi.c --
*
* CGI to FastCGI bridge
*
* 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: cgi-fcgi.c,v 1.4 1999/07/26 04:55:14 roberts Exp $";
+static const char rcsid[] = "$Id: cgi-fcgi.c,v 1.16 2003/06/22 02:02:33 robs Exp $";
#endif /* not lint */
-#include <stdio.h>
-#if defined HAVE_UNISTD_H || defined __linux__
-#include <unistd.h>
-#endif
-#include <fcntl.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>
+
+#include "fcgi_config.h"
+
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+
+#ifdef _WIN32
+#include <stdlib.h>
+#include <io.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
+
+#ifdef 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"
-extern char *environ[];
static int wsReadPending = 0;
static int fcgiReadPending = 0;
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;
}
{
FCGI_BeginRequestBody body;
ASSERT((role >> 16) == 0);
- body.roleB1 = (role >> 8) & 0xff;
- body.roleB0 = (role ) & 0xff;
- body.flags = (keepConnection) ? FCGI_KEEP_CONN : 0;
+ body.roleB1 = (unsigned char) ((role >> 8) & 0xff);
+ body.roleB0 = (unsigned char) (role & 0xff);
+ body.flags = (unsigned char) ((keepConnection) ? FCGI_KEEP_CONN : 0);
memset(body.reserved, 0, sizeof(body.reserved));
return body;
}
static void FCGIexit(int exitCode)
{
if(appServerSock != -1) {
- OS_Close(appServerSock);
+ OS_Close(appServerSock, TRUE);
appServerSock = -1;
}
OS_LibShutdown();
*----------------------------------------------------------------------
*/
-static void AppServerReadHandler(ClientData clientData, int bytesRead)
+static void AppServerReadHandler(ClientData dc, int bytesRead)
{
int count, outFD;
char *ptr;
+ /* Touch unused parameters to avoid warnings */
+ dc = NULL;
+
assert(fcgiReadPending == TRUE);
fcgiReadPending = FALSE;
count = bytesRead;
exit(FCGX_PROTOCOL_ERROR);
}
if(appServerSock != -1) {
- OS_Close(appServerSock);
+ OS_Close(appServerSock, TRUE);
appServerSock = -1;
}
/*
* 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;
+}
+
/*
*----------------------------------------------------------------------
*
*----------------------------------------------------------------------
*/
-static void WebServerReadHandler(ClientData clientData, int bytesRead)
+static void WebServerReadHandler(ClientData dc, int bytesRead)
{
+ /* Touch unused parameters to avoid warnings */
+ dc = NULL;
+
assert(fromWS.next == fromWS.stop);
assert(fromWS.next == &fromWS.buff[0]);
assert(wsReadPending == TRUE);
bytesToRead -= bytesRead;
fromWS.stop = &fromWS.buff[sizeof(FCGI_Header) + bytesRead];
webServerReadHandlerEOF = (bytesRead == 0);
+
+ if (bytesToRead <= 0)
+ WriteStdinEof();
+
ScheduleIo();
}
\f
*----------------------------------------------------------------------
*/
-static void AppServerWriteHandler(ClientData clientData, int bytesWritten)
+static void AppServerWriteHandler(ClientData dc, int bytesWritten)
{
int length = fromWS.stop - fromWS.next;
+ /* Touch unused parameters to avoid warnings */
+ dc = NULL;
+
assert(length > 0);
assert(fcgiWritePending == TRUE);
}
ScheduleIo();
-}
+}
\f
/*
*
* Side effects:
* This routine will signal the ioEvent upon completion.
- *
+ *
*/
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);
!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 {
{
int listenFd, i;
- 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);
exit(OS_Errno);
}
}
- OS_Close(listenFd);
+ OS_Close(listenFd, TRUE);
}
\f
/*
unsigned char *startHeaderBuffPtr = headerBuffPtr;
ASSERT(nameLen >= 0);
- if (nameLen < 0x80 == 0) {
- *headerBuffPtr++ = nameLen;
+ if (nameLen < 0x80) {
+ *headerBuffPtr++ = (unsigned char) nameLen;
} else {
- *headerBuffPtr++ = (nameLen >> 24) | 0x80;
- *headerBuffPtr++ = (nameLen >> 16);
- *headerBuffPtr++ = (nameLen >> 8);
- *headerBuffPtr++ = nameLen;
+ *headerBuffPtr++ = (unsigned char) ((nameLen >> 24) | 0x80);
+ *headerBuffPtr++ = (unsigned char) (nameLen >> 16);
+ *headerBuffPtr++ = (unsigned char) (nameLen >> 8);
+ *headerBuffPtr++ = (unsigned char) nameLen;
}
ASSERT(valueLen >= 0);
- if (valueLen < 0x80 == 0) {
- *headerBuffPtr++ = valueLen;
+ if (valueLen < 0x80) {
+ *headerBuffPtr++ = (unsigned char) valueLen;
} else {
- *headerBuffPtr++ = (valueLen >> 24) | 0x80;
- *headerBuffPtr++ = (valueLen >> 16);
- *headerBuffPtr++ = (valueLen >> 8);
- *headerBuffPtr++ = valueLen;
+ *headerBuffPtr++ = (unsigned char) ((valueLen >> 24) | 0x80);
+ *headerBuffPtr++ = (unsigned char) (valueLen >> 16);
+ *headerBuffPtr++ = (unsigned char) (valueLen >> 8);
+ *headerBuffPtr++ = (unsigned char) valueLen;
}
*headerLenPtr = headerBuffPtr - startHeaderBuffPtr;
}
"%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);
}
} 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");
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 "
} else {
bytesToRead = 0;
}
-
+
if(doBind) {
appServerSock = OS_FcgiConnect(bindPath);
}
/*
* Send environment to the FCGI application server
*/
- paramsStream = CreateWriter(appServerSock, requestId, 8192, FCGI_PARAMS);
+ paramsStream = FCGX_CreateWriter(appServerSock, requestId, 8192, FCGI_PARAMS);
for( ; *envp != NULL; envp++) {
equalPtr = strchr(*envp, '=');
if(equalPtr == NULL) {
}
}
FCGX_FClose(paramsStream);
- FreeStream(¶msStream);
+ FCGX_FreeStream(¶msStream);
/*
* Perform the event loop until AppServerReadHander sees FCGI_END_REQUEST
*/
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