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