X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=libfcgi%2Fos_unix.c;h=7912c9b62f76d283391eeeb7bd3341a547d0d21c;hb=378bd843b7f5879f55c7eafc72abfa0931c22860;hp=3d7dcee026bf353afde61925c397919cefba2194;hpb=8eac3e1ba7969bca72432c271d3e6dde3910c3dc;p=catagits%2Ffcgi2.git diff --git a/libfcgi/os_unix.c b/libfcgi/os_unix.c index 3d7dcee..7912c9b 100755 --- a/libfcgi/os_unix.c +++ b/libfcgi/os_unix.c @@ -17,11 +17,17 @@ */ #ifndef lint -static const char rcsid[] = "$Id: os_unix.c,v 1.11 1999/08/02 19:22:00 skimo Exp $"; +static const char rcsid[] = "$Id: os_unix.c,v 1.26 2001/06/18 14:24:28 robs Exp $"; #endif /* not lint */ #include "fcgi_config.h" +#include + +#ifdef HAVE_NETINET_IN_H +#include +#endif + #include #include #include @@ -34,17 +40,12 @@ static const char rcsid[] = "$Id: os_unix.c,v 1.11 1999/08/02 19:22:00 skimo Exp #include #include #include -#include #include #ifdef HAVE_NETDB_H #include #endif -#ifdef HAVE_NETINET_IN_H -#include -#endif - #ifdef HAVE_SYS_SOCKET_H #include /* for getpeername */ #endif @@ -59,12 +60,8 @@ static const char rcsid[] = "$Id: os_unix.c,v 1.11 1999/08/02 19:22:00 skimo Exp #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 /* @@ -89,10 +86,10 @@ typedef struct { #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 isFastCGI = FALSE; static int libInitialized = FALSE; static fd_set readFdSet; @@ -104,7 +101,6 @@ static fd_set writeFdSetPost; static int numWrPosted = 0; static int volatile maxFd = -1; - /* *-------------------------------------------------------------- * @@ -145,7 +141,6 @@ int OS_LibInit(int stdioFds[3]) return 0; } - /* *-------------------------------------------------------------- * @@ -172,7 +167,6 @@ void OS_LibShutdown() return; } - /* *---------------------------------------------------------------------- * @@ -191,7 +185,7 @@ void OS_LibShutdown() *---------------------------------------------------------------------- */ -static int OS_BuildSockAddrUn(char *bindPath, +static int OS_BuildSockAddrUn(const char *bindPath, struct sockaddr_un *servAddrPtr, int *servAddrLen) { @@ -219,13 +213,11 @@ static int OS_BuildSockAddrUn(char *bindPath, #endif return 0; } - union SockAddrUnion { struct sockaddr_un unixVariant; struct sockaddr_in inetVariant; }; - /* * OS_CreateLocalIpcFd -- * @@ -243,11 +235,12 @@ union SockAddrUnion { * *---------------------------------------------------------------------- */ -int OS_CreateLocalIpcFd(char *bindPath) +int OS_CreateLocalIpcFd(const char *bindPath, int backlog) { int listenSock, servLen; union SockAddrUnion sa; int tcp = FALSE; + unsigned long tcp_ia; char *tp; short port; char host[MAXPATHLEN]; @@ -261,12 +254,26 @@ int OS_CreateLocalIpcFd(char *bindPath) 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:\" or " - " just use \":.\"\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) { @@ -292,7 +299,7 @@ int OS_CreateLocalIpcFd(char *bindPath) 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 { @@ -303,7 +310,7 @@ int OS_CreateLocalIpcFd(char *bindPath) } } if(bind(listenSock, (struct sockaddr *) &sa.unixVariant, servLen) < 0 - || listen(listenSock, 5) < 0) { + || listen(listenSock, backlog) < 0) { perror("bind/listen"); exit(errno); } @@ -311,7 +318,6 @@ int OS_CreateLocalIpcFd(char *bindPath) return listenSock; } - /* *---------------------------------------------------------------------- * @@ -370,7 +376,7 @@ int OS_FcgiConnect(char *bindPath) resultSock = socket(AF_UNIX, SOCK_STREAM, 0); } - assert(resultSock >= 0); + ASSERT(resultSock >= 0); connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant, servLen); if(connectStatus >= 0) { @@ -385,7 +391,6 @@ int OS_FcgiConnect(char *bindPath) } } - /* *-------------------------------------------------------------- * @@ -406,7 +411,7 @@ int OS_Read(int fd, char * buf, size_t len) { return(read(fd, buf, len)); } - + /* *-------------------------------------------------------------- * @@ -428,7 +433,6 @@ int OS_Write(int fd, char * buf, size_t len) return(write(fd, buf, len)); } - /* *---------------------------------------------------------------------- * @@ -494,7 +498,6 @@ int OS_SpawnChild(char *appPath, int listenFd) return 0; } - /* *-------------------------------------------------------------- * @@ -521,6 +524,7 @@ int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr, { int index = AIO_RD_IX(STDIN_FILENO); + asyncIoInUse = TRUE; ASSERT(asyncIoTable[index].inUse == 0); asyncIoTable[index].procPtr = procPtr; asyncIoTable[index].clientData = clientData; @@ -550,7 +554,6 @@ static void GrowAsyncTable(void) } - /* *-------------------------------------------------------------- * @@ -581,6 +584,7 @@ int OS_AsyncRead(int fd, int offset, void *buf, int len, int index = AIO_RD_IX(fd); ASSERT(asyncIoTable != NULL); + asyncIoInUse = TRUE; if(fd > maxFd) maxFd = fd; @@ -600,7 +604,7 @@ int OS_AsyncRead(int fd, int offset, void *buf, int len, FD_SET(fd, &readFdSet); return 0; } - + /* *-------------------------------------------------------------- * @@ -629,6 +633,8 @@ int OS_AsyncWrite(int fd, int offset, void *buf, int len, { int index = AIO_WR_IX(fd); + asyncIoInUse = TRUE; + if(fd > maxFd) maxFd = fd; @@ -647,7 +653,7 @@ int OS_AsyncWrite(int fd, int offset, void *buf, int len, FD_SET(fd, &writeFdSet); return 0; } - + /* *-------------------------------------------------------------- * @@ -666,25 +672,32 @@ int OS_AsyncWrite(int fd, int offset, void *buf, int len, */ 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, &writeFdSet); - FD_CLR(fd, &writeFdSetPost); - index = AIO_WR_IX(fd); - if(asyncIoTable[index].inUse != 0) { - asyncIoTable[index].inUse = 0; + 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; + } + + if (maxFd == fd) { + maxFd--; + } } - if(maxFd == fd) - maxFd--; return close(fd); } - + /* *-------------------------------------------------------------- * @@ -709,7 +722,6 @@ int OS_CloseRead(int fd) return shutdown(fd, 0); } - /* *-------------------------------------------------------------- * @@ -736,6 +748,7 @@ int OS_DoIo(struct timeval *tmo) fd_set readFdSetCpy; fd_set writeFdSetCpy; + asyncIoInUse = TRUE; FD_ZERO(&readFdSetCpy); FD_ZERO(&writeFdSetCpy); @@ -825,7 +838,20 @@ int OS_DoIo(struct timeval *tmo) return 0; } - +/* + * Not all systems have strdup(). + * @@@ autoconf should determine whether or not this is needed, but for now.. + */ +char * str_dup(const char * str) +{ + char * sdup = (char *) malloc(strlen(str) + 1); + + if (sdup) + strcpy(sdup, str); + + return sdup; +} + /* *---------------------------------------------------------------------- * @@ -839,38 +865,32 @@ int OS_DoIo(struct timeval *tmo) * *---------------------------------------------------------------------- */ -static int ClientAddrOK(struct sockaddr_in *saPtr, char *clientList) +static int ClientAddrOK(struct sockaddr_in *saPtr, const char *clientList) { 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; } - /* *---------------------------------------------------------------------- * @@ -889,24 +909,27 @@ static int ClientAddrOK(struct sockaddr_in *saPtr, char *clientList) * *---------------------------------------------------------------------- */ -static int AcquireLock(int blocking) +static int AcquireLock(int sock, int fail_on_intr) { #ifdef USE_LOCKING - struct flock lock; - lock.l_type = F_WRLCK; - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - - if(fcntl(FCGI_LISTENSOCK_FILENO, - blocking ? F_SETLKW : F_SETLK, &lock) < 0) { - if (errno != EINTR) - return -1; - } -#endif /* USE_LOCKING */ + do { + struct flock lock; + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; + + if (fcntl(sock, F_SETLKW, &lock) != -1) + return 0; + } while (errno == EINTR && !fail_on_intr); + + return -1; + +#else return 0; +#endif } - + /* *---------------------------------------------------------------------- * @@ -924,23 +947,27 @@ static int AcquireLock(int blocking) * *---------------------------------------------------------------------- */ -static int ReleaseLock(void) +static int ReleaseLock(int sock) { #ifdef USE_LOCKING - struct flock lock; - lock.l_type = F_UNLCK; - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; + do { + struct flock lock; + lock.l_type = F_UNLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; + + if (fcntl(sock, F_SETLK, &lock) != -1) + return 0; + } while (errno == EINTR); - if(fcntl(FCGI_LISTENSOCK_FILENO, F_SETLK, &lock) < 0) { - return -1; - } -#endif /* USE_LOCKING */ + return -1; + +#else return 0; +#endif } - /********************************************************************** * Determine if the errno resulting from a failed accept() warrants a * retry or exit(). Based on Apache's http_main.c accept() handling @@ -1022,7 +1049,7 @@ static int is_af_unix_keeper(const int fd) /* *---------------------------------------------------------------------- * - * OS_FcgiIpcAccept -- + * OS_Accept -- * * Accepts a new FastCGI connection. This routine knows whether * we're dealing with TCP based sockets or NT Named Pipes for IPC. @@ -1035,40 +1062,38 @@ static int is_af_unix_keeper(const int fd) * *---------------------------------------------------------------------- */ -int OS_FcgiIpcAccept(char *clientAddrList) +int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs) { int socket; union { struct sockaddr_un un; struct sockaddr_in in; } sa; -#ifdef HAVE_SOCKLEN - socklen_t len; -#else - int len; -#endif - while (1) { - if (AcquireLock(TRUE) < 0) - return (-1); + for (;;) { + if (AcquireLock(listen_sock, fail_on_intr)) + return -1; - while (1) { + for (;;) { do { - len = sizeof(sa); - socket = accept(FCGI_LISTENSOCK_FILENO, (struct sockaddr *) &sa.un, &len); - } while (socket < 0 && errno == EINTR); +#ifdef HAVE_SOCKLEN + socklen_t len = sizeof(sa); +#else + int len = sizeof(sa); +#endif + socket = accept(listen_sock, (struct sockaddr *)&sa, &len); + } while (socket < 0 && errno == EINTR && !fail_on_intr); if (socket < 0) { if (!is_reasonable_accept_errno(errno)) { int errnoSave = errno; - - ReleaseLock(); + ReleaseLock(listen_sock); errno = errnoSave; return (-1); } errno = 0; } - else { + else { /* socket >= 0 */ int set = 1; if (sa.in.sin_family != AF_INET) @@ -1080,14 +1105,14 @@ int OS_FcgiIpcAccept(char *clientAddrList) #endif /* Check that the client IP address is approved */ - if (ClientAddrOK(&sa.in, clientAddrList)) + if (ClientAddrOK(&sa.in, webServerAddrs)) break; close(socket); - } - } /* while(1) - accept */ + } /* socket >= 0 */ + } /* for(;;) */ - if (ReleaseLock() < 0) + if (ReleaseLock(listen_sock)) return (-1); if (sa.in.sin_family != AF_UNIX || is_af_unix_keeper(socket)) @@ -1098,7 +1123,7 @@ int OS_FcgiIpcAccept(char *clientAddrList) return (socket); } - + /* *---------------------------------------------------------------------- * @@ -1119,7 +1144,6 @@ int OS_IpcClose(int ipcFd) return OS_Close(ipcFd); } - /* *---------------------------------------------------------------------- * @@ -1135,7 +1159,7 @@ int OS_IpcClose(int ipcFd) * *---------------------------------------------------------------------- */ -int OS_IsFcgi() +int OS_IsFcgi(int sock) { union { struct sockaddr_in in; @@ -1147,15 +1171,16 @@ int OS_IsFcgi() int len = sizeof(sa); #endif - if (getpeername(FCGI_LISTENSOCK_FILENO, (struct sockaddr *)&sa, &len) != 0 - && errno == ENOTCONN) - isFastCGI = TRUE; - else - isFastCGI = FALSE; + errno = 0; - return (isFastCGI); + if (getpeername(sock, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) { + return TRUE; + } + else { + return FALSE; + } } - + /* *---------------------------------------------------------------------- *