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