3d7dcee026bf353afde61925c397919cefba2194
[catagits/fcgi2.git] / libfcgi / os_unix.c
1 /*
2  * os_unix.c --
3  *
4  *      Description of file.
5  *
6  *
7  *  Copyright (c) 1995 Open Market, Inc.
8  *  All rights reserved.
9  *
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.
14  *
15  *  Bill Snapper
16  *  snapper@openmarket.com
17  */
18
19 #ifndef lint
20 static const char rcsid[] = "$Id: os_unix.c,v 1.11 1999/08/02 19:22:00 skimo Exp $";
21 #endif /* not lint */
22
23 #include "fcgi_config.h"
24
25 #include <arpa/inet.h>
26 #include <assert.h>
27 #include <errno.h>
28 #include <fcntl.h>      /* for fcntl */
29 #include <math.h>
30 #include <memory.h>     /* for memchr() */
31 #include <netinet/tcp.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <sys/un.h>
39
40 #ifdef HAVE_NETDB_H
41 #include <netdb.h>
42 #endif
43
44 #ifdef HAVE_NETINET_IN_H
45 #include <netinet/in.h>
46 #endif
47
48 #ifdef HAVE_SYS_SOCKET_H
49 #include <sys/socket.h> /* for getpeername */
50 #endif
51
52 #ifdef HAVE_UNISTD_H
53 #include <unistd.h>
54 #endif
55
56 #include "fastcgi.h"
57 #include "fcgiapp.h"
58 #include "fcgiappmisc.h"
59 #include "fcgimisc.h"
60 #include "fcgios.h"
61
62 #ifndef FALSE
63 #define FALSE 0
64 #endif
65
66 #ifndef TRUE
67 #define TRUE 1
68 #endif
69
70 /*
71  * This structure holds an entry for each oustanding async I/O operation.
72  */
73 typedef struct {
74     OS_AsyncProc procPtr;           /* callout completion procedure */
75     ClientData clientData;          /* caller private data */
76     int fd;
77     int len;
78     int offset;
79     void *buf;
80     int inUse;
81 } AioInfo;
82
83 /*
84  * Entries in the async I/O table are allocated 2 per file descriptor.
85  *
86  * Read Entry Index  = fd * 2
87  * Write Entry Index = (fd * 2) + 1
88  */
89 #define AIO_RD_IX(fd) (fd * 2)
90 #define AIO_WR_IX(fd) ((fd * 2) + 1)
91
92 static int asyncIoTableSize = 16;
93 static AioInfo *asyncIoTable = NULL;
94
95 static int isFastCGI = FALSE;
96 static int libInitialized = FALSE;
97
98 static fd_set readFdSet;
99 static fd_set writeFdSet;
100
101 static fd_set readFdSetPost;
102 static int numRdPosted = 0;
103 static fd_set writeFdSetPost;
104 static int numWrPosted = 0;
105 static int volatile maxFd = -1;
106
107 \f
108 /*
109  *--------------------------------------------------------------
110  *
111  * OS_LibInit --
112  *
113  *      Set up the OS library for use.
114  *
115  *      NOTE: This function is really only needed for application
116  *            asynchronous I/O.  It will most likely change in the
117  *            future to setup the multi-threaded environment.
118  *
119  * Results:
120  *      Returns 0 if success, -1 if not.
121  *
122  * Side effects:
123  *      Async I/O table allocated and initialized.
124  *
125  *--------------------------------------------------------------
126  */
127 int OS_LibInit(int stdioFds[3])
128 {
129     if(libInitialized)
130         return 0;
131
132     asyncIoTable = (AioInfo *)malloc(asyncIoTableSize * sizeof(AioInfo));
133     if(asyncIoTable == NULL) {
134         errno = ENOMEM;
135         return -1;
136     }
137     memset((char *) asyncIoTable, 0,
138            asyncIoTableSize * sizeof(AioInfo));
139
140     FD_ZERO(&readFdSet);
141     FD_ZERO(&writeFdSet);
142     FD_ZERO(&readFdSetPost);
143     FD_ZERO(&writeFdSetPost);
144     libInitialized = TRUE;
145     return 0;
146 }
147
148 \f
149 /*
150  *--------------------------------------------------------------
151  *
152  * OS_LibShutdown --
153  *
154  *      Shutdown the OS library.
155  *
156  * Results:
157  *      None.
158  *
159  * Side effects:
160  *      Memory freed, fds closed.
161  *
162  *--------------------------------------------------------------
163  */
164 void OS_LibShutdown()
165 {
166     if(!libInitialized)
167         return;
168
169     free(asyncIoTable);
170     asyncIoTable = NULL;
171     libInitialized = FALSE;
172     return;
173 }
174
175 \f
176 /*
177  *----------------------------------------------------------------------
178  *
179  * OS_BuildSockAddrUn --
180  *
181  *      Using the pathname bindPath, fill in the sockaddr_un structure
182  *      *servAddrPtr and the length of this structure *servAddrLen.
183  *
184  *      The format of the sockaddr_un structure changed incompatibly in
185  *      4.3BSD Reno.  Digital UNIX supports both formats, other systems
186  *      support one or the other.
187  *
188  * Results:
189  *      0 for normal return, -1 for failure (bindPath too long).
190  *
191  *----------------------------------------------------------------------
192  */
193
194 static int OS_BuildSockAddrUn(char *bindPath,
195                               struct sockaddr_un *servAddrPtr,
196                               int *servAddrLen)
197 {
198     int bindPathLen = strlen(bindPath);
199
200 #ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
201     if(bindPathLen >= sizeof(servAddrPtr->sun_path)) {
202         return -1;
203     }
204 #else                           /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
205     if(bindPathLen > sizeof(servAddrPtr->sun_path)) {
206         return -1;
207     }
208 #endif
209     memset((char *) servAddrPtr, 0, sizeof(*servAddrPtr));
210     servAddrPtr->sun_family = AF_UNIX;
211     memcpy(servAddrPtr->sun_path, bindPath, bindPathLen);
212 #ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
213     *servAddrLen = sizeof(servAddrPtr->sun_len)
214             + sizeof(servAddrPtr->sun_family)
215             + bindPathLen + 1;
216     servAddrPtr->sun_len = *servAddrLen;
217 #else                           /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
218     *servAddrLen = sizeof(servAddrPtr->sun_family) + bindPathLen;
219 #endif
220     return 0;
221 }
222 \f
223 union SockAddrUnion {
224     struct  sockaddr_un unixVariant;
225     struct  sockaddr_in inetVariant;
226 };
227
228 \f
229 /*
230  * OS_CreateLocalIpcFd --
231  *
232  *   This procedure is responsible for creating the listener socket
233  *   on Unix for local process communication.  It will create a
234  *   domain socket or a TCP/IP socket bound to "localhost" and return
235  *   a file descriptor to it to the caller.
236  *
237  * Results:
238  *      Listener socket created.  This call returns either a valid
239  *      file descriptor or -1 on error.
240  *
241  * Side effects:
242  *      None.
243  *
244  *----------------------------------------------------------------------
245  */
246 int OS_CreateLocalIpcFd(char *bindPath)
247 {
248     int listenSock, servLen;
249     union   SockAddrUnion sa;
250     int     tcp = FALSE;
251     char    *tp;
252     short   port;
253     char    host[MAXPATHLEN];
254
255     strcpy(host, bindPath);
256     if((tp = strchr(host, ':')) != 0) {
257         *tp++ = 0;
258         if((port = atoi(tp)) == 0) {
259             *--tp = ':';
260          } else {
261             tcp = TRUE;
262          }
263     }
264     if(tcp && (*host && strcmp(host, "localhost") != 0)) {
265         fprintf(stderr, "To start a service on a TCP port can not "
266                         "specify a host name.\n"
267                         "You should either use \"localhost:<port>\" or "
268                         " just use \":<port>.\"\n");
269         exit(1);
270     }
271
272     if(tcp) {
273         listenSock = socket(AF_INET, SOCK_STREAM, 0);
274         if(listenSock >= 0) {
275             int flag = 1;
276             if(setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR,
277                           (char *) &flag, sizeof(flag)) < 0) {
278                 fprintf(stderr, "Can't set SO_REUSEADDR.\n");
279                 exit(1001);
280             }
281         }
282     } else {
283         listenSock = socket(AF_UNIX, SOCK_STREAM, 0);
284     }
285     if(listenSock < 0) {
286         return -1;
287     }
288
289     /*
290      * Bind the listening socket.
291      */
292     if(tcp) {
293         memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant));
294         sa.inetVariant.sin_family = AF_INET;
295         sa.inetVariant.sin_addr.s_addr = htonl(INADDR_ANY);
296         sa.inetVariant.sin_port = htons(port);
297         servLen = sizeof(sa.inetVariant);
298     } else {
299         unlink(bindPath);
300         if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
301             fprintf(stderr, "Listening socket's path name is too long.\n");
302             exit(1000);
303         }
304     }
305     if(bind(listenSock, (struct sockaddr *) &sa.unixVariant, servLen) < 0
306        || listen(listenSock, 5) < 0) {
307         perror("bind/listen");
308         exit(errno);
309     }
310
311     return listenSock;
312 }
313
314 \f
315 /*
316  *----------------------------------------------------------------------
317  *
318  * OS_FcgiConnect --
319  *
320  *      Create the socket and connect to the remote application if
321  *      possible.
322  *
323  *      This was lifted from the cgi-fcgi application and was abstracted
324  *      out because Windows NT does not have a domain socket and must
325  *      use a named pipe which has a different API altogether.
326  *
327  * Results:
328  *      -1 if fail or a valid file descriptor if connection succeeds.
329  *
330  * Side effects:
331  *      Remote connection established.
332  *
333  *----------------------------------------------------------------------
334  */
335 int OS_FcgiConnect(char *bindPath)
336 {
337     union   SockAddrUnion sa;
338     int servLen, resultSock;
339     int connectStatus;
340     char    *tp;
341     char    host[MAXPATHLEN];
342     short   port;
343     int     tcp = FALSE;
344
345     strcpy(host, bindPath);
346     if((tp = strchr(host, ':')) != 0) {
347         *tp++ = 0;
348         if((port = atoi(tp)) == 0) {
349             *--tp = ':';
350          } else {
351             tcp = TRUE;
352          }
353     }
354     if(tcp == TRUE) {
355         struct  hostent *hp;
356         if((hp = gethostbyname((*host ? host : "localhost"))) == NULL) {
357             fprintf(stderr, "Unknown host: %s\n", bindPath);
358             exit(1000);
359         }
360         sa.inetVariant.sin_family = AF_INET;
361         memcpy(&sa.inetVariant.sin_addr, hp->h_addr, hp->h_length);
362         sa.inetVariant.sin_port = htons(port);
363         servLen = sizeof(sa.inetVariant);
364         resultSock = socket(AF_INET, SOCK_STREAM, 0);
365     } else {
366         if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
367             fprintf(stderr, "Listening socket's path name is too long.\n");
368             exit(1000);
369         }
370         resultSock = socket(AF_UNIX, SOCK_STREAM, 0);
371     }
372
373     assert(resultSock >= 0);
374     connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant,
375                              servLen);
376     if(connectStatus >= 0) {
377         return resultSock;
378     } else {
379         /*
380          * Most likely (errno == ENOENT || errno == ECONNREFUSED)
381          * and no FCGI application server is running.
382          */
383         close(resultSock);
384         return -1;
385     }
386 }
387
388 \f
389 /*
390  *--------------------------------------------------------------
391  *
392  * OS_Read --
393  *
394  *      Pass through to the unix read function.
395  *
396  * Results:
397  *      Returns number of byes read, 0, or -1 failure: errno
398  *      contains actual error.
399  *
400  * Side effects:
401  *      None.
402  *
403  *--------------------------------------------------------------
404  */
405 int OS_Read(int fd, char * buf, size_t len)
406 {
407     return(read(fd, buf, len));
408 }
409 \f
410 /*
411  *--------------------------------------------------------------
412  *
413  * OS_Write --
414  *
415  *      Pass through to unix write function.
416  *
417  * Results:
418  *      Returns number of byes read, 0, or -1 failure: errno
419  *      contains actual error.
420  *
421  * Side effects:
422  *      none.
423  *
424  *--------------------------------------------------------------
425  */
426 int OS_Write(int fd, char * buf, size_t len)
427 {
428     return(write(fd, buf, len));
429 }
430
431 \f
432 /*
433  *----------------------------------------------------------------------
434  *
435  * OS_SpawnChild --
436  *
437  *      Spawns a new FastCGI listener process.
438  *
439  * Results:
440  *      0 if success, -1 if error.
441  *
442  * Side effects:
443  *      Child process spawned.
444  *
445  *----------------------------------------------------------------------
446  */
447 int OS_SpawnChild(char *appPath, int listenFd)
448 {
449     int forkResult;
450
451     forkResult = fork();
452     if(forkResult < 0) {
453         exit(errno);
454     }
455
456     if(forkResult == 0) {
457         /*
458          * Close STDIN unconditionally.  It's used by the parent
459          * process for CGI communication.  The FastCGI applciation
460          * will be replacing this with the FastCGI listenFd IF
461          * STDIN_FILENO is the same as FCGI_LISTENSOCK_FILENO
462          * (which it is on Unix).  Regardless, STDIN, STDOUT, and
463          * STDERR will be closed as the FastCGI process uses a
464          * multiplexed socket in their place.
465          */
466         close(STDIN_FILENO);
467
468         /*
469          * If the listenFd is already the value of FCGI_LISTENSOCK_FILENO
470          * we're set.  If not, change it so the child knows where to
471          * get the listen socket from.
472          */
473         if(listenFd != FCGI_LISTENSOCK_FILENO) {
474             dup2(listenFd, FCGI_LISTENSOCK_FILENO);
475             close(listenFd);
476         }
477
478         close(STDOUT_FILENO);
479         close(STDERR_FILENO);
480
481         /*
482          * We're a child.  Exec the application.
483          *
484          * XXX: entire environment passes through
485          */
486         execl(appPath, appPath, NULL);
487         /*
488          * XXX: Can't do this as we've already closed STDERR!!!
489          *
490          * perror("exec");
491          */
492         exit(errno);
493     }
494     return 0;
495 }
496
497 \f
498 /*
499  *--------------------------------------------------------------
500  *
501  * OS_AsyncReadStdin --
502  *
503  *      This initiates an asynchronous read on the standard
504  *      input handle.
505  *
506  *      The abstraction is necessary because Windows NT does not
507  *      have a clean way of "select"ing a file descriptor for
508  *      I/O.
509  *
510  * Results:
511  *      -1 if error, 0 otherwise.
512  *
513  * Side effects:
514  *      Asynchronous bit is set in the readfd variable and
515  *      request is enqueued.
516  *
517  *--------------------------------------------------------------
518  */
519 int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr,
520                       ClientData clientData)
521 {
522     int index = AIO_RD_IX(STDIN_FILENO);
523
524     ASSERT(asyncIoTable[index].inUse == 0);
525     asyncIoTable[index].procPtr = procPtr;
526     asyncIoTable[index].clientData = clientData;
527     asyncIoTable[index].fd = STDIN_FILENO;
528     asyncIoTable[index].len = len;
529     asyncIoTable[index].offset = 0;
530     asyncIoTable[index].buf = buf;
531     asyncIoTable[index].inUse = 1;
532     FD_SET(STDIN_FILENO, &readFdSet);
533     if(STDIN_FILENO > maxFd)
534         maxFd = STDIN_FILENO;
535     return 0;
536 }
537
538 static void GrowAsyncTable(void)
539 {
540     int oldTableSize = asyncIoTableSize;
541
542     asyncIoTableSize = asyncIoTableSize * 2;
543     asyncIoTable = (AioInfo *)realloc(asyncIoTable, asyncIoTableSize * sizeof(AioInfo));
544     if(asyncIoTable == NULL) {
545         errno = ENOMEM;
546         exit(errno);
547     }
548     memset((char *) &asyncIoTable[oldTableSize], 0,
549            oldTableSize * sizeof(AioInfo));
550
551 }
552
553 \f
554 /*
555  *--------------------------------------------------------------
556  *
557  * OS_AsyncRead --
558  *
559  *      This initiates an asynchronous read on the file
560  *      handle which may be a socket or named pipe.
561  *
562  *      We also must save the ProcPtr and ClientData, so later
563  *      when the io completes, we know who to call.
564  *
565  *      We don't look at any results here (the ReadFile may
566  *      return data if it is cached) but do all completion
567  *      processing in OS_Select when we get the io completion
568  *      port done notifications.  Then we call the callback.
569  *
570  * Results:
571  *      -1 if error, 0 otherwise.
572  *
573  * Side effects:
574  *      Asynchronous I/O operation is queued for completion.
575  *
576  *--------------------------------------------------------------
577  */
578 int OS_AsyncRead(int fd, int offset, void *buf, int len,
579                  OS_AsyncProc procPtr, ClientData clientData)
580 {
581     int index = AIO_RD_IX(fd);
582
583     ASSERT(asyncIoTable != NULL);
584
585     if(fd > maxFd)
586         maxFd = fd;
587
588     if(index >= asyncIoTableSize) {
589         GrowAsyncTable();
590     }
591
592     ASSERT(asyncIoTable[index].inUse == 0);
593     asyncIoTable[index].procPtr = procPtr;
594     asyncIoTable[index].clientData = clientData;
595     asyncIoTable[index].fd = fd;
596     asyncIoTable[index].len = len;
597     asyncIoTable[index].offset = offset;
598     asyncIoTable[index].buf = buf;
599     asyncIoTable[index].inUse = 1;
600     FD_SET(fd, &readFdSet);
601     return 0;
602 }
603 \f
604 /*
605  *--------------------------------------------------------------
606  *
607  * OS_AsyncWrite --
608  *
609  *      This initiates an asynchronous write on the "fake" file
610  *      descriptor (which may be a file, socket, or named pipe).
611  *      We also must save the ProcPtr and ClientData, so later
612  *      when the io completes, we know who to call.
613  *
614  *      We don't look at any results here (the WriteFile generally
615  *      completes immediately) but do all completion processing
616  *      in OS_DoIo when we get the io completion port done
617  *      notifications.  Then we call the callback.
618  *
619  * Results:
620  *      -1 if error, 0 otherwise.
621  *
622  * Side effects:
623  *      Asynchronous I/O operation is queued for completion.
624  *
625  *--------------------------------------------------------------
626  */
627 int OS_AsyncWrite(int fd, int offset, void *buf, int len,
628                   OS_AsyncProc procPtr, ClientData clientData)
629 {
630     int index = AIO_WR_IX(fd);
631
632     if(fd > maxFd)
633         maxFd = fd;
634
635     if(index >= asyncIoTableSize) {
636         GrowAsyncTable();
637     }
638
639     ASSERT(asyncIoTable[index].inUse == 0);
640     asyncIoTable[index].procPtr = procPtr;
641     asyncIoTable[index].clientData = clientData;
642     asyncIoTable[index].fd = fd;
643     asyncIoTable[index].len = len;
644     asyncIoTable[index].offset = offset;
645     asyncIoTable[index].buf = buf;
646     asyncIoTable[index].inUse = 1;
647     FD_SET(fd, &writeFdSet);
648     return 0;
649 }
650 \f
651 /*
652  *--------------------------------------------------------------
653  *
654  * OS_Close --
655  *
656  *      Closes the descriptor.  This is a pass through to the
657  *      Unix close.
658  *
659  * Results:
660  *      0 for success, -1 on failure
661  *
662  * Side effects:
663  *      None.
664  *
665  *--------------------------------------------------------------
666  */
667 int OS_Close(int fd)
668 {
669     int index = AIO_RD_IX(fd);
670
671     FD_CLR(fd, &readFdSet);
672     FD_CLR(fd, &readFdSetPost);
673     if(asyncIoTable[index].inUse != 0) {
674         asyncIoTable[index].inUse = 0;
675     }
676
677     FD_CLR(fd, &writeFdSet);
678     FD_CLR(fd, &writeFdSetPost);
679     index = AIO_WR_IX(fd);
680     if(asyncIoTable[index].inUse != 0) {
681         asyncIoTable[index].inUse = 0;
682     }
683     if(maxFd == fd)
684         maxFd--;
685     return close(fd);
686 }
687 \f
688 /*
689  *--------------------------------------------------------------
690  *
691  * OS_CloseRead --
692  *
693  *      Cancel outstanding asynchronous reads and prevent subsequent
694  *      reads from completing.
695  *
696  * Results:
697  *      Socket or file is shutdown. Return values mimic Unix shutdown:
698  *              0 success, -1 failure
699  *
700  *--------------------------------------------------------------
701  */
702 int OS_CloseRead(int fd)
703 {
704     if(asyncIoTable[AIO_RD_IX(fd)].inUse != 0) {
705         asyncIoTable[AIO_RD_IX(fd)].inUse = 0;
706         FD_CLR(fd, &readFdSet);
707     }
708
709     return shutdown(fd, 0);
710 }
711
712 \f
713 /*
714  *--------------------------------------------------------------
715  *
716  * OS_DoIo --
717  *
718  *      This function was formerly OS_Select.  It's purpose is
719  *      to pull I/O completion events off the queue and dispatch
720  *      them to the appropriate place.
721  *
722  * Results:
723  *      Returns 0.
724  *
725  * Side effects:
726  *      Handlers are called.
727  *
728  *--------------------------------------------------------------
729  */
730 int OS_DoIo(struct timeval *tmo)
731 {
732     int fd, len, selectStatus;
733     OS_AsyncProc procPtr;
734     ClientData clientData;
735     AioInfo *aioPtr;
736     fd_set readFdSetCpy;
737     fd_set writeFdSetCpy;
738
739     FD_ZERO(&readFdSetCpy);
740     FD_ZERO(&writeFdSetCpy);
741
742     for(fd = 0; fd <= maxFd; fd++) {
743         if(FD_ISSET(fd, &readFdSet)) {
744             FD_SET(fd, &readFdSetCpy);
745         }
746         if(FD_ISSET(fd, &writeFdSet)) {
747             FD_SET(fd, &writeFdSetCpy);
748         }
749     }
750
751     /*
752      * If there were no completed events from a prior call, see if there's
753      * any work to do.
754      */
755     if(numRdPosted == 0 && numWrPosted == 0) {
756         selectStatus = select((maxFd+1), &readFdSetCpy, &writeFdSetCpy,
757                               NULL, tmo);
758         if(selectStatus < 0) {
759             exit(errno);
760         }
761
762         for(fd = 0; fd <= maxFd; fd++) {
763             /*
764              * Build up a list of completed events.  We'll work off of
765              * this list as opposed to looping through the read and write
766              * fd sets since they can be affected by a callbacl routine.
767              */
768             if(FD_ISSET(fd, &readFdSetCpy)) {
769                 numRdPosted++;
770                 FD_SET(fd, &readFdSetPost);
771                 FD_CLR(fd, &readFdSet);
772             }
773
774             if(FD_ISSET(fd, &writeFdSetCpy)) {
775                 numWrPosted++;
776                 FD_SET(fd, &writeFdSetPost);
777                 FD_CLR(fd, &writeFdSet);
778             }
779         }
780     }
781
782     if(numRdPosted == 0 && numWrPosted == 0)
783         return 0;
784
785     for(fd = 0; fd <= maxFd; fd++) {
786         /*
787          * Do reads and dispatch callback.
788          */
789         if(FD_ISSET(fd, &readFdSetPost)
790            && asyncIoTable[AIO_RD_IX(fd)].inUse) {
791
792             numRdPosted--;
793             FD_CLR(fd, &readFdSetPost);
794             aioPtr = &asyncIoTable[AIO_RD_IX(fd)];
795
796             len = read(aioPtr->fd, aioPtr->buf, aioPtr->len);
797
798             procPtr = aioPtr->procPtr;
799             aioPtr->procPtr = NULL;
800             clientData = aioPtr->clientData;
801             aioPtr->inUse = 0;
802
803             (*procPtr)(clientData, len);
804         }
805
806         /*
807          * Do writes and dispatch callback.
808          */
809         if(FD_ISSET(fd, &writeFdSetPost) &&
810            asyncIoTable[AIO_WR_IX(fd)].inUse) {
811
812             numWrPosted--;
813             FD_CLR(fd, &writeFdSetPost);
814             aioPtr = &asyncIoTable[AIO_WR_IX(fd)];
815
816             len = write(aioPtr->fd, aioPtr->buf, aioPtr->len);
817
818             procPtr = aioPtr->procPtr;
819             aioPtr->procPtr = NULL;
820             clientData = aioPtr->clientData;
821             aioPtr->inUse = 0;
822             (*procPtr)(clientData, len);
823         }
824     }
825     return 0;
826 }
827
828 \f
829 /*
830  *----------------------------------------------------------------------
831  *
832  * ClientAddrOK --
833  *
834  *      Checks if a client address is in a list of allowed addresses
835  *
836  * Results:
837  *      TRUE if address list is empty or client address is present
838  *      in the list, FALSE otherwise.
839  *
840  *----------------------------------------------------------------------
841  */
842 static int ClientAddrOK(struct sockaddr_in *saPtr, char *clientList)
843 {
844     int result = FALSE;
845     char *clientListCopy, *cur, *next;
846     char *newString = NULL;
847     int strLen;
848
849     if(clientList == NULL || *clientList == '\0') {
850         return TRUE;
851     }
852
853     strLen = strlen(clientList);
854     clientListCopy = (char *)malloc(strLen + 1);
855     assert(newString != NULL);
856     memcpy(newString, clientList, strLen);
857     newString[strLen] = '\000';
858
859     for(cur = clientListCopy; cur != NULL; cur = next) {
860         next = strchr(cur, ',');
861         if(next != NULL) {
862             *next++ = '\0';
863         }
864         if(inet_addr(cur) == saPtr->sin_addr.s_addr) {
865             result = TRUE;
866             break;
867         }
868     }
869     free(clientListCopy);
870     return result;
871 }
872
873 \f
874 /*
875  *----------------------------------------------------------------------
876  *
877  * AcquireLock --
878  *
879  *      On platforms that implement concurrent calls to accept
880  *      on a shared listening ipcFd, returns 0.  On other platforms,
881  *      acquires an exclusive lock across all processes sharing a
882  *      listening ipcFd, blocking until the lock has been acquired.
883  *
884  * Results:
885  *      0 for successful call, -1 in case of system error (fatal).
886  *
887  * Side effects:
888  *      This process now has the exclusive lock.
889  *
890  *----------------------------------------------------------------------
891  */
892 static int AcquireLock(int blocking)
893 {
894 #ifdef USE_LOCKING
895     struct flock lock;
896     lock.l_type = F_WRLCK;
897     lock.l_start = 0;
898     lock.l_whence = SEEK_SET;
899     lock.l_len = 0;
900
901     if(fcntl(FCGI_LISTENSOCK_FILENO,
902              blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
903         if (errno != EINTR)
904             return -1;
905     }
906 #endif /* USE_LOCKING */
907     return 0;
908 }
909 \f
910 /*
911  *----------------------------------------------------------------------
912  *
913  * ReleaseLock --
914  *
915  *      On platforms that implement concurrent calls to accept
916  *      on a shared listening ipcFd, does nothing.  On other platforms,
917  *      releases an exclusive lock acquired by AcquireLock.
918  *
919  * Results:
920  *      0 for successful call, -1 in case of system error (fatal).
921  *
922  * Side effects:
923  *      This process no longer holds the lock.
924  *
925  *----------------------------------------------------------------------
926  */
927 static int ReleaseLock(void)
928 {
929 #ifdef USE_LOCKING
930     struct flock lock;
931     lock.l_type = F_UNLCK;
932     lock.l_start = 0;
933     lock.l_whence = SEEK_SET;
934     lock.l_len = 0;
935
936     if(fcntl(FCGI_LISTENSOCK_FILENO, F_SETLK, &lock) < 0) {
937         return -1;
938     }
939 #endif /* USE_LOCKING */
940     return 0;
941 }
942
943 \f
944 /**********************************************************************
945  * Determine if the errno resulting from a failed accept() warrants a
946  * retry or exit().  Based on Apache's http_main.c accept() handling
947  * and Stevens' Unix Network Programming Vol 1, 2nd Ed, para. 15.6.
948  */
949 static int is_reasonable_accept_errno (const int error)
950 {
951     switch (error) {
952 #ifdef EPROTO
953         /* EPROTO on certain older kernels really means ECONNABORTED, so
954          * we need to ignore it for them.  See discussion in new-httpd
955          * archives nh.9701 search for EPROTO.  Also see nh.9603, search
956          * for EPROTO:  There is potentially a bug in Solaris 2.x x<6, and
957          * other boxes that implement tcp sockets in userland (i.e. on top of
958          * STREAMS).  On these systems, EPROTO can actually result in a fatal
959          * loop.  See PR#981 for example.  It's hard to handle both uses of
960          * EPROTO. */
961         case EPROTO:
962 #endif
963 #ifdef ECONNABORTED
964         case ECONNABORTED:
965 #endif
966         /* Linux generates the rest of these, other tcp stacks (i.e.
967          * bsd) tend to hide them behind getsockopt() interfaces.  They
968          * occur when the net goes sour or the client disconnects after the
969          * three-way handshake has been done in the kernel but before
970          * userland has picked up the socket. */
971 #ifdef ECONNRESET
972         case ECONNRESET:
973 #endif
974 #ifdef ETIMEDOUT
975         case ETIMEDOUT:
976 #endif
977 #ifdef EHOSTUNREACH
978         case EHOSTUNREACH:
979 #endif
980 #ifdef ENETUNREACH
981         case ENETUNREACH:
982 #endif
983             return 1;
984
985         default:
986             return 0;
987     }
988 }
989
990 /**********************************************************************
991  * This works around a problem on Linux 2.0.x and SCO Unixware (maybe
992  * others?).  When a connect() is made to a Unix Domain socket, but its
993  * not accept()ed before the web server gets impatient and close()s, an
994  * accept() results in a valid file descriptor, but no data to read.
995  * This causes a block on the first read() - which never returns!
996  *
997  * Another approach to this is to write() to the socket to provoke a
998  * SIGPIPE, but this is a pain because of the FastCGI protocol, the fact
999  * that whatever is written has to be universally ignored by all FastCGI
1000  * web servers, and a SIGPIPE handler has to be installed which returns
1001  * (or SIGPIPE is ignored).
1002  *
1003  * READABLE_UNIX_FD_DROP_DEAD_TIMEVAL = 2,0 by default.
1004  *
1005  * Making it shorter is probably safe, but I'll leave that to you.  Making
1006  * it 0,0 doesn't work reliably.  The shorter you can reliably make it,
1007  * the faster your application will be able to recover (waiting 2 seconds
1008  * may _cause_ the problem when there is a very high demand). At any rate,
1009  * this is better than perma-blocking.
1010  */
1011 static int is_af_unix_keeper(const int fd)
1012 {
1013     struct timeval tval = { READABLE_UNIX_FD_DROP_DEAD_TIMEVAL };
1014     fd_set read_fds;
1015
1016     FD_ZERO(&read_fds);
1017     FD_SET(fd, &read_fds);
1018
1019     return select(fd + 1, &read_fds, NULL, NULL, &tval) >= 0 && FD_ISSET(fd, &read_fds);
1020 }
1021
1022 /*
1023  *----------------------------------------------------------------------
1024  *
1025  * OS_FcgiIpcAccept --
1026  *
1027  *      Accepts a new FastCGI connection.  This routine knows whether
1028  *      we're dealing with TCP based sockets or NT Named Pipes for IPC.
1029  *
1030  * Results:
1031  *      -1 if the operation fails, otherwise this is a valid IPC fd.
1032  *
1033  * Side effects:
1034  *      New IPC connection is accepted.
1035  *
1036  *----------------------------------------------------------------------
1037  */
1038 int OS_FcgiIpcAccept(char *clientAddrList)
1039 {
1040     int socket;
1041     union {
1042         struct sockaddr_un un;
1043         struct sockaddr_in in;
1044     } sa;
1045 #ifdef HAVE_SOCKLEN
1046     socklen_t len;
1047 #else
1048     int len;
1049 #endif
1050
1051     while (1) {
1052         if (AcquireLock(TRUE) < 0)
1053             return (-1);
1054
1055         while (1) {
1056             do {
1057                 len = sizeof(sa);
1058                 socket = accept(FCGI_LISTENSOCK_FILENO, (struct sockaddr *) &sa.un, &len);
1059             } while (socket < 0 && errno == EINTR);
1060
1061             if (socket < 0) {
1062                 if (!is_reasonable_accept_errno(errno)) {
1063                     int errnoSave = errno;
1064
1065                     ReleaseLock();
1066                     errno = errnoSave;
1067                     return (-1);
1068                 }
1069                 errno = 0;
1070             }
1071             else {
1072                 int set = 1;
1073
1074                 if (sa.in.sin_family != AF_INET)
1075                     break;
1076
1077 #ifdef TCP_NODELAY
1078                 /* No replies to outgoing data, so disable Nagle */
1079                 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&set, sizeof(set));
1080 #endif
1081
1082                 /* Check that the client IP address is approved */
1083                 if (ClientAddrOK(&sa.in, clientAddrList))
1084                     break;
1085
1086                 close(socket);
1087             }
1088         }  /* while(1) - accept */
1089
1090         if (ReleaseLock() < 0)
1091             return (-1);
1092
1093         if (sa.in.sin_family != AF_UNIX || is_af_unix_keeper(socket))
1094             break;
1095
1096         close(socket);
1097     }  /* while(1) - lock */
1098
1099     return (socket);
1100 }
1101 \f
1102 /*
1103  *----------------------------------------------------------------------
1104  *
1105  * OS_IpcClose
1106  *
1107  *      OS IPC routine to close an IPC connection.
1108  *
1109  * Results:
1110  *
1111  *
1112  * Side effects:
1113  *      IPC connection is closed.
1114  *
1115  *----------------------------------------------------------------------
1116  */
1117 int OS_IpcClose(int ipcFd)
1118 {
1119     return OS_Close(ipcFd);
1120 }
1121
1122 \f
1123 /*
1124  *----------------------------------------------------------------------
1125  *
1126  * OS_IsFcgi --
1127  *
1128  *      Determines whether this process is a FastCGI process or not.
1129  *
1130  * Results:
1131  *      Returns 1 if FastCGI, 0 if not.
1132  *
1133  * Side effects:
1134  *      None.
1135  *
1136  *----------------------------------------------------------------------
1137  */
1138 int OS_IsFcgi()
1139 {
1140         union {
1141         struct sockaddr_in in;
1142         struct sockaddr_un un;
1143     } sa;
1144 #ifdef HAVE_SOCKLEN
1145     socklen_t len = sizeof(sa);
1146 #else
1147     int len = sizeof(sa);
1148 #endif
1149
1150     if (getpeername(FCGI_LISTENSOCK_FILENO, (struct sockaddr *)&sa, &len) != 0
1151             && errno == ENOTCONN)
1152         isFastCGI = TRUE;
1153     else
1154         isFastCGI = FALSE;
1155
1156     return (isFastCGI);
1157 }
1158 \f
1159 /*
1160  *----------------------------------------------------------------------
1161  *
1162  * OS_SetFlags --
1163  *
1164  *      Sets selected flag bits in an open file descriptor.
1165  *
1166  *----------------------------------------------------------------------
1167  */
1168 void OS_SetFlags(int fd, int flags)
1169 {
1170     int val;
1171     if((val = fcntl(fd, F_GETFL, 0)) < 0) {
1172         exit(errno);
1173     }
1174     val |= flags;
1175     if(fcntl(fd, F_SETFL, val) < 0) {
1176         exit(errno);
1177     }
1178 }