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.3 1998/12/04 02:57:35 roberts Exp $";
25 #include "fcgiappmisc.h"
35 #include <memory.h> /* for memchr() */
39 #ifdef HAVE_SYS_SOCKET_H
40 #include <sys/socket.h> /* for getpeername */
43 #include <fcntl.h> /* for fcntl */
49 #include <sys/types.h>
50 #ifdef HAVE_NETINET_IN_H
51 #include <netinet/in.h>
53 #include <arpa/inet.h>
58 # if defined(__STDC__) || defined(__cplusplus)
59 typedef void *ClientData;
61 typedef int *ClientData;
62 # endif /* __STDC__ */
67 * This structure holds an entry for each oustanding async I/O operation.
70 OS_AsyncProc procPtr; /* callout completion procedure */
71 ClientData clientData; /* caller private data */
80 * Entries in the async I/O table are allocated 2 per file descriptor.
82 * Read Entry Index = fd * 2
83 * Write Entry Index = (fd * 2) + 1
85 #define AIO_RD_IX(fd) (fd * 2)
86 #define AIO_WR_IX(fd) ((fd * 2) + 1)
88 static int asyncIoTableSize = 16;
89 static AioInfo *asyncIoTable = NULL;
90 #define STDIN_FILENO 0
91 #define STDOUT_FILENO 1
92 #define STDERR_FILENO 2
102 static int isFastCGI = FALSE;
103 static int libInitialized = FALSE;
105 static fd_set readFdSet;
106 static fd_set writeFdSet;
108 static fd_set readFdSetPost;
109 static int numRdPosted = 0;
110 static fd_set writeFdSetPost;
111 static int numWrPosted = 0;
112 static int volatile maxFd = -1;
116 *--------------------------------------------------------------
120 * Set up the OS library for use.
122 * NOTE: This function is really only needed for application
123 * asynchronous I/O. It will most likely change in the
124 * future to setup the multi-threaded environment.
127 * Returns 0 if success, -1 if not.
130 * Async I/O table allocated and initialized.
132 *--------------------------------------------------------------
134 int OS_LibInit(int stdioFds[3])
139 asyncIoTable = malloc(asyncIoTableSize * sizeof(AioInfo));
140 if(asyncIoTable == NULL) {
144 memset((char *) asyncIoTable, 0,
145 asyncIoTableSize * sizeof(AioInfo));
148 FD_ZERO(&writeFdSet);
149 FD_ZERO(&readFdSetPost);
150 FD_ZERO(&writeFdSetPost);
151 libInitialized = TRUE;
157 *--------------------------------------------------------------
161 * Shutdown the OS library.
167 * Memory freed, fds closed.
169 *--------------------------------------------------------------
171 void OS_LibShutdown()
178 libInitialized = FALSE;
184 *----------------------------------------------------------------------
186 * OS_BuildSockAddrUn --
188 * Using the pathname bindPath, fill in the sockaddr_un structure
189 * *servAddrPtr and the length of this structure *servAddrLen.
191 * The format of the sockaddr_un structure changed incompatibly in
192 * 4.3BSD Reno. Digital UNIX supports both formats, other systems
193 * support one or the other.
196 * 0 for normal return, -1 for failure (bindPath too long).
198 *----------------------------------------------------------------------
201 static int OS_BuildSockAddrUn(char *bindPath,
202 struct sockaddr_un *servAddrPtr,
205 int bindPathLen = strlen(bindPath);
207 #ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
208 if(bindPathLen >= sizeof(servAddrPtr->sun_path)) {
211 #else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
212 if(bindPathLen > sizeof(servAddrPtr->sun_path)) {
216 memset((char *) servAddrPtr, 0, sizeof(*servAddrPtr));
217 servAddrPtr->sun_family = AF_UNIX;
218 memcpy(servAddrPtr->sun_path, bindPath, bindPathLen);
219 #ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
220 *servAddrLen = sizeof(servAddrPtr->sun_len)
221 + sizeof(servAddrPtr->sun_family)
223 servAddrPtr->sun_len = *servAddrLen;
224 #else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
225 *servAddrLen = sizeof(servAddrPtr->sun_family) + bindPathLen;
230 union SockAddrUnion {
231 struct sockaddr_un unixVariant;
232 struct sockaddr_in inetVariant;
237 * OS_CreateLocalIpcFd --
239 * This procedure is responsible for creating the listener socket
240 * on Unix for local process communication. It will create a
241 * domain socket or a TCP/IP socket bound to "localhost" and return
242 * a file descriptor to it to the caller.
245 * Listener socket created. This call returns either a valid
246 * file descriptor or -1 on error.
251 *----------------------------------------------------------------------
253 int OS_CreateLocalIpcFd(char *bindPath)
255 int listenSock, servLen;
256 union SockAddrUnion sa;
260 char host[MAXPATHLEN];
262 strcpy(host, bindPath);
263 if((tp = strchr(host, ':')) != 0) {
265 if((port = atoi(tp)) == 0) {
271 if(tcp && (*host && strcmp(host, "localhost") != 0)) {
272 fprintf(stderr, "To start a service on a TCP port can not "
273 "specify a host name.\n"
274 "You should either use \"localhost:<port>\" or "
275 " just use \":<port>.\"\n");
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 = htonl(INADDR_ANY);
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, 5) < 0) {
314 perror("bind/listen");
323 *----------------------------------------------------------------------
327 * Create the socket and connect to the remote application if
330 * This was lifted from the cgi-fcgi application and was abstracted
331 * out because Windows NT does not have a domain socket and must
332 * use a named pipe which has a different API altogether.
335 * -1 if fail or a valid file descriptor if connection succeeds.
338 * Remote connection established.
340 *----------------------------------------------------------------------
342 int OS_FcgiConnect(char *bindPath)
344 union SockAddrUnion sa;
345 int servLen, resultSock;
348 char host[MAXPATHLEN];
352 strcpy(host, bindPath);
353 if((tp = strchr(host, ':')) != 0) {
355 if((port = atoi(tp)) == 0) {
363 if((hp = gethostbyname((*host ? host : "localhost"))) == NULL) {
364 fprintf(stderr, "Unknown host: %s\n", bindPath);
367 sa.inetVariant.sin_family = AF_INET;
368 memcpy((caddr_t)&sa.inetVariant.sin_addr, hp->h_addr, hp->h_length);
369 sa.inetVariant.sin_port = htons(port);
370 servLen = sizeof(sa.inetVariant);
371 resultSock = socket(AF_INET, SOCK_STREAM, 0);
373 if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
374 fprintf(stderr, "Listening socket's path name is too long.\n");
377 resultSock = socket(AF_UNIX, SOCK_STREAM, 0);
380 assert(resultSock >= 0);
381 connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant,
383 if(connectStatus >= 0) {
387 * Most likely (errno == ENOENT || errno == ECONNREFUSED)
388 * and no FCGI application server is running.
397 *--------------------------------------------------------------
401 * Pass through to the unix read function.
404 * Returns number of byes read, 0, or -1 failure: errno
405 * contains actual error.
410 *--------------------------------------------------------------
412 int OS_Read(int fd, char * buf, size_t len)
414 return(read(fd, buf, len));
418 *--------------------------------------------------------------
422 * Pass through to unix write function.
425 * Returns number of byes read, 0, or -1 failure: errno
426 * contains actual error.
431 *--------------------------------------------------------------
433 int OS_Write(int fd, char * buf, size_t len)
435 return(write(fd, buf, len));
440 *----------------------------------------------------------------------
444 * Spawns a new FastCGI listener process.
447 * 0 if success, -1 if error.
450 * Child process spawned.
452 *----------------------------------------------------------------------
454 int OS_SpawnChild(char *appPath, int listenFd)
463 if(forkResult == 0) {
465 * Close STDIN unconditionally. It's used by the parent
466 * process for CGI communication. The FastCGI applciation
467 * will be replacing this with the FastCGI listenFd IF
468 * STDIN_FILENO is the same as FCGI_LISTENSOCK_FILENO
469 * (which it is on Unix). Regardless, STDIN, STDOUT, and
470 * STDERR will be closed as the FastCGI process uses a
471 * multiplexed socket in their place.
476 * If the listenFd is already the value of FCGI_LISTENSOCK_FILENO
477 * we're set. If not, change it so the child knows where to
478 * get the listen socket from.
480 if(listenFd != FCGI_LISTENSOCK_FILENO) {
481 dup2(listenFd, FCGI_LISTENSOCK_FILENO);
485 close(STDOUT_FILENO);
486 close(STDERR_FILENO);
489 * We're a child. Exec the application.
491 * XXX: entire environment passes through
493 execl(appPath, appPath, NULL);
495 * XXX: Can't do this as we've already closed STDERR!!!
506 *--------------------------------------------------------------
508 * OS_AsyncReadStdin --
510 * This initiates an asynchronous read on the standard
513 * The abstraction is necessary because Windows NT does not
514 * have a clean way of "select"ing a file descriptor for
518 * -1 if error, 0 otherwise.
521 * Asynchronous bit is set in the readfd variable and
522 * request is enqueued.
524 *--------------------------------------------------------------
526 int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr,
527 ClientData clientData)
529 int index = AIO_RD_IX(STDIN_FILENO);
531 ASSERT(asyncIoTable[index].inUse == 0);
532 asyncIoTable[index].procPtr = procPtr;
533 asyncIoTable[index].clientData = clientData;
534 asyncIoTable[index].fd = STDIN_FILENO;
535 asyncIoTable[index].len = len;
536 asyncIoTable[index].offset = 0;
537 asyncIoTable[index].buf = buf;
538 asyncIoTable[index].inUse = 1;
539 FD_SET(STDIN_FILENO, &readFdSet);
540 if(STDIN_FILENO > maxFd)
541 maxFd = STDIN_FILENO;
545 static void GrowAsyncTable(void)
547 int oldTableSize = asyncIoTableSize;
549 asyncIoTableSize = asyncIoTableSize * 2;
550 asyncIoTable = realloc(asyncIoTable, asyncIoTableSize * sizeof(AioInfo));
551 if(asyncIoTable == NULL) {
555 memset((char *) &asyncIoTable[oldTableSize], 0,
556 oldTableSize * sizeof(AioInfo));
562 *--------------------------------------------------------------
566 * This initiates an asynchronous read on the file
567 * handle which may be a socket or named pipe.
569 * We also must save the ProcPtr and ClientData, so later
570 * when the io completes, we know who to call.
572 * We don't look at any results here (the ReadFile may
573 * return data if it is cached) but do all completion
574 * processing in OS_Select when we get the io completion
575 * port done notifications. Then we call the callback.
578 * -1 if error, 0 otherwise.
581 * Asynchronous I/O operation is queued for completion.
583 *--------------------------------------------------------------
585 int OS_AsyncRead(int fd, int offset, void *buf, int len,
586 OS_AsyncProc procPtr, ClientData clientData)
588 int index = AIO_RD_IX(fd);
590 ASSERT(asyncIoTable != NULL);
595 if(index >= asyncIoTableSize) {
599 ASSERT(asyncIoTable[index].inUse == 0);
600 asyncIoTable[index].procPtr = procPtr;
601 asyncIoTable[index].clientData = clientData;
602 asyncIoTable[index].fd = fd;
603 asyncIoTable[index].len = len;
604 asyncIoTable[index].offset = offset;
605 asyncIoTable[index].buf = buf;
606 asyncIoTable[index].inUse = 1;
607 FD_SET(fd, &readFdSet);
612 *--------------------------------------------------------------
616 * This initiates an asynchronous write on the "fake" file
617 * descriptor (which may be a file, socket, or named pipe).
618 * We also must save the ProcPtr and ClientData, so later
619 * when the io completes, we know who to call.
621 * We don't look at any results here (the WriteFile generally
622 * completes immediately) but do all completion processing
623 * in OS_DoIo when we get the io completion port done
624 * notifications. Then we call the callback.
627 * -1 if error, 0 otherwise.
630 * Asynchronous I/O operation is queued for completion.
632 *--------------------------------------------------------------
634 int OS_AsyncWrite(int fd, int offset, void *buf, int len,
635 OS_AsyncProc procPtr, ClientData clientData)
637 int index = AIO_WR_IX(fd);
642 if(index >= asyncIoTableSize) {
646 ASSERT(asyncIoTable[index].inUse == 0);
647 asyncIoTable[index].procPtr = procPtr;
648 asyncIoTable[index].clientData = clientData;
649 asyncIoTable[index].fd = fd;
650 asyncIoTable[index].len = len;
651 asyncIoTable[index].offset = offset;
652 asyncIoTable[index].buf = buf;
653 asyncIoTable[index].inUse = 1;
654 FD_SET(fd, &writeFdSet);
659 *--------------------------------------------------------------
663 * Closes the descriptor. This is a pass through to the
667 * 0 for success, -1 on failure
672 *--------------------------------------------------------------
676 int index = AIO_RD_IX(fd);
678 FD_CLR(fd, &readFdSet);
679 FD_CLR(fd, &readFdSetPost);
680 if(asyncIoTable[index].inUse != 0) {
681 asyncIoTable[index].inUse = 0;
684 FD_CLR(fd, &writeFdSet);
685 FD_CLR(fd, &writeFdSetPost);
686 index = AIO_WR_IX(fd);
687 if(asyncIoTable[index].inUse != 0) {
688 asyncIoTable[index].inUse = 0;
696 *--------------------------------------------------------------
700 * Cancel outstanding asynchronous reads and prevent subsequent
701 * reads from completing.
704 * Socket or file is shutdown. Return values mimic Unix shutdown:
705 * 0 success, -1 failure
707 *--------------------------------------------------------------
709 int OS_CloseRead(int fd)
711 if(asyncIoTable[AIO_RD_IX(fd)].inUse != 0) {
712 asyncIoTable[AIO_RD_IX(fd)].inUse = 0;
713 FD_CLR(fd, &readFdSet);
716 return shutdown(fd, 0);
721 *--------------------------------------------------------------
725 * This function was formerly OS_Select. It's purpose is
726 * to pull I/O completion events off the queue and dispatch
727 * them to the appropriate place.
733 * Handlers are called.
735 *--------------------------------------------------------------
737 int OS_DoIo(struct timeval *tmo)
739 int fd, len, selectStatus;
740 OS_AsyncProc procPtr;
741 ClientData clientData;
744 fd_set writeFdSetCpy;
746 FD_ZERO(&readFdSetCpy);
747 FD_ZERO(&writeFdSetCpy);
749 for(fd = 0; fd <= maxFd; fd++) {
750 if(FD_ISSET(fd, &readFdSet)) {
751 FD_SET(fd, &readFdSetCpy);
753 if(FD_ISSET(fd, &writeFdSet)) {
754 FD_SET(fd, &writeFdSetCpy);
759 * If there were no completed events from a prior call, see if there's
762 if(numRdPosted == 0 && numWrPosted == 0) {
763 selectStatus = select((maxFd+1), &readFdSetCpy, &writeFdSetCpy,
765 if(selectStatus < 0) {
769 for(fd = 0; fd <= maxFd; fd++) {
771 * Build up a list of completed events. We'll work off of
772 * this list as opposed to looping through the read and write
773 * fd sets since they can be affected by a callbacl routine.
775 if(FD_ISSET(fd, &readFdSetCpy)) {
777 FD_SET(fd, &readFdSetPost);
778 FD_CLR(fd, &readFdSet);
781 if(FD_ISSET(fd, &writeFdSetCpy)) {
783 FD_SET(fd, &writeFdSetPost);
784 FD_CLR(fd, &writeFdSet);
789 if(numRdPosted == 0 && numWrPosted == 0)
792 for(fd = 0; fd <= maxFd; fd++) {
794 * Do reads and dispatch callback.
796 if(FD_ISSET(fd, &readFdSetPost)
797 && asyncIoTable[AIO_RD_IX(fd)].inUse) {
800 FD_CLR(fd, &readFdSetPost);
801 aioPtr = &asyncIoTable[AIO_RD_IX(fd)];
803 len = read(aioPtr->fd, aioPtr->buf, aioPtr->len);
805 procPtr = aioPtr->procPtr;
806 aioPtr->procPtr = NULL;
807 clientData = aioPtr->clientData;
810 (*procPtr)(clientData, len);
814 * Do writes and dispatch callback.
816 if(FD_ISSET(fd, &writeFdSetPost) &&
817 asyncIoTable[AIO_WR_IX(fd)].inUse) {
820 FD_CLR(fd, &writeFdSetPost);
821 aioPtr = &asyncIoTable[AIO_WR_IX(fd)];
823 len = write(aioPtr->fd, aioPtr->buf, aioPtr->len);
825 procPtr = aioPtr->procPtr;
826 aioPtr->procPtr = NULL;
827 clientData = aioPtr->clientData;
829 (*procPtr)(clientData, len);
837 *----------------------------------------------------------------------
841 * Checks if a client address is in a list of allowed addresses
844 * TRUE if address list is empty or client address is present
845 * in the list, FALSE otherwise.
847 *----------------------------------------------------------------------
849 static int ClientAddrOK(struct sockaddr_in *saPtr, char *clientList)
852 char *clientListCopy, *cur, *next;
853 char *newString = NULL;
856 if(clientList == NULL || *clientList == '\0') {
860 strLen = strlen(clientList);
861 clientListCopy = malloc(strLen + 1);
862 assert(newString != NULL);
863 memcpy(newString, clientList, strLen);
864 newString[strLen] = '\000';
866 for(cur = clientListCopy; cur != NULL; cur = next) {
867 next = strchr(cur, ',');
871 if(inet_addr(cur) == saPtr->sin_addr.s_addr) {
876 free(clientListCopy);
882 *----------------------------------------------------------------------
886 * On platforms that implement concurrent calls to accept
887 * on a shared listening ipcFd, returns 0. On other platforms,
888 * acquires an exclusive lock across all processes sharing a
889 * listening ipcFd, blocking until the lock has been acquired.
892 * 0 for successful call, -1 in case of system error (fatal).
895 * This process now has the exclusive lock.
897 *----------------------------------------------------------------------
899 static int AcquireLock(int blocking)
903 lock.l_type = F_WRLCK;
905 lock.l_whence = SEEK_SET;
908 if(fcntl(FCGI_LISTENSOCK_FILENO,
909 blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
913 #endif /* USE_LOCKING */
918 *----------------------------------------------------------------------
922 * On platforms that implement concurrent calls to accept
923 * on a shared listening ipcFd, does nothing. On other platforms,
924 * releases an exclusive lock acquired by AcquireLock.
927 * 0 for successful call, -1 in case of system error (fatal).
930 * This process no longer holds the lock.
932 *----------------------------------------------------------------------
934 static int ReleaseLock(void)
938 lock.l_type = F_UNLCK;
940 lock.l_whence = SEEK_SET;
943 if(fcntl(FCGI_LISTENSOCK_FILENO, F_SETLK, &lock) < 0) {
946 #endif /* USE_LOCKING */
952 *----------------------------------------------------------------------
954 * OS_FcgiIpcAccept --
956 * Accepts a new FastCGI connection. This routine knows whether
957 * we're dealing with TCP based sockets or NT Named Pipes for IPC.
960 * -1 if the operation fails, otherwise this is a valid IPC fd.
963 * New IPC connection is accepted.
965 *----------------------------------------------------------------------
967 int OS_FcgiIpcAccept(char *clientAddrList)
971 struct sockaddr_un un;
972 struct sockaddr_in in;
976 if (AcquireLock(TRUE) < 0) {
982 socket = accept(FCGI_LISTENSOCK_FILENO,
983 (struct sockaddr *) &sa.un,
985 } while ((socket < 0) && (errno == EINTR));
989 * If the new connection uses TCP/IP, check the client IP address;
990 * if the address isn't valid, close the connection and
993 if ((sa.in.sin_family == AF_INET)
994 && (!ClientAddrOK(&sa.in, clientAddrList))) {
1001 /* Based on Apache's (v1.3.1) http_main.c accept() handling and
1002 * Stevens' Unix Network Programming Vol 1, 2nd Ed, para. 15.6
1006 /* EPROTO on certain older kernels really means
1007 * ECONNABORTED, so we need to ignore it for them.
1008 * See discussion in new-httpd archives nh.9701
1009 * search for EPROTO.
1011 * Also see nh.9603, search for EPROTO:
1012 * There is potentially a bug in Solaris 2.x x<6,
1013 * and other boxes that implement tcp sockets in
1014 * userland (i.e. on top of STREAMS). On these
1015 * systems, EPROTO can actually result in a fatal
1016 * loop. See PR#981 for example. It's hard to
1017 * handle both uses of EPROTO.
1024 /* Linux generates the rest of these, other tcp
1025 * stacks (i.e. bsd) tend to hide them behind
1026 * getsockopt() interfaces. They occur when
1027 * the net goes sour or the client disconnects
1028 * after the three-way handshake has been done
1029 * in the kernel but before userland has picked
1044 break; /* switch(errno) */
1047 int errnoSave = errno;
1052 } /* switch(errno) */
1055 if (ReleaseLock() < 0) {
1062 *----------------------------------------------------------------------
1066 * OS IPC routine to close an IPC connection.
1072 * IPC connection is closed.
1074 *----------------------------------------------------------------------
1076 int OS_IpcClose(int ipcFd)
1078 return OS_Close(ipcFd);
1083 *----------------------------------------------------------------------
1087 * Determines whether this process is a FastCGI process or not.
1090 * Returns 1 if FastCGI, 0 if not.
1095 *----------------------------------------------------------------------
1100 struct sockaddr_in in;
1101 struct sockaddr_un un;
1103 int len = sizeof(sa);
1105 if (getpeername(FCGI_LISTENSOCK_FILENO, (struct sockaddr *)&sa, &len) != 0
1106 && errno == ENOTCONN)
1115 *----------------------------------------------------------------------
1119 * Sets selected flag bits in an open file descriptor.
1121 *----------------------------------------------------------------------
1123 void OS_SetFlags(int fd, int flags)
1126 if((val = fcntl(fd, F_GETFL, 0)) < 0) {
1130 if(fcntl(fd, F_SETFL, val) < 0) {