Back to index

php5  5.3.10
lsapilib.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2007 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available at through the world-wide-web at the following url:        |
00010    | http://www.php.net/license/3_01.txt.                                 |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: George Wang <gwang@litespeedtech.com>                        |
00016    +----------------------------------------------------------------------+
00017 */
00018 
00019 /* $Id: lsapilib.c 311935 2011-06-08 16:51:59Z gwang $ */
00020 
00021 /*
00022 Copyright (c) 2007, Lite Speed Technologies Inc.
00023 All rights reserved.
00024 
00025 Redistribution and use in source and binary forms, with or without
00026 modification, are permitted provided that the following conditions are
00027 met: 
00028 
00029     * Redistributions of source code must retain the above copyright
00030       notice, this list of conditions and the following disclaimer. 
00031     * Redistributions in binary form must reproduce the above
00032       copyright notice, this list of conditions and the following
00033       disclaimer in the documentation and/or other materials provided
00034       with the distribution. 
00035     * Neither the name of the Lite Speed Technologies Inc nor the
00036       names of its contributors may be used to endorse or promote
00037       products derived from this software without specific prior
00038       written permission.  
00039 
00040 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00041 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00042 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00043 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00044 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00045 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00046 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00047 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00048 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00049 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00050 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00051 */
00052 
00053 #include <lsapilib.h>
00054 
00055 #include <ctype.h>
00056 #include <errno.h>
00057 #include <fcntl.h>
00058 
00059 #include <arpa/inet.h>
00060 #include <netdb.h>
00061 #include <netinet/in.h>
00062 #include <netinet/tcp.h>
00063 #include <sys/un.h>
00064 #include <signal.h>
00065 #include <stdlib.h>
00066 #include <stdio.h>
00067 #include <string.h>
00068 #include <sys/mman.h>
00069 #include <sys/resource.h>
00070 #include <sys/socket.h>
00071 #include <sys/time.h>
00072 #include <sys/uio.h>
00073 #include <sys/wait.h>
00074 #include <time.h>
00075 #include <unistd.h>
00076 
00077 #define LSAPI_ST_REQ_HEADER     1
00078 #define LSAPI_ST_REQ_BODY       2
00079 #define LSAPI_ST_RESP_HEADER    4
00080 #define LSAPI_ST_RESP_BODY      8
00081 
00082 #define LSAPI_RESP_BUF_SIZE     8192
00083 #define LSAPI_INIT_RESP_HEADER_LEN 4096
00084 
00085 
00086 static int g_inited = 0;
00087 static int g_running = 1;
00088 static int s_ppid;
00089 static int s_slow_req_msecs = 0;
00090 LSAPI_Request g_req = { -1, -1 };
00091 
00092 void Flush_RespBuf_r( LSAPI_Request * pReq );
00093 
00094 static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
00095 {
00096     "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
00097     "HTTP_ACCEPT_ENCODING",
00098     "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
00099     "HTTP_CONNECTION", "CONTENT_TYPE",
00100     "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
00101     "HTTP_HOST", "HTTP_PRAGMA",
00102     "HTTP_REFERER", "HTTP_USER_AGENT",
00103     "HTTP_CACHE_CONTROL",
00104     "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
00105     "HTTP_IF_NONE_MATCH",
00106     "HTTP_IF_RANGE",
00107     "HTTP_IF_UNMODIFIED_SINCE",
00108     "HTTP_KEEP_ALIVE",
00109     "HTTP_RANGE",
00110     "HTTP_X_FORWARDED_FOR",
00111     "HTTP_VIA",
00112     "HTTP_TRANSFER_ENCODING"
00113 };
00114      
00115 static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = {
00116      11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
00117      22, 13, 18, 13, 24, 15, 10, 20, 8, 22 
00118 };
00119 
00120 
00121 static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = {
00122     "Accept", "Accept-Charset",
00123     "Accept-Encoding",
00124     "Accept-Language", "Authorization",
00125     "Connection", "Content-Type",
00126     "Content-Length", "Cookie", "Cookie2",
00127     "Host", "Pragma",
00128     "Referer", "User-Agent",
00129     "Cache-Control",
00130     "If-Modified-Since", "If-Match",
00131     "If-None-Match",
00132     "If-Range",
00133     "If-Unmodified-Since",
00134     "Keep-Alive",
00135     "Range",
00136     "X-Forwarded-For",
00137     "Via",
00138     "Transfer-Encoding"
00139 };
00140 
00141 static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = {
00142     6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, /* user-agent */
00143     13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
00144 };
00145      
00146 static void lsapi_sigpipe( int sig )
00147 {
00148 }
00149 static void lsapi_siguser1( int sig )
00150 {
00151     g_running = 0;
00152 }
00153 
00154 #ifndef sighandler_t
00155 typedef void (*sighandler_t)(int);
00156 #endif
00157           
00158 static void lsapi_signal(int signo, sighandler_t handler)
00159 {
00160     struct sigaction sa;
00161 
00162     sigaction(signo, NULL, &sa);
00163 
00164     if (sa.sa_handler == SIG_DFL) {
00165         sigemptyset(&sa.sa_mask);
00166         sa.sa_flags = 0;
00167         sa.sa_handler = handler;
00168         sigaction(signo, &sa, NULL);
00169     }
00170 }
00171 
00172 
00173 static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
00174                                 char type, int len )
00175 {
00176     pHeader->m_versionB0 = LSAPI_VERSION_B0;  /* LSAPI protocol version */
00177     pHeader->m_versionB1 = LSAPI_VERSION_B1;
00178     pHeader->m_type      = type;
00179     pHeader->m_flag      = LSAPI_ENDIAN;
00180     pHeader->m_packetLen.m_iLen = len;
00181 }
00182 
00183 static  int lsapi_set_nblock( int fd, int nonblock )
00184 {
00185     int val = fcntl( fd, F_GETFL, 0 );
00186     if ( nonblock )
00187     {
00188         if (!( val & O_NONBLOCK ))
00189         {
00190             return fcntl( fd, F_SETFL, val | O_NONBLOCK );
00191         }
00192     }
00193     else
00194     {
00195         if ( val & O_NONBLOCK )
00196         {
00197             return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
00198         }
00199     }
00200     return 0;
00201 }
00202 
00203 
00204 static int lsapi_close( int fd )
00205 {
00206     int ret;
00207     while( 1 ) {
00208         ret = close( fd );
00209         if (( ret == -1 )&&( errno == EINTR )&&(g_running)) {
00210             continue;
00211         }
00212         return ret;
00213     }
00214 }
00215 
00216 static inline int lsapi_read( int fd, void * pBuf, int len )
00217 {
00218     int ret;
00219     while( 1 ) {
00220         ret = read( fd, (char *)pBuf, len );
00221         if (( ret == -1 )&&( errno == EINTR )&&(g_running)) {
00222             continue;
00223         }
00224         return ret;
00225     }
00226 }
00227 
00228 
00229 static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
00230 {
00231     int ret;
00232     int left = totalLen;
00233     int n = count;
00234     while(( left > 0 )&&g_running ) {
00235         ret = writev( fd, *pVec, n );
00236         if ( ret > 0 ) {
00237             left -= ret;
00238             if (( left <= 0)||( !g_running )) {
00239                 return totalLen - left;
00240             }
00241             while( ret > 0 ) {
00242                 if ( (*pVec)->iov_len <= ret ) {
00243                     ret -= (*pVec)->iov_len;
00244                     ++(*pVec);
00245                 } else {
00246                     (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
00247                     (*pVec)->iov_len -= ret;
00248                     break;
00249                 }
00250             }
00251         } else if ( ret == -1 ) {
00252             if ( errno == EAGAIN ) {
00253                 if ( totalLen - left > 0 ) {
00254                     return totalLen - left;
00255                 } else {
00256                     return -1;
00257                 }
00258             } else {
00259                 if ( errno != EINTR ) {
00260                     return ret;
00261                 }
00262             }
00263         }
00264     }
00265     return totalLen - left;
00266 }
00267 
00268 static inline int allocateBuf( LSAPI_Request * pReq, int size )
00269 {
00270     char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
00271     if ( pBuf ) {
00272         pReq->m_pReqBuf = pBuf;
00273         pReq->m_reqBufSize = size;
00274         pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
00275         return 0;
00276     }
00277     return -1;
00278 }
00279 
00280 
00281 static int allocateIovec( LSAPI_Request * pReq, int n )
00282 {
00283     struct iovec * p = (struct iovec *)realloc(
00284                 pReq->m_pIovec, sizeof(struct iovec) * n );
00285     if ( !p ) {
00286         return -1;
00287     }
00288     pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
00289     pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
00290     pReq->m_pIovec = p;
00291     pReq->m_pIovecEnd = p + n;
00292     return 0;
00293 }
00294 
00295 static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
00296 {
00297     char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
00298     if ( !p ) {
00299         return -1;
00300     }
00301     pReq->m_pRespHeaderBufPos   = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
00302     pReq->m_pRespHeaderBuf      = p;
00303     pReq->m_pRespHeaderBufEnd   = p + size;
00304     return 0;
00305 }
00306 
00307 
00308 static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
00309 {
00310     if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
00311         ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
00312         ( pktType != pHeader->m_type )) {
00313         return -1;
00314     }
00315     if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) {
00316         register char b;
00317         b = pHeader->m_packetLen.m_bytes[0];
00318         pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
00319         pHeader->m_packetLen.m_bytes[3] = b;
00320         b = pHeader->m_packetLen.m_bytes[1];
00321         pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
00322         pHeader->m_packetLen.m_bytes[2] = b;
00323     }
00324     return pHeader->m_packetLen.m_iLen;
00325 }
00326 
00327 static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
00328                         int *curSize, int newSize )
00329 {
00330     struct LSAPI_key_value_pair * pBuf;
00331     if ( *curSize >= newSize ) {
00332         return 0;
00333     }
00334     if ( newSize > 8192 ) {
00335         return -1;
00336     }
00337     pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
00338                     sizeof(struct LSAPI_key_value_pair) );
00339     if ( pBuf ) {
00340         *pEnvList = pBuf;
00341         *curSize  = newSize;
00342         return 0;
00343     } else {
00344         return -1;
00345     }
00346 
00347 }
00348 
00349 static inline int isPipe( int fd )
00350 {
00351     char        achPeer[128];
00352     socklen_t   len = 128;
00353     if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
00354         ( errno == ENOTCONN )) {
00355         return 0;
00356     } else {
00357         return 1;
00358     }
00359 }
00360 
00361 static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
00362             char **pBegin, char * pEnd )
00363 {
00364     struct LSAPI_key_value_pair * pEnvEnd;
00365     int keyLen = 0, valLen = 0;
00366     if ( count > 8192 ) {
00367         return -1;
00368     }
00369     pEnvEnd = pEnvList + count;
00370     while( pEnvList != pEnvEnd ) {
00371         if ( pEnd - *pBegin < 4 ) {
00372             return -1;
00373         }
00374         keyLen = *((unsigned char *)((*pBegin)++));
00375         keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
00376         valLen = *((unsigned char *)((*pBegin)++));
00377         valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
00378         if ( *pBegin + keyLen + valLen > pEnd ) {
00379             return -1;
00380         }
00381         if (( !keyLen )||( !valLen )) {
00382             return -1;
00383         }
00384 
00385         pEnvList->pKey = *pBegin;
00386         *pBegin += keyLen;
00387         pEnvList->pValue = *pBegin;
00388         *pBegin += valLen;
00389 
00390         pEnvList->keyLen = keyLen - 1;
00391         pEnvList->valLen = valLen - 1;
00392         ++pEnvList;
00393     }
00394     if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) {
00395         return -1;
00396     }
00397     *pBegin += 4;
00398     return 0;
00399 }
00400 
00401 static inline void swapIntEndian( int * pInteger )
00402 {
00403     char * p = (char *)pInteger;
00404     register char b;
00405     b = p[0];
00406     p[0] = p[3];
00407     p[3] = b;
00408     b = p[1];
00409     p[1] = p[2];
00410     p[2] = b;
00411     
00412 }
00413 
00414 static inline void fixEndian( LSAPI_Request * pReq )
00415 {
00416     struct lsapi_req_header *p= pReq->m_pHeader;
00417     swapIntEndian( &p->m_httpHeaderLen );
00418     swapIntEndian( &p->m_reqBodyLen );
00419     swapIntEndian( &p->m_scriptFileOff );
00420     swapIntEndian( &p->m_scriptNameOff );
00421     swapIntEndian( &p->m_queryStringOff );
00422     swapIntEndian( &p->m_requestMethodOff );
00423     swapIntEndian( &p->m_cntUnknownHeaders );
00424     swapIntEndian( &p->m_cntEnv );
00425     swapIntEndian( &p->m_cntSpecialEnv );
00426 }
00427 
00428 static void fixHeaderIndexEndian( LSAPI_Request * pReq )
00429 {
00430     int i;
00431     for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
00432         if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
00433             register char b;
00434             char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
00435             b = p[0];
00436             p[0] = p[1];
00437             p[1] = b;
00438             swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
00439         }
00440     }
00441     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
00442         struct lsapi_header_offset * pCur, *pEnd;
00443         pCur = pReq->m_pUnknownHeader;
00444         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
00445         while( pCur < pEnd ) {
00446             swapIntEndian( &pCur->nameOff );
00447             swapIntEndian( &pCur->nameLen );
00448             swapIntEndian( &pCur->valueOff );
00449             swapIntEndian( &pCur->valueLen );
00450             ++pCur;
00451         }
00452     }    
00453 }
00454 
00455 static int parseRequest( LSAPI_Request * pReq, int totalLen )
00456 {
00457     int shouldFixEndian;
00458     char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
00459     char * pEnd = pReq->m_pReqBuf + totalLen;
00460     shouldFixEndian = ( LSAPI_ENDIAN != (
00461                 pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
00462     if ( shouldFixEndian ) {
00463         fixEndian( pReq );
00464     }
00465     if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
00466             allocateEnvList( &pReq->m_pSpecialEnvList,
00467                               &pReq->m_specialEnvListSize,
00468                              pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) {
00469         return -1;
00470     }
00471     if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
00472             allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
00473                              pReq->m_pHeader->m_cntEnv ) == -1 ) {
00474         return -1;
00475     }
00476     if ( parseEnv( pReq->m_pSpecialEnvList,
00477                    pReq->m_pHeader->m_cntSpecialEnv,
00478                    &pBegin, pEnd ) == -1 ) {
00479         return -1;
00480     }
00481     if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
00482                    &pBegin, pEnd ) == -1 ) {
00483         return -1;
00484     }
00485     pReq->m_pScriptFile     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
00486     pReq->m_pScriptName     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
00487     pReq->m_pQueryString    = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
00488     pReq->m_pRequestMethod  = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
00489     
00490     pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
00491     pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
00492     pBegin += sizeof( struct lsapi_http_header_index );
00493 
00494     pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
00495     pBegin += sizeof( struct lsapi_header_offset) *
00496                     pReq->m_pHeader->m_cntUnknownHeaders;
00497 
00498     pReq->m_pHttpHeader = pBegin;
00499     pBegin += pReq->m_pHeader->m_httpHeaderLen;
00500     if ( pBegin != pEnd ) {
00501         return -1;
00502     }
00503 
00504     if ( shouldFixEndian ) {
00505         fixHeaderIndexEndian( pReq );
00506     }
00507 
00508     return 0;
00509 }
00510 
00511 static int s_accept_notify = 0;
00512 
00513 static struct lsapi_packet_header ack = {'L', 'S',
00514                 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
00515 static inline int notify_req_received( int fd )
00516 {
00517     if ( write( fd, &ack, LSAPI_PACKET_HEADER_LEN )
00518          < LSAPI_PACKET_HEADER_LEN ) {
00519         return -1;
00520     }
00521     return 0;
00522 }
00523 
00524 
00525 static int readReq( LSAPI_Request * pReq )
00526 {
00527     int len;
00528     int packetLen;
00529     if ( !pReq ) {
00530         return -1;
00531     }
00532     if ( pReq->m_reqBufSize < 8192 ) {
00533         if ( allocateBuf( pReq, 8192 ) == -1 ) {
00534             return -1;
00535         }
00536     }
00537 
00538     while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) {
00539         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
00540         if ( len <= 0 ) {
00541             return -1;
00542         }
00543         pReq->m_bufRead += len;
00544     }
00545     pReq->m_reqState = LSAPI_ST_REQ_HEADER;
00546 
00547     packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
00548     if ( packetLen < 0 ) {
00549         return -1;
00550     }
00551     if ( packetLen > LSAPI_MAX_HEADER_LEN ) {
00552         return -1;
00553     }
00554 
00555     if ( packetLen + 1024 > pReq->m_reqBufSize ) {
00556         if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) {
00557             return -1;
00558         }
00559     }
00560     while( packetLen > pReq->m_bufRead ) {
00561         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
00562         if ( len <= 0 ) {
00563             return -1;
00564         }
00565         pReq->m_bufRead += len;
00566     }
00567     if ( parseRequest( pReq, packetLen ) < 0 ) {
00568         return -1;
00569     }
00570     pReq->m_bufProcessed = packetLen;
00571     pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
00572 
00573     if ( !s_accept_notify )
00574         return notify_req_received( pReq->m_fd );
00575     else
00576         return 0;
00577 }
00578 
00579 
00580 
00581 int LSAPI_Init(void)
00582 {
00583     if ( !g_inited ) {
00584         lsapi_signal(SIGPIPE, lsapi_sigpipe);
00585         lsapi_signal(SIGUSR1, lsapi_siguser1);
00586 
00587 #if defined(SIGXFSZ) && defined(SIG_IGN)
00588         signal(SIGXFSZ, SIG_IGN);
00589 #endif
00590         /* let STDOUT function as STDERR, 
00591            just in case writing to STDOUT directly */
00592         dup2( 2, 1 );
00593 
00594         if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) {
00595             return -1;
00596         }
00597         g_inited = 1;
00598         s_ppid = getppid();
00599     }
00600     return 0;
00601 }
00602 
00603 void LSAPI_Stop(void)
00604 {
00605     g_running = 0;
00606 }
00607 
00608 int LSAPI_IsRunning(void)
00609 {
00610     return g_running;
00611 }
00612 
00613 int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
00614 {
00615     if ( !pReq ) {
00616         return -1;
00617     }
00618     memset( pReq, 0, sizeof( LSAPI_Request ) );
00619     if ( allocateIovec( pReq, 16 ) == -1 ) {
00620         return -1;
00621     }
00622     pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
00623     if ( !pReq->m_pRespBuf ) {
00624         return -1;
00625     }
00626     pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
00627     pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
00628     pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
00629     if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) {
00630         return -1;
00631     }
00632  
00633     if ( isPipe( fd ) ) {
00634         pReq->m_fdListen = -1;
00635         pReq->m_fd = fd;
00636     } else {
00637         pReq->m_fdListen = fd;
00638         pReq->m_fd = -1;
00639         lsapi_set_nblock( fd, 1 );
00640     }
00641     return 0;
00642 }
00643 
00644 int LSAPI_Is_Listen( void )
00645 {
00646     return LSAPI_Is_Listen_r( &g_req );
00647 }
00648 
00649 int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
00650 {
00651     return pReq->m_fdListen != -1;
00652 }
00653 
00654 
00655 
00656 int LSAPI_Accept_r( LSAPI_Request * pReq )
00657 {
00658     char        achPeer[128];
00659     socklen_t   len;
00660     int         nodelay = 1;
00661     
00662     if ( !pReq ) {
00663         return -1;
00664     }
00665     if ( LSAPI_Finish_r( pReq ) == -1 ) {
00666         return -1;
00667     }
00668     while( g_running ) {
00669         if ( pReq->m_fd == -1 ) {
00670             if ( pReq->m_fdListen != -1) {
00671                 len = sizeof( achPeer );
00672                 pReq->m_fd = accept( pReq->m_fdListen,
00673                             (struct sockaddr *)&achPeer, &len );
00674                 if ( pReq->m_fd == -1 ) {
00675                     if (( errno == EINTR )||( errno == EAGAIN)) {
00676                         continue;
00677                     } else {
00678                         return -1;
00679                     }
00680                 } else {
00681                     lsapi_set_nblock( pReq->m_fd , 0 );
00682                     if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) {    
00683                         setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
00684                                 (char *)&nodelay, sizeof(nodelay));
00685                     }
00686 
00687                     if ( s_accept_notify )
00688                         return notify_req_received( pReq->m_fd );
00689 
00690                 }
00691             } else {
00692                 return -1;
00693             }
00694         }
00695         if ( !readReq( pReq ) ) {
00696             break;
00697         }
00698         lsapi_close( pReq->m_fd );
00699         pReq->m_fd = -1;
00700         LSAPI_Reset_r( pReq );
00701     }
00702     return 0;
00703 }
00704 
00705 static struct lsapi_packet_header   finish = {'L', 'S',
00706                 LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
00707 
00708 int LSAPI_Finish_r( LSAPI_Request * pReq )
00709 {
00710     /* finish req body */
00711     if ( !pReq ) {
00712         return -1;
00713     }
00714     if (pReq->m_reqState) {
00715         if ( pReq->m_fd != -1 ) {
00716             if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
00717                 LSAPI_FinalizeRespHeaders_r( pReq );
00718             }
00719             if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
00720                 Flush_RespBuf_r( pReq );
00721             }
00722             
00723             pReq->m_pIovecCur->iov_base = (void *)&finish;
00724             pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
00725             pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
00726             ++pReq->m_pIovecCur;
00727             LSAPI_Flush_r( pReq );
00728         }
00729         LSAPI_Reset_r( pReq );
00730     }
00731     return 0;
00732 }
00733 
00734 
00735 void LSAPI_Reset_r( LSAPI_Request * pReq )
00736 {
00737     pReq->m_pRespBufPos         = pReq->m_pRespBuf;
00738     pReq->m_pIovecCur           = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
00739     pReq->m_pRespHeaderBufPos   = pReq->m_pRespHeaderBuf;
00740     
00741     memset( &pReq->m_pHeaderIndex, 0,
00742             (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
00743 }
00744 
00745 
00746 int LSAPI_Release_r( LSAPI_Request * pReq )
00747 {
00748     if ( pReq->m_pReqBuf ) {
00749         free( pReq->m_pReqBuf );
00750     }
00751     if ( pReq->m_pSpecialEnvList ) {
00752         free( pReq->m_pSpecialEnvList );
00753     }
00754     if ( pReq->m_pEnvList ) {
00755         free( pReq->m_pEnvList );
00756     }
00757     if ( pReq->m_pRespHeaderBuf ) {
00758         free( pReq->m_pRespHeaderBuf );  
00759     }
00760     return 0;
00761 }
00762 
00763 
00764 char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
00765 {
00766     int off;
00767     if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) {
00768         return NULL;
00769     }
00770     off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
00771     if ( !off ) {
00772         return NULL;
00773     }
00774     if ( *(pReq->m_pHttpHeader + off + 
00775            pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) {
00776         *( pReq->m_pHttpHeader + off + 
00777             pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
00778     }
00779     return pReq->m_pHttpHeader + off;
00780 }
00781 
00782 static int readBodyToReqBuf( LSAPI_Request * pReq )
00783 {
00784     int bodyLeft;
00785     int len = pReq->m_bufRead - pReq->m_bufProcessed;
00786     if ( len > 0 ) {
00787         return len;
00788     }
00789     pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
00790 
00791     bodyLeft = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
00792     len = pReq->m_reqBufSize - pReq->m_bufRead;
00793     if ( len < 0 ) {
00794         return -1;
00795     }
00796     if ( len > bodyLeft ) {
00797         len = bodyLeft;
00798     }
00799     len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
00800     if ( len > 0 ) {
00801         pReq->m_bufRead += len;
00802     }
00803     return len;
00804 }
00805 
00806 
00807 int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
00808 {
00809     if (!pReq || (pReq->m_fd ==-1) ) {
00810         return EOF;
00811     }
00812     if ( pReq->m_bufProcessed >= pReq->m_bufRead ) {
00813         if ( readBodyToReqBuf( pReq ) <= 0 ) {
00814             return EOF;
00815         }
00816     }
00817     ++pReq->m_reqBodyRead;
00818     return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
00819 }
00820 
00821 
00822 
00823 int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF )
00824 {
00825     int len;
00826     int left;
00827     char * pBufEnd = pBuf + bufLen - 1;
00828     char * pBufCur = pBuf;
00829     char * pCur;
00830     char * p;
00831     if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF ) {
00832         return -1;
00833     }
00834     *getLF = 0;
00835     while( (left = pBufEnd - pBufCur ) > 0 ) {
00836         
00837         len = pReq->m_bufRead - pReq->m_bufProcessed;
00838         if ( len <= 0 ) {
00839             if ( (len = readBodyToReqBuf( pReq )) <= 0 ) {
00840                 *getLF = 1;
00841                 break;
00842             }
00843         }
00844         if ( len > left ) {
00845             len = left;
00846         }
00847         pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
00848         p = memchr( pCur, '\n', len );
00849         if ( p ) {
00850             len = p - pCur + 1;
00851         }
00852         memmove( pBufCur, pCur, len );
00853         pBufCur += len;
00854         pReq->m_bufProcessed += len;
00855 
00856         pReq->m_reqBodyRead += len;
00857         
00858         if ( p ) {
00859             *getLF = 1;
00860             break;
00861         }
00862     }
00863     *pBufCur = 0;
00864   
00865     return pBufCur - pBuf;
00866 }
00867 
00868 
00869 int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
00870 {
00871     int len;
00872     int total;
00873     /* char *pOldBuf = pBuf; */
00874     if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 )) {
00875         return -1;
00876     }
00877     total = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
00878     
00879     if ( total <= 0 ) {
00880         return 0;
00881     }
00882     if ( total < bufLen ) {
00883         bufLen = total;
00884     }
00885 
00886     total = 0;
00887     len = pReq->m_bufRead - pReq->m_bufProcessed;
00888     if ( len > 0 ) {
00889         if ( len > bufLen ) {
00890             len = bufLen;
00891         }
00892         memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
00893         pReq->m_bufProcessed += len;
00894         total += len;
00895         pBuf += len;
00896         bufLen -= len;
00897     }
00898     while( bufLen > 0 ) {
00899         len = lsapi_read( pReq->m_fd, pBuf, bufLen );
00900         if ( len > 0 ) {
00901             total += len;
00902             pBuf += len;
00903             bufLen -= len;
00904         } else {
00905             if ( len <= 0 ) {
00906                 if ( !total) {
00907                     return -1;
00908                 }
00909                 break;
00910             }
00911         }
00912     }
00913     pReq->m_reqBodyRead += total;
00914     return total;
00915         
00916 }
00917 
00918 
00919 int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
00920 {
00921     struct lsapi_packet_header * pHeader;
00922     const char * pEnd;
00923     const char * p;
00924     int bufLen;
00925     int toWrite;
00926     int packetLen;
00927     
00928     if ( !pReq || !pBuf || (pReq->m_fd == -1) ) {
00929         return -1;
00930     }
00931     if ( len < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) {
00932         memmove( pReq->m_pRespBufPos, pBuf, len );
00933         pReq->m_pRespBufPos += len;
00934         return len;
00935     }
00936     
00937     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
00938         LSAPI_FinalizeRespHeaders_r( pReq );
00939     }
00940     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
00941     
00942     pHeader = pReq->m_respPktHeader;
00943     p       = pBuf;
00944     pEnd    = pBuf + len;
00945     bufLen  = pReq->m_pRespBufPos - pReq->m_pRespBuf;
00946     
00947     while( ( toWrite = pEnd - p ) > 0 ) {
00948         packetLen = toWrite + bufLen;
00949         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) {
00950             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
00951             toWrite = packetLen - bufLen;
00952         }
00953         
00954         lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
00955                             packetLen + LSAPI_PACKET_HEADER_LEN );
00956         pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
00957 
00958         pReq->m_pIovecCur->iov_base = (void *)pHeader;
00959         pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
00960         ++pReq->m_pIovecCur;
00961         ++pHeader;
00962         if ( bufLen > 0 ) {
00963             pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
00964             pReq->m_pIovecCur->iov_len  = bufLen;
00965             pReq->m_pRespBufPos = pReq->m_pRespBuf;
00966             ++pReq->m_pIovecCur;       
00967             bufLen = 0;
00968         }
00969 
00970         pReq->m_pIovecCur->iov_base = (void *)p;
00971         pReq->m_pIovecCur->iov_len  = toWrite;
00972         ++pReq->m_pIovecCur;
00973         p += toWrite;
00974 
00975         if ( pHeader >= pReq->m_respPktHeaderEnd - 1) {
00976             if ( LSAPI_Flush_r( pReq ) == -1 ) {
00977                 return -1;
00978             }
00979             pHeader = pReq->m_respPktHeader;
00980         }
00981     }
00982     if ( pHeader != pReq->m_respPktHeader ) {
00983         if ( LSAPI_Flush_r( pReq ) == -1 ) {
00984             return -1;
00985         }
00986     }
00987     return p - pBuf;
00988 }
00989 
00990 void Flush_RespBuf_r( LSAPI_Request * pReq )
00991 {
00992     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
00993     int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
00994     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
00995     lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
00996                         bufLen + LSAPI_PACKET_HEADER_LEN );
00997     pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
00998 
00999     pReq->m_pIovecCur->iov_base = (void *)pHeader;
01000     pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
01001     ++pReq->m_pIovecCur;
01002     ++pHeader;
01003     if ( bufLen > 0 ) {
01004         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
01005         pReq->m_pIovecCur->iov_len  = bufLen;
01006         pReq->m_pRespBufPos = pReq->m_pRespBuf;
01007         ++pReq->m_pIovecCur;       
01008         bufLen = 0;
01009     }
01010 }
01011 
01012 
01013 
01014 
01015 int LSAPI_Flush_r( LSAPI_Request * pReq )
01016 {
01017     int ret = 0;
01018     int n;
01019     if ( !pReq ) {
01020         return -1;
01021     }
01022     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
01023     if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) {
01024         return 0;
01025     }
01026     if ( pReq->m_fd == -1 ) {
01027         pReq->m_pRespBufPos = pReq->m_pRespBuf;
01028         pReq->m_totalLen = 0;
01029         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
01030         return -1;
01031     }
01032     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
01033         LSAPI_FinalizeRespHeaders_r( pReq );
01034     }
01035     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
01036         Flush_RespBuf_r( pReq );
01037     }
01038     
01039     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
01040     if ( n > 0 ) {
01041         
01042         ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
01043                   n, pReq->m_totalLen );
01044         if ( ret < pReq->m_totalLen ) {
01045             lsapi_close( pReq->m_fd );
01046             pReq->m_fd = -1;
01047             ret = -1;
01048         }
01049         pReq->m_totalLen = 0;
01050         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
01051     }
01052     return ret;
01053 }
01054 
01055 
01056 int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len )
01057 {
01058     struct lsapi_packet_header header;
01059     const char * pEnd;
01060     const char * p;
01061     int packetLen;
01062     int totalLen;
01063     int ret;
01064     struct iovec iov[2];
01065     struct iovec *pIov;
01066     
01067     if ( !pReq ) {
01068         return -1;
01069     }
01070     if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen )) {
01071         return write( 2, pBuf, len );
01072     }
01073     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
01074         LSAPI_Flush_r( pReq );
01075     }
01076     
01077     p       = pBuf;
01078     pEnd    = pBuf + len;
01079 
01080     while( ( packetLen = pEnd - p ) > 0 ) {
01081         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) {
01082             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
01083         }
01084 
01085         lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
01086                             packetLen + LSAPI_PACKET_HEADER_LEN );
01087         totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
01088 
01089         iov[0].iov_base = (void *)&header;
01090         iov[0].iov_len  = LSAPI_PACKET_HEADER_LEN;
01091 
01092         iov[1].iov_base = (void *)p;
01093         iov[1].iov_len  = packetLen;
01094         p += packetLen;
01095         pIov = iov;
01096         ret = lsapi_writev( pReq->m_fd, &pIov,
01097                   2, totalLen );
01098         if ( ret < totalLen ) {
01099             lsapi_close( pReq->m_fd );
01100             pReq->m_fd = -1;
01101             ret = -1;
01102         }
01103     }
01104     return p - pBuf;
01105 }
01106 
01107 static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
01108 {
01109     int i;
01110     for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
01111         if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
01112             if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) {
01113                 return pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
01114             }
01115         }
01116     }
01117     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
01118         const char *p;
01119         char *pKey;
01120         char *pKeyEnd;
01121         int  keyLen;
01122         struct lsapi_header_offset * pCur, *pEnd;
01123         pCur = pReq->m_pUnknownHeader;
01124         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
01125         while( pCur < pEnd ) {
01126             pKey = pReq->m_pHttpHeader + pCur->nameOff;
01127             keyLen = pCur->nameLen;
01128             pKeyEnd = pKey + keyLen;
01129             p = &name[5];
01130 
01131             while(( pKey < pKeyEnd )&&( *p )) {
01132                 char ch = toupper( *pKey );
01133                 if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) {
01134                     break;
01135                 }
01136                 ++p; ++pKey;
01137             }
01138             if (( pKey == pKeyEnd )&& (!*p )) {
01139                 return pReq->m_pHttpHeader + pCur->valueOff;
01140             }
01141             ++pCur;
01142         }
01143     }
01144     return NULL;
01145 }
01146 
01147 
01148 char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
01149 {
01150     struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
01151     struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
01152     if ( !pReq || !name ) {
01153         return NULL;
01154     }
01155     if ( strncmp( name, "HTTP_", 5 ) == 0 ) {
01156         return GetHeaderVar( pReq, name );
01157     }
01158     while( pBegin < pEnd ) {
01159         if ( strcmp( name, pBegin->pKey ) == 0 ) {
01160             return pBegin->pValue;
01161         }
01162         ++pBegin;
01163     }
01164     return NULL;
01165 }
01166 
01167 int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
01168             LSAPI_CB_EnvHandler fn, void * arg )
01169 {
01170     int i;
01171     int len = 0;
01172     char * pValue;
01173     int ret;
01174     int count = 0;
01175     if ( !pReq || !fn ) {
01176         return -1;
01177     }
01178     for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
01179         if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
01180             len = pReq->m_pHeaderIndex->m_headerLen[i];
01181             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
01182             *(pValue + len ) = 0;
01183             ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
01184                         pValue, len, arg );
01185             ++count;
01186             if ( ret <= 0 ) {
01187                 return ret;
01188             }
01189         }
01190     }
01191     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
01192         char *pKey;
01193         int  keyLen;
01194         struct lsapi_header_offset * pCur, *pEnd;
01195         pCur = pReq->m_pUnknownHeader;
01196         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
01197         while( pCur < pEnd ) {
01198             pKey = pReq->m_pHttpHeader + pCur->nameOff;
01199             keyLen = pCur->nameLen;
01200 
01201             pValue = pReq->m_pHttpHeader + pCur->valueOff;
01202             *(pValue + pCur->valueLen ) = 0;
01203             ret = (*fn)( pKey, keyLen, 
01204                         pValue, pCur->valueLen, arg );
01205             if ( ret <= 0 ) {
01206                 return ret;
01207             }
01208             ++pCur;
01209         }
01210     }
01211     return count + pReq->m_pHeader->m_cntUnknownHeaders;
01212     
01213 }
01214 
01215 
01216 int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
01217             LSAPI_CB_EnvHandler fn, void * arg )
01218 {
01219     int i;
01220     int len = 0;
01221     char * pValue;
01222     int ret;
01223     int count = 0;
01224     if ( !pReq || !fn ) {
01225         return -1;
01226     }
01227     for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
01228         if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
01229             len = pReq->m_pHeaderIndex->m_headerLen[i];
01230             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
01231             *(pValue + len ) = 0;
01232             ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
01233                         pValue, len, arg );
01234             ++count;
01235             if ( ret <= 0 ) {
01236                 return ret;
01237             }
01238         }
01239     }
01240     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
01241         char achHeaderName[256];
01242         char *p;
01243         char *pKey;
01244         char *pKeyEnd ;
01245         int  keyLen;
01246         struct lsapi_header_offset * pCur, *pEnd;
01247         pCur = pReq->m_pUnknownHeader;
01248         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
01249         while( pCur < pEnd ) {
01250             pKey = pReq->m_pHttpHeader + pCur->nameOff;
01251             keyLen = pCur->nameLen;
01252             if ( keyLen > 250 ) {
01253                 keyLen = 250;
01254             }
01255 
01256             pKeyEnd = pKey + keyLen;
01257             memcpy( achHeaderName, "HTTP_", 5 );
01258             p = &achHeaderName[5];
01259 
01260             while( pKey < pKeyEnd ) {
01261                 char ch = *pKey++;
01262                 if ( ch == '-' ) {
01263                     *p++ = '_';
01264                 } else {
01265                     *p++ = toupper( ch );
01266                 }
01267             }
01268             *p = 0;
01269             keyLen += 5;
01270 
01271             pValue = pReq->m_pHttpHeader + pCur->valueOff;
01272             *(pValue + pCur->valueLen ) = 0;
01273             ret = (*fn)( achHeaderName, keyLen, 
01274                         pValue, pCur->valueLen, arg );
01275             if ( ret <= 0 ) {
01276                 return ret;
01277             }
01278             ++pCur;
01279         }
01280     }
01281     return count + pReq->m_pHeader->m_cntUnknownHeaders;
01282     
01283 }
01284 
01285 static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
01286             int n, LSAPI_CB_EnvHandler fn, void * arg )
01287 {
01288     struct LSAPI_key_value_pair * pEnd = pEnv + n;
01289     int ret;
01290     if ( !pEnv || !fn ) {
01291         return -1;
01292     }
01293     while( pEnv < pEnd ) {
01294         ret = (*fn)( pEnv->pKey, pEnv->keyLen,
01295                     pEnv->pValue, pEnv->valLen, arg );
01296         if ( ret <= 0 ) {
01297             return ret;
01298         }
01299         ++pEnv;
01300     }
01301     return n;
01302 }
01303 
01304 
01305 
01306 int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
01307             LSAPI_CB_EnvHandler fn, void * arg )
01308 {
01309     if ( !pReq || !fn ) {
01310         return -1;
01311     }
01312     if ( pReq->m_pHeader->m_cntEnv > 0 ) {
01313         return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
01314                     fn, arg );
01315     }
01316     return 0;
01317 }
01318 
01319 
01320 
01321 int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
01322             LSAPI_CB_EnvHandler fn, void * arg )
01323 {
01324     if ( !pReq || !fn ) {
01325         return -1;
01326     }
01327     if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) {
01328         return EnvForeach( pReq->m_pSpecialEnvList,
01329                 pReq->m_pHeader->m_cntSpecialEnv,
01330                     fn, arg );
01331     }
01332     return 0;
01333 
01334 }
01335 
01336 
01337 
01338 int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
01339 {
01340     if ( !pReq || !pReq->m_pIovec ) {
01341         return -1;
01342     }
01343     if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) {
01344         return 0;
01345     }
01346     pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
01347     if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) {
01348         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
01349         pReq->m_pIovecCur->iov_len  = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
01350         pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
01351         ++pReq->m_pIovecCur;
01352     }
01353     
01354     pReq->m_pIovec->iov_len  = sizeof( struct lsapi_resp_header)
01355             + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
01356     pReq->m_totalLen += pReq->m_pIovec->iov_len;
01357 
01358     lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
01359                     LSAPI_RESP_HEADER, pReq->m_totalLen  );
01360     pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
01361     pReq->m_pIovecToWrite = pReq->m_pIovec;
01362     return 0;
01363 }
01364 
01365 
01366 
01367 
01368 int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, char * pBuf, int len )
01369 {
01370     if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) {
01371         return -1;
01372     }
01373     if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) {
01374         return -1;
01375     }
01376     if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) {
01377         return -1;
01378     }
01379     if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) {
01380         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
01381         newlen -= newlen % 4096;
01382         if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) {
01383             return -1;
01384         }
01385     }
01386     memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
01387     pReq->m_pRespHeaderBufPos += len;
01388     *pReq->m_pRespHeaderBufPos++ = 0;
01389     ++len;  /* add one byte padding for \0 */
01390     pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
01391     ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
01392     return 0;
01393 }
01394 
01395 
01396 int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
01397 {
01398     int ret;
01399     int fd;
01400     int flag = 1;
01401     int addr_len;
01402 
01403     switch( pServerAddr->sa_family ) {
01404     case AF_INET:
01405         addr_len = 16;
01406         break;
01407     case AF_INET6:
01408         addr_len = sizeof( struct sockaddr_in6 );
01409         break;
01410     case AF_UNIX:
01411         addr_len = sizeof( struct sockaddr_un );
01412         unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
01413         break;
01414     default:
01415         return -1;
01416     }
01417 
01418     fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
01419     if ( fd == -1 ) {
01420         return -1;
01421     }
01422 
01423     fcntl( fd, F_SETFD, FD_CLOEXEC );
01424 
01425     if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
01426                 (char *)( &flag ), sizeof(flag)) == 0) {
01427         ret = bind( fd, pServerAddr, addr_len );
01428         if ( !ret ) {
01429             ret = listen( fd, backlog );
01430             if ( !ret ) {
01431                 return fd;
01432             }
01433         }
01434     }
01435 
01436     ret = errno;
01437     close(fd);
01438     errno = ret;
01439     return -1;
01440 
01441 }
01442 
01443 int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
01444 {
01445     char achAddr[256];
01446     char * p = achAddr;
01447     char * pEnd;
01448     struct addrinfo *res, hints;
01449     int  doAddrInfo = 0;
01450     int port;
01451     
01452     if ( !pBind ) {
01453         return -1;
01454     }
01455 
01456     while( isspace( *pBind ) ) {
01457         ++pBind;
01458     }
01459 
01460     strncpy( achAddr, pBind, 256 );
01461 
01462     switch( *p ) {
01463     case '/':
01464         pAddr->sa_family = AF_UNIX;
01465         strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
01466                 sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
01467         return 0;
01468 
01469     case '[':
01470         pAddr->sa_family = AF_INET6;
01471         ++p;
01472         pEnd = strchr( p, ']' );
01473         if ( !pEnd )
01474             return -1;
01475         *pEnd++ = 0;
01476         
01477         if ( *p == '*' ) {
01478             strcpy( achAddr, "::" );
01479             p = achAddr;
01480         }
01481         doAddrInfo = 1;
01482         break;
01483 
01484     default:
01485         pAddr->sa_family = AF_INET;
01486         pEnd = strchr( p, ':' );
01487         if ( !pEnd ) {
01488             return -1;
01489         }
01490         *pEnd++ = 0;
01491         
01492         doAddrInfo = 0;
01493         if ( *p == '*' ) {
01494             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
01495         } else {
01496             if (!strcasecmp( p, "localhost" ) ) {
01497                 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
01498             } else  {
01499                 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
01500                 if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) {
01501                     doAddrInfo = 1;
01502                 }
01503             }
01504         }
01505         break;
01506     }
01507     if ( *pEnd == ':' ) {
01508         ++pEnd;
01509     }
01510         
01511     port = atoi( pEnd );
01512     if (( port <= 0 )||( port > 65535 )) {
01513         return -1;
01514     }
01515     if ( doAddrInfo ) {
01516 
01517         memset(&hints, 0, sizeof(hints));
01518 
01519         hints.ai_family   = pAddr->sa_family;
01520         hints.ai_socktype = SOCK_STREAM;
01521         hints.ai_protocol = IPPROTO_TCP;
01522 
01523         if ( getaddrinfo(p, NULL, &hints, &res) ) {
01524             return -1;
01525         }
01526 
01527         memcpy(pAddr, res->ai_addr, res->ai_addrlen);
01528         freeaddrinfo(res);
01529     }
01530     
01531     if ( pAddr->sa_family == AF_INET ) {
01532         ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
01533     } else {
01534         ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
01535     }
01536     return 0;
01537     
01538 }
01539 
01540 int LSAPI_CreateListenSock( const char * pBind, int backlog )
01541 {
01542     char serverAddr[128];
01543     int ret;
01544     int fd = -1;
01545     ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
01546     if ( !ret ) {
01547         fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
01548     }
01549     return fd;
01550 }
01551 
01552 static fn_select_t g_fnSelect = select;
01553 
01554 typedef struct _lsapi_child_status
01555 {
01556     int     m_pid;
01557 
01558     volatile short   m_iKillSent;
01559     volatile short   m_inProcess;
01560 
01561     volatile long    m_tmWaitBegin;
01562     volatile long    m_tmReqBegin;
01563     volatile long    m_tmLastCheckPoint;
01564 }
01565 lsapi_child_status;
01566 
01567 static lsapi_child_status * s_pChildStatus = NULL;
01568 
01569 typedef struct _lsapi_prefork_server
01570 {
01571     int m_fd;
01572     int m_iMaxChildren;
01573     int m_iExtraChildren;
01574     int m_iCurChildren;
01575     int m_iMaxIdleChildren;
01576     int m_iServerMaxIdle;
01577     int m_iChildrenMaxIdleTime;
01578     int m_iMaxReqProcessTime;
01579     int m_iAvoidFork;
01580     
01581     lsapi_child_status * m_pChildrenStatus;
01582     
01583 }lsapi_prefork_server;
01584 
01585 static lsapi_prefork_server * g_prefork_server = NULL;
01586 
01587 int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
01588 {
01589     if ( g_prefork_server ) {
01590         return 0;
01591     }
01592     if ( max_children <= 1 ) {
01593         return -1;
01594     }
01595     if ( max_children >= 10000) {
01596         max_children = 10000;
01597     }
01598 
01599     
01600     g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
01601     if ( !g_prefork_server ) {
01602         return -1;
01603     }
01604     memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
01605 
01606     if ( fp != NULL ) {
01607         g_fnSelect = fp;
01608     }
01609 
01610     s_ppid = getppid();
01611     g_prefork_server->m_iAvoidFork = avoidFork;
01612     g_prefork_server->m_iMaxChildren = max_children;
01613     
01614     g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
01615     g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
01616     g_prefork_server->m_iChildrenMaxIdleTime = 300;
01617     g_prefork_server->m_iMaxReqProcessTime = 300;
01618     return 0;    
01619 }
01620 
01621 void LSAPI_Set_Server_fd( int fd )
01622 {
01623     if( g_prefork_server ) {
01624         g_prefork_server->m_fd = fd;
01625     }
01626 }
01627 
01628 
01629 static int lsapi_accept( int fdListen )
01630 {
01631     int         fd;
01632     int         nodelay = 1;
01633     socklen_t   len;
01634     char        achPeer[128];
01635 
01636     len = sizeof( achPeer );
01637     fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
01638     if ( fd != -1 ) {
01639         if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) {
01640             setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
01641                     (char *)&nodelay, sizeof(nodelay));
01642         }
01643 
01644         if ( s_accept_notify )
01645             notify_req_received( fd );
01646     }
01647     return fd;
01648 
01649 }
01650 
01651 
01652 
01653 
01654 static int s_req_processed = 0;
01655 static int s_max_reqs = 10000;
01656 static int s_max_idle_secs = 300;
01657 
01658 static int s_stop;
01659 
01660 static void lsapi_cleanup(int signal)
01661 {
01662     s_stop = signal;
01663 }
01664 
01665 static lsapi_child_status * find_child_status( int pid )
01666 {
01667     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
01668     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
01669     while( pStatus < pEnd ) {
01670         if ( pStatus->m_pid == pid ) {
01671             return pStatus;
01672         }
01673         ++pStatus;
01674     }
01675     return NULL;
01676 }
01677 
01678 
01679 
01680 static void lsapi_sigchild( int signal )
01681 {
01682     int status, pid;
01683     lsapi_child_status * child_status;
01684     while( 1 ) {
01685         pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
01686         if ( pid <= 0 ) {
01687             break;
01688         }
01689         child_status = find_child_status( pid );
01690         if ( child_status ) {
01691             child_status->m_pid = 0;
01692         }
01693         --g_prefork_server->m_iCurChildren;
01694     }
01695 
01696 }
01697 
01698 static int lsapi_init_children_status()
01699 {
01700     int size = 4096;
01701     
01702     char * pBuf;
01703     size = g_prefork_server->m_iMaxChildren * sizeof( lsapi_child_status ) * 2;
01704     size = (size + 4095 ) / 4096 * 4096;
01705     pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
01706         MAP_ANON | MAP_SHARED, -1, 0 );
01707     if ( pBuf == MAP_FAILED ) {
01708         perror( "Anonymous mmap() failed" );
01709         return -1;
01710     }
01711     memset( pBuf, 0, size );
01712     g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;    
01713     return 0;
01714 }
01715 
01716 static void lsapi_check_child_status( long tmCur )
01717 {
01718     int idle = 0;
01719     int tobekilled;
01720     int dying = 0;
01721     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
01722     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
01723     while( pStatus < pEnd ) {
01724         tobekilled = pStatus->m_iKillSent;
01725         if ( pStatus->m_pid != 0 ) {
01726             if ( !tobekilled ) {
01727                 if ( !pStatus->m_inProcess ) {
01728                     
01729                     if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
01730                         ( idle >= g_prefork_server->m_iMaxIdleChildren )) {
01731                     
01732                         tobekilled = 1;
01733                     } else {
01734                         if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 )) {
01735                             tobekilled = 1;
01736                         }
01737                     }
01738                     if ( !tobekilled ) {
01739                         ++idle;
01740                     }
01741                 } else {
01742                     if ( tmCur - pStatus->m_tmReqBegin > 
01743                          g_prefork_server->m_iMaxReqProcessTime ) {
01744                         tobekilled = 1;
01745                     }
01746                 }
01747             } else {
01748                 if ( pStatus->m_inProcess ) {
01749                     tobekilled = pStatus->m_iKillSent = 0;
01750                 }
01751             }
01752             if ( tobekilled ) {
01753                 tobekilled = 0;
01754                 if ( pStatus->m_iKillSent > 5 ) {
01755                     tobekilled = SIGKILL;
01756                 } else {    
01757                     if ( pStatus->m_iKillSent == 3 ) {
01758                         tobekilled = SIGTERM;
01759                     } else {
01760                         if ( pStatus->m_iKillSent == 1 ) {
01761                             tobekilled = SIGUSR1;
01762                         }
01763                     }
01764                 }
01765                 if ( tobekilled ) {
01766                     kill( pStatus->m_pid, tobekilled );
01767                 }
01768                 ++pStatus->m_iKillSent;
01769                 ++dying;
01770             }
01771                 
01772         } else {
01773             ++dying;
01774         }
01775         ++pStatus;
01776     }
01777 }
01778 
01779 static int lsapi_all_children_must_die()
01780 {
01781     int maxWait;
01782     int sec =0;
01783     g_prefork_server->m_iMaxReqProcessTime = 10;
01784     g_prefork_server->m_iMaxIdleChildren = -1;
01785     maxWait = 15;
01786 
01787     while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) {
01788         lsapi_check_child_status(time(NULL));
01789         sleep( 1 );
01790         sec++;
01791     }
01792     if ( g_prefork_server->m_iCurChildren != 0 ) {
01793         kill( -getpgrp(), SIGKILL );
01794     }
01795     return 0;
01796 }
01797 
01798 
01799 
01800 static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq )
01801 {
01802     struct sigaction act, old_term, old_quit, old_int,
01803                     old_usr1, old_child;
01804     lsapi_child_status * child_status;
01805     int             wait_secs = 0;
01806     int             ret = 0;
01807     int             pid;
01808     time_t          lastTime = 0;
01809     time_t          curTime = 0;
01810     fd_set          readfds;
01811     struct timeval  timeout;
01812 
01813     lsapi_init_children_status();
01814     
01815     setsid();
01816 
01817     act.sa_flags = 0;
01818     act.sa_handler = lsapi_sigchild;
01819     if( sigaction( SIGCHLD, &act, &old_child ) ) {
01820         perror( "Can't set signal handler for SIGCHILD" );
01821         return -1;
01822     }
01823 
01824     /* Set up handler to kill children upon exit */
01825     act.sa_flags = 0;
01826     act.sa_handler = lsapi_cleanup;
01827     if( sigaction( SIGTERM, &act, &old_term ) ||
01828         sigaction( SIGINT,  &act, &old_int  ) ||
01829         sigaction( SIGUSR1, &act, &old_usr1 ) ||
01830         sigaction( SIGQUIT, &act, &old_quit )) {
01831         perror( "Can't set signals" );
01832         return -1;
01833     }
01834     s_stop = 0;
01835     while( !s_stop ) {
01836         if ( ret ) {
01837             curTime = time( NULL );
01838         } else {
01839             ++curTime;
01840         }
01841         if (curTime != lastTime ) {
01842             lastTime = curTime;
01843             if (s_ppid && (getppid() != s_ppid )) {
01844                 break;
01845             }
01846             lsapi_check_child_status(curTime );
01847             if (pServer->m_iServerMaxIdle) {
01848                 if ( pServer->m_iCurChildren <= 0 ) {
01849                     ++wait_secs;
01850                     if ( wait_secs > pServer->m_iServerMaxIdle ) {
01851                         return -1;
01852                     }
01853                 } else {
01854                     wait_secs = 0;
01855                 }
01856             }
01857         }
01858 
01859         if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) ) {
01860             usleep( 100000 );
01861             continue;
01862         }
01863 
01864         FD_ZERO( &readfds );
01865         FD_SET( pServer->m_fd, &readfds );
01866         timeout.tv_sec = 1; timeout.tv_usec = 0;
01867         if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 ) {
01868             if ( pServer->m_iCurChildren >= 0 ) {
01869                 usleep( 10 );
01870                 FD_ZERO( &readfds );
01871                 FD_SET( pServer->m_fd, &readfds );
01872                 timeout.tv_sec = 0; timeout.tv_usec = 0;
01873                 if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 ) {
01874                     continue;
01875                 }
01876             }
01877         } else {
01878             if ( ret == -1 ) {
01879                 if ( errno == EINTR ) {
01880                     continue;
01881                 }
01882                 /* perror( "select()" ); */
01883                 break;
01884             } else {
01885                 continue;
01886             }
01887         }
01888 
01889         pReq->m_fd = lsapi_accept( pServer->m_fd );
01890         if ( pReq->m_fd != -1 ) {
01891             child_status = find_child_status( 0 );
01892             pid = fork();
01893             if ( !pid ) {
01894                 g_prefork_server = NULL;
01895                 s_ppid = getppid();
01896                 s_req_processed = 0;
01897                 s_pChildStatus = child_status;
01898                 child_status->m_iKillSent = 0;
01899                 lsapi_set_nblock( pReq->m_fd, 0 );
01900 
01901                 /* don't catch our signals */
01902                 sigaction( SIGCHLD, &old_child, 0 );
01903                 sigaction( SIGTERM, &old_term, 0 );
01904                 sigaction( SIGQUIT, &old_quit, 0 );
01905                 sigaction( SIGINT,  &old_int,  0 );
01906                 sigaction( SIGUSR1, &old_usr1, 0 );
01907                 return 0;
01908             } else {
01909                 if ( pid == -1 ) {
01910                     perror( "fork() failed, please increase process limit" );
01911                 } else {
01912                     ++pServer->m_iCurChildren;
01913                     if ( child_status ) {
01914                         child_status->m_pid = pid;
01915                         child_status->m_iKillSent = 0;
01916                         child_status->m_tmWaitBegin = time(NULL);
01917                     }
01918                 }
01919             }
01920             close( pReq->m_fd );
01921             pReq->m_fd = -1;
01922 
01923         } else {
01924             if (( errno == EINTR )||( errno == EAGAIN)) {
01925                 continue;
01926             }
01927             perror( "accept() failed" );
01928             return -1;
01929         }
01930     }
01931     sigaction( SIGUSR1, &old_usr1, 0 );
01932     kill( -getpgrp(), SIGUSR1 );
01933     lsapi_all_children_must_die();  /* Sorry, children ;-) */
01934     return -1;
01935 
01936 }
01937 
01938 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
01939 {
01940     int             fd;
01941     int             ret;
01942     int             wait_secs;
01943     fd_set          readfds;
01944     struct timeval  timeout;
01945 
01946     LSAPI_Finish_r( pReq );
01947 
01948 
01949     if ( g_prefork_server ) {
01950         if ( g_prefork_server->m_fd != -1 ) {
01951             if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) {
01952                 return -1;
01953             }
01954         }
01955     }
01956     if ( s_req_processed >= s_max_reqs ) {
01957         return -1;
01958     }
01959 
01960     if ( s_pChildStatus ) {
01961         s_pChildStatus->m_tmWaitBegin = time( NULL );
01962     }
01963     
01964     while( g_running ) {
01965         if ( pReq->m_fd != -1 ) {
01966             fd = pReq->m_fd;
01967         } else {
01968             if ( pReq->m_fdListen != -1 ) {
01969                 fd = pReq->m_fdListen;
01970             } else {
01971                 return -1;
01972             }
01973         }
01974         wait_secs = 0;
01975         while( 1 ) {
01976             if ( !g_running ) {
01977                 return -1;
01978             }
01979             if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
01980                 return -1; 
01981             }
01982             FD_ZERO( &readfds );
01983             FD_SET( fd, &readfds );
01984             timeout.tv_sec = 1;
01985             timeout.tv_usec = 0;
01986             ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
01987             if ( ret == 0 ) {
01988                 if ( s_pChildStatus ) {
01989                     s_pChildStatus->m_inProcess = 0;
01990                 }
01991                 ++wait_secs;
01992                 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) {
01993                     return -1;
01994                 }
01995                 if ( s_ppid &&( getppid() != s_ppid)) {
01996                     return -1;
01997                 }
01998             } else {
01999                 if ( ret == -1 ) {
02000                     if ( errno == EINTR ) {
02001                         continue;
02002                     } else {
02003                         return -1;
02004                     }
02005                 } else {
02006                     if ( ret >= 1 ) {
02007                         if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
02008                             return -1; 
02009                         }
02010                         if ( fd == pReq->m_fdListen ) {
02011                             pReq->m_fd = lsapi_accept( pReq->m_fdListen );
02012                             if ( pReq->m_fd != -1 ) {
02013                                 fd = pReq->m_fd;
02014                                 lsapi_set_nblock( fd, 0 );
02015                             } else {
02016                                 if (( errno == EINTR )||( errno == EAGAIN)) {
02017                                     continue;
02018                                                         }
02019                                 return -1;
02020                             }
02021                         } else {
02022                             break;
02023                         }
02024                     }
02025                 }
02026             }
02027         }
02028         if ( !readReq( pReq ) ) {
02029             if ( s_pChildStatus ) {
02030                 s_pChildStatus->m_inProcess = 1;
02031                 s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
02032             }
02033             ++s_req_processed;
02034             return 0;
02035         }
02036         lsapi_close( pReq->m_fd );
02037         pReq->m_fd = -1;
02038         LSAPI_Reset_r( pReq );
02039     }
02040     return -1;
02041     
02042 }
02043 
02044 void LSAPI_Set_Max_Reqs( int reqs )
02045 {   
02046     s_max_reqs = reqs;          
02047 }
02048 
02049 void LSAPI_Set_Max_Idle( int secs )
02050 {   
02051     s_max_idle_secs = secs;     
02052 }
02053 
02054 void LSAPI_Set_Max_Children( int maxChildren )
02055 {
02056     if ( g_prefork_server ) {
02057         g_prefork_server->m_iMaxChildren = maxChildren;
02058     }
02059 }
02060 
02061 void LSAPI_Set_Extra_Children( int extraChildren )
02062 {
02063     if (( g_prefork_server )&&( extraChildren >= 0 )) {
02064         g_prefork_server->m_iExtraChildren = extraChildren;
02065     }
02066 }
02067 
02068 void LSAPI_Set_Max_Process_Time( int secs )
02069 {
02070     if (( g_prefork_server )&&( secs > 0 )) {
02071         g_prefork_server->m_iMaxReqProcessTime = secs;
02072     }
02073 }
02074 
02075 
02076 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
02077 {
02078     if (( g_prefork_server )&&( maxIdleChld > 0 )) {
02079         g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
02080     }
02081 }
02082 
02083 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
02084 {
02085     if ( g_prefork_server ) {
02086         g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
02087     }
02088 }
02089 
02090 void LSAPI_Set_Slow_Req_Msecs( int msecs )
02091 {
02092        s_slow_req_msecs = msecs;
02093 }
02094 
02095 int  LSAPI_Get_Slow_Req_Msecs()
02096 {
02097        return s_slow_req_msecs;
02098 }
02099 
02100 void LSAPI_No_Check_ppid()
02101 {
02102     s_ppid = 0;
02103 }
02104 
02105 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
02106 #include <crt_externs.h>
02107 #else
02108 extern char ** environ;
02109 #endif
02110 static void unset_lsapi_envs()
02111 {
02112     char **env;
02113 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
02114     env = *_NSGetEnviron();
02115 #else
02116     env = environ;
02117 #endif
02118     while( env != NULL && *env != NULL ) {
02119         if ( !strncmp(*env, "LSAPI_", 6) || 
02120              !strncmp( *env, "PHP_LSAPI_", 10 ) ) {   
02121             char ** del = env;
02122             do {
02123                 *del = del[1];
02124             } while( *del++ );
02125         } else {
02126             ++env;
02127         }
02128     }  
02129 }
02130 
02131 void LSAPI_Init_Env_Parameters( fn_select_t fp )
02132 {
02133     const char *p;
02134     int n;
02135     int avoidFork = 0;
02136     p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
02137     if ( !p ) {
02138         p = getenv( "LSAPI_MAX_REQS" );
02139     }
02140     if ( p ) {
02141         n = atoi( p );
02142         if ( n > 0 ) {
02143             LSAPI_Set_Max_Reqs( n );
02144         }
02145     }
02146 
02147     p = getenv( "LSAPI_AVOID_FORK" );
02148     if ( p ) {
02149         avoidFork = atoi( p );
02150     }    
02151 
02152     p = getenv( "LSAPI_ACCEPT_NOTIFY" );
02153     if ( p ) {
02154         s_accept_notify = atoi( p );
02155     }    
02156 
02157     p = getenv( "LSAPI_SLOW_REQ_MSECS" );
02158     if ( p ) {
02159         n = atoi( p );
02160         LSAPI_Set_Slow_Req_Msecs( n );
02161     }    
02162 
02163 
02164 #if defined( RLIMIT_CORE )
02165     p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
02166     if ( !p ) {
02167         struct rlimit limit = { 0, 0 };
02168         setrlimit( RLIMIT_CORE, &limit );
02169     }
02170 #endif    
02171 
02172     p = getenv( "LSAPI_MAX_IDLE" );
02173     if ( p ) {
02174         n = atoi( p );
02175         LSAPI_Set_Max_Idle( n );
02176     }
02177 
02178     if ( LSAPI_Is_Listen() ) {
02179         n = 0;
02180         p = getenv( "PHP_LSAPI_CHILDREN" );
02181         if ( !p ) {
02182             p = getenv( "LSAPI_CHILDREN" );
02183         }
02184         if ( p ) {
02185             n = atoi( p );
02186         }
02187         if ( n > 1 ) {
02188             LSAPI_Init_Prefork_Server( n, fp, avoidFork );
02189             LSAPI_Set_Server_fd( g_req.m_fdListen );
02190         }
02191 
02192         p = getenv( "LSAPI_EXTRA_CHILDREN" );
02193         if ( p ) {
02194             LSAPI_Set_Extra_Children( atoi( p ) );
02195         }
02196         
02197         p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
02198         if ( p ) {
02199             LSAPI_Set_Max_Idle_Children( atoi( p ) );
02200         }
02201         p = getenv( "LSAPI_PGRP_MAX_IDLE" );
02202         if ( p ) {
02203             LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
02204         }
02205         
02206         p = getenv( "LSAPI_MAX_PROCESS_TIME" );
02207         if ( p ) {     
02208             LSAPI_Set_Max_Process_Time( atoi( p ) );
02209         }
02210         if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) {
02211             LSAPI_No_Check_ppid();
02212         }
02213     }
02214     unset_lsapi_envs();
02215 }
02216 
02217 
02218 /*
02219  * Local variables:
02220  * tab-width: 4
02221  * c-basic-offset: 4
02222  * End:
02223  * vim600: sw=4 ts=4 fdm=marker
02224  * vim<600: sw=4 ts=4
02225  */
02226 
02227