Annotation of embedaddon/php/sapi/litespeed/lsapilib.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2007 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available at through the world-wide-web at the following url:        |
        !            10:    | http://www.php.net/license/3_01.txt.                                 |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Author: George Wang <gwang@litespeedtech.com>                        |
        !            16:    +----------------------------------------------------------------------+
        !            17: */
        !            18: 
        !            19: /* $Id: lsapilib.c 311935 2011-06-08 16:51:59Z gwang $ */
        !            20: 
        !            21: /*
        !            22: Copyright (c) 2007, Lite Speed Technologies Inc.
        !            23: All rights reserved.
        !            24: 
        !            25: Redistribution and use in source and binary forms, with or without
        !            26: modification, are permitted provided that the following conditions are
        !            27: met: 
        !            28: 
        !            29:     * Redistributions of source code must retain the above copyright
        !            30:       notice, this list of conditions and the following disclaimer. 
        !            31:     * Redistributions in binary form must reproduce the above
        !            32:       copyright notice, this list of conditions and the following
        !            33:       disclaimer in the documentation and/or other materials provided
        !            34:       with the distribution. 
        !            35:     * Neither the name of the Lite Speed Technologies Inc nor the
        !            36:       names of its contributors may be used to endorse or promote
        !            37:       products derived from this software without specific prior
        !            38:       written permission.  
        !            39: 
        !            40: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        !            41: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        !            42: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
        !            43: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
        !            44: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            45: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
        !            46: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            47: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            48: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            49: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        !            50: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
        !            51: */
        !            52: 
        !            53: #include <lsapilib.h>
        !            54: 
        !            55: #include <ctype.h>
        !            56: #include <errno.h>
        !            57: #include <fcntl.h>
        !            58: 
        !            59: #include <arpa/inet.h>
        !            60: #include <netdb.h>
        !            61: #include <netinet/in.h>
        !            62: #include <netinet/tcp.h>
        !            63: #include <sys/un.h>
        !            64: #include <signal.h>
        !            65: #include <stdlib.h>
        !            66: #include <stdio.h>
        !            67: #include <string.h>
        !            68: #include <sys/mman.h>
        !            69: #include <sys/resource.h>
        !            70: #include <sys/socket.h>
        !            71: #include <sys/time.h>
        !            72: #include <sys/uio.h>
        !            73: #include <sys/wait.h>
        !            74: #include <time.h>
        !            75: #include <unistd.h>
        !            76: 
        !            77: #define LSAPI_ST_REQ_HEADER     1
        !            78: #define LSAPI_ST_REQ_BODY       2
        !            79: #define LSAPI_ST_RESP_HEADER    4
        !            80: #define LSAPI_ST_RESP_BODY      8
        !            81: 
        !            82: #define LSAPI_RESP_BUF_SIZE     8192
        !            83: #define LSAPI_INIT_RESP_HEADER_LEN 4096
        !            84: 
        !            85: 
        !            86: static int g_inited = 0;
        !            87: static int g_running = 1;
        !            88: static int s_ppid;
        !            89: static int s_slow_req_msecs = 0;
        !            90: LSAPI_Request g_req = { -1, -1 };
        !            91: 
        !            92: void Flush_RespBuf_r( LSAPI_Request * pReq );
        !            93: 
        !            94: static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
        !            95: {
        !            96:     "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
        !            97:     "HTTP_ACCEPT_ENCODING",
        !            98:     "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
        !            99:     "HTTP_CONNECTION", "CONTENT_TYPE",
        !           100:     "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
        !           101:     "HTTP_HOST", "HTTP_PRAGMA",
        !           102:     "HTTP_REFERER", "HTTP_USER_AGENT",
        !           103:     "HTTP_CACHE_CONTROL",
        !           104:     "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
        !           105:     "HTTP_IF_NONE_MATCH",
        !           106:     "HTTP_IF_RANGE",
        !           107:     "HTTP_IF_UNMODIFIED_SINCE",
        !           108:     "HTTP_KEEP_ALIVE",
        !           109:     "HTTP_RANGE",
        !           110:     "HTTP_X_FORWARDED_FOR",
        !           111:     "HTTP_VIA",
        !           112:     "HTTP_TRANSFER_ENCODING"
        !           113: };
        !           114:      
        !           115: static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = {
        !           116:      11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
        !           117:      22, 13, 18, 13, 24, 15, 10, 20, 8, 22 
        !           118: };
        !           119: 
        !           120: 
        !           121: static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = {
        !           122:     "Accept", "Accept-Charset",
        !           123:     "Accept-Encoding",
        !           124:     "Accept-Language", "Authorization",
        !           125:     "Connection", "Content-Type",
        !           126:     "Content-Length", "Cookie", "Cookie2",
        !           127:     "Host", "Pragma",
        !           128:     "Referer", "User-Agent",
        !           129:     "Cache-Control",
        !           130:     "If-Modified-Since", "If-Match",
        !           131:     "If-None-Match",
        !           132:     "If-Range",
        !           133:     "If-Unmodified-Since",
        !           134:     "Keep-Alive",
        !           135:     "Range",
        !           136:     "X-Forwarded-For",
        !           137:     "Via",
        !           138:     "Transfer-Encoding"
        !           139: };
        !           140: 
        !           141: static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = {
        !           142:     6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, /* user-agent */
        !           143:     13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
        !           144: };
        !           145:      
        !           146: static void lsapi_sigpipe( int sig )
        !           147: {
        !           148: }
        !           149: static void lsapi_siguser1( int sig )
        !           150: {
        !           151:     g_running = 0;
        !           152: }
        !           153: 
        !           154: #ifndef sighandler_t
        !           155: typedef void (*sighandler_t)(int);
        !           156: #endif
        !           157:           
        !           158: static void lsapi_signal(int signo, sighandler_t handler)
        !           159: {
        !           160:     struct sigaction sa;
        !           161: 
        !           162:     sigaction(signo, NULL, &sa);
        !           163: 
        !           164:     if (sa.sa_handler == SIG_DFL) {
        !           165:         sigemptyset(&sa.sa_mask);
        !           166:         sa.sa_flags = 0;
        !           167:         sa.sa_handler = handler;
        !           168:         sigaction(signo, &sa, NULL);
        !           169:     }
        !           170: }
        !           171: 
        !           172: 
        !           173: static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
        !           174:                                 char type, int len )
        !           175: {
        !           176:     pHeader->m_versionB0 = LSAPI_VERSION_B0;  /* LSAPI protocol version */
        !           177:     pHeader->m_versionB1 = LSAPI_VERSION_B1;
        !           178:     pHeader->m_type      = type;
        !           179:     pHeader->m_flag      = LSAPI_ENDIAN;
        !           180:     pHeader->m_packetLen.m_iLen = len;
        !           181: }
        !           182: 
        !           183: static  int lsapi_set_nblock( int fd, int nonblock )
        !           184: {
        !           185:     int val = fcntl( fd, F_GETFL, 0 );
        !           186:     if ( nonblock )
        !           187:     {
        !           188:         if (!( val & O_NONBLOCK ))
        !           189:         {
        !           190:             return fcntl( fd, F_SETFL, val | O_NONBLOCK );
        !           191:         }
        !           192:     }
        !           193:     else
        !           194:     {
        !           195:         if ( val & O_NONBLOCK )
        !           196:         {
        !           197:             return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
        !           198:         }
        !           199:     }
        !           200:     return 0;
        !           201: }
        !           202: 
        !           203: 
        !           204: static int lsapi_close( int fd )
        !           205: {
        !           206:     int ret;
        !           207:     while( 1 ) {
        !           208:         ret = close( fd );
        !           209:         if (( ret == -1 )&&( errno == EINTR )&&(g_running)) {
        !           210:             continue;
        !           211:         }
        !           212:         return ret;
        !           213:     }
        !           214: }
        !           215: 
        !           216: static inline int lsapi_read( int fd, void * pBuf, int len )
        !           217: {
        !           218:     int ret;
        !           219:     while( 1 ) {
        !           220:         ret = read( fd, (char *)pBuf, len );
        !           221:         if (( ret == -1 )&&( errno == EINTR )&&(g_running)) {
        !           222:             continue;
        !           223:         }
        !           224:         return ret;
        !           225:     }
        !           226: }
        !           227: 
        !           228: 
        !           229: static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
        !           230: {
        !           231:     int ret;
        !           232:     int left = totalLen;
        !           233:     int n = count;
        !           234:     while(( left > 0 )&&g_running ) {
        !           235:         ret = writev( fd, *pVec, n );
        !           236:         if ( ret > 0 ) {
        !           237:             left -= ret;
        !           238:             if (( left <= 0)||( !g_running )) {
        !           239:                 return totalLen - left;
        !           240:             }
        !           241:             while( ret > 0 ) {
        !           242:                 if ( (*pVec)->iov_len <= ret ) {
        !           243:                     ret -= (*pVec)->iov_len;
        !           244:                     ++(*pVec);
        !           245:                 } else {
        !           246:                     (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
        !           247:                     (*pVec)->iov_len -= ret;
        !           248:                     break;
        !           249:                 }
        !           250:             }
        !           251:         } else if ( ret == -1 ) {
        !           252:             if ( errno == EAGAIN ) {
        !           253:                 if ( totalLen - left > 0 ) {
        !           254:                     return totalLen - left;
        !           255:                 } else {
        !           256:                     return -1;
        !           257:                 }
        !           258:             } else {
        !           259:                 if ( errno != EINTR ) {
        !           260:                     return ret;
        !           261:                 }
        !           262:             }
        !           263:         }
        !           264:     }
        !           265:     return totalLen - left;
        !           266: }
        !           267: 
        !           268: static inline int allocateBuf( LSAPI_Request * pReq, int size )
        !           269: {
        !           270:     char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
        !           271:     if ( pBuf ) {
        !           272:         pReq->m_pReqBuf = pBuf;
        !           273:         pReq->m_reqBufSize = size;
        !           274:         pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
        !           275:         return 0;
        !           276:     }
        !           277:     return -1;
        !           278: }
        !           279: 
        !           280: 
        !           281: static int allocateIovec( LSAPI_Request * pReq, int n )
        !           282: {
        !           283:     struct iovec * p = (struct iovec *)realloc(
        !           284:                 pReq->m_pIovec, sizeof(struct iovec) * n );
        !           285:     if ( !p ) {
        !           286:         return -1;
        !           287:     }
        !           288:     pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
        !           289:     pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
        !           290:     pReq->m_pIovec = p;
        !           291:     pReq->m_pIovecEnd = p + n;
        !           292:     return 0;
        !           293: }
        !           294: 
        !           295: static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
        !           296: {
        !           297:     char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
        !           298:     if ( !p ) {
        !           299:         return -1;
        !           300:     }
        !           301:     pReq->m_pRespHeaderBufPos   = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
        !           302:     pReq->m_pRespHeaderBuf      = p;
        !           303:     pReq->m_pRespHeaderBufEnd   = p + size;
        !           304:     return 0;
        !           305: }
        !           306: 
        !           307: 
        !           308: static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
        !           309: {
        !           310:     if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
        !           311:         ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
        !           312:         ( pktType != pHeader->m_type )) {
        !           313:         return -1;
        !           314:     }
        !           315:     if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) {
        !           316:         register char b;
        !           317:         b = pHeader->m_packetLen.m_bytes[0];
        !           318:         pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
        !           319:         pHeader->m_packetLen.m_bytes[3] = b;
        !           320:         b = pHeader->m_packetLen.m_bytes[1];
        !           321:         pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
        !           322:         pHeader->m_packetLen.m_bytes[2] = b;
        !           323:     }
        !           324:     return pHeader->m_packetLen.m_iLen;
        !           325: }
        !           326: 
        !           327: static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
        !           328:                         int *curSize, int newSize )
        !           329: {
        !           330:     struct LSAPI_key_value_pair * pBuf;
        !           331:     if ( *curSize >= newSize ) {
        !           332:         return 0;
        !           333:     }
        !           334:     if ( newSize > 8192 ) {
        !           335:         return -1;
        !           336:     }
        !           337:     pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
        !           338:                     sizeof(struct LSAPI_key_value_pair) );
        !           339:     if ( pBuf ) {
        !           340:         *pEnvList = pBuf;
        !           341:         *curSize  = newSize;
        !           342:         return 0;
        !           343:     } else {
        !           344:         return -1;
        !           345:     }
        !           346: 
        !           347: }
        !           348: 
        !           349: static inline int isPipe( int fd )
        !           350: {
        !           351:     char        achPeer[128];
        !           352:     socklen_t   len = 128;
        !           353:     if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
        !           354:         ( errno == ENOTCONN )) {
        !           355:         return 0;
        !           356:     } else {
        !           357:         return 1;
        !           358:     }
        !           359: }
        !           360: 
        !           361: static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
        !           362:             char **pBegin, char * pEnd )
        !           363: {
        !           364:     struct LSAPI_key_value_pair * pEnvEnd;
        !           365:     int keyLen = 0, valLen = 0;
        !           366:     if ( count > 8192 ) {
        !           367:         return -1;
        !           368:     }
        !           369:     pEnvEnd = pEnvList + count;
        !           370:     while( pEnvList != pEnvEnd ) {
        !           371:         if ( pEnd - *pBegin < 4 ) {
        !           372:             return -1;
        !           373:         }
        !           374:         keyLen = *((unsigned char *)((*pBegin)++));
        !           375:         keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
        !           376:         valLen = *((unsigned char *)((*pBegin)++));
        !           377:         valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
        !           378:         if ( *pBegin + keyLen + valLen > pEnd ) {
        !           379:             return -1;
        !           380:         }
        !           381:         if (( !keyLen )||( !valLen )) {
        !           382:             return -1;
        !           383:         }
        !           384: 
        !           385:         pEnvList->pKey = *pBegin;
        !           386:         *pBegin += keyLen;
        !           387:         pEnvList->pValue = *pBegin;
        !           388:         *pBegin += valLen;
        !           389: 
        !           390:         pEnvList->keyLen = keyLen - 1;
        !           391:         pEnvList->valLen = valLen - 1;
        !           392:         ++pEnvList;
        !           393:     }
        !           394:     if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) {
        !           395:         return -1;
        !           396:     }
        !           397:     *pBegin += 4;
        !           398:     return 0;
        !           399: }
        !           400: 
        !           401: static inline void swapIntEndian( int * pInteger )
        !           402: {
        !           403:     char * p = (char *)pInteger;
        !           404:     register char b;
        !           405:     b = p[0];
        !           406:     p[0] = p[3];
        !           407:     p[3] = b;
        !           408:     b = p[1];
        !           409:     p[1] = p[2];
        !           410:     p[2] = b;
        !           411:     
        !           412: }
        !           413: 
        !           414: static inline void fixEndian( LSAPI_Request * pReq )
        !           415: {
        !           416:     struct lsapi_req_header *p= pReq->m_pHeader;
        !           417:     swapIntEndian( &p->m_httpHeaderLen );
        !           418:     swapIntEndian( &p->m_reqBodyLen );
        !           419:     swapIntEndian( &p->m_scriptFileOff );
        !           420:     swapIntEndian( &p->m_scriptNameOff );
        !           421:     swapIntEndian( &p->m_queryStringOff );
        !           422:     swapIntEndian( &p->m_requestMethodOff );
        !           423:     swapIntEndian( &p->m_cntUnknownHeaders );
        !           424:     swapIntEndian( &p->m_cntEnv );
        !           425:     swapIntEndian( &p->m_cntSpecialEnv );
        !           426: }
        !           427: 
        !           428: static void fixHeaderIndexEndian( LSAPI_Request * pReq )
        !           429: {
        !           430:     int i;
        !           431:     for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
        !           432:         if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
        !           433:             register char b;
        !           434:             char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
        !           435:             b = p[0];
        !           436:             p[0] = p[1];
        !           437:             p[1] = b;
        !           438:             swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
        !           439:         }
        !           440:     }
        !           441:     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
        !           442:         struct lsapi_header_offset * pCur, *pEnd;
        !           443:         pCur = pReq->m_pUnknownHeader;
        !           444:         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
        !           445:         while( pCur < pEnd ) {
        !           446:             swapIntEndian( &pCur->nameOff );
        !           447:             swapIntEndian( &pCur->nameLen );
        !           448:             swapIntEndian( &pCur->valueOff );
        !           449:             swapIntEndian( &pCur->valueLen );
        !           450:             ++pCur;
        !           451:         }
        !           452:     }    
        !           453: }
        !           454: 
        !           455: static int parseRequest( LSAPI_Request * pReq, int totalLen )
        !           456: {
        !           457:     int shouldFixEndian;
        !           458:     char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
        !           459:     char * pEnd = pReq->m_pReqBuf + totalLen;
        !           460:     shouldFixEndian = ( LSAPI_ENDIAN != (
        !           461:                 pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
        !           462:     if ( shouldFixEndian ) {
        !           463:         fixEndian( pReq );
        !           464:     }
        !           465:     if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
        !           466:             allocateEnvList( &pReq->m_pSpecialEnvList,
        !           467:                               &pReq->m_specialEnvListSize,
        !           468:                              pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) {
        !           469:         return -1;
        !           470:     }
        !           471:     if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
        !           472:             allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
        !           473:                              pReq->m_pHeader->m_cntEnv ) == -1 ) {
        !           474:         return -1;
        !           475:     }
        !           476:     if ( parseEnv( pReq->m_pSpecialEnvList,
        !           477:                    pReq->m_pHeader->m_cntSpecialEnv,
        !           478:                    &pBegin, pEnd ) == -1 ) {
        !           479:         return -1;
        !           480:     }
        !           481:     if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
        !           482:                    &pBegin, pEnd ) == -1 ) {
        !           483:         return -1;
        !           484:     }
        !           485:     pReq->m_pScriptFile     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
        !           486:     pReq->m_pScriptName     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
        !           487:     pReq->m_pQueryString    = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
        !           488:     pReq->m_pRequestMethod  = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
        !           489:     
        !           490:     pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
        !           491:     pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
        !           492:     pBegin += sizeof( struct lsapi_http_header_index );
        !           493: 
        !           494:     pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
        !           495:     pBegin += sizeof( struct lsapi_header_offset) *
        !           496:                     pReq->m_pHeader->m_cntUnknownHeaders;
        !           497: 
        !           498:     pReq->m_pHttpHeader = pBegin;
        !           499:     pBegin += pReq->m_pHeader->m_httpHeaderLen;
        !           500:     if ( pBegin != pEnd ) {
        !           501:         return -1;
        !           502:     }
        !           503: 
        !           504:     if ( shouldFixEndian ) {
        !           505:         fixHeaderIndexEndian( pReq );
        !           506:     }
        !           507: 
        !           508:     return 0;
        !           509: }
        !           510: 
        !           511: static int s_accept_notify = 0;
        !           512: 
        !           513: static struct lsapi_packet_header ack = {'L', 'S',
        !           514:                 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
        !           515: static inline int notify_req_received( int fd )
        !           516: {
        !           517:     if ( write( fd, &ack, LSAPI_PACKET_HEADER_LEN )
        !           518:          < LSAPI_PACKET_HEADER_LEN ) {
        !           519:         return -1;
        !           520:     }
        !           521:     return 0;
        !           522: }
        !           523: 
        !           524: 
        !           525: static int readReq( LSAPI_Request * pReq )
        !           526: {
        !           527:     int len;
        !           528:     int packetLen;
        !           529:     if ( !pReq ) {
        !           530:         return -1;
        !           531:     }
        !           532:     if ( pReq->m_reqBufSize < 8192 ) {
        !           533:         if ( allocateBuf( pReq, 8192 ) == -1 ) {
        !           534:             return -1;
        !           535:         }
        !           536:     }
        !           537: 
        !           538:     while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) {
        !           539:         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
        !           540:         if ( len <= 0 ) {
        !           541:             return -1;
        !           542:         }
        !           543:         pReq->m_bufRead += len;
        !           544:     }
        !           545:     pReq->m_reqState = LSAPI_ST_REQ_HEADER;
        !           546: 
        !           547:     packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
        !           548:     if ( packetLen < 0 ) {
        !           549:         return -1;
        !           550:     }
        !           551:     if ( packetLen > LSAPI_MAX_HEADER_LEN ) {
        !           552:         return -1;
        !           553:     }
        !           554: 
        !           555:     if ( packetLen + 1024 > pReq->m_reqBufSize ) {
        !           556:         if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) {
        !           557:             return -1;
        !           558:         }
        !           559:     }
        !           560:     while( packetLen > pReq->m_bufRead ) {
        !           561:         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
        !           562:         if ( len <= 0 ) {
        !           563:             return -1;
        !           564:         }
        !           565:         pReq->m_bufRead += len;
        !           566:     }
        !           567:     if ( parseRequest( pReq, packetLen ) < 0 ) {
        !           568:         return -1;
        !           569:     }
        !           570:     pReq->m_bufProcessed = packetLen;
        !           571:     pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
        !           572: 
        !           573:     if ( !s_accept_notify )
        !           574:         return notify_req_received( pReq->m_fd );
        !           575:     else
        !           576:         return 0;
        !           577: }
        !           578: 
        !           579: 
        !           580: 
        !           581: int LSAPI_Init(void)
        !           582: {
        !           583:     if ( !g_inited ) {
        !           584:         lsapi_signal(SIGPIPE, lsapi_sigpipe);
        !           585:         lsapi_signal(SIGUSR1, lsapi_siguser1);
        !           586: 
        !           587: #if defined(SIGXFSZ) && defined(SIG_IGN)
        !           588:         signal(SIGXFSZ, SIG_IGN);
        !           589: #endif
        !           590:         /* let STDOUT function as STDERR, 
        !           591:            just in case writing to STDOUT directly */
        !           592:         dup2( 2, 1 );
        !           593: 
        !           594:         if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) {
        !           595:             return -1;
        !           596:         }
        !           597:         g_inited = 1;
        !           598:         s_ppid = getppid();
        !           599:     }
        !           600:     return 0;
        !           601: }
        !           602: 
        !           603: void LSAPI_Stop(void)
        !           604: {
        !           605:     g_running = 0;
        !           606: }
        !           607: 
        !           608: int LSAPI_IsRunning(void)
        !           609: {
        !           610:     return g_running;
        !           611: }
        !           612: 
        !           613: int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
        !           614: {
        !           615:     if ( !pReq ) {
        !           616:         return -1;
        !           617:     }
        !           618:     memset( pReq, 0, sizeof( LSAPI_Request ) );
        !           619:     if ( allocateIovec( pReq, 16 ) == -1 ) {
        !           620:         return -1;
        !           621:     }
        !           622:     pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
        !           623:     if ( !pReq->m_pRespBuf ) {
        !           624:         return -1;
        !           625:     }
        !           626:     pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
        !           627:     pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
        !           628:     pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
        !           629:     if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) {
        !           630:         return -1;
        !           631:     }
        !           632:  
        !           633:     if ( isPipe( fd ) ) {
        !           634:         pReq->m_fdListen = -1;
        !           635:         pReq->m_fd = fd;
        !           636:     } else {
        !           637:         pReq->m_fdListen = fd;
        !           638:         pReq->m_fd = -1;
        !           639:         lsapi_set_nblock( fd, 1 );
        !           640:     }
        !           641:     return 0;
        !           642: }
        !           643: 
        !           644: int LSAPI_Is_Listen( void )
        !           645: {
        !           646:     return LSAPI_Is_Listen_r( &g_req );
        !           647: }
        !           648: 
        !           649: int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
        !           650: {
        !           651:     return pReq->m_fdListen != -1;
        !           652: }
        !           653: 
        !           654: 
        !           655: 
        !           656: int LSAPI_Accept_r( LSAPI_Request * pReq )
        !           657: {
        !           658:     char        achPeer[128];
        !           659:     socklen_t   len;
        !           660:     int         nodelay = 1;
        !           661:     
        !           662:     if ( !pReq ) {
        !           663:         return -1;
        !           664:     }
        !           665:     if ( LSAPI_Finish_r( pReq ) == -1 ) {
        !           666:         return -1;
        !           667:     }
        !           668:     while( g_running ) {
        !           669:         if ( pReq->m_fd == -1 ) {
        !           670:             if ( pReq->m_fdListen != -1) {
        !           671:                 len = sizeof( achPeer );
        !           672:                 pReq->m_fd = accept( pReq->m_fdListen,
        !           673:                             (struct sockaddr *)&achPeer, &len );
        !           674:                 if ( pReq->m_fd == -1 ) {
        !           675:                     if (( errno == EINTR )||( errno == EAGAIN)) {
        !           676:                         continue;
        !           677:                     } else {
        !           678:                         return -1;
        !           679:                     }
        !           680:                 } else {
        !           681:                     lsapi_set_nblock( pReq->m_fd , 0 );
        !           682:                     if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) {    
        !           683:                         setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
        !           684:                                 (char *)&nodelay, sizeof(nodelay));
        !           685:                     }
        !           686: 
        !           687:                     if ( s_accept_notify )
        !           688:                         return notify_req_received( pReq->m_fd );
        !           689: 
        !           690:                 }
        !           691:             } else {
        !           692:                 return -1;
        !           693:             }
        !           694:         }
        !           695:         if ( !readReq( pReq ) ) {
        !           696:             break;
        !           697:         }
        !           698:         lsapi_close( pReq->m_fd );
        !           699:         pReq->m_fd = -1;
        !           700:         LSAPI_Reset_r( pReq );
        !           701:     }
        !           702:     return 0;
        !           703: }
        !           704: 
        !           705: static struct lsapi_packet_header   finish = {'L', 'S',
        !           706:                 LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
        !           707: 
        !           708: int LSAPI_Finish_r( LSAPI_Request * pReq )
        !           709: {
        !           710:     /* finish req body */
        !           711:     if ( !pReq ) {
        !           712:         return -1;
        !           713:     }
        !           714:     if (pReq->m_reqState) {
        !           715:         if ( pReq->m_fd != -1 ) {
        !           716:             if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
        !           717:                 LSAPI_FinalizeRespHeaders_r( pReq );
        !           718:             }
        !           719:             if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
        !           720:                 Flush_RespBuf_r( pReq );
        !           721:             }
        !           722:             
        !           723:             pReq->m_pIovecCur->iov_base = (void *)&finish;
        !           724:             pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
        !           725:             pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
        !           726:             ++pReq->m_pIovecCur;
        !           727:             LSAPI_Flush_r( pReq );
        !           728:         }
        !           729:         LSAPI_Reset_r( pReq );
        !           730:     }
        !           731:     return 0;
        !           732: }
        !           733: 
        !           734: 
        !           735: void LSAPI_Reset_r( LSAPI_Request * pReq )
        !           736: {
        !           737:     pReq->m_pRespBufPos         = pReq->m_pRespBuf;
        !           738:     pReq->m_pIovecCur           = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
        !           739:     pReq->m_pRespHeaderBufPos   = pReq->m_pRespHeaderBuf;
        !           740:     
        !           741:     memset( &pReq->m_pHeaderIndex, 0,
        !           742:             (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
        !           743: }
        !           744: 
        !           745: 
        !           746: int LSAPI_Release_r( LSAPI_Request * pReq )
        !           747: {
        !           748:     if ( pReq->m_pReqBuf ) {
        !           749:         free( pReq->m_pReqBuf );
        !           750:     }
        !           751:     if ( pReq->m_pSpecialEnvList ) {
        !           752:         free( pReq->m_pSpecialEnvList );
        !           753:     }
        !           754:     if ( pReq->m_pEnvList ) {
        !           755:         free( pReq->m_pEnvList );
        !           756:     }
        !           757:     if ( pReq->m_pRespHeaderBuf ) {
        !           758:         free( pReq->m_pRespHeaderBuf );  
        !           759:     }
        !           760:     return 0;
        !           761: }
        !           762: 
        !           763: 
        !           764: char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
        !           765: {
        !           766:     int off;
        !           767:     if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) {
        !           768:         return NULL;
        !           769:     }
        !           770:     off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
        !           771:     if ( !off ) {
        !           772:         return NULL;
        !           773:     }
        !           774:     if ( *(pReq->m_pHttpHeader + off + 
        !           775:            pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) {
        !           776:         *( pReq->m_pHttpHeader + off + 
        !           777:             pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
        !           778:     }
        !           779:     return pReq->m_pHttpHeader + off;
        !           780: }
        !           781: 
        !           782: static int readBodyToReqBuf( LSAPI_Request * pReq )
        !           783: {
        !           784:     int bodyLeft;
        !           785:     int len = pReq->m_bufRead - pReq->m_bufProcessed;
        !           786:     if ( len > 0 ) {
        !           787:         return len;
        !           788:     }
        !           789:     pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
        !           790: 
        !           791:     bodyLeft = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
        !           792:     len = pReq->m_reqBufSize - pReq->m_bufRead;
        !           793:     if ( len < 0 ) {
        !           794:         return -1;
        !           795:     }
        !           796:     if ( len > bodyLeft ) {
        !           797:         len = bodyLeft;
        !           798:     }
        !           799:     len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
        !           800:     if ( len > 0 ) {
        !           801:         pReq->m_bufRead += len;
        !           802:     }
        !           803:     return len;
        !           804: }
        !           805: 
        !           806: 
        !           807: int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
        !           808: {
        !           809:     if (!pReq || (pReq->m_fd ==-1) ) {
        !           810:         return EOF;
        !           811:     }
        !           812:     if ( pReq->m_bufProcessed >= pReq->m_bufRead ) {
        !           813:         if ( readBodyToReqBuf( pReq ) <= 0 ) {
        !           814:             return EOF;
        !           815:         }
        !           816:     }
        !           817:     ++pReq->m_reqBodyRead;
        !           818:     return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
        !           819: }
        !           820: 
        !           821: 
        !           822: 
        !           823: int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF )
        !           824: {
        !           825:     int len;
        !           826:     int left;
        !           827:     char * pBufEnd = pBuf + bufLen - 1;
        !           828:     char * pBufCur = pBuf;
        !           829:     char * pCur;
        !           830:     char * p;
        !           831:     if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF ) {
        !           832:         return -1;
        !           833:     }
        !           834:     *getLF = 0;
        !           835:     while( (left = pBufEnd - pBufCur ) > 0 ) {
        !           836:         
        !           837:         len = pReq->m_bufRead - pReq->m_bufProcessed;
        !           838:         if ( len <= 0 ) {
        !           839:             if ( (len = readBodyToReqBuf( pReq )) <= 0 ) {
        !           840:                 *getLF = 1;
        !           841:                 break;
        !           842:             }
        !           843:         }
        !           844:         if ( len > left ) {
        !           845:             len = left;
        !           846:         }
        !           847:         pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
        !           848:         p = memchr( pCur, '\n', len );
        !           849:         if ( p ) {
        !           850:             len = p - pCur + 1;
        !           851:         }
        !           852:         memmove( pBufCur, pCur, len );
        !           853:         pBufCur += len;
        !           854:         pReq->m_bufProcessed += len;
        !           855: 
        !           856:         pReq->m_reqBodyRead += len;
        !           857:         
        !           858:         if ( p ) {
        !           859:             *getLF = 1;
        !           860:             break;
        !           861:         }
        !           862:     }
        !           863:     *pBufCur = 0;
        !           864:   
        !           865:     return pBufCur - pBuf;
        !           866: }
        !           867: 
        !           868: 
        !           869: int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
        !           870: {
        !           871:     int len;
        !           872:     int total;
        !           873:     /* char *pOldBuf = pBuf; */
        !           874:     if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 )) {
        !           875:         return -1;
        !           876:     }
        !           877:     total = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
        !           878:     
        !           879:     if ( total <= 0 ) {
        !           880:         return 0;
        !           881:     }
        !           882:     if ( total < bufLen ) {
        !           883:         bufLen = total;
        !           884:     }
        !           885: 
        !           886:     total = 0;
        !           887:     len = pReq->m_bufRead - pReq->m_bufProcessed;
        !           888:     if ( len > 0 ) {
        !           889:         if ( len > bufLen ) {
        !           890:             len = bufLen;
        !           891:         }
        !           892:         memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
        !           893:         pReq->m_bufProcessed += len;
        !           894:         total += len;
        !           895:         pBuf += len;
        !           896:         bufLen -= len;
        !           897:     }
        !           898:     while( bufLen > 0 ) {
        !           899:         len = lsapi_read( pReq->m_fd, pBuf, bufLen );
        !           900:         if ( len > 0 ) {
        !           901:             total += len;
        !           902:             pBuf += len;
        !           903:             bufLen -= len;
        !           904:         } else {
        !           905:             if ( len <= 0 ) {
        !           906:                 if ( !total) {
        !           907:                     return -1;
        !           908:                 }
        !           909:                 break;
        !           910:             }
        !           911:         }
        !           912:     }
        !           913:     pReq->m_reqBodyRead += total;
        !           914:     return total;
        !           915:         
        !           916: }
        !           917: 
        !           918: 
        !           919: int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
        !           920: {
        !           921:     struct lsapi_packet_header * pHeader;
        !           922:     const char * pEnd;
        !           923:     const char * p;
        !           924:     int bufLen;
        !           925:     int toWrite;
        !           926:     int packetLen;
        !           927:     
        !           928:     if ( !pReq || !pBuf || (pReq->m_fd == -1) ) {
        !           929:         return -1;
        !           930:     }
        !           931:     if ( len < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) {
        !           932:         memmove( pReq->m_pRespBufPos, pBuf, len );
        !           933:         pReq->m_pRespBufPos += len;
        !           934:         return len;
        !           935:     }
        !           936:     
        !           937:     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
        !           938:         LSAPI_FinalizeRespHeaders_r( pReq );
        !           939:     }
        !           940:     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
        !           941:     
        !           942:     pHeader = pReq->m_respPktHeader;
        !           943:     p       = pBuf;
        !           944:     pEnd    = pBuf + len;
        !           945:     bufLen  = pReq->m_pRespBufPos - pReq->m_pRespBuf;
        !           946:     
        !           947:     while( ( toWrite = pEnd - p ) > 0 ) {
        !           948:         packetLen = toWrite + bufLen;
        !           949:         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) {
        !           950:             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
        !           951:             toWrite = packetLen - bufLen;
        !           952:         }
        !           953:         
        !           954:         lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
        !           955:                             packetLen + LSAPI_PACKET_HEADER_LEN );
        !           956:         pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
        !           957: 
        !           958:         pReq->m_pIovecCur->iov_base = (void *)pHeader;
        !           959:         pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
        !           960:         ++pReq->m_pIovecCur;
        !           961:         ++pHeader;
        !           962:         if ( bufLen > 0 ) {
        !           963:             pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
        !           964:             pReq->m_pIovecCur->iov_len  = bufLen;
        !           965:             pReq->m_pRespBufPos = pReq->m_pRespBuf;
        !           966:             ++pReq->m_pIovecCur;       
        !           967:             bufLen = 0;
        !           968:         }
        !           969: 
        !           970:         pReq->m_pIovecCur->iov_base = (void *)p;
        !           971:         pReq->m_pIovecCur->iov_len  = toWrite;
        !           972:         ++pReq->m_pIovecCur;
        !           973:         p += toWrite;
        !           974: 
        !           975:         if ( pHeader >= pReq->m_respPktHeaderEnd - 1) {
        !           976:             if ( LSAPI_Flush_r( pReq ) == -1 ) {
        !           977:                 return -1;
        !           978:             }
        !           979:             pHeader = pReq->m_respPktHeader;
        !           980:         }
        !           981:     }
        !           982:     if ( pHeader != pReq->m_respPktHeader ) {
        !           983:         if ( LSAPI_Flush_r( pReq ) == -1 ) {
        !           984:             return -1;
        !           985:         }
        !           986:     }
        !           987:     return p - pBuf;
        !           988: }
        !           989: 
        !           990: void Flush_RespBuf_r( LSAPI_Request * pReq )
        !           991: {
        !           992:     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
        !           993:     int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
        !           994:     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
        !           995:     lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
        !           996:                         bufLen + LSAPI_PACKET_HEADER_LEN );
        !           997:     pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
        !           998: 
        !           999:     pReq->m_pIovecCur->iov_base = (void *)pHeader;
        !          1000:     pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
        !          1001:     ++pReq->m_pIovecCur;
        !          1002:     ++pHeader;
        !          1003:     if ( bufLen > 0 ) {
        !          1004:         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
        !          1005:         pReq->m_pIovecCur->iov_len  = bufLen;
        !          1006:         pReq->m_pRespBufPos = pReq->m_pRespBuf;
        !          1007:         ++pReq->m_pIovecCur;       
        !          1008:         bufLen = 0;
        !          1009:     }
        !          1010: }
        !          1011: 
        !          1012: 
        !          1013: 
        !          1014: 
        !          1015: int LSAPI_Flush_r( LSAPI_Request * pReq )
        !          1016: {
        !          1017:     int ret = 0;
        !          1018:     int n;
        !          1019:     if ( !pReq ) {
        !          1020:         return -1;
        !          1021:     }
        !          1022:     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
        !          1023:     if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) {
        !          1024:         return 0;
        !          1025:     }
        !          1026:     if ( pReq->m_fd == -1 ) {
        !          1027:         pReq->m_pRespBufPos = pReq->m_pRespBuf;
        !          1028:         pReq->m_totalLen = 0;
        !          1029:         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
        !          1030:         return -1;
        !          1031:     }
        !          1032:     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
        !          1033:         LSAPI_FinalizeRespHeaders_r( pReq );
        !          1034:     }
        !          1035:     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
        !          1036:         Flush_RespBuf_r( pReq );
        !          1037:     }
        !          1038:     
        !          1039:     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
        !          1040:     if ( n > 0 ) {
        !          1041:         
        !          1042:         ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
        !          1043:                   n, pReq->m_totalLen );
        !          1044:         if ( ret < pReq->m_totalLen ) {
        !          1045:             lsapi_close( pReq->m_fd );
        !          1046:             pReq->m_fd = -1;
        !          1047:             ret = -1;
        !          1048:         }
        !          1049:         pReq->m_totalLen = 0;
        !          1050:         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
        !          1051:     }
        !          1052:     return ret;
        !          1053: }
        !          1054: 
        !          1055: 
        !          1056: int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len )
        !          1057: {
        !          1058:     struct lsapi_packet_header header;
        !          1059:     const char * pEnd;
        !          1060:     const char * p;
        !          1061:     int packetLen;
        !          1062:     int totalLen;
        !          1063:     int ret;
        !          1064:     struct iovec iov[2];
        !          1065:     struct iovec *pIov;
        !          1066:     
        !          1067:     if ( !pReq ) {
        !          1068:         return -1;
        !          1069:     }
        !          1070:     if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen )) {
        !          1071:         return write( 2, pBuf, len );
        !          1072:     }
        !          1073:     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
        !          1074:         LSAPI_Flush_r( pReq );
        !          1075:     }
        !          1076:     
        !          1077:     p       = pBuf;
        !          1078:     pEnd    = pBuf + len;
        !          1079: 
        !          1080:     while( ( packetLen = pEnd - p ) > 0 ) {
        !          1081:         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) {
        !          1082:             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
        !          1083:         }
        !          1084: 
        !          1085:         lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
        !          1086:                             packetLen + LSAPI_PACKET_HEADER_LEN );
        !          1087:         totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
        !          1088: 
        !          1089:         iov[0].iov_base = (void *)&header;
        !          1090:         iov[0].iov_len  = LSAPI_PACKET_HEADER_LEN;
        !          1091: 
        !          1092:         iov[1].iov_base = (void *)p;
        !          1093:         iov[1].iov_len  = packetLen;
        !          1094:         p += packetLen;
        !          1095:         pIov = iov;
        !          1096:         ret = lsapi_writev( pReq->m_fd, &pIov,
        !          1097:                   2, totalLen );
        !          1098:         if ( ret < totalLen ) {
        !          1099:             lsapi_close( pReq->m_fd );
        !          1100:             pReq->m_fd = -1;
        !          1101:             ret = -1;
        !          1102:         }
        !          1103:     }
        !          1104:     return p - pBuf;
        !          1105: }
        !          1106: 
        !          1107: static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
        !          1108: {
        !          1109:     int i;
        !          1110:     for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
        !          1111:         if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
        !          1112:             if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) {
        !          1113:                 return pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
        !          1114:             }
        !          1115:         }
        !          1116:     }
        !          1117:     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
        !          1118:         const char *p;
        !          1119:         char *pKey;
        !          1120:         char *pKeyEnd;
        !          1121:         int  keyLen;
        !          1122:         struct lsapi_header_offset * pCur, *pEnd;
        !          1123:         pCur = pReq->m_pUnknownHeader;
        !          1124:         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
        !          1125:         while( pCur < pEnd ) {
        !          1126:             pKey = pReq->m_pHttpHeader + pCur->nameOff;
        !          1127:             keyLen = pCur->nameLen;
        !          1128:             pKeyEnd = pKey + keyLen;
        !          1129:             p = &name[5];
        !          1130: 
        !          1131:             while(( pKey < pKeyEnd )&&( *p )) {
        !          1132:                 char ch = toupper( *pKey );
        !          1133:                 if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) {
        !          1134:                     break;
        !          1135:                 }
        !          1136:                 ++p; ++pKey;
        !          1137:             }
        !          1138:             if (( pKey == pKeyEnd )&& (!*p )) {
        !          1139:                 return pReq->m_pHttpHeader + pCur->valueOff;
        !          1140:             }
        !          1141:             ++pCur;
        !          1142:         }
        !          1143:     }
        !          1144:     return NULL;
        !          1145: }
        !          1146: 
        !          1147: 
        !          1148: char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
        !          1149: {
        !          1150:     struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
        !          1151:     struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
        !          1152:     if ( !pReq || !name ) {
        !          1153:         return NULL;
        !          1154:     }
        !          1155:     if ( strncmp( name, "HTTP_", 5 ) == 0 ) {
        !          1156:         return GetHeaderVar( pReq, name );
        !          1157:     }
        !          1158:     while( pBegin < pEnd ) {
        !          1159:         if ( strcmp( name, pBegin->pKey ) == 0 ) {
        !          1160:             return pBegin->pValue;
        !          1161:         }
        !          1162:         ++pBegin;
        !          1163:     }
        !          1164:     return NULL;
        !          1165: }
        !          1166: 
        !          1167: int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
        !          1168:             LSAPI_CB_EnvHandler fn, void * arg )
        !          1169: {
        !          1170:     int i;
        !          1171:     int len = 0;
        !          1172:     char * pValue;
        !          1173:     int ret;
        !          1174:     int count = 0;
        !          1175:     if ( !pReq || !fn ) {
        !          1176:         return -1;
        !          1177:     }
        !          1178:     for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
        !          1179:         if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
        !          1180:             len = pReq->m_pHeaderIndex->m_headerLen[i];
        !          1181:             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
        !          1182:             *(pValue + len ) = 0;
        !          1183:             ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
        !          1184:                         pValue, len, arg );
        !          1185:             ++count;
        !          1186:             if ( ret <= 0 ) {
        !          1187:                 return ret;
        !          1188:             }
        !          1189:         }
        !          1190:     }
        !          1191:     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
        !          1192:         char *pKey;
        !          1193:         int  keyLen;
        !          1194:         struct lsapi_header_offset * pCur, *pEnd;
        !          1195:         pCur = pReq->m_pUnknownHeader;
        !          1196:         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
        !          1197:         while( pCur < pEnd ) {
        !          1198:             pKey = pReq->m_pHttpHeader + pCur->nameOff;
        !          1199:             keyLen = pCur->nameLen;
        !          1200: 
        !          1201:             pValue = pReq->m_pHttpHeader + pCur->valueOff;
        !          1202:             *(pValue + pCur->valueLen ) = 0;
        !          1203:             ret = (*fn)( pKey, keyLen, 
        !          1204:                         pValue, pCur->valueLen, arg );
        !          1205:             if ( ret <= 0 ) {
        !          1206:                 return ret;
        !          1207:             }
        !          1208:             ++pCur;
        !          1209:         }
        !          1210:     }
        !          1211:     return count + pReq->m_pHeader->m_cntUnknownHeaders;
        !          1212:     
        !          1213: }
        !          1214: 
        !          1215: 
        !          1216: int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
        !          1217:             LSAPI_CB_EnvHandler fn, void * arg )
        !          1218: {
        !          1219:     int i;
        !          1220:     int len = 0;
        !          1221:     char * pValue;
        !          1222:     int ret;
        !          1223:     int count = 0;
        !          1224:     if ( !pReq || !fn ) {
        !          1225:         return -1;
        !          1226:     }
        !          1227:     for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
        !          1228:         if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
        !          1229:             len = pReq->m_pHeaderIndex->m_headerLen[i];
        !          1230:             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
        !          1231:             *(pValue + len ) = 0;
        !          1232:             ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
        !          1233:                         pValue, len, arg );
        !          1234:             ++count;
        !          1235:             if ( ret <= 0 ) {
        !          1236:                 return ret;
        !          1237:             }
        !          1238:         }
        !          1239:     }
        !          1240:     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
        !          1241:         char achHeaderName[256];
        !          1242:         char *p;
        !          1243:         char *pKey;
        !          1244:         char *pKeyEnd ;
        !          1245:         int  keyLen;
        !          1246:         struct lsapi_header_offset * pCur, *pEnd;
        !          1247:         pCur = pReq->m_pUnknownHeader;
        !          1248:         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
        !          1249:         while( pCur < pEnd ) {
        !          1250:             pKey = pReq->m_pHttpHeader + pCur->nameOff;
        !          1251:             keyLen = pCur->nameLen;
        !          1252:             if ( keyLen > 250 ) {
        !          1253:                 keyLen = 250;
        !          1254:             }
        !          1255: 
        !          1256:             pKeyEnd = pKey + keyLen;
        !          1257:             memcpy( achHeaderName, "HTTP_", 5 );
        !          1258:             p = &achHeaderName[5];
        !          1259: 
        !          1260:             while( pKey < pKeyEnd ) {
        !          1261:                 char ch = *pKey++;
        !          1262:                 if ( ch == '-' ) {
        !          1263:                     *p++ = '_';
        !          1264:                 } else {
        !          1265:                     *p++ = toupper( ch );
        !          1266:                 }
        !          1267:             }
        !          1268:             *p = 0;
        !          1269:             keyLen += 5;
        !          1270: 
        !          1271:             pValue = pReq->m_pHttpHeader + pCur->valueOff;
        !          1272:             *(pValue + pCur->valueLen ) = 0;
        !          1273:             ret = (*fn)( achHeaderName, keyLen, 
        !          1274:                         pValue, pCur->valueLen, arg );
        !          1275:             if ( ret <= 0 ) {
        !          1276:                 return ret;
        !          1277:             }
        !          1278:             ++pCur;
        !          1279:         }
        !          1280:     }
        !          1281:     return count + pReq->m_pHeader->m_cntUnknownHeaders;
        !          1282:     
        !          1283: }
        !          1284: 
        !          1285: static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
        !          1286:             int n, LSAPI_CB_EnvHandler fn, void * arg )
        !          1287: {
        !          1288:     struct LSAPI_key_value_pair * pEnd = pEnv + n;
        !          1289:     int ret;
        !          1290:     if ( !pEnv || !fn ) {
        !          1291:         return -1;
        !          1292:     }
        !          1293:     while( pEnv < pEnd ) {
        !          1294:         ret = (*fn)( pEnv->pKey, pEnv->keyLen,
        !          1295:                     pEnv->pValue, pEnv->valLen, arg );
        !          1296:         if ( ret <= 0 ) {
        !          1297:             return ret;
        !          1298:         }
        !          1299:         ++pEnv;
        !          1300:     }
        !          1301:     return n;
        !          1302: }
        !          1303: 
        !          1304: 
        !          1305: 
        !          1306: int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
        !          1307:             LSAPI_CB_EnvHandler fn, void * arg )
        !          1308: {
        !          1309:     if ( !pReq || !fn ) {
        !          1310:         return -1;
        !          1311:     }
        !          1312:     if ( pReq->m_pHeader->m_cntEnv > 0 ) {
        !          1313:         return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
        !          1314:                     fn, arg );
        !          1315:     }
        !          1316:     return 0;
        !          1317: }
        !          1318: 
        !          1319: 
        !          1320: 
        !          1321: int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
        !          1322:             LSAPI_CB_EnvHandler fn, void * arg )
        !          1323: {
        !          1324:     if ( !pReq || !fn ) {
        !          1325:         return -1;
        !          1326:     }
        !          1327:     if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) {
        !          1328:         return EnvForeach( pReq->m_pSpecialEnvList,
        !          1329:                 pReq->m_pHeader->m_cntSpecialEnv,
        !          1330:                     fn, arg );
        !          1331:     }
        !          1332:     return 0;
        !          1333: 
        !          1334: }
        !          1335: 
        !          1336: 
        !          1337: 
        !          1338: int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
        !          1339: {
        !          1340:     if ( !pReq || !pReq->m_pIovec ) {
        !          1341:         return -1;
        !          1342:     }
        !          1343:     if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) {
        !          1344:         return 0;
        !          1345:     }
        !          1346:     pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
        !          1347:     if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) {
        !          1348:         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
        !          1349:         pReq->m_pIovecCur->iov_len  = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
        !          1350:         pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
        !          1351:         ++pReq->m_pIovecCur;
        !          1352:     }
        !          1353:     
        !          1354:     pReq->m_pIovec->iov_len  = sizeof( struct lsapi_resp_header)
        !          1355:             + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
        !          1356:     pReq->m_totalLen += pReq->m_pIovec->iov_len;
        !          1357: 
        !          1358:     lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
        !          1359:                     LSAPI_RESP_HEADER, pReq->m_totalLen  );
        !          1360:     pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
        !          1361:     pReq->m_pIovecToWrite = pReq->m_pIovec;
        !          1362:     return 0;
        !          1363: }
        !          1364: 
        !          1365: 
        !          1366: 
        !          1367: 
        !          1368: int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, char * pBuf, int len )
        !          1369: {
        !          1370:     if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) {
        !          1371:         return -1;
        !          1372:     }
        !          1373:     if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) {
        !          1374:         return -1;
        !          1375:     }
        !          1376:     if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) {
        !          1377:         return -1;
        !          1378:     }
        !          1379:     if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) {
        !          1380:         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
        !          1381:         newlen -= newlen % 4096;
        !          1382:         if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) {
        !          1383:             return -1;
        !          1384:         }
        !          1385:     }
        !          1386:     memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
        !          1387:     pReq->m_pRespHeaderBufPos += len;
        !          1388:     *pReq->m_pRespHeaderBufPos++ = 0;
        !          1389:     ++len;  /* add one byte padding for \0 */
        !          1390:     pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
        !          1391:     ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
        !          1392:     return 0;
        !          1393: }
        !          1394: 
        !          1395: 
        !          1396: int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
        !          1397: {
        !          1398:     int ret;
        !          1399:     int fd;
        !          1400:     int flag = 1;
        !          1401:     int addr_len;
        !          1402: 
        !          1403:     switch( pServerAddr->sa_family ) {
        !          1404:     case AF_INET:
        !          1405:         addr_len = 16;
        !          1406:         break;
        !          1407:     case AF_INET6:
        !          1408:         addr_len = sizeof( struct sockaddr_in6 );
        !          1409:         break;
        !          1410:     case AF_UNIX:
        !          1411:         addr_len = sizeof( struct sockaddr_un );
        !          1412:         unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
        !          1413:         break;
        !          1414:     default:
        !          1415:         return -1;
        !          1416:     }
        !          1417: 
        !          1418:     fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
        !          1419:     if ( fd == -1 ) {
        !          1420:         return -1;
        !          1421:     }
        !          1422: 
        !          1423:     fcntl( fd, F_SETFD, FD_CLOEXEC );
        !          1424: 
        !          1425:     if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
        !          1426:                 (char *)( &flag ), sizeof(flag)) == 0) {
        !          1427:         ret = bind( fd, pServerAddr, addr_len );
        !          1428:         if ( !ret ) {
        !          1429:             ret = listen( fd, backlog );
        !          1430:             if ( !ret ) {
        !          1431:                 return fd;
        !          1432:             }
        !          1433:         }
        !          1434:     }
        !          1435: 
        !          1436:     ret = errno;
        !          1437:     close(fd);
        !          1438:     errno = ret;
        !          1439:     return -1;
        !          1440: 
        !          1441: }
        !          1442: 
        !          1443: int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
        !          1444: {
        !          1445:     char achAddr[256];
        !          1446:     char * p = achAddr;
        !          1447:     char * pEnd;
        !          1448:     struct addrinfo *res, hints;
        !          1449:     int  doAddrInfo = 0;
        !          1450:     int port;
        !          1451:     
        !          1452:     if ( !pBind ) {
        !          1453:         return -1;
        !          1454:     }
        !          1455: 
        !          1456:     while( isspace( *pBind ) ) {
        !          1457:         ++pBind;
        !          1458:     }
        !          1459: 
        !          1460:     strncpy( achAddr, pBind, 256 );
        !          1461: 
        !          1462:     switch( *p ) {
        !          1463:     case '/':
        !          1464:         pAddr->sa_family = AF_UNIX;
        !          1465:         strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
        !          1466:                 sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
        !          1467:         return 0;
        !          1468: 
        !          1469:     case '[':
        !          1470:         pAddr->sa_family = AF_INET6;
        !          1471:         ++p;
        !          1472:         pEnd = strchr( p, ']' );
        !          1473:         if ( !pEnd )
        !          1474:             return -1;
        !          1475:         *pEnd++ = 0;
        !          1476:         
        !          1477:         if ( *p == '*' ) {
        !          1478:             strcpy( achAddr, "::" );
        !          1479:             p = achAddr;
        !          1480:         }
        !          1481:         doAddrInfo = 1;
        !          1482:         break;
        !          1483: 
        !          1484:     default:
        !          1485:         pAddr->sa_family = AF_INET;
        !          1486:         pEnd = strchr( p, ':' );
        !          1487:         if ( !pEnd ) {
        !          1488:             return -1;
        !          1489:         }
        !          1490:         *pEnd++ = 0;
        !          1491:         
        !          1492:         doAddrInfo = 0;
        !          1493:         if ( *p == '*' ) {
        !          1494:             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
        !          1495:         } else {
        !          1496:             if (!strcasecmp( p, "localhost" ) ) {
        !          1497:                 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
        !          1498:             } else  {
        !          1499:                 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
        !          1500:                 if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) {
        !          1501:                     doAddrInfo = 1;
        !          1502:                 }
        !          1503:             }
        !          1504:         }
        !          1505:         break;
        !          1506:     }
        !          1507:     if ( *pEnd == ':' ) {
        !          1508:         ++pEnd;
        !          1509:     }
        !          1510:         
        !          1511:     port = atoi( pEnd );
        !          1512:     if (( port <= 0 )||( port > 65535 )) {
        !          1513:         return -1;
        !          1514:     }
        !          1515:     if ( doAddrInfo ) {
        !          1516: 
        !          1517:         memset(&hints, 0, sizeof(hints));
        !          1518: 
        !          1519:         hints.ai_family   = pAddr->sa_family;
        !          1520:         hints.ai_socktype = SOCK_STREAM;
        !          1521:         hints.ai_protocol = IPPROTO_TCP;
        !          1522: 
        !          1523:         if ( getaddrinfo(p, NULL, &hints, &res) ) {
        !          1524:             return -1;
        !          1525:         }
        !          1526: 
        !          1527:         memcpy(pAddr, res->ai_addr, res->ai_addrlen);
        !          1528:         freeaddrinfo(res);
        !          1529:     }
        !          1530:     
        !          1531:     if ( pAddr->sa_family == AF_INET ) {
        !          1532:         ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
        !          1533:     } else {
        !          1534:         ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
        !          1535:     }
        !          1536:     return 0;
        !          1537:     
        !          1538: }
        !          1539: 
        !          1540: int LSAPI_CreateListenSock( const char * pBind, int backlog )
        !          1541: {
        !          1542:     char serverAddr[128];
        !          1543:     int ret;
        !          1544:     int fd = -1;
        !          1545:     ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
        !          1546:     if ( !ret ) {
        !          1547:         fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
        !          1548:     }
        !          1549:     return fd;
        !          1550: }
        !          1551: 
        !          1552: static fn_select_t g_fnSelect = select;
        !          1553: 
        !          1554: typedef struct _lsapi_child_status
        !          1555: {
        !          1556:     int     m_pid;
        !          1557: 
        !          1558:     volatile short   m_iKillSent;
        !          1559:     volatile short   m_inProcess;
        !          1560: 
        !          1561:     volatile long    m_tmWaitBegin;
        !          1562:     volatile long    m_tmReqBegin;
        !          1563:     volatile long    m_tmLastCheckPoint;
        !          1564: }
        !          1565: lsapi_child_status;
        !          1566: 
        !          1567: static lsapi_child_status * s_pChildStatus = NULL;
        !          1568: 
        !          1569: typedef struct _lsapi_prefork_server
        !          1570: {
        !          1571:     int m_fd;
        !          1572:     int m_iMaxChildren;
        !          1573:     int m_iExtraChildren;
        !          1574:     int m_iCurChildren;
        !          1575:     int m_iMaxIdleChildren;
        !          1576:     int m_iServerMaxIdle;
        !          1577:     int m_iChildrenMaxIdleTime;
        !          1578:     int m_iMaxReqProcessTime;
        !          1579:     int m_iAvoidFork;
        !          1580:     
        !          1581:     lsapi_child_status * m_pChildrenStatus;
        !          1582:     
        !          1583: }lsapi_prefork_server;
        !          1584: 
        !          1585: static lsapi_prefork_server * g_prefork_server = NULL;
        !          1586: 
        !          1587: int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
        !          1588: {
        !          1589:     if ( g_prefork_server ) {
        !          1590:         return 0;
        !          1591:     }
        !          1592:     if ( max_children <= 1 ) {
        !          1593:         return -1;
        !          1594:     }
        !          1595:     if ( max_children >= 10000) {
        !          1596:         max_children = 10000;
        !          1597:     }
        !          1598: 
        !          1599:     
        !          1600:     g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
        !          1601:     if ( !g_prefork_server ) {
        !          1602:         return -1;
        !          1603:     }
        !          1604:     memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
        !          1605: 
        !          1606:     if ( fp != NULL ) {
        !          1607:         g_fnSelect = fp;
        !          1608:     }
        !          1609: 
        !          1610:     s_ppid = getppid();
        !          1611:     g_prefork_server->m_iAvoidFork = avoidFork;
        !          1612:     g_prefork_server->m_iMaxChildren = max_children;
        !          1613:     
        !          1614:     g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
        !          1615:     g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
        !          1616:     g_prefork_server->m_iChildrenMaxIdleTime = 300;
        !          1617:     g_prefork_server->m_iMaxReqProcessTime = 300;
        !          1618:     return 0;    
        !          1619: }
        !          1620: 
        !          1621: void LSAPI_Set_Server_fd( int fd )
        !          1622: {
        !          1623:     if( g_prefork_server ) {
        !          1624:         g_prefork_server->m_fd = fd;
        !          1625:     }
        !          1626: }
        !          1627: 
        !          1628: 
        !          1629: static int lsapi_accept( int fdListen )
        !          1630: {
        !          1631:     int         fd;
        !          1632:     int         nodelay = 1;
        !          1633:     socklen_t   len;
        !          1634:     char        achPeer[128];
        !          1635: 
        !          1636:     len = sizeof( achPeer );
        !          1637:     fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
        !          1638:     if ( fd != -1 ) {
        !          1639:         if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) {
        !          1640:             setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
        !          1641:                     (char *)&nodelay, sizeof(nodelay));
        !          1642:         }
        !          1643: 
        !          1644:         if ( s_accept_notify )
        !          1645:             notify_req_received( fd );
        !          1646:     }
        !          1647:     return fd;
        !          1648: 
        !          1649: }
        !          1650: 
        !          1651: 
        !          1652: 
        !          1653: 
        !          1654: static int s_req_processed = 0;
        !          1655: static int s_max_reqs = 10000;
        !          1656: static int s_max_idle_secs = 300;
        !          1657: 
        !          1658: static int s_stop;
        !          1659: 
        !          1660: static void lsapi_cleanup(int signal)
        !          1661: {
        !          1662:     s_stop = signal;
        !          1663: }
        !          1664: 
        !          1665: static lsapi_child_status * find_child_status( int pid )
        !          1666: {
        !          1667:     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
        !          1668:     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
        !          1669:     while( pStatus < pEnd ) {
        !          1670:         if ( pStatus->m_pid == pid ) {
        !          1671:             return pStatus;
        !          1672:         }
        !          1673:         ++pStatus;
        !          1674:     }
        !          1675:     return NULL;
        !          1676: }
        !          1677: 
        !          1678: 
        !          1679: 
        !          1680: static void lsapi_sigchild( int signal )
        !          1681: {
        !          1682:     int status, pid;
        !          1683:     lsapi_child_status * child_status;
        !          1684:     while( 1 ) {
        !          1685:         pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
        !          1686:         if ( pid <= 0 ) {
        !          1687:             break;
        !          1688:         }
        !          1689:         child_status = find_child_status( pid );
        !          1690:         if ( child_status ) {
        !          1691:             child_status->m_pid = 0;
        !          1692:         }
        !          1693:         --g_prefork_server->m_iCurChildren;
        !          1694:     }
        !          1695: 
        !          1696: }
        !          1697: 
        !          1698: static int lsapi_init_children_status()
        !          1699: {
        !          1700:     int size = 4096;
        !          1701:     
        !          1702:     char * pBuf;
        !          1703:     size = g_prefork_server->m_iMaxChildren * sizeof( lsapi_child_status ) * 2;
        !          1704:     size = (size + 4095 ) / 4096 * 4096;
        !          1705:     pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
        !          1706:         MAP_ANON | MAP_SHARED, -1, 0 );
        !          1707:     if ( pBuf == MAP_FAILED ) {
        !          1708:         perror( "Anonymous mmap() failed" );
        !          1709:         return -1;
        !          1710:     }
        !          1711:     memset( pBuf, 0, size );
        !          1712:     g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;    
        !          1713:     return 0;
        !          1714: }
        !          1715: 
        !          1716: static void lsapi_check_child_status( long tmCur )
        !          1717: {
        !          1718:     int idle = 0;
        !          1719:     int tobekilled;
        !          1720:     int dying = 0;
        !          1721:     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
        !          1722:     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
        !          1723:     while( pStatus < pEnd ) {
        !          1724:         tobekilled = pStatus->m_iKillSent;
        !          1725:         if ( pStatus->m_pid != 0 ) {
        !          1726:             if ( !tobekilled ) {
        !          1727:                 if ( !pStatus->m_inProcess ) {
        !          1728:                     
        !          1729:                     if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
        !          1730:                         ( idle >= g_prefork_server->m_iMaxIdleChildren )) {
        !          1731:                     
        !          1732:                         tobekilled = 1;
        !          1733:                     } else {
        !          1734:                         if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 )) {
        !          1735:                             tobekilled = 1;
        !          1736:                         }
        !          1737:                     }
        !          1738:                     if ( !tobekilled ) {
        !          1739:                         ++idle;
        !          1740:                     }
        !          1741:                 } else {
        !          1742:                     if ( tmCur - pStatus->m_tmReqBegin > 
        !          1743:                          g_prefork_server->m_iMaxReqProcessTime ) {
        !          1744:                         tobekilled = 1;
        !          1745:                     }
        !          1746:                 }
        !          1747:             } else {
        !          1748:                 if ( pStatus->m_inProcess ) {
        !          1749:                     tobekilled = pStatus->m_iKillSent = 0;
        !          1750:                 }
        !          1751:             }
        !          1752:             if ( tobekilled ) {
        !          1753:                 tobekilled = 0;
        !          1754:                 if ( pStatus->m_iKillSent > 5 ) {
        !          1755:                     tobekilled = SIGKILL;
        !          1756:                 } else {    
        !          1757:                     if ( pStatus->m_iKillSent == 3 ) {
        !          1758:                         tobekilled = SIGTERM;
        !          1759:                     } else {
        !          1760:                         if ( pStatus->m_iKillSent == 1 ) {
        !          1761:                             tobekilled = SIGUSR1;
        !          1762:                         }
        !          1763:                     }
        !          1764:                 }
        !          1765:                 if ( tobekilled ) {
        !          1766:                     kill( pStatus->m_pid, tobekilled );
        !          1767:                 }
        !          1768:                 ++pStatus->m_iKillSent;
        !          1769:                 ++dying;
        !          1770:             }
        !          1771:                 
        !          1772:         } else {
        !          1773:             ++dying;
        !          1774:         }
        !          1775:         ++pStatus;
        !          1776:     }
        !          1777: }
        !          1778: 
        !          1779: static int lsapi_all_children_must_die()
        !          1780: {
        !          1781:     int maxWait;
        !          1782:     int sec =0;
        !          1783:     g_prefork_server->m_iMaxReqProcessTime = 10;
        !          1784:     g_prefork_server->m_iMaxIdleChildren = -1;
        !          1785:     maxWait = 15;
        !          1786: 
        !          1787:     while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) {
        !          1788:         lsapi_check_child_status(time(NULL));
        !          1789:         sleep( 1 );
        !          1790:         sec++;
        !          1791:     }
        !          1792:     if ( g_prefork_server->m_iCurChildren != 0 ) {
        !          1793:         kill( -getpgrp(), SIGKILL );
        !          1794:     }
        !          1795:     return 0;
        !          1796: }
        !          1797: 
        !          1798: 
        !          1799: 
        !          1800: static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq )
        !          1801: {
        !          1802:     struct sigaction act, old_term, old_quit, old_int,
        !          1803:                     old_usr1, old_child;
        !          1804:     lsapi_child_status * child_status;
        !          1805:     int             wait_secs = 0;
        !          1806:     int             ret = 0;
        !          1807:     int             pid;
        !          1808:     time_t          lastTime = 0;
        !          1809:     time_t          curTime = 0;
        !          1810:     fd_set          readfds;
        !          1811:     struct timeval  timeout;
        !          1812: 
        !          1813:     lsapi_init_children_status();
        !          1814:     
        !          1815:     setsid();
        !          1816: 
        !          1817:     act.sa_flags = 0;
        !          1818:     act.sa_handler = lsapi_sigchild;
        !          1819:     if( sigaction( SIGCHLD, &act, &old_child ) ) {
        !          1820:         perror( "Can't set signal handler for SIGCHILD" );
        !          1821:         return -1;
        !          1822:     }
        !          1823: 
        !          1824:     /* Set up handler to kill children upon exit */
        !          1825:     act.sa_flags = 0;
        !          1826:     act.sa_handler = lsapi_cleanup;
        !          1827:     if( sigaction( SIGTERM, &act, &old_term ) ||
        !          1828:         sigaction( SIGINT,  &act, &old_int  ) ||
        !          1829:         sigaction( SIGUSR1, &act, &old_usr1 ) ||
        !          1830:         sigaction( SIGQUIT, &act, &old_quit )) {
        !          1831:         perror( "Can't set signals" );
        !          1832:         return -1;
        !          1833:     }
        !          1834:     s_stop = 0;
        !          1835:     while( !s_stop ) {
        !          1836:         if ( ret ) {
        !          1837:             curTime = time( NULL );
        !          1838:         } else {
        !          1839:             ++curTime;
        !          1840:         }
        !          1841:         if (curTime != lastTime ) {
        !          1842:             lastTime = curTime;
        !          1843:             if (s_ppid && (getppid() != s_ppid )) {
        !          1844:                 break;
        !          1845:             }
        !          1846:             lsapi_check_child_status(curTime );
        !          1847:             if (pServer->m_iServerMaxIdle) {
        !          1848:                 if ( pServer->m_iCurChildren <= 0 ) {
        !          1849:                     ++wait_secs;
        !          1850:                     if ( wait_secs > pServer->m_iServerMaxIdle ) {
        !          1851:                         return -1;
        !          1852:                     }
        !          1853:                 } else {
        !          1854:                     wait_secs = 0;
        !          1855:                 }
        !          1856:             }
        !          1857:         }
        !          1858: 
        !          1859:         if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) ) {
        !          1860:             usleep( 100000 );
        !          1861:             continue;
        !          1862:         }
        !          1863: 
        !          1864:         FD_ZERO( &readfds );
        !          1865:         FD_SET( pServer->m_fd, &readfds );
        !          1866:         timeout.tv_sec = 1; timeout.tv_usec = 0;
        !          1867:         if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 ) {
        !          1868:             if ( pServer->m_iCurChildren >= 0 ) {
        !          1869:                 usleep( 10 );
        !          1870:                 FD_ZERO( &readfds );
        !          1871:                 FD_SET( pServer->m_fd, &readfds );
        !          1872:                 timeout.tv_sec = 0; timeout.tv_usec = 0;
        !          1873:                 if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 ) {
        !          1874:                     continue;
        !          1875:                 }
        !          1876:             }
        !          1877:         } else {
        !          1878:             if ( ret == -1 ) {
        !          1879:                 if ( errno == EINTR ) {
        !          1880:                     continue;
        !          1881:                 }
        !          1882:                 /* perror( "select()" ); */
        !          1883:                 break;
        !          1884:             } else {
        !          1885:                 continue;
        !          1886:             }
        !          1887:         }
        !          1888: 
        !          1889:         pReq->m_fd = lsapi_accept( pServer->m_fd );
        !          1890:         if ( pReq->m_fd != -1 ) {
        !          1891:             child_status = find_child_status( 0 );
        !          1892:             pid = fork();
        !          1893:             if ( !pid ) {
        !          1894:                 g_prefork_server = NULL;
        !          1895:                 s_ppid = getppid();
        !          1896:                 s_req_processed = 0;
        !          1897:                 s_pChildStatus = child_status;
        !          1898:                 child_status->m_iKillSent = 0;
        !          1899:                 lsapi_set_nblock( pReq->m_fd, 0 );
        !          1900: 
        !          1901:                 /* don't catch our signals */
        !          1902:                 sigaction( SIGCHLD, &old_child, 0 );
        !          1903:                 sigaction( SIGTERM, &old_term, 0 );
        !          1904:                 sigaction( SIGQUIT, &old_quit, 0 );
        !          1905:                 sigaction( SIGINT,  &old_int,  0 );
        !          1906:                 sigaction( SIGUSR1, &old_usr1, 0 );
        !          1907:                 return 0;
        !          1908:             } else {
        !          1909:                 if ( pid == -1 ) {
        !          1910:                     perror( "fork() failed, please increase process limit" );
        !          1911:                 } else {
        !          1912:                     ++pServer->m_iCurChildren;
        !          1913:                     if ( child_status ) {
        !          1914:                         child_status->m_pid = pid;
        !          1915:                         child_status->m_iKillSent = 0;
        !          1916:                         child_status->m_tmWaitBegin = time(NULL);
        !          1917:                     }
        !          1918:                 }
        !          1919:             }
        !          1920:             close( pReq->m_fd );
        !          1921:             pReq->m_fd = -1;
        !          1922: 
        !          1923:         } else {
        !          1924:             if (( errno == EINTR )||( errno == EAGAIN)) {
        !          1925:                 continue;
        !          1926:             }
        !          1927:             perror( "accept() failed" );
        !          1928:             return -1;
        !          1929:         }
        !          1930:     }
        !          1931:     sigaction( SIGUSR1, &old_usr1, 0 );
        !          1932:     kill( -getpgrp(), SIGUSR1 );
        !          1933:     lsapi_all_children_must_die();  /* Sorry, children ;-) */
        !          1934:     return -1;
        !          1935: 
        !          1936: }
        !          1937: 
        !          1938: int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
        !          1939: {
        !          1940:     int             fd;
        !          1941:     int             ret;
        !          1942:     int             wait_secs;
        !          1943:     fd_set          readfds;
        !          1944:     struct timeval  timeout;
        !          1945: 
        !          1946:     LSAPI_Finish_r( pReq );
        !          1947: 
        !          1948: 
        !          1949:     if ( g_prefork_server ) {
        !          1950:         if ( g_prefork_server->m_fd != -1 ) {
        !          1951:             if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) {
        !          1952:                 return -1;
        !          1953:             }
        !          1954:         }
        !          1955:     }
        !          1956:     if ( s_req_processed >= s_max_reqs ) {
        !          1957:         return -1;
        !          1958:     }
        !          1959: 
        !          1960:     if ( s_pChildStatus ) {
        !          1961:         s_pChildStatus->m_tmWaitBegin = time( NULL );
        !          1962:     }
        !          1963:     
        !          1964:     while( g_running ) {
        !          1965:         if ( pReq->m_fd != -1 ) {
        !          1966:             fd = pReq->m_fd;
        !          1967:         } else {
        !          1968:             if ( pReq->m_fdListen != -1 ) {
        !          1969:                 fd = pReq->m_fdListen;
        !          1970:             } else {
        !          1971:                 return -1;
        !          1972:             }
        !          1973:         }
        !          1974:         wait_secs = 0;
        !          1975:         while( 1 ) {
        !          1976:             if ( !g_running ) {
        !          1977:                 return -1;
        !          1978:             }
        !          1979:             if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
        !          1980:                 return -1; 
        !          1981:             }
        !          1982:             FD_ZERO( &readfds );
        !          1983:             FD_SET( fd, &readfds );
        !          1984:             timeout.tv_sec = 1;
        !          1985:             timeout.tv_usec = 0;
        !          1986:             ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
        !          1987:             if ( ret == 0 ) {
        !          1988:                 if ( s_pChildStatus ) {
        !          1989:                     s_pChildStatus->m_inProcess = 0;
        !          1990:                 }
        !          1991:                 ++wait_secs;
        !          1992:                 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) {
        !          1993:                     return -1;
        !          1994:                 }
        !          1995:                 if ( s_ppid &&( getppid() != s_ppid)) {
        !          1996:                     return -1;
        !          1997:                 }
        !          1998:             } else {
        !          1999:                 if ( ret == -1 ) {
        !          2000:                     if ( errno == EINTR ) {
        !          2001:                         continue;
        !          2002:                     } else {
        !          2003:                         return -1;
        !          2004:                     }
        !          2005:                 } else {
        !          2006:                     if ( ret >= 1 ) {
        !          2007:                         if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
        !          2008:                             return -1; 
        !          2009:                         }
        !          2010:                         if ( fd == pReq->m_fdListen ) {
        !          2011:                             pReq->m_fd = lsapi_accept( pReq->m_fdListen );
        !          2012:                             if ( pReq->m_fd != -1 ) {
        !          2013:                                 fd = pReq->m_fd;
        !          2014:                                 lsapi_set_nblock( fd, 0 );
        !          2015:                             } else {
        !          2016:                                 if (( errno == EINTR )||( errno == EAGAIN)) {
        !          2017:                                     continue;
        !          2018:                                                                }
        !          2019:                                 return -1;
        !          2020:                             }
        !          2021:                         } else {
        !          2022:                             break;
        !          2023:                         }
        !          2024:                     }
        !          2025:                 }
        !          2026:             }
        !          2027:         }
        !          2028:         if ( !readReq( pReq ) ) {
        !          2029:             if ( s_pChildStatus ) {
        !          2030:                 s_pChildStatus->m_inProcess = 1;
        !          2031:                 s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
        !          2032:             }
        !          2033:             ++s_req_processed;
        !          2034:             return 0;
        !          2035:         }
        !          2036:         lsapi_close( pReq->m_fd );
        !          2037:         pReq->m_fd = -1;
        !          2038:         LSAPI_Reset_r( pReq );
        !          2039:     }
        !          2040:     return -1;
        !          2041:     
        !          2042: }
        !          2043: 
        !          2044: void LSAPI_Set_Max_Reqs( int reqs )
        !          2045: {   
        !          2046:     s_max_reqs = reqs;          
        !          2047: }
        !          2048: 
        !          2049: void LSAPI_Set_Max_Idle( int secs )
        !          2050: {   
        !          2051:     s_max_idle_secs = secs;     
        !          2052: }
        !          2053: 
        !          2054: void LSAPI_Set_Max_Children( int maxChildren )
        !          2055: {
        !          2056:     if ( g_prefork_server ) {
        !          2057:         g_prefork_server->m_iMaxChildren = maxChildren;
        !          2058:     }
        !          2059: }
        !          2060: 
        !          2061: void LSAPI_Set_Extra_Children( int extraChildren )
        !          2062: {
        !          2063:     if (( g_prefork_server )&&( extraChildren >= 0 )) {
        !          2064:         g_prefork_server->m_iExtraChildren = extraChildren;
        !          2065:     }
        !          2066: }
        !          2067: 
        !          2068: void LSAPI_Set_Max_Process_Time( int secs )
        !          2069: {
        !          2070:     if (( g_prefork_server )&&( secs > 0 )) {
        !          2071:         g_prefork_server->m_iMaxReqProcessTime = secs;
        !          2072:     }
        !          2073: }
        !          2074: 
        !          2075: 
        !          2076: void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
        !          2077: {
        !          2078:     if (( g_prefork_server )&&( maxIdleChld > 0 )) {
        !          2079:         g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
        !          2080:     }
        !          2081: }
        !          2082: 
        !          2083: void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
        !          2084: {
        !          2085:     if ( g_prefork_server ) {
        !          2086:         g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
        !          2087:     }
        !          2088: }
        !          2089: 
        !          2090: void LSAPI_Set_Slow_Req_Msecs( int msecs )
        !          2091: {
        !          2092:        s_slow_req_msecs = msecs;
        !          2093: }
        !          2094: 
        !          2095: int  LSAPI_Get_Slow_Req_Msecs()
        !          2096: {
        !          2097:        return s_slow_req_msecs;
        !          2098: }
        !          2099: 
        !          2100: void LSAPI_No_Check_ppid()
        !          2101: {
        !          2102:     s_ppid = 0;
        !          2103: }
        !          2104: 
        !          2105: #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
        !          2106: #include <crt_externs.h>
        !          2107: #else
        !          2108: extern char ** environ;
        !          2109: #endif
        !          2110: static void unset_lsapi_envs()
        !          2111: {
        !          2112:     char **env;
        !          2113: #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
        !          2114:     env = *_NSGetEnviron();
        !          2115: #else
        !          2116:     env = environ;
        !          2117: #endif
        !          2118:     while( env != NULL && *env != NULL ) {
        !          2119:         if ( !strncmp(*env, "LSAPI_", 6) || 
        !          2120:              !strncmp( *env, "PHP_LSAPI_", 10 ) ) {   
        !          2121:             char ** del = env;
        !          2122:             do {
        !          2123:                 *del = del[1];
        !          2124:             } while( *del++ );
        !          2125:         } else {
        !          2126:             ++env;
        !          2127:         }
        !          2128:     }  
        !          2129: }
        !          2130: 
        !          2131: void LSAPI_Init_Env_Parameters( fn_select_t fp )
        !          2132: {
        !          2133:     const char *p;
        !          2134:     int n;
        !          2135:     int avoidFork = 0;
        !          2136:     p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
        !          2137:     if ( !p ) {
        !          2138:         p = getenv( "LSAPI_MAX_REQS" );
        !          2139:     }
        !          2140:     if ( p ) {
        !          2141:         n = atoi( p );
        !          2142:         if ( n > 0 ) {
        !          2143:             LSAPI_Set_Max_Reqs( n );
        !          2144:         }
        !          2145:     }
        !          2146: 
        !          2147:     p = getenv( "LSAPI_AVOID_FORK" );
        !          2148:     if ( p ) {
        !          2149:         avoidFork = atoi( p );
        !          2150:     }    
        !          2151: 
        !          2152:     p = getenv( "LSAPI_ACCEPT_NOTIFY" );
        !          2153:     if ( p ) {
        !          2154:         s_accept_notify = atoi( p );
        !          2155:     }    
        !          2156: 
        !          2157:     p = getenv( "LSAPI_SLOW_REQ_MSECS" );
        !          2158:     if ( p ) {
        !          2159:         n = atoi( p );
        !          2160:         LSAPI_Set_Slow_Req_Msecs( n );
        !          2161:     }    
        !          2162: 
        !          2163: 
        !          2164: #if defined( RLIMIT_CORE )
        !          2165:     p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
        !          2166:     if ( !p ) {
        !          2167:         struct rlimit limit = { 0, 0 };
        !          2168:         setrlimit( RLIMIT_CORE, &limit );
        !          2169:     }
        !          2170: #endif    
        !          2171: 
        !          2172:     p = getenv( "LSAPI_MAX_IDLE" );
        !          2173:     if ( p ) {
        !          2174:         n = atoi( p );
        !          2175:         LSAPI_Set_Max_Idle( n );
        !          2176:     }
        !          2177: 
        !          2178:     if ( LSAPI_Is_Listen() ) {
        !          2179:         n = 0;
        !          2180:         p = getenv( "PHP_LSAPI_CHILDREN" );
        !          2181:         if ( !p ) {
        !          2182:             p = getenv( "LSAPI_CHILDREN" );
        !          2183:         }
        !          2184:         if ( p ) {
        !          2185:             n = atoi( p );
        !          2186:         }
        !          2187:         if ( n > 1 ) {
        !          2188:             LSAPI_Init_Prefork_Server( n, fp, avoidFork );
        !          2189:             LSAPI_Set_Server_fd( g_req.m_fdListen );
        !          2190:         }
        !          2191: 
        !          2192:         p = getenv( "LSAPI_EXTRA_CHILDREN" );
        !          2193:         if ( p ) {
        !          2194:             LSAPI_Set_Extra_Children( atoi( p ) );
        !          2195:         }
        !          2196:         
        !          2197:         p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
        !          2198:         if ( p ) {
        !          2199:             LSAPI_Set_Max_Idle_Children( atoi( p ) );
        !          2200:         }
        !          2201:         p = getenv( "LSAPI_PGRP_MAX_IDLE" );
        !          2202:         if ( p ) {
        !          2203:             LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
        !          2204:         }
        !          2205:         
        !          2206:         p = getenv( "LSAPI_MAX_PROCESS_TIME" );
        !          2207:         if ( p ) {     
        !          2208:             LSAPI_Set_Max_Process_Time( atoi( p ) );
        !          2209:         }
        !          2210:         if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) {
        !          2211:             LSAPI_No_Check_ppid();
        !          2212:         }
        !          2213:     }
        !          2214:     unset_lsapi_envs();
        !          2215: }
        !          2216: 
        !          2217: 
        !          2218: /*
        !          2219:  * Local variables:
        !          2220:  * tab-width: 4
        !          2221:  * c-basic-offset: 4
        !          2222:  * End:
        !          2223:  * vim600: sw=4 ts=4 fdm=marker
        !          2224:  * vim<600: sw=4 ts=4
        !          2225:  */
        !          2226: 
        !          2227: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>