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