*/
#ifndef lint
-static const char rcsid[] = "$Id: os_unix.c,v 1.14 1999/08/12 23:56:11 roberts Exp $";
+static const char rcsid[] = "$Id: os_unix.c,v 1.28 2001/06/22 14:26:39 robs Exp $";
#endif /* not lint */
#include "fcgi_config.h"
+#include <sys/types.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
-#include <sys/types.h>
#include <sys/un.h>
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> /* for getpeername */
#endif
#endif
#include "fastcgi.h"
-#include "fcgiapp.h"
-#include "fcgiappmisc.h"
#include "fcgimisc.h"
#include "fcgios.h"
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
+#ifndef INADDR_NONE
+#define INADDR_NONE ((unsigned long) -1)
#endif
/*
#define AIO_RD_IX(fd) (fd * 2)
#define AIO_WR_IX(fd) ((fd * 2) + 1)
+static int asyncIoInUse = FALSE;
static int asyncIoTableSize = 16;
static AioInfo *asyncIoTable = NULL;
static int numWrPosted = 0;
static int volatile maxFd = -1;
-\f
/*
*--------------------------------------------------------------
*
return 0;
}
-\f
/*
*--------------------------------------------------------------
*
return;
}
-\f
/*
*----------------------------------------------------------------------
*
#endif
return 0;
}
-\f
union SockAddrUnion {
struct sockaddr_un unixVariant;
struct sockaddr_in inetVariant;
};
-\f
/*
* OS_CreateLocalIpcFd --
*
int listenSock, servLen;
union SockAddrUnion sa;
int tcp = FALSE;
+ unsigned long tcp_ia;
char *tp;
short port;
char host[MAXPATHLEN];
tcp = TRUE;
}
}
- if(tcp && (*host && strcmp(host, "localhost") != 0)) {
- fprintf(stderr, "To start a service on a TCP port can not "
- "specify a host name.\n"
- "You should either use \"localhost:<port>\" or "
- " just use \":<port>.\"\n");
- exit(1);
+ if(tcp) {
+ if (!*host || !strcmp(host,"*")) {
+ tcp_ia = htonl(INADDR_ANY);
+ } else {
+ tcp_ia = inet_addr(host);
+ if (tcp_ia == INADDR_NONE) {
+ struct hostent * hep;
+ hep = gethostbyname(host);
+ if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
+ fprintf(stderr, "Cannot resolve host name %s -- exiting!\n", host);
+ exit(1);
+ }
+ if (hep->h_addr_list[1]) {
+ fprintf(stderr, "Host %s has multiple addresses ---\n", host);
+ fprintf(stderr, "you must choose one explicitly!!!\n");
+ exit(1);
+ }
+ tcp_ia = ((struct in_addr *) (hep->h_addr))->s_addr;
+ }
+ }
}
if(tcp) {
if(tcp) {
memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant));
sa.inetVariant.sin_family = AF_INET;
- sa.inetVariant.sin_addr.s_addr = htonl(INADDR_ANY);
+ sa.inetVariant.sin_addr.s_addr = tcp_ia;
sa.inetVariant.sin_port = htons(port);
servLen = sizeof(sa.inetVariant);
} else {
return listenSock;
}
-\f
/*
*----------------------------------------------------------------------
*
resultSock = socket(AF_UNIX, SOCK_STREAM, 0);
}
- assert(resultSock >= 0);
+ ASSERT(resultSock >= 0);
connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant,
servLen);
if(connectStatus >= 0) {
}
}
-\f
/*
*--------------------------------------------------------------
*
{
return(read(fd, buf, len));
}
-\f
+
/*
*--------------------------------------------------------------
*
return(write(fd, buf, len));
}
-\f
/*
*----------------------------------------------------------------------
*
return 0;
}
-\f
/*
*--------------------------------------------------------------
*
{
int index = AIO_RD_IX(STDIN_FILENO);
+ asyncIoInUse = TRUE;
ASSERT(asyncIoTable[index].inUse == 0);
asyncIoTable[index].procPtr = procPtr;
asyncIoTable[index].clientData = clientData;
}
-\f
/*
*--------------------------------------------------------------
*
int index = AIO_RD_IX(fd);
ASSERT(asyncIoTable != NULL);
+ asyncIoInUse = TRUE;
if(fd > maxFd)
maxFd = fd;
FD_SET(fd, &readFdSet);
return 0;
}
-\f
+
/*
*--------------------------------------------------------------
*
{
int index = AIO_WR_IX(fd);
+ asyncIoInUse = TRUE;
+
if(fd > maxFd)
maxFd = fd;
FD_SET(fd, &writeFdSet);
return 0;
}
-\f
+
/*
*--------------------------------------------------------------
*
*/
int OS_Close(int fd)
{
- int index = AIO_RD_IX(fd);
+ if (fd == -1)
+ return 0;
- FD_CLR(fd, &readFdSet);
- FD_CLR(fd, &readFdSetPost);
- if(asyncIoTable[index].inUse != 0) {
- asyncIoTable[index].inUse = 0;
- }
+ if (asyncIoInUse) {
+ int index = AIO_RD_IX(fd);
+
+ FD_CLR(fd, &readFdSet);
+ FD_CLR(fd, &readFdSetPost);
+ if (asyncIoTable[index].inUse != 0) {
+ asyncIoTable[index].inUse = 0;
+ }
+
+ FD_CLR(fd, &writeFdSet);
+ FD_CLR(fd, &writeFdSetPost);
+ index = AIO_WR_IX(fd);
+ if (asyncIoTable[index].inUse != 0) {
+ asyncIoTable[index].inUse = 0;
+ }
- FD_CLR(fd, &writeFdSet);
- FD_CLR(fd, &writeFdSetPost);
- index = AIO_WR_IX(fd);
- if(asyncIoTable[index].inUse != 0) {
- asyncIoTable[index].inUse = 0;
+ if (maxFd == fd) {
+ maxFd--;
+ }
}
- if(maxFd == fd)
- maxFd--;
return close(fd);
}
-\f
+
/*
*--------------------------------------------------------------
*
return shutdown(fd, 0);
}
-\f
/*
*--------------------------------------------------------------
*
fd_set readFdSetCpy;
fd_set writeFdSetCpy;
+ asyncIoInUse = TRUE;
FD_ZERO(&readFdSetCpy);
FD_ZERO(&writeFdSetCpy);
return 0;
}
-\f
+/*
+ * Not all systems have strdup().
+ * @@@ autoconf should determine whether or not this is needed, but for now..
+ */
+static char * str_dup(const char * str)
+{
+ char * sdup = (char *) malloc(strlen(str) + 1);
+
+ if (sdup)
+ strcpy(sdup, str);
+
+ return sdup;
+}
+
/*
*----------------------------------------------------------------------
*
{
int result = FALSE;
char *clientListCopy, *cur, *next;
- char *newString = NULL;
- int strLen;
- if(clientList == NULL || *clientList == '\0') {
+ if (clientList == NULL || *clientList == '\0') {
return TRUE;
}
- strLen = strlen(clientList);
- clientListCopy = (char *)malloc(strLen + 1);
- assert(newString != NULL);
- memcpy(newString, clientList, strLen);
- newString[strLen] = '\000';
+ clientListCopy = str_dup(clientList);
- for(cur = clientListCopy; cur != NULL; cur = next) {
+ for (cur = clientListCopy; cur != NULL; cur = next) {
next = strchr(cur, ',');
- if(next != NULL) {
+ if (next != NULL) {
*next++ = '\0';
- }
- if(inet_addr(cur) == saPtr->sin_addr.s_addr) {
+ }
+ if (inet_addr(cur) == saPtr->sin_addr.s_addr) {
result = TRUE;
break;
}
}
+
free(clientListCopy);
return result;
}
-\f
/*
*----------------------------------------------------------------------
*
return 0;
#endif
}
-\f
+
/*
*----------------------------------------------------------------------
*
#endif
}
-\f
/**********************************************************************
* Determine if the errno resulting from a failed accept() warrants a
* retry or exit(). Based on Apache's http_main.c accept() handling
return (socket);
}
-\f
+
/*
*----------------------------------------------------------------------
*
return OS_Close(ipcFd);
}
-\f
/*
*----------------------------------------------------------------------
*
int len = sizeof(sa);
#endif
+ errno = 0;
+
if (getpeername(sock, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) {
return TRUE;
}
return FALSE;
}
}
-\f
+
/*
*----------------------------------------------------------------------
*