7 * Copyright (c) 1995 Open Market, Inc.
10 * This file contains proprietary and confidential information and
11 * remains the unpublished property of Open Market, Inc. Use,
12 * disclosure, or reproduction is prohibited except as permitted by
13 * express written license agreement with Open Market, Inc.
16 * snapper@openmarket.com
20 static const char rcsid[] = "$Id: os_unix.c,v 1.26 2001/06/18 14:24:28 robs Exp $";
23 #include "fcgi_config.h"
25 #include <sys/types.h>
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
31 #include <arpa/inet.h>
34 #include <fcntl.h> /* for fcntl */
36 #include <memory.h> /* for memchr() */
37 #include <netinet/tcp.h>
49 #ifdef HAVE_SYS_SOCKET_H
50 #include <sys/socket.h> /* for getpeername */
59 #include "fcgiappmisc.h"
64 #define INADDR_NONE ((unsigned long) -1)
68 * This structure holds an entry for each oustanding async I/O operation.
71 OS_AsyncProc procPtr; /* callout completion procedure */
72 ClientData clientData; /* caller private data */
81 * Entries in the async I/O table are allocated 2 per file descriptor.
83 * Read Entry Index = fd * 2
84 * Write Entry Index = (fd * 2) + 1
86 #define AIO_RD_IX(fd) (fd * 2)
87 #define AIO_WR_IX(fd) ((fd * 2) + 1)
89 static int asyncIoInUse = FALSE;
90 static int asyncIoTableSize = 16;
91 static AioInfo *asyncIoTable = NULL;
93 static int libInitialized = FALSE;
95 static fd_set readFdSet;
96 static fd_set writeFdSet;
98 static fd_set readFdSetPost;
99 static int numRdPosted = 0;
100 static fd_set writeFdSetPost;
101 static int numWrPosted = 0;
102 static int volatile maxFd = -1;
105 *--------------------------------------------------------------
109 * Set up the OS library for use.
111 * NOTE: This function is really only needed for application
112 * asynchronous I/O. It will most likely change in the
113 * future to setup the multi-threaded environment.
116 * Returns 0 if success, -1 if not.
119 * Async I/O table allocated and initialized.
121 *--------------------------------------------------------------
123 int OS_LibInit(int stdioFds[3])
128 asyncIoTable = (AioInfo *)malloc(asyncIoTableSize * sizeof(AioInfo));
129 if(asyncIoTable == NULL) {
133 memset((char *) asyncIoTable, 0,
134 asyncIoTableSize * sizeof(AioInfo));
137 FD_ZERO(&writeFdSet);
138 FD_ZERO(&readFdSetPost);
139 FD_ZERO(&writeFdSetPost);
140 libInitialized = TRUE;
145 *--------------------------------------------------------------
149 * Shutdown the OS library.
155 * Memory freed, fds closed.
157 *--------------------------------------------------------------
159 void OS_LibShutdown()
166 libInitialized = FALSE;
171 *----------------------------------------------------------------------
173 * OS_BuildSockAddrUn --
175 * Using the pathname bindPath, fill in the sockaddr_un structure
176 * *servAddrPtr and the length of this structure *servAddrLen.
178 * The format of the sockaddr_un structure changed incompatibly in
179 * 4.3BSD Reno. Digital UNIX supports both formats, other systems
180 * support one or the other.
183 * 0 for normal return, -1 for failure (bindPath too long).
185 *----------------------------------------------------------------------
188 static int OS_BuildSockAddrUn(const char *bindPath,
189 struct sockaddr_un *servAddrPtr,
192 int bindPathLen = strlen(bindPath);
194 #ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
195 if(bindPathLen >= sizeof(servAddrPtr->sun_path)) {
198 #else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
199 if(bindPathLen > sizeof(servAddrPtr->sun_path)) {
203 memset((char *) servAddrPtr, 0, sizeof(*servAddrPtr));
204 servAddrPtr->sun_family = AF_UNIX;
205 memcpy(servAddrPtr->sun_path, bindPath, bindPathLen);
206 #ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
207 *servAddrLen = sizeof(servAddrPtr->sun_len)
208 + sizeof(servAddrPtr->sun_family)
210 servAddrPtr->sun_len = *servAddrLen;
211 #else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
212 *servAddrLen = sizeof(servAddrPtr->sun_family) + bindPathLen;
216 union SockAddrUnion {
217 struct sockaddr_un unixVariant;
218 struct sockaddr_in inetVariant;
222 * OS_CreateLocalIpcFd --
224 * This procedure is responsible for creating the listener socket
225 * on Unix for local process communication. It will create a
226 * domain socket or a TCP/IP socket bound to "localhost" and return
227 * a file descriptor to it to the caller.
230 * Listener socket created. This call returns either a valid
231 * file descriptor or -1 on error.
236 *----------------------------------------------------------------------
238 int OS_CreateLocalIpcFd(const char *bindPath, int backlog)
240 int listenSock, servLen;
241 union SockAddrUnion sa;
243 unsigned long tcp_ia;
246 char host[MAXPATHLEN];
248 strcpy(host, bindPath);
249 if((tp = strchr(host, ':')) != 0) {
251 if((port = atoi(tp)) == 0) {
258 if (!*host || !strcmp(host,"*")) {
259 tcp_ia = htonl(INADDR_ANY);
261 tcp_ia = inet_addr(host);
262 if (tcp_ia == INADDR_NONE) {
263 struct hostent * hep;
264 hep = gethostbyname(host);
265 if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
266 fprintf(stderr, "Cannot resolve host name %s -- exiting!\n", host);
269 if (hep->h_addr_list[1]) {
270 fprintf(stderr, "Host %s has multiple addresses ---\n", host);
271 fprintf(stderr, "you must choose one explicitly!!!\n");
274 tcp_ia = ((struct in_addr *) (hep->h_addr))->s_addr;
280 listenSock = socket(AF_INET, SOCK_STREAM, 0);
281 if(listenSock >= 0) {
283 if(setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR,
284 (char *) &flag, sizeof(flag)) < 0) {
285 fprintf(stderr, "Can't set SO_REUSEADDR.\n");
290 listenSock = socket(AF_UNIX, SOCK_STREAM, 0);
297 * Bind the listening socket.
300 memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant));
301 sa.inetVariant.sin_family = AF_INET;
302 sa.inetVariant.sin_addr.s_addr = tcp_ia;
303 sa.inetVariant.sin_port = htons(port);
304 servLen = sizeof(sa.inetVariant);
307 if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
308 fprintf(stderr, "Listening socket's path name is too long.\n");
312 if(bind(listenSock, (struct sockaddr *) &sa.unixVariant, servLen) < 0
313 || listen(listenSock, backlog) < 0) {
314 perror("bind/listen");
322 *----------------------------------------------------------------------
326 * Create the socket and connect to the remote application if
329 * This was lifted from the cgi-fcgi application and was abstracted
330 * out because Windows NT does not have a domain socket and must
331 * use a named pipe which has a different API altogether.
334 * -1 if fail or a valid file descriptor if connection succeeds.
337 * Remote connection established.
339 *----------------------------------------------------------------------
341 int OS_FcgiConnect(char *bindPath)
343 union SockAddrUnion sa;
344 int servLen, resultSock;
347 char host[MAXPATHLEN];
351 strcpy(host, bindPath);
352 if((tp = strchr(host, ':')) != 0) {
354 if((port = atoi(tp)) == 0) {
362 if((hp = gethostbyname((*host ? host : "localhost"))) == NULL) {
363 fprintf(stderr, "Unknown host: %s\n", bindPath);
366 sa.inetVariant.sin_family = AF_INET;
367 memcpy(&sa.inetVariant.sin_addr, hp->h_addr, hp->h_length);
368 sa.inetVariant.sin_port = htons(port);
369 servLen = sizeof(sa.inetVariant);
370 resultSock = socket(AF_INET, SOCK_STREAM, 0);
372 if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
373 fprintf(stderr, "Listening socket's path name is too long.\n");
376 resultSock = socket(AF_UNIX, SOCK_STREAM, 0);
379 ASSERT(resultSock >= 0);
380 connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant,
382 if(connectStatus >= 0) {
386 * Most likely (errno == ENOENT || errno == ECONNREFUSED)
387 * and no FCGI application server is running.
395 *--------------------------------------------------------------
399 * Pass through to the unix read function.
402 * Returns number of byes read, 0, or -1 failure: errno
403 * contains actual error.
408 *--------------------------------------------------------------
410 int OS_Read(int fd, char * buf, size_t len)
412 return(read(fd, buf, len));
416 *--------------------------------------------------------------
420 * Pass through to unix write function.
423 * Returns number of byes read, 0, or -1 failure: errno
424 * contains actual error.
429 *--------------------------------------------------------------
431 int OS_Write(int fd, char * buf, size_t len)
433 return(write(fd, buf, len));
437 *----------------------------------------------------------------------
441 * Spawns a new FastCGI listener process.
444 * 0 if success, -1 if error.
447 * Child process spawned.
449 *----------------------------------------------------------------------
451 int OS_SpawnChild(char *appPath, int listenFd)
460 if(forkResult == 0) {
462 * Close STDIN unconditionally. It's used by the parent
463 * process for CGI communication. The FastCGI applciation
464 * will be replacing this with the FastCGI listenFd IF
465 * STDIN_FILENO is the same as FCGI_LISTENSOCK_FILENO
466 * (which it is on Unix). Regardless, STDIN, STDOUT, and
467 * STDERR will be closed as the FastCGI process uses a
468 * multiplexed socket in their place.
473 * If the listenFd is already the value of FCGI_LISTENSOCK_FILENO
474 * we're set. If not, change it so the child knows where to
475 * get the listen socket from.
477 if(listenFd != FCGI_LISTENSOCK_FILENO) {
478 dup2(listenFd, FCGI_LISTENSOCK_FILENO);
482 close(STDOUT_FILENO);
483 close(STDERR_FILENO);
486 * We're a child. Exec the application.
488 * XXX: entire environment passes through
490 execl(appPath, appPath, NULL);
492 * XXX: Can't do this as we've already closed STDERR!!!
502 *--------------------------------------------------------------
504 * OS_AsyncReadStdin --
506 * This initiates an asynchronous read on the standard
509 * The abstraction is necessary because Windows NT does not
510 * have a clean way of "select"ing a file descriptor for
514 * -1 if error, 0 otherwise.
517 * Asynchronous bit is set in the readfd variable and
518 * request is enqueued.
520 *--------------------------------------------------------------
522 int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr,
523 ClientData clientData)
525 int index = AIO_RD_IX(STDIN_FILENO);
528 ASSERT(asyncIoTable[index].inUse == 0);
529 asyncIoTable[index].procPtr = procPtr;
530 asyncIoTable[index].clientData = clientData;
531 asyncIoTable[index].fd = STDIN_FILENO;
532 asyncIoTable[index].len = len;
533 asyncIoTable[index].offset = 0;
534 asyncIoTable[index].buf = buf;
535 asyncIoTable[index].inUse = 1;
536 FD_SET(STDIN_FILENO, &readFdSet);
537 if(STDIN_FILENO > maxFd)
538 maxFd = STDIN_FILENO;
542 static void GrowAsyncTable(void)
544 int oldTableSize = asyncIoTableSize;
546 asyncIoTableSize = asyncIoTableSize * 2;
547 asyncIoTable = (AioInfo *)realloc(asyncIoTable, asyncIoTableSize * sizeof(AioInfo));
548 if(asyncIoTable == NULL) {
552 memset((char *) &asyncIoTable[oldTableSize], 0,
553 oldTableSize * sizeof(AioInfo));
558 *--------------------------------------------------------------
562 * This initiates an asynchronous read on the file
563 * handle which may be a socket or named pipe.
565 * We also must save the ProcPtr and ClientData, so later
566 * when the io completes, we know who to call.
568 * We don't look at any results here (the ReadFile may
569 * return data if it is cached) but do all completion
570 * processing in OS_Select when we get the io completion
571 * port done notifications. Then we call the callback.
574 * -1 if error, 0 otherwise.
577 * Asynchronous I/O operation is queued for completion.
579 *--------------------------------------------------------------
581 int OS_AsyncRead(int fd, int offset, void *buf, int len,
582 OS_AsyncProc procPtr, ClientData clientData)
584 int index = AIO_RD_IX(fd);
586 ASSERT(asyncIoTable != NULL);
592 if(index >= asyncIoTableSize) {
596 ASSERT(asyncIoTable[index].inUse == 0);
597 asyncIoTable[index].procPtr = procPtr;
598 asyncIoTable[index].clientData = clientData;
599 asyncIoTable[index].fd = fd;
600 asyncIoTable[index].len = len;
601 asyncIoTable[index].offset = offset;
602 asyncIoTable[index].buf = buf;
603 asyncIoTable[index].inUse = 1;
604 FD_SET(fd, &readFdSet);
609 *--------------------------------------------------------------
613 * This initiates an asynchronous write on the "fake" file
614 * descriptor (which may be a file, socket, or named pipe).
615 * We also must save the ProcPtr and ClientData, so later
616 * when the io completes, we know who to call.
618 * We don't look at any results here (the WriteFile generally
619 * completes immediately) but do all completion processing
620 * in OS_DoIo when we get the io completion port done
621 * notifications. Then we call the callback.
624 * -1 if error, 0 otherwise.
627 * Asynchronous I/O operation is queued for completion.
629 *--------------------------------------------------------------
631 int OS_AsyncWrite(int fd, int offset, void *buf, int len,
632 OS_AsyncProc procPtr, ClientData clientData)
634 int index = AIO_WR_IX(fd);
641 if(index >= asyncIoTableSize) {
645 ASSERT(asyncIoTable[index].inUse == 0);
646 asyncIoTable[index].procPtr = procPtr;
647 asyncIoTable[index].clientData = clientData;
648 asyncIoTable[index].fd = fd;
649 asyncIoTable[index].len = len;
650 asyncIoTable[index].offset = offset;
651 asyncIoTable[index].buf = buf;
652 asyncIoTable[index].inUse = 1;
653 FD_SET(fd, &writeFdSet);
658 *--------------------------------------------------------------
662 * Closes the descriptor. This is a pass through to the
666 * 0 for success, -1 on failure
671 *--------------------------------------------------------------
679 int index = AIO_RD_IX(fd);
681 FD_CLR(fd, &readFdSet);
682 FD_CLR(fd, &readFdSetPost);
683 if (asyncIoTable[index].inUse != 0) {
684 asyncIoTable[index].inUse = 0;
687 FD_CLR(fd, &writeFdSet);
688 FD_CLR(fd, &writeFdSetPost);
689 index = AIO_WR_IX(fd);
690 if (asyncIoTable[index].inUse != 0) {
691 asyncIoTable[index].inUse = 0;
702 *--------------------------------------------------------------
706 * Cancel outstanding asynchronous reads and prevent subsequent
707 * reads from completing.
710 * Socket or file is shutdown. Return values mimic Unix shutdown:
711 * 0 success, -1 failure
713 *--------------------------------------------------------------
715 int OS_CloseRead(int fd)
717 if(asyncIoTable[AIO_RD_IX(fd)].inUse != 0) {
718 asyncIoTable[AIO_RD_IX(fd)].inUse = 0;
719 FD_CLR(fd, &readFdSet);
722 return shutdown(fd, 0);
726 *--------------------------------------------------------------
730 * This function was formerly OS_Select. It's purpose is
731 * to pull I/O completion events off the queue and dispatch
732 * them to the appropriate place.
738 * Handlers are called.
740 *--------------------------------------------------------------
742 int OS_DoIo(struct timeval *tmo)
744 int fd, len, selectStatus;
745 OS_AsyncProc procPtr;
746 ClientData clientData;
749 fd_set writeFdSetCpy;
752 FD_ZERO(&readFdSetCpy);
753 FD_ZERO(&writeFdSetCpy);
755 for(fd = 0; fd <= maxFd; fd++) {
756 if(FD_ISSET(fd, &readFdSet)) {
757 FD_SET(fd, &readFdSetCpy);
759 if(FD_ISSET(fd, &writeFdSet)) {
760 FD_SET(fd, &writeFdSetCpy);
765 * If there were no completed events from a prior call, see if there's
768 if(numRdPosted == 0 && numWrPosted == 0) {
769 selectStatus = select((maxFd+1), &readFdSetCpy, &writeFdSetCpy,
771 if(selectStatus < 0) {
775 for(fd = 0; fd <= maxFd; fd++) {
777 * Build up a list of completed events. We'll work off of
778 * this list as opposed to looping through the read and write
779 * fd sets since they can be affected by a callbacl routine.
781 if(FD_ISSET(fd, &readFdSetCpy)) {
783 FD_SET(fd, &readFdSetPost);
784 FD_CLR(fd, &readFdSet);
787 if(FD_ISSET(fd, &writeFdSetCpy)) {
789 FD_SET(fd, &writeFdSetPost);
790 FD_CLR(fd, &writeFdSet);
795 if(numRdPosted == 0 && numWrPosted == 0)
798 for(fd = 0; fd <= maxFd; fd++) {
800 * Do reads and dispatch callback.
802 if(FD_ISSET(fd, &readFdSetPost)
803 && asyncIoTable[AIO_RD_IX(fd)].inUse) {
806 FD_CLR(fd, &readFdSetPost);
807 aioPtr = &asyncIoTable[AIO_RD_IX(fd)];
809 len = read(aioPtr->fd, aioPtr->buf, aioPtr->len);
811 procPtr = aioPtr->procPtr;
812 aioPtr->procPtr = NULL;
813 clientData = aioPtr->clientData;
816 (*procPtr)(clientData, len);
820 * Do writes and dispatch callback.
822 if(FD_ISSET(fd, &writeFdSetPost) &&
823 asyncIoTable[AIO_WR_IX(fd)].inUse) {
826 FD_CLR(fd, &writeFdSetPost);
827 aioPtr = &asyncIoTable[AIO_WR_IX(fd)];
829 len = write(aioPtr->fd, aioPtr->buf, aioPtr->len);
831 procPtr = aioPtr->procPtr;
832 aioPtr->procPtr = NULL;
833 clientData = aioPtr->clientData;
835 (*procPtr)(clientData, len);
842 * Not all systems have strdup().
843 * @@@ autoconf should determine whether or not this is needed, but for now..
845 char * str_dup(const char * str)
847 char * sdup = (char *) malloc(strlen(str) + 1);
856 *----------------------------------------------------------------------
860 * Checks if a client address is in a list of allowed addresses
863 * TRUE if address list is empty or client address is present
864 * in the list, FALSE otherwise.
866 *----------------------------------------------------------------------
868 static int ClientAddrOK(struct sockaddr_in *saPtr, const char *clientList)
871 char *clientListCopy, *cur, *next;
873 if (clientList == NULL || *clientList == '\0') {
877 clientListCopy = str_dup(clientList);
879 for (cur = clientListCopy; cur != NULL; cur = next) {
880 next = strchr(cur, ',');
884 if (inet_addr(cur) == saPtr->sin_addr.s_addr) {
890 free(clientListCopy);
895 *----------------------------------------------------------------------
899 * On platforms that implement concurrent calls to accept
900 * on a shared listening ipcFd, returns 0. On other platforms,
901 * acquires an exclusive lock across all processes sharing a
902 * listening ipcFd, blocking until the lock has been acquired.
905 * 0 for successful call, -1 in case of system error (fatal).
908 * This process now has the exclusive lock.
910 *----------------------------------------------------------------------
912 static int AcquireLock(int sock, int fail_on_intr)
917 lock.l_type = F_WRLCK;
919 lock.l_whence = SEEK_SET;
922 if (fcntl(sock, F_SETLKW, &lock) != -1)
924 } while (errno == EINTR && !fail_on_intr);
934 *----------------------------------------------------------------------
938 * On platforms that implement concurrent calls to accept
939 * on a shared listening ipcFd, does nothing. On other platforms,
940 * releases an exclusive lock acquired by AcquireLock.
943 * 0 for successful call, -1 in case of system error (fatal).
946 * This process no longer holds the lock.
948 *----------------------------------------------------------------------
950 static int ReleaseLock(int sock)
955 lock.l_type = F_UNLCK;
957 lock.l_whence = SEEK_SET;
960 if (fcntl(sock, F_SETLK, &lock) != -1)
962 } while (errno == EINTR);
971 /**********************************************************************
972 * Determine if the errno resulting from a failed accept() warrants a
973 * retry or exit(). Based on Apache's http_main.c accept() handling
974 * and Stevens' Unix Network Programming Vol 1, 2nd Ed, para. 15.6.
976 static int is_reasonable_accept_errno (const int error)
980 /* EPROTO on certain older kernels really means ECONNABORTED, so
981 * we need to ignore it for them. See discussion in new-httpd
982 * archives nh.9701 search for EPROTO. Also see nh.9603, search
983 * for EPROTO: There is potentially a bug in Solaris 2.x x<6, and
984 * other boxes that implement tcp sockets in userland (i.e. on top of
985 * STREAMS). On these systems, EPROTO can actually result in a fatal
986 * loop. See PR#981 for example. It's hard to handle both uses of
993 /* Linux generates the rest of these, other tcp stacks (i.e.
994 * bsd) tend to hide them behind getsockopt() interfaces. They
995 * occur when the net goes sour or the client disconnects after the
996 * three-way handshake has been done in the kernel but before
997 * userland has picked up the socket. */
1017 /**********************************************************************
1018 * This works around a problem on Linux 2.0.x and SCO Unixware (maybe
1019 * others?). When a connect() is made to a Unix Domain socket, but its
1020 * not accept()ed before the web server gets impatient and close()s, an
1021 * accept() results in a valid file descriptor, but no data to read.
1022 * This causes a block on the first read() - which never returns!
1024 * Another approach to this is to write() to the socket to provoke a
1025 * SIGPIPE, but this is a pain because of the FastCGI protocol, the fact
1026 * that whatever is written has to be universally ignored by all FastCGI
1027 * web servers, and a SIGPIPE handler has to be installed which returns
1028 * (or SIGPIPE is ignored).
1030 * READABLE_UNIX_FD_DROP_DEAD_TIMEVAL = 2,0 by default.
1032 * Making it shorter is probably safe, but I'll leave that to you. Making
1033 * it 0,0 doesn't work reliably. The shorter you can reliably make it,
1034 * the faster your application will be able to recover (waiting 2 seconds
1035 * may _cause_ the problem when there is a very high demand). At any rate,
1036 * this is better than perma-blocking.
1038 static int is_af_unix_keeper(const int fd)
1040 struct timeval tval = { READABLE_UNIX_FD_DROP_DEAD_TIMEVAL };
1044 FD_SET(fd, &read_fds);
1046 return select(fd + 1, &read_fds, NULL, NULL, &tval) >= 0 && FD_ISSET(fd, &read_fds);
1050 *----------------------------------------------------------------------
1054 * Accepts a new FastCGI connection. This routine knows whether
1055 * we're dealing with TCP based sockets or NT Named Pipes for IPC.
1058 * -1 if the operation fails, otherwise this is a valid IPC fd.
1061 * New IPC connection is accepted.
1063 *----------------------------------------------------------------------
1065 int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs)
1069 struct sockaddr_un un;
1070 struct sockaddr_in in;
1074 if (AcquireLock(listen_sock, fail_on_intr))
1080 socklen_t len = sizeof(sa);
1082 int len = sizeof(sa);
1084 socket = accept(listen_sock, (struct sockaddr *)&sa, &len);
1085 } while (socket < 0 && errno == EINTR && !fail_on_intr);
1088 if (!is_reasonable_accept_errno(errno)) {
1089 int errnoSave = errno;
1090 ReleaseLock(listen_sock);
1096 else { /* socket >= 0 */
1099 if (sa.in.sin_family != AF_INET)
1103 /* No replies to outgoing data, so disable Nagle */
1104 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&set, sizeof(set));
1107 /* Check that the client IP address is approved */
1108 if (ClientAddrOK(&sa.in, webServerAddrs))
1115 if (ReleaseLock(listen_sock))
1118 if (sa.in.sin_family != AF_UNIX || is_af_unix_keeper(socket))
1122 } /* while(1) - lock */
1128 *----------------------------------------------------------------------
1132 * OS IPC routine to close an IPC connection.
1138 * IPC connection is closed.
1140 *----------------------------------------------------------------------
1142 int OS_IpcClose(int ipcFd)
1144 return OS_Close(ipcFd);
1148 *----------------------------------------------------------------------
1152 * Determines whether this process is a FastCGI process or not.
1155 * Returns 1 if FastCGI, 0 if not.
1160 *----------------------------------------------------------------------
1162 int OS_IsFcgi(int sock)
1165 struct sockaddr_in in;
1166 struct sockaddr_un un;
1169 socklen_t len = sizeof(sa);
1171 int len = sizeof(sa);
1176 if (getpeername(sock, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) {
1185 *----------------------------------------------------------------------
1189 * Sets selected flag bits in an open file descriptor.
1191 *----------------------------------------------------------------------
1193 void OS_SetFlags(int fd, int flags)
1196 if((val = fcntl(fd, F_GETFL, 0)) < 0) {
1200 if(fcntl(fd, F_SETFL, val) < 0) {