File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / litespeed / lsapilib.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:04:02 2014 UTC (10 years ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 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,v 1.1.1.4 2014/06/15 20:04:02 misho Exp $ */
   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>