root/sapi/litespeed/lsapilib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lsapi_sigpipe
  2. lsapi_siguser1
  3. lsapi_signal
  4. lsapi_enable_core_dump
  5. lsapi_buildPacketHeader
  6. lsapi_set_nblock
  7. lsapi_close
  8. lsapi_read
  9. lsapi_writev
  10. allocateBuf
  11. allocateIovec
  12. allocateRespHeaderBuf
  13. verifyHeader
  14. allocateEnvList
  15. isPipe
  16. parseEnv
  17. swapIntEndian
  18. fixEndian
  19. fixHeaderIndexEndian
  20. validateHeaders
  21. lsapi_load_lve_lib
  22. init_lve_ex
  23. readSecret
  24. LSAPI_is_suEXEC_Daemon
  25. LSAPI_perror_r
  26. lsapi_lve_error
  27. lsapi_enterLVE
  28. lsapi_jailLVE
  29. lsapi_initLVE
  30. setUID_LVE
  31. lsapi_suexec_auth
  32. lsapi_changeUGid
  33. parseContentLenFromHeader
  34. parseRequest
  35. write_req_received_notification
  36. lsapi_sigalarm
  37. lsapi_schedule_notify
  38. notify_req_received
  39. lsapi_notify_pid
  40. init_conn_key
  41. readReq
  42. LSAPI_Init
  43. LSAPI_Stop
  44. LSAPI_IsRunning
  45. LSAPI_InitRequest
  46. LSAPI_Is_Listen
  47. LSAPI_Is_Listen_r
  48. LSAPI_Accept_r
  49. LSAPI_Finish_r
  50. LSAPI_Reset_r
  51. LSAPI_Release_r
  52. LSAPI_GetHeader_r
  53. readBodyToReqBuf
  54. LSAPI_ReqBodyGetChar_r
  55. LSAPI_ReqBodyGetLine_r
  56. LSAPI_ReadReqBody_r
  57. LSAPI_Write_r
  58. gsendfile
  59. gsendfile
  60. gsendfile
  61. gsendfile
  62. LSAPI_sendfile_r
  63. Flush_RespBuf_r
  64. LSAPI_Flush_r
  65. LSAPI_Write_Stderr_r
  66. GetHeaderVar
  67. LSAPI_GetEnv_r
  68. compareValueLocation
  69. LSAPI_ForeachOrgHeader_r
  70. LSAPI_ForeachHeader_r
  71. EnvForeach
  72. LSAPI_ForeachEnv_r
  73. LSAPI_ForeachSpecialEnv_r
  74. LSAPI_FinalizeRespHeaders_r
  75. LSAPI_AppendRespHeader2_r
  76. LSAPI_AppendRespHeader_r
  77. LSAPI_CreateListenSock2
  78. LSAPI_ParseSockAddr
  79. LSAPI_CreateListenSock
  80. LSAPI_Init_Prefork_Server
  81. LSAPI_Set_Server_fd
  82. lsapi_accept
  83. lsapi_cleanup
  84. find_child_status
  85. lsapi_sigchild
  86. lsapi_init_children_status
  87. dump_debug_info
  88. lsapi_check_child_status
  89. lsapi_all_children_must_die
  90. lsapi_prefork_server_accept
  91. lsapi_error
  92. LSAPI_Prefork_Accept_r
  93. LSAPI_Set_Max_Reqs
  94. LSAPI_Set_Max_Idle
  95. LSAPI_Set_Max_Children
  96. LSAPI_Set_Extra_Children
  97. LSAPI_Set_Max_Process_Time
  98. LSAPI_Set_Max_Idle_Children
  99. LSAPI_Set_Server_Max_Idle_Secs
  100. LSAPI_Set_Slow_Req_Msecs
  101. LSAPI_Get_Slow_Req_Msecs
  102. LSAPI_No_Check_ppid
  103. unset_lsapi_envs
  104. lsapi_initSuEXEC
  105. LSAPI_Init_Env_Parameters
  106. LSAPI_ErrResponse_r
  107. byteReverse
  108. lsapi_MD5Init
  109. lsapi_MD5Update
  110. lsapi_MD5Final
  111. lsapi_MD5Transform

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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 /*
  20 Copyright (c) 2002-2015, Lite Speed Technologies Inc.
  21 All rights reserved.
  22 
  23 Redistribution and use in source and binary forms, with or without
  24 modification, are permitted provided that the following conditions are
  25 met:
  26 
  27     * Redistributions of source code must retain the above copyright
  28       notice, this list of conditions and the following disclaimer.
  29     * Redistributions in binary form must reproduce the above
  30       copyright notice, this list of conditions and the following
  31       disclaimer in the documentation and/or other materials provided
  32       with the distribution.
  33     * Neither the name of the Lite Speed Technologies Inc nor the
  34       names of its contributors may be used to endorse or promote
  35       products derived from this software without specific prior
  36       written permission.
  37 
  38 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  39 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  40 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  41 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  42 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  44 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  45 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  46 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  47 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  48 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  49 */
  50 
  51 
  52 #include <ctype.h>
  53 #include <dlfcn.h>
  54 #include <errno.h>
  55 #include <fcntl.h>
  56 
  57 #include <sys/stat.h>
  58 #include <signal.h>
  59 #include <stdlib.h>
  60 #include <stdio.h>
  61 #include <string.h>
  62 #include <sys/mman.h>
  63 #include <sys/resource.h>
  64 #include <sys/socket.h>
  65 #include <sys/time.h>
  66 #include <sys/uio.h>
  67 #include <sys/wait.h>
  68 #include <grp.h>
  69 #include <pwd.h>
  70 #include <time.h>
  71 #include <unistd.h>
  72 #include <arpa/inet.h>
  73 #include <netdb.h>
  74 #include <netinet/in.h>
  75 #include <netinet/tcp.h>
  76 #include <sys/un.h>
  77 
  78 #include "lsapilib.h"
  79 
  80 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
  81 #include <sys/prctl.h>
  82 #endif
  83 
  84 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
  85     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
  86 #include <sys/sysctl.h>
  87 #endif
  88 
  89 #include <inttypes.h>
  90 #ifndef uint32
  91 #define uint32 uint32_t
  92 #endif
  93 
  94 struct lsapi_MD5Context {
  95     uint32 buf[4];
  96     uint32 bits[2];
  97     unsigned char in[64];
  98 };
  99 
 100 void lsapi_MD5Init(struct lsapi_MD5Context *context);
 101 void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
 102            unsigned len);
 103 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
 104 
 105 /*
 106  * This is needed to make RSAREF happy on some MS-DOS compilers.
 107  */
 108 typedef struct lsapi_MD5Context lsapi_MD5_CTX;
 109 
 110 
 111 #define LSAPI_ST_REQ_HEADER     1
 112 #define LSAPI_ST_REQ_BODY       2
 113 #define LSAPI_ST_RESP_HEADER    4
 114 #define LSAPI_ST_RESP_BODY      8
 115 
 116 #define LSAPI_RESP_BUF_SIZE     8192
 117 #define LSAPI_INIT_RESP_HEADER_LEN 4096
 118 
 119 
 120 
 121 static int g_inited = 0;
 122 static int g_running = 1;
 123 static int s_ppid;
 124 static int s_slow_req_msecs = 0;
 125 static int s_keepListener = 0;
 126 static int s_dump_debug_info = 0;
 127 static int s_pid_dump_debug_info = 0;
 128 
 129 LSAPI_Request g_req = { -1, -1 };
 130 
 131 static char         s_secret[24];
 132 
 133 
 134 void Flush_RespBuf_r( LSAPI_Request * pReq );
 135 
 136 static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
 137 {
 138     "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
 139     "HTTP_ACCEPT_ENCODING",
 140     "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
 141     "HTTP_CONNECTION", "CONTENT_TYPE",
 142     "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
 143     "HTTP_HOST", "HTTP_PRAGMA",
 144     "HTTP_REFERER", "HTTP_USER_AGENT",
 145     "HTTP_CACHE_CONTROL",
 146     "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
 147     "HTTP_IF_NONE_MATCH",
 148     "HTTP_IF_RANGE",
 149     "HTTP_IF_UNMODIFIED_SINCE",
 150     "HTTP_KEEP_ALIVE",
 151     "HTTP_RANGE",
 152     "HTTP_X_FORWARDED_FOR",
 153     "HTTP_VIA",
 154     "HTTP_TRANSFER_ENCODING"
 155 };
 156 
 157 static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
 158 {    11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
 159      22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
 160 
 161 
 162 static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
 163 {
 164     "Accept", "Accept-Charset",
 165     "Accept-Encoding",
 166     "Accept-Language", "Authorization",
 167     "Connection", "Content-Type",
 168     "Content-Length", "Cookie", "Cookie2",
 169     "Host", "Pragma",
 170     "Referer", "User-Agent",
 171     "Cache-Control",
 172     "If-Modified-Since", "If-Match",
 173     "If-None-Match",
 174     "If-Range",
 175     "If-Unmodified-Since",
 176     "Keep-Alive",
 177     "Range",
 178     "X-Forwarded-For",
 179     "Via",
 180     "Transfer-Encoding"
 181 };
 182 
 183 static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
 184 {   6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
 185     13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
 186 };
 187 
 188 static void lsapi_sigpipe( int sig )
 189 {
 190 }
 191 static void lsapi_siguser1( int sig )
 192 {
 193     g_running = 0;
 194 }
 195 
 196 #ifndef sighandler_t
 197 typedef void (*sighandler_t)(int);
 198 #endif
 199 
 200 static void lsapi_signal(int signo, sighandler_t handler)
 201 {
 202     struct sigaction sa;
 203 
 204     sigaction(signo, NULL, &sa);
 205 
 206     if (sa.sa_handler == SIG_DFL)
 207     {
 208         sigemptyset(&sa.sa_mask);
 209         sa.sa_flags = 0;
 210         sa.sa_handler = handler;
 211         sigaction(signo, &sa, NULL);
 212     }
 213 }
 214 
 215 
 216 static int s_enable_core_dump = 0;
 217 static void lsapi_enable_core_dump()
 218 {
 219 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
 220     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
 221     int  mib[2];
 222     size_t len;
 223 
 224     len = 2;
 225     if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
 226     {
 227         len = sizeof(s_enable_core_dump);
 228         if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
 229             perror( "sysctl: Failed to set 'kern.sugid_coredump', "
 230                     "core dump may not be available!");
 231     }
 232 
 233 
 234 #endif
 235 
 236 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
 237     if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
 238         perror( "prctl: Failed to set dumpable, "
 239                     "core dump may not be available!");
 240 #endif
 241 }
 242 
 243 
 244 static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
 245                                 char type, int len )
 246 {
 247     pHeader->m_versionB0 = LSAPI_VERSION_B0;  /* LSAPI protocol version */
 248     pHeader->m_versionB1 = LSAPI_VERSION_B1;
 249     pHeader->m_type      = type;
 250     pHeader->m_flag      = LSAPI_ENDIAN;
 251     pHeader->m_packetLen.m_iLen = len;
 252 }
 253 
 254 static  int lsapi_set_nblock( int fd, int nonblock )
 255 {
 256     int val = fcntl( fd, F_GETFL, 0 );
 257     if ( nonblock )
 258     {
 259         if (!( val & O_NONBLOCK ))
 260         {
 261             return fcntl( fd, F_SETFL, val | O_NONBLOCK );
 262         }
 263     }
 264     else
 265     {
 266         if ( val & O_NONBLOCK )
 267         {
 268             return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
 269         }
 270     }
 271     return 0;
 272 }
 273 
 274 static int lsapi_close( int fd )
 275 {
 276     int ret;
 277     while( 1 )
 278     {
 279         ret = close( fd );
 280         if (( ret == -1 )&&( errno == EINTR )&&(g_running))
 281             continue;
 282         return ret;
 283     }
 284 }
 285 
 286 static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
 287 {
 288     ssize_t ret;
 289     while( 1 )
 290     {
 291         ret = read( fd, (char *)pBuf, len );
 292         if (( ret == -1 )&&( errno == EINTR )&&(g_running))
 293             continue;
 294         return ret;
 295     }
 296 }
 297 
 298 /*
 299 static int lsapi_write( int fd, const void * pBuf, int len )
 300 {
 301    int ret;
 302    const char * pCur;
 303    const char * pEnd;
 304    if ( len == 0 )
 305        return 0;
 306    pCur = (const char *)pBuf;
 307    pEnd = pCur + len;
 308    while( g_running && (pCur < pEnd) )
 309    {
 310        ret = write( fd, pCur, pEnd - pCur );
 311        if ( ret >= 0)
 312            pCur += ret;
 313        else if (( ret == -1 )&&( errno != EINTR ))
 314            return ret;
 315    }
 316    return pCur - (const char *)pBuf;
 317 }
 318 */
 319 
 320 static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
 321 {
 322     int ret;
 323     int left = totalLen;
 324     int n = count;
 325     while(( left > 0 )&&g_running )
 326     {
 327         ret = writev( fd, *pVec, n );
 328         if ( ret > 0 )
 329         {
 330             left -= ret;
 331             if (( left <= 0)||( !g_running ))
 332                 return totalLen - left;
 333             while( ret > 0 )
 334             {
 335                 if ( (*pVec)->iov_len <= (unsigned int )ret )
 336                 {
 337                     ret -= (*pVec)->iov_len;
 338                     ++(*pVec);
 339                 }
 340                 else
 341                 {
 342                     (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
 343                     (*pVec)->iov_len -= ret;
 344                     break;
 345                 }
 346             }
 347         }
 348         else if ( ret == -1 )
 349         {
 350             if ( errno == EAGAIN )
 351             {
 352                 if ( totalLen - left > 0 )
 353                     return totalLen - left;
 354                 else
 355                     return -1;
 356             }
 357             else if ( errno != EINTR )
 358                 return ret;
 359         }
 360     }
 361     return totalLen - left;
 362 }
 363 
 364 /*
 365 static int getTotalLen( struct iovec * pVec, int count )
 366 {
 367    struct iovec * pEnd = pVec + count;
 368    int total = 0;
 369    while( pVec < pEnd )
 370    {
 371        total += pVec->iov_len;
 372        ++pVec;
 373    }
 374    return total;
 375 }
 376 */
 377 
 378 static inline int allocateBuf( LSAPI_Request * pReq, int size )
 379 {
 380     char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
 381     if ( pBuf )
 382     {
 383         pReq->m_pReqBuf = pBuf;
 384         pReq->m_reqBufSize = size;
 385         pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
 386         return 0;
 387     }
 388     return -1;
 389 }
 390 
 391 
 392 static int allocateIovec( LSAPI_Request * pReq, int n )
 393 {
 394     struct iovec * p = (struct iovec *)realloc(
 395                 pReq->m_pIovec, sizeof(struct iovec) * n );
 396     if ( !p )
 397         return -1;
 398     pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
 399     pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
 400     pReq->m_pIovec = p;
 401     pReq->m_pIovecEnd = p + n;
 402     return 0;
 403 }
 404 
 405 static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
 406 {
 407     char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
 408     if ( !p )
 409         return -1;
 410     pReq->m_pRespHeaderBufPos   = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
 411     pReq->m_pRespHeaderBuf      = p;
 412     pReq->m_pRespHeaderBufEnd   = p + size;
 413     return 0;
 414 }
 415 
 416 
 417 static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
 418 {
 419     if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
 420         ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
 421         ( pktType != pHeader->m_type ))
 422         return -1;
 423     if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
 424     {
 425         register char b;
 426         b = pHeader->m_packetLen.m_bytes[0];
 427         pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
 428         pHeader->m_packetLen.m_bytes[3] = b;
 429         b = pHeader->m_packetLen.m_bytes[1];
 430         pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
 431         pHeader->m_packetLen.m_bytes[2] = b;
 432     }
 433     return pHeader->m_packetLen.m_iLen;
 434 }
 435 
 436 static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
 437                         int *curSize, int newSize )
 438 {
 439     struct LSAPI_key_value_pair * pBuf;
 440     if ( *curSize >= newSize )
 441         return 0;
 442     if ( newSize > 8192 )
 443         return -1;
 444     pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
 445                     sizeof(struct LSAPI_key_value_pair) );
 446     if ( pBuf )
 447     {
 448         *pEnvList = pBuf;
 449         *curSize  = newSize;
 450         return 0;
 451     }
 452     else
 453         return -1;
 454 
 455 }
 456 
 457 static inline int isPipe( int fd )
 458 {
 459     char        achPeer[128];
 460     socklen_t   len = 128;
 461     if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
 462         ( errno == ENOTCONN ))
 463         return 0;
 464     else
 465         return 1;
 466 }
 467 
 468 static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
 469             char **pBegin, char * pEnd )
 470 {
 471     struct LSAPI_key_value_pair * pEnvEnd;
 472         int keyLen = 0, valLen = 0;
 473     if ( count > 8192 )
 474         return -1;
 475     pEnvEnd = pEnvList + count;
 476     while( pEnvList != pEnvEnd )
 477     {
 478         if ( pEnd - *pBegin < 4 )
 479             return -1;
 480         keyLen = *((unsigned char *)((*pBegin)++));
 481         keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
 482         valLen = *((unsigned char *)((*pBegin)++));
 483         valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
 484         if ( *pBegin + keyLen + valLen > pEnd )
 485             return -1;
 486         if (( !keyLen )||( !valLen ))
 487             return -1;
 488 
 489         pEnvList->pKey = *pBegin;
 490         *pBegin += keyLen;
 491         pEnvList->pValue = *pBegin;
 492         *pBegin += valLen;
 493 
 494         pEnvList->keyLen = keyLen - 1;
 495         pEnvList->valLen = valLen - 1;
 496         ++pEnvList;
 497     }
 498     if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
 499         return -1;
 500     *pBegin += 4;
 501     return 0;
 502 }
 503 
 504 static inline void swapIntEndian( int * pInteger )
 505 {
 506     char * p = (char *)pInteger;
 507     register char b;
 508     b = p[0];
 509     p[0] = p[3];
 510     p[3] = b;
 511     b = p[1];
 512     p[1] = p[2];
 513     p[2] = b;
 514 
 515 }
 516 
 517 static inline void fixEndian( LSAPI_Request * pReq )
 518 {
 519     struct lsapi_req_header *p= pReq->m_pHeader;
 520     swapIntEndian( &p->m_httpHeaderLen );
 521     swapIntEndian( &p->m_reqBodyLen );
 522     swapIntEndian( &p->m_scriptFileOff );
 523     swapIntEndian( &p->m_scriptNameOff );
 524     swapIntEndian( &p->m_queryStringOff );
 525     swapIntEndian( &p->m_requestMethodOff );
 526     swapIntEndian( &p->m_cntUnknownHeaders );
 527     swapIntEndian( &p->m_cntEnv );
 528     swapIntEndian( &p->m_cntSpecialEnv );
 529 }
 530 
 531 static void fixHeaderIndexEndian( LSAPI_Request * pReq )
 532 {
 533     int i;
 534     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
 535     {
 536         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
 537         {
 538             register char b;
 539             char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
 540             b = p[0];
 541             p[0] = p[1];
 542             p[1] = b;
 543             swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
 544         }
 545     }
 546     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
 547     {
 548         struct lsapi_header_offset * pCur, *pEnd;
 549         pCur = pReq->m_pUnknownHeader;
 550         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
 551         while( pCur < pEnd )
 552         {
 553             swapIntEndian( &pCur->nameOff );
 554             swapIntEndian( &pCur->nameLen );
 555             swapIntEndian( &pCur->valueOff );
 556             swapIntEndian( &pCur->valueLen );
 557             ++pCur;
 558         }
 559     }
 560 }
 561 
 562 
 563 static int validateHeaders( LSAPI_Request * pReq )
 564 {
 565     int totalLen = pReq->m_pHeader->m_httpHeaderLen;
 566     int i;
 567     for(i = 0; i < H_TRANSFER_ENCODING; ++i)
 568     {
 569         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
 570         {
 571             if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen 
 572                 || pReq->m_pHeaderIndex->m_headerLen[i] 
 573                     + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen)
 574                 return -1;
 575         }
 576     }
 577     if (pReq->m_pHeader->m_cntUnknownHeaders > 0)
 578     {
 579         struct lsapi_header_offset * pCur, *pEnd;
 580         pCur = pReq->m_pUnknownHeader;
 581         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
 582         while( pCur < pEnd )
 583         {
 584             if (pCur->nameOff > totalLen 
 585                 || pCur->nameOff + pCur->nameLen > totalLen 
 586                 || pCur->valueOff > totalLen
 587                 || pCur->valueOff + pCur->valueLen > totalLen)
 588                 return -1;
 589             ++pCur;
 590         }
 591     }
 592     return 0;
 593 }
 594 
 595 
 596 static uid_t s_uid = 0;
 597 static uid_t s_defaultUid;  //web server need set this
 598 static gid_t s_defaultGid;
 599 
 600 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
 601 
 602 #define LSAPI_LVE_DISABLED  0
 603 #define LSAPI_LVE_ENABLED   1
 604 #define LSAPI_CAGEFS_ENABLED 2
 605 #define LSAPI_CAGEFS_NO_SUEXEC 3
 606 struct liblve;
 607 static int s_enable_lve = LSAPI_LVE_DISABLED;
 608 static struct liblve * s_lve = NULL;
 609 
 610 static void *s_liblve;
 611 static int (*fp_lve_is_available)(void) = NULL;
 612 static int (*fp_lve_instance_init)(struct liblve *) = NULL;
 613 static int (*fp_lve_destroy)(struct liblve *) = NULL;
 614 static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
 615 static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
 616 static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
 617 static int lsapi_load_lve_lib()
 618 {
 619     s_liblve = dlopen("liblve.so.0", RTLD_LAZY);
 620     if (s_liblve)
 621     {
 622         fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
 623         if (dlerror() == NULL)
 624         {
 625             if ( !(*fp_lve_is_available)() )
 626             {
 627                 int uid = getuid();
 628                 if ( uid )
 629                 {
 630                     setreuid( s_uid, uid );
 631                     if ( !(*fp_lve_is_available)() )
 632                         s_enable_lve = 0;
 633                     setreuid( uid, s_uid );
 634                 }
 635             }
 636         }
 637     }
 638     else
 639     {
 640         s_enable_lve = LSAPI_LVE_DISABLED;
 641     }
 642     return (s_liblve)? 0 : -1;
 643 }
 644 
 645 static int init_lve_ex()
 646 {
 647     int rc;
 648     if ( !s_liblve )
 649         return -1;
 650     fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
 651     fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
 652     fp_lve_enter = dlsym(s_liblve, "lve_enter");
 653     fp_lve_leave = dlsym(s_liblve, "lve_leave");
 654     if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
 655         fp_lve_jail = dlsym(s_liblve, "jail" );
 656 
 657     if ( s_lve == NULL )
 658     {
 659         rc = (*fp_lve_instance_init)(NULL);
 660         s_lve = malloc(rc);
 661     }
 662     rc = (*fp_lve_instance_init)(s_lve);
 663     if (rc != 0)
 664     {
 665         perror( "LSAPI: Unable to initialize LVE" );
 666         free( s_lve );
 667         s_lve = NULL;
 668         return -1;
 669     }
 670     return 0;
 671 
 672 }
 673 
 674 #endif
 675 
 676 
 677 
 678 static int readSecret( const char * pSecretFile )
 679 {
 680     struct stat st;
 681     int fd = open( pSecretFile, O_RDONLY , 0600 );
 682     if ( fd == -1 )
 683     {
 684         fprintf( stderr, "LSAPI: failed to open secret file: %s!\n", pSecretFile );
 685         return -1;
 686     }
 687     if ( fstat( fd, &st ) == -1 )
 688     {
 689         fprintf( stderr, "LSAPI: failed to check state of file: %s!\n", pSecretFile );
 690         close( fd );
 691         return -1;
 692     }
 693 /*
 694     if ( st.st_uid != s_uid )
 695     {
 696         fprintf( stderr, "LSAPI: file owner check failure: %s!\n", pSecretFile );
 697         close( fd );
 698         return -1;
 699     }
 700 */
 701     if ( st.st_mode & 0077 )
 702     {
 703         fprintf( stderr, "LSAPI: file permission check failure: %s\n", pSecretFile );
 704         close( fd );
 705         return -1;
 706     }
 707     if ( read( fd, s_secret, 16 ) < 16 )
 708     {
 709         fprintf( stderr, "LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
 710         close( fd );
 711         return -1;
 712     }
 713     close( fd );
 714     return 0;
 715 }
 716 
 717 int LSAPI_is_suEXEC_Daemon()
 718 {
 719     if (( !s_uid )&&( s_secret[0] ))
 720         return 1;
 721     else
 722         return 0;
 723 }
 724 
 725 static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
 726 {
 727     char achError[1024];
 728     int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) );
 729     if ( pReq )
 730         LSAPI_Write_Stderr_r( pReq, achError, n );
 731     else
 732         write( STDERR_FILENO, achError, n );
 733     return 0;
 734 }
 735 
 736 static int lsapi_lve_error( LSAPI_Request * pReq )
 737 {
 738     static const char * headers[] =
 739     {
 740         "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
 741         "Pragma: no-cache",
 742         "Retry-After: 60",
 743         "Content-Type: text/html",
 744         NULL
 745     };
 746     static const char achBody[] =
 747         "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
 748         "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
 749         "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
 750         "The website is temporarily unable to service your request as it exceeded resource limit.\n"
 751         "Please try again later.\n"
 752         "<HR>\n"
 753         "</BODY></HTML>\n";
 754 
 755     LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
 756     return 0;
 757 }
 758 
 759 static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
 760 {
 761 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
 762     if ( s_lve && uid ) //root user should not do that
 763     {
 764         uint32_t cookie;
 765         int ret = -1;
 766         ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
 767         if ( ret < 0 )
 768         {
 769             fprintf( stderr, "Pid (%d): enter LVE (%d) : ressult: %d !\n", getpid(), uid, ret );
 770             LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
 771             lsapi_lve_error( pReq );
 772             return -1;
 773         }
 774     }
 775 #endif
 776 
 777     return 0;
 778 }
 779 
 780 static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
 781 {
 782     int ret = 0;
 783 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
 784     char  error_msg[1024] = "";
 785     ret = (*fp_lve_jail)( pw, error_msg );
 786     if ( ret < 0 )
 787     {
 788         fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n",
 789                         getpid(), uid, ret, error_msg );
 790         LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
 791         return -1;
 792     }
 793 #endif
 794     return ret;
 795 }
 796 
 797 
 798 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
 799 static int lsapi_initLVE()
 800 {
 801     const char * pEnv;
 802     if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
 803     {
 804         s_enable_lve = atol( pEnv );
 805         pEnv = NULL;
 806     }
 807     else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
 808     {
 809         s_enable_lve = atol( pEnv );
 810         pEnv = NULL;
 811     }
 812     if ( s_enable_lve && !s_uid )
 813     {
 814         lsapi_load_lve_lib();
 815         if ( s_enable_lve )
 816         {
 817             return init_lve_ex();
 818         }
 819 
 820     }
 821     return 0;
 822 }
 823 #endif
 824 
 825 
 826 static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
 827 {
 828     int rv;
 829     struct passwd * pw;
 830     pw = getpwuid( uid );
 831 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
 832     if ( s_lve )
 833     {
 834         if( lsapi_enterLVE( pReq, uid ) == -1 )
 835             return -1;
 836         if ( pw && fp_lve_jail)
 837         {
 838             rv = lsapi_jailLVE( pReq, uid, pw );
 839             if ( rv == -1 )
 840                 return -1;
 841             if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC ))    //this mode only use cageFS, does not use suEXEC
 842             {
 843                 uid = s_defaultUid;
 844                 gid = s_defaultGid;
 845                 pw = getpwuid( uid );
 846             }
 847         }
 848     }
 849 #endif
 850     //if ( !uid || !gid )  //do not allow root
 851     //{
 852     //    return -1;
 853     //}
 854 
 855 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
 856     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
 857     if ( s_enable_core_dump )
 858         lsapi_enable_core_dump();
 859 #endif
 860 
 861     rv = setgid(gid);
 862     if (rv == -1)
 863     {
 864         LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
 865         return -1;
 866     }
 867     if ( pw && (pw->pw_gid == gid ))
 868     {
 869         rv = initgroups( pw->pw_name, gid );
 870         if (rv == -1)
 871         {
 872             LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
 873             return -1;
 874         }
 875     }
 876     else
 877     {
 878         rv = setgroups(1, &gid);
 879         if (rv == -1)
 880         {
 881             LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
 882         }
 883     }
 884     if ( pChroot )
 885     {
 886         rv = chroot( pChroot );
 887         if ( rv == -1 )
 888         {
 889             LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
 890             return -1;
 891         }
 892     }
 893     rv = setuid(uid);
 894     if (rv == -1)
 895     {
 896         LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
 897         return -1;
 898     }
 899 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
 900     if ( s_enable_core_dump )
 901         lsapi_enable_core_dump();
 902 #endif
 903     return 0;
 904 }
 905 
 906 static int lsapi_suexec_auth( LSAPI_Request *pReq,
 907             char * pAuth, int len, char * pUgid, int ugidLen )
 908 {
 909     lsapi_MD5_CTX md5ctx;
 910     unsigned char achMD5[16];
 911     if ( len < 32 )
 912         return -1;
 913     memmove( achMD5, pAuth + 16, 16 );
 914     memmove( pAuth + 16, s_secret, 16 );
 915     lsapi_MD5Init( &md5ctx );
 916     lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
 917     lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
 918     lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
 919     if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
 920         return 0;
 921     return 1;
 922 }
 923 
 924 
 925 static int lsapi_changeUGid( LSAPI_Request * pReq )
 926 {
 927     int uid = s_defaultUid;
 928     int gid = s_defaultGid;
 929     const char * pChroot = NULL;
 930     struct LSAPI_key_value_pair * pEnv;
 931     struct LSAPI_key_value_pair * pAuth;
 932     int i;
 933     if ( s_uid )
 934         return 0;
 935     //with special ID  0x00
 936     //authenticate the suEXEC request;
 937     //first one should be MD5( nonce + lscgid secret )
 938     //remember to clear the secret after verification
 939     //it should be set at the end of special env
 940     i = pReq->m_pHeader->m_cntSpecialEnv - 1;
 941     if ( i >= 0 )
 942     {
 943         pEnv = pReq->m_pSpecialEnvList + i;
 944         if (( *pEnv->pKey == '\000' )&&
 945             ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
 946         {
 947             --pReq->m_pHeader->m_cntSpecialEnv;
 948             pAuth = pEnv--;
 949             if (( *pEnv->pKey == '\000' )&&
 950                 ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
 951             {
 952                 --pReq->m_pHeader->m_cntSpecialEnv;
 953                 uid = *(uint32_t *)pEnv->pValue;
 954                 gid = *(((uint32_t *)pEnv->pValue) + 1 );
 955                 //fprintf( stderr, "LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
 956             }
 957             else
 958             {
 959                 fprintf( stderr, "LSAPI: missing SUEXEC_UGID env, use default user!\n" );
 960                 pEnv = NULL;
 961             }
 962             if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
 963             {
 964                 //read UID, GID from specialEnv
 965 
 966             }
 967             else
 968             {
 969                 //authentication error
 970                 fprintf( stderr, "LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
 971                 uid = 0;
 972             }
 973         }
 974         else
 975         {
 976             //fprintf( stderr, "LSAPI: no SUEXEC_AUTH env, use default user!\n" );
 977         }
 978     }
 979 
 980 
 981     if ( !uid )
 982     {
 983         uid = s_defaultUid;
 984         gid = s_defaultGid;
 985     }
 986 
 987     //change uid
 988     if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
 989     {
 990         return -1;
 991     }
 992 
 993     s_uid = uid;
 994 
 995     return 0;
 996 
 997 }
 998 
 999 static int parseContentLenFromHeader(LSAPI_Request * pReq)
1000 {
1001     const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
1002     if ( pContentLen )
1003         pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
1004     return 0;
1005 }
1006 
1007 
1008 static int parseRequest( LSAPI_Request * pReq, int totalLen )
1009 {
1010     int shouldFixEndian;
1011     char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
1012     char * pEnd = pReq->m_pReqBuf + totalLen;
1013     shouldFixEndian = ( LSAPI_ENDIAN != (
1014                 pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
1015     if ( shouldFixEndian )
1016     {
1017         fixEndian( pReq );
1018     }
1019     if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
1020             allocateEnvList( &pReq->m_pSpecialEnvList,
1021                 &pReq->m_specialEnvListSize,
1022                 pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
1023         return -1;
1024     if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
1025             allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
1026                 pReq->m_pHeader->m_cntEnv ) == -1 )
1027         return -1;
1028 
1029     if ( parseEnv( pReq->m_pSpecialEnvList,
1030                 pReq->m_pHeader->m_cntSpecialEnv,
1031                 &pBegin, pEnd ) == -1 )
1032         return -1;
1033     if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
1034                 &pBegin, pEnd ) == -1 )
1035         return -1;
1036     if (pReq->m_pHeader->m_scriptFileOff < 0 
1037         || pReq->m_pHeader->m_scriptFileOff >= totalLen 
1038         || pReq->m_pHeader->m_scriptNameOff < 0
1039         || pReq->m_pHeader->m_scriptNameOff >= totalLen
1040         || pReq->m_pHeader->m_queryStringOff < 0
1041         || pReq->m_pHeader->m_queryStringOff >= totalLen
1042         || pReq->m_pHeader->m_requestMethodOff < 0 
1043         || pReq->m_pHeader->m_requestMethodOff >= totalLen)
1044     {
1045         fprintf(stderr, "%d: bad request header - ERROR#1\n", getpid());
1046         return -1;
1047     }
1048     pReq->m_pScriptFile     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
1049     pReq->m_pScriptName     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
1050     pReq->m_pQueryString    = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
1051     pReq->m_pRequestMethod  = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
1052 
1053     pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
1054     pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
1055     pBegin += sizeof( struct lsapi_http_header_index );
1056 
1057     pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
1058     pBegin += sizeof( struct lsapi_header_offset) *
1059                     pReq->m_pHeader->m_cntUnknownHeaders;
1060 
1061     pReq->m_pHttpHeader = pBegin;
1062     pBegin += pReq->m_pHeader->m_httpHeaderLen;
1063     if ( pBegin != pEnd )
1064     {
1065         fprintf( stderr, "%d: request header does match total size, total: %d, real: %ld\n", getpid(), totalLen,
1066                     pBegin - pReq->m_pReqBuf );
1067         return -1;
1068     }
1069     if ( shouldFixEndian )
1070     {
1071         fixHeaderIndexEndian( pReq );
1072     }
1073     
1074     if (validateHeaders(pReq) == -1)
1075     {
1076         fprintf(stderr, "%d: bad request header - ERROR#2\n", getpid());
1077         return -1;
1078     }
1079     
1080     pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1081     if ( pReq->m_reqBodyLen == -2 )
1082     {
1083         parseContentLenFromHeader(pReq);
1084     }
1085 
1086     return 0;
1087 }
1088 
1089 //OPTIMIZATION
1090 static char s_accept_notify = 0;
1091 static char s_schedule_notify = 0;
1092 static char s_notify_scheduled = 0;
1093 static char s_notified_pid = 0;
1094 
1095 static struct lsapi_packet_header s_ack = {'L', 'S',
1096                 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1097 
1098 
1099 static inline int write_req_received_notification( int fd )
1100 {
1101     if ( write( fd, &s_ack, LSAPI_PACKET_HEADER_LEN )
1102                 < LSAPI_PACKET_HEADER_LEN )
1103         return -1;
1104     return 0;
1105 }
1106 
1107 static void lsapi_sigalarm( int sig )
1108 {
1109     if ( s_notify_scheduled )
1110     {
1111         s_notify_scheduled = 0;
1112         if ( g_req.m_fd != -1 )
1113             write_req_received_notification( g_req.m_fd );
1114     }
1115 }
1116 
1117 static inline int lsapi_schedule_notify()
1118 {
1119     if ( !s_notify_scheduled )
1120     {
1121         alarm( 2 );
1122         s_notify_scheduled = 1;
1123     }
1124     return 0;
1125 }
1126 
1127 static inline int notify_req_received( int fd )
1128 {
1129     if ( s_schedule_notify )
1130         return lsapi_schedule_notify();
1131     return write_req_received_notification( fd );
1132 
1133 }
1134 
1135 
1136 static inline int lsapi_notify_pid( int fd )
1137 {
1138     char achBuf[16];
1139     lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
1140                         8 + LSAPI_PACKET_HEADER_LEN );
1141     memmove( &achBuf[8], "\0PID", 4 );
1142     *((int *)&achBuf[12]) = getpid();
1143 
1144     if ( write( fd, achBuf, 16 ) < 16 )
1145         return -1;
1146     return 0;
1147 }
1148 
1149 static char s_conn_key_packet[16];
1150 static inline int init_conn_key( int fd )
1151 {
1152     struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet;
1153     struct timeval tv;
1154     int i;
1155     gettimeofday( &tv, NULL );
1156     srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() );
1157     for( i = 8; i < 16; ++i )
1158     {
1159         s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0));
1160     }
1161     lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED,
1162                         8 + LSAPI_PACKET_HEADER_LEN );
1163     if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 )
1164                 < LSAPI_PACKET_HEADER_LEN+8 )
1165         return -1;
1166     return 0;
1167 
1168 
1169 }
1170 
1171 static int readReq( LSAPI_Request * pReq )
1172 {
1173     int len;
1174     int packetLen;
1175     if ( !pReq )
1176         return -1;
1177     if ( pReq->m_reqBufSize < 8192 )
1178     {
1179         if ( allocateBuf( pReq, 8192 ) == -1 )
1180             return -1;
1181     }
1182 
1183     while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
1184     {
1185         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
1186         if ( len <= 0 )
1187             return -1;
1188         pReq->m_bufRead += len;
1189     }
1190     pReq->m_reqState = LSAPI_ST_REQ_HEADER;
1191 
1192     packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
1193     if ( packetLen < 0 )
1194     {
1195         fprintf( stderr, "%d: packetLen < 0\n", getpid() );
1196         return -1;
1197     }
1198     if ( packetLen > LSAPI_MAX_HEADER_LEN )
1199     {
1200         fprintf( stderr, "%d: packetLen > %d\n", getpid(), LSAPI_MAX_HEADER_LEN );
1201         return -1;
1202     }
1203 
1204     if ( packetLen + 1024 > pReq->m_reqBufSize )
1205     {
1206         if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
1207             return -1;
1208     }
1209     while( packetLen > pReq->m_bufRead )
1210     {
1211         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
1212         if ( len <= 0 )
1213             return -1;
1214         pReq->m_bufRead += len;
1215     }
1216     if ( parseRequest( pReq, packetLen ) < 0 )
1217     {
1218         fprintf( stderr, "%d: parseRequest error\n", getpid() );
1219         return -1;
1220     }
1221 
1222     pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
1223 
1224     if ( !s_uid )
1225     {
1226         if ( lsapi_changeUGid( pReq ) )
1227             return -1;
1228         memset(s_secret, 0, sizeof(s_secret));
1229     }
1230     pReq->m_bufProcessed = packetLen;
1231 
1232     //OPTIMIZATION
1233     if ( !s_accept_notify && !s_notified_pid )
1234         return notify_req_received( pReq->m_fd );
1235     else
1236     {
1237         s_notified_pid = 0;
1238         return 0;
1239     }
1240 }
1241 
1242 
1243 
1244 int LSAPI_Init(void)
1245 {
1246     if ( !g_inited )
1247     {
1248         s_uid = geteuid();
1249         s_secret[0] = 0;
1250         lsapi_signal(SIGPIPE, lsapi_sigpipe);
1251         lsapi_signal(SIGUSR1, lsapi_siguser1);
1252 
1253 #if defined(SIGXFSZ) && defined(SIG_IGN)
1254         signal(SIGXFSZ, SIG_IGN);
1255 #endif
1256         /* let STDOUT function as STDERR,
1257            just in case writing to STDOUT directly */
1258         dup2( 2, 1 );
1259         if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
1260             return -1;
1261         g_inited = 1;
1262         s_ppid = getppid();
1263     }
1264     return 0;
1265 }
1266 
1267 void LSAPI_Stop(void)
1268 {
1269     g_running = 0;
1270 }
1271 
1272 int LSAPI_IsRunning(void)
1273 {
1274     return g_running;
1275 }
1276 
1277 int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1278 {
1279     int newfd;
1280     if ( !pReq )
1281         return -1;
1282     memset( pReq, 0, sizeof( LSAPI_Request ) );
1283     if ( allocateIovec( pReq, 16 ) == -1 )
1284         return -1;
1285     pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
1286     if ( !pReq->m_pRespBuf )
1287         return -1;
1288     pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
1289     pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1290     pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
1291     if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
1292         return -1;
1293 
1294     if ( fd == STDIN_FILENO )
1295     {
1296         fd = dup( fd );
1297         newfd = open( "/dev/null", O_RDWR );
1298         dup2( newfd, STDIN_FILENO );
1299     }
1300 
1301     if ( isPipe( fd ) )
1302     {
1303         pReq->m_fdListen = -1;
1304         pReq->m_fd = fd;
1305     }
1306     else
1307     {
1308         pReq->m_fdListen = fd;
1309         pReq->m_fd = -1;
1310         lsapi_set_nblock( fd, 1 );
1311     }
1312     return 0;
1313 }
1314 
1315 int LSAPI_Is_Listen( void )
1316 {
1317     return LSAPI_Is_Listen_r( &g_req );
1318 }
1319 
1320 int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
1321 {
1322     return pReq->m_fdListen != -1;
1323 }
1324 
1325 
1326 
1327 int LSAPI_Accept_r( LSAPI_Request * pReq )
1328 {
1329     char        achPeer[128];
1330     socklen_t   len;
1331     int         nodelay = 1;
1332 
1333     if ( !pReq )
1334         return -1;
1335     if ( LSAPI_Finish_r( pReq ) == -1 )
1336         return -1;
1337     lsapi_set_nblock( pReq->m_fdListen , 0 );
1338     while( g_running )
1339     {
1340         if ( pReq->m_fd == -1 )
1341         {
1342             if ( pReq->m_fdListen != -1)
1343             {
1344                 len = sizeof( achPeer );
1345                 pReq->m_fd = accept( pReq->m_fdListen,
1346                             (struct sockaddr *)&achPeer, &len );
1347                 if ( pReq->m_fd == -1 )
1348                 {
1349                     if (( errno == EINTR )||( errno == EAGAIN))
1350                         continue;
1351                     else
1352                         return -1;
1353                 }
1354                 else
1355                 {
1356                     lsapi_set_nblock( pReq->m_fd , 0 );
1357                     if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
1358                     {
1359                         setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
1360                                    (char *)&nodelay, sizeof(nodelay));
1361                     }
1362                     //init_conn_key( pReq->m_fd );
1363                     //OPTIMIZATION
1364                     if ( s_accept_notify )
1365                         if ( notify_req_received( pReq->m_fd ) == -1 )
1366                                 return -1;
1367                 }
1368             }
1369             else
1370                 return -1;
1371         }
1372         if ( !readReq( pReq ) )
1373             break;
1374         //abort();
1375         lsapi_close( pReq->m_fd );
1376         pReq->m_fd = -1;
1377         LSAPI_Reset_r( pReq );
1378     }
1379     return 0;
1380 }
1381 
1382 static struct lsapi_packet_header   finish = {'L', 'S',
1383                 LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1384 
1385 int LSAPI_Finish_r( LSAPI_Request * pReq )
1386 {
1387     /* finish req body */
1388     if ( !pReq )
1389         return -1;
1390     if (pReq->m_reqState)
1391     {
1392         if ( pReq->m_fd != -1 )
1393         {
1394             if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1395             {
1396                 LSAPI_FinalizeRespHeaders_r( pReq );
1397             }
1398             if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1399             {
1400                 Flush_RespBuf_r( pReq );
1401             }
1402 
1403             pReq->m_pIovecCur->iov_base = (void *)&finish;
1404             pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1405             pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
1406             ++pReq->m_pIovecCur;
1407             LSAPI_Flush_r( pReq );
1408         }
1409         LSAPI_Reset_r( pReq );
1410     }
1411     return 0;
1412 }
1413 
1414 
1415 void LSAPI_Reset_r( LSAPI_Request * pReq )
1416 {
1417     pReq->m_pRespBufPos         = pReq->m_pRespBuf;
1418     pReq->m_pIovecCur           = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1419     pReq->m_pRespHeaderBufPos   = pReq->m_pRespHeaderBuf;
1420 
1421     memset( &pReq->m_pHeaderIndex, 0,
1422             (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
1423 }
1424 
1425 
1426 int LSAPI_Release_r( LSAPI_Request * pReq )
1427 {
1428     if ( pReq->m_pReqBuf )
1429         free( pReq->m_pReqBuf );
1430     if ( pReq->m_pSpecialEnvList )
1431         free( pReq->m_pSpecialEnvList );
1432     if ( pReq->m_pEnvList )
1433         free( pReq->m_pEnvList );
1434     if ( pReq->m_pRespHeaderBuf )
1435         free( pReq->m_pRespHeaderBuf );
1436     return 0;
1437 }
1438 
1439 
1440 char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
1441 {
1442     int off;
1443     if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
1444         return NULL;
1445     off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
1446     if ( !off )
1447         return NULL;
1448     if ( *(pReq->m_pHttpHeader + off 
1449         + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
1450     {
1451         *( pReq->m_pHttpHeader + off 
1452             + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
1453     }
1454     return pReq->m_pHttpHeader + off;
1455 }
1456 
1457 static int readBodyToReqBuf( LSAPI_Request * pReq )
1458 {
1459     off_t bodyLeft;
1460     ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
1461     if ( len > 0 )
1462         return len;
1463     pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
1464 
1465     bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1466     len = pReq->m_reqBufSize - pReq->m_bufRead;
1467     if ( len < 0 )
1468         return -1;
1469     if ( len > bodyLeft )
1470         len = bodyLeft;
1471 
1472     len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
1473     if ( len > 0 )
1474         pReq->m_bufRead += len;
1475     return len;
1476 }
1477 
1478 
1479 int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
1480 {
1481     if (!pReq || (pReq->m_fd ==-1) )
1482         return EOF;
1483     if ( pReq->m_bufProcessed >= pReq->m_bufRead )
1484     {
1485         if ( readBodyToReqBuf( pReq ) <= 0 )
1486             return EOF;
1487     }
1488     ++pReq->m_reqBodyRead;
1489     return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
1490 }
1491 
1492 
1493 
1494 int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
1495 {
1496     ssize_t len;
1497     ssize_t left;
1498     char * pBufEnd = pBuf + bufLen - 1;
1499     char * pBufCur = pBuf;
1500     char * pCur;
1501     char * p;
1502     if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )|| !getLF )
1503         return -1;
1504     *getLF = 0;
1505     while( (left = pBufEnd - pBufCur ) > 0 )
1506     {
1507 
1508         len = pReq->m_bufRead - pReq->m_bufProcessed;
1509         if ( len <= 0 )
1510         {
1511             if ( (len = readBodyToReqBuf( pReq )) <= 0 )
1512             {
1513                 *getLF = 1;
1514                 break;
1515             }
1516         }
1517         if ( len > left )
1518             len = left;
1519         pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
1520         p = memchr( pCur, '\n', len );
1521         if ( p )
1522             len = p - pCur + 1;
1523         memmove( pBufCur, pCur, len );
1524         pBufCur += len;
1525         pReq->m_bufProcessed += len;
1526 
1527         pReq->m_reqBodyRead += len;
1528 
1529         if ( p )
1530         {
1531             *getLF = 1;
1532             break;
1533         }
1534     }
1535     *pBufCur = 0;
1536 
1537     return pBufCur - pBuf;
1538 }
1539 
1540 
1541 ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1542 {
1543     ssize_t len;
1544     off_t total;
1545     /* char *pOldBuf = pBuf; */
1546     if (!pReq || (pReq->m_fd ==-1) || ( !pBuf ))
1547         return -1;
1548 
1549     total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1550 
1551     if ( total <= 0 )
1552         return 0;
1553     if ( total < bufLen )
1554         bufLen = total;
1555 
1556     total = 0;
1557     len = pReq->m_bufRead - pReq->m_bufProcessed;
1558     if ( len > 0 )
1559     {
1560         if ( len > bufLen )
1561             len = bufLen;
1562         memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
1563         pReq->m_bufProcessed += len;
1564         total += len;
1565         pBuf += len;
1566         bufLen -= len;
1567     }
1568     while( bufLen > 0 )
1569     {
1570         len = lsapi_read( pReq->m_fd, pBuf, bufLen );
1571         if ( len > 0 )
1572         {
1573             total += len;
1574             pBuf += len;
1575             bufLen -= len;
1576         }
1577         else if ( len <= 0 )
1578         {
1579             if ( !total)
1580                 return -1;
1581             break;
1582         }
1583     }
1584     pReq->m_reqBodyRead += total;
1585     return total;
1586 
1587 }
1588 
1589 
1590 ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1591 {
1592     struct lsapi_packet_header * pHeader;
1593     const char * pEnd;
1594     const char * p;
1595     ssize_t bufLen;
1596     ssize_t toWrite;
1597     ssize_t packetLen;
1598     int skip = 0;
1599 
1600     if ( !pReq || !pBuf || (pReq->m_fd == -1) )
1601         return -1;
1602     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1603     {
1604         LSAPI_FinalizeRespHeaders_r( pReq );
1605 /*
1606         if ( *pBuf == '\r' )
1607         {
1608             ++skip;
1609         }
1610         if ( *pBuf == '\n' )
1611         {
1612             ++skip;
1613         }
1614 */
1615     }
1616     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1617 
1618     if ( (len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
1619     {
1620         memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
1621         pReq->m_pRespBufPos += len - skip;
1622         return len;
1623     }
1624 
1625 
1626     pHeader = pReq->m_respPktHeader;
1627     p       = pBuf + skip;
1628     pEnd    = pBuf + len;
1629     bufLen  = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1630 
1631     while( ( toWrite = pEnd - p ) > 0 )
1632     {
1633         packetLen = toWrite + bufLen;
1634         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1635         {
1636             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1637             toWrite = packetLen - bufLen;
1638         }
1639 
1640         lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1641                             packetLen + LSAPI_PACKET_HEADER_LEN );
1642         pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
1643 
1644         pReq->m_pIovecCur->iov_base = (void *)pHeader;
1645         pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1646         ++pReq->m_pIovecCur;
1647         ++pHeader;
1648         if ( bufLen > 0 )
1649         {
1650             pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1651             pReq->m_pIovecCur->iov_len  = bufLen;
1652             pReq->m_pRespBufPos = pReq->m_pRespBuf;
1653             ++pReq->m_pIovecCur;
1654             bufLen = 0;
1655         }
1656 
1657         pReq->m_pIovecCur->iov_base = (void *)p;
1658         pReq->m_pIovecCur->iov_len  = toWrite;
1659         ++pReq->m_pIovecCur;
1660         p += toWrite;
1661 
1662         if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
1663         {
1664             if ( LSAPI_Flush_r( pReq ) == -1 )
1665                 return -1;
1666             pHeader = pReq->m_respPktHeader;
1667         }
1668     }
1669     if ( pHeader != pReq->m_respPktHeader )
1670         if ( LSAPI_Flush_r( pReq ) == -1 )
1671             return -1;
1672     return p - pBuf;
1673 }
1674 
1675 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__)
1676 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1677 {
1678     ssize_t ret;
1679     off_t written;
1680     ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
1681     if ( written > 0 )
1682     {
1683         ret = written;
1684         *off += ret;
1685     }
1686     return ret;
1687 }
1688 #endif
1689 
1690 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
1691 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1692 {
1693     ssize_t ret;
1694     off_t len = size;
1695     ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
1696     if (( ret == 0 )&&( len > 0 ))
1697     {
1698         ret = len;
1699         *off += len;
1700     }
1701     return ret;
1702 }
1703 #endif
1704 
1705 #if defined(sun) || defined(__sun)
1706 #include <sys/sendfile.h>
1707 ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
1708 {
1709     int n = 0 ;
1710     sendfilevec_t vec[1];
1711 
1712     vec[n].sfv_fd   = fdIn;
1713     vec[n].sfv_flag = 0;
1714     vec[n].sfv_off  = *off;
1715     vec[n].sfv_len  = size;
1716     ++n;
1717 
1718     size_t written;
1719     ssize_t ret = sendfilev( fdOut, vec, n, &written );
1720     if (( !ret )||( errno == EAGAIN ))
1721         ret = written;
1722     if ( ret > 0 )
1723         *off += ret;
1724     return ret;
1725 }
1726 #endif
1727 
1728 #if defined(linux) || defined(__linux) || defined(__linux__) || \
1729     defined(__gnu_linux__)
1730 #include <sys/sendfile.h>
1731 #define gsendfile sendfile
1732 #endif
1733 #if defined(HPUX)
1734 ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
1735 {
1736     return sendfile( fdOut, fdIn, off, size, NULL, 0 );
1737 }
1738 #endif
1739 
1740 ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
1741 {
1742     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
1743     if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
1744         return -1;
1745     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1746     {
1747         LSAPI_FinalizeRespHeaders_r( pReq );
1748     }
1749     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1750 
1751     LSAPI_Flush_r(pReq);
1752 
1753     lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1754                             size + LSAPI_PACKET_HEADER_LEN );
1755 
1756 
1757     if (write(pReq->m_fd,  (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
1758         return -1;
1759 
1760     return gsendfile( pReq->m_fd, fdIn, off, size );
1761 }
1762 
1763 
1764 void Flush_RespBuf_r( LSAPI_Request * pReq )
1765 {
1766     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
1767     int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1768     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1769     lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1770                         bufLen + LSAPI_PACKET_HEADER_LEN );
1771     pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
1772 
1773     pReq->m_pIovecCur->iov_base = (void *)pHeader;
1774     pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1775     ++pReq->m_pIovecCur;
1776     ++pHeader;
1777     if ( bufLen > 0 )
1778     {
1779         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1780         pReq->m_pIovecCur->iov_len  = bufLen;
1781         pReq->m_pRespBufPos = pReq->m_pRespBuf;
1782         ++pReq->m_pIovecCur;
1783         bufLen = 0;
1784     }
1785 }
1786 
1787 
1788 
1789 
1790 int LSAPI_Flush_r( LSAPI_Request * pReq )
1791 {
1792     int ret = 0;
1793     int n;
1794     if ( !pReq )
1795         return -1;
1796     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
1797     if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
1798         return 0;
1799     if ( pReq->m_fd == -1 )
1800     {
1801         pReq->m_pRespBufPos = pReq->m_pRespBuf;
1802         pReq->m_totalLen = 0;
1803         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
1804         return -1;
1805     }
1806     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1807     {
1808         LSAPI_FinalizeRespHeaders_r( pReq );
1809     }
1810     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1811     {
1812         Flush_RespBuf_r( pReq );
1813     }
1814 
1815     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
1816     if ( n > 0 )
1817     {
1818 
1819         ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
1820                   n, pReq->m_totalLen );
1821         if ( ret < pReq->m_totalLen )
1822         {
1823             lsapi_close( pReq->m_fd );
1824             pReq->m_fd = -1;
1825             ret = -1;
1826         }
1827         pReq->m_totalLen = 0;
1828         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
1829     }
1830     return ret;
1831 }
1832 
1833 
1834 ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1835 {
1836     struct lsapi_packet_header header;
1837     const char * pEnd;
1838     const char * p;
1839     ssize_t packetLen;
1840     ssize_t totalLen;
1841     int ret;
1842     struct iovec iov[2];
1843     struct iovec *pIov;
1844 
1845     if ( !pReq )
1846         return -1;
1847     if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen ))
1848         return write( 2, pBuf, len );
1849     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1850     {
1851         LSAPI_Flush_r( pReq );
1852     }
1853 
1854     p       = pBuf;
1855     pEnd    = pBuf + len;
1856 
1857     while( ( packetLen = pEnd - p ) > 0 )
1858     {
1859         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1860         {
1861             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1862         }
1863 
1864         lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
1865                             packetLen + LSAPI_PACKET_HEADER_LEN );
1866         totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
1867 
1868         iov[0].iov_base = (void *)&header;
1869         iov[0].iov_len  = LSAPI_PACKET_HEADER_LEN;
1870 
1871         iov[1].iov_base = (void *)p;
1872         iov[1].iov_len  = packetLen;
1873         p += packetLen;
1874         pIov = iov;
1875         ret = lsapi_writev( pReq->m_fd, &pIov,
1876                   2, totalLen );
1877         if ( ret < totalLen )
1878         {
1879             lsapi_close( pReq->m_fd );
1880             pReq->m_fd = -1;
1881             ret = -1;
1882         }
1883     }
1884     return p - pBuf;
1885 }
1886 
1887 static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
1888 {
1889     int i;
1890     char * pValue;
1891     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1892     {
1893         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
1894         {
1895             if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
1896             {
1897                 pValue = pReq->m_pHttpHeader 
1898                          + pReq->m_pHeaderIndex->m_headerOff[i];
1899                 if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
1900                 {
1901                     *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
1902                 }
1903                 return pValue;
1904             }
1905         }
1906     }
1907     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
1908     {
1909         const char *p;
1910         char *pKey;
1911         char *pKeyEnd;
1912         int  keyLen;
1913         struct lsapi_header_offset * pCur, *pEnd;
1914         pCur = pReq->m_pUnknownHeader;
1915         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
1916         while( pCur < pEnd )
1917         {
1918             pKey = pReq->m_pHttpHeader + pCur->nameOff;
1919             keyLen = pCur->nameLen;
1920             pKeyEnd = pKey + keyLen;
1921             p = &name[5];
1922 
1923             while(( pKey < pKeyEnd )&&( *p ))
1924             {
1925                 char ch = toupper( *pKey );
1926                 if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
1927                     break;
1928                 ++p; ++pKey;
1929             }
1930             if (( pKey == pKeyEnd )&& (!*p ))
1931             {
1932                 pValue = pReq->m_pHttpHeader + pCur->valueOff;
1933                 
1934                 if ( *(pValue + pCur->valueLen) != '\0')
1935                 {
1936                     *(pValue + pCur->valueLen) = '\0';
1937                 }
1938                 return pValue;
1939             }
1940             ++pCur;
1941         }
1942     }
1943     return NULL;
1944 }
1945 
1946 
1947 char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
1948 {
1949     struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
1950     struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
1951     if ( !pReq || !name )
1952         return NULL;
1953     if ( strncmp( name, "HTTP_", 5 ) == 0 )
1954     {
1955         return GetHeaderVar( pReq, name );
1956     }
1957     while( pBegin < pEnd )
1958     {
1959         if ( strcmp( name, pBegin->pKey ) == 0 )
1960             return pBegin->pValue;
1961         ++pBegin;
1962     }
1963     return NULL;
1964 }
1965 
1966 struct _headerInfo
1967 {
1968     const char * _name;
1969     int          _nameLen;
1970     const char * _value;
1971     int          _valueLen;
1972 };
1973 
1974 int compareValueLocation(const void * v1, const void *v2 )
1975 {
1976     return ((const struct _headerInfo *)v1)->_value -
1977            ((const struct _headerInfo *)v2)->_value;
1978 }
1979 
1980 int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1981             LSAPI_CB_EnvHandler fn, void * arg )
1982 {
1983     int i;
1984     int len = 0;
1985     char * pValue;
1986     int ret;
1987     int count = 0;
1988     struct _headerInfo headers[512];
1989 
1990     if ( !pReq || !fn )
1991         return -1;
1992 
1993     if ( !pReq->m_pHeaderIndex )
1994         return 0;
1995 
1996     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1997     {
1998         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
1999         {
2000             len = pReq->m_pHeaderIndex->m_headerLen[i];
2001             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2002             *(pValue + len ) = 0;
2003             headers[count]._name = HTTP_HEADERS[i];
2004             headers[count]._nameLen = HTTP_HEADER_LEN[i];
2005             headers[count]._value = pValue;
2006             headers[count]._valueLen = len;
2007             ++count;
2008 
2009             //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
2010             //            pValue, len, arg );
2011             //if ( ret <= 0 )
2012             //    return ret;
2013         }
2014     }
2015     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2016     {
2017         char *pKey;
2018         int  keyLen;
2019         struct lsapi_header_offset * pCur, *pEnd;
2020         pCur = pReq->m_pUnknownHeader;
2021         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2022         while( pCur < pEnd )
2023         {
2024             pKey = pReq->m_pHttpHeader + pCur->nameOff;
2025             keyLen = pCur->nameLen;
2026             *(pKey + keyLen ) = 0;
2027 
2028             pValue = pReq->m_pHttpHeader + pCur->valueOff;
2029             *(pValue + pCur->valueLen ) = 0;
2030             headers[count]._name = pKey;
2031             headers[count]._nameLen = keyLen;
2032             headers[count]._value = pValue;
2033             headers[count]._valueLen = pCur->valueLen;
2034             ++count;
2035             if ( count == 512 )
2036                 break;
2037             //ret = (*fn)( pKey, keyLen,
2038             //            pValue, pCur->valueLen, arg );
2039             //if ( ret <= 0 )
2040             //    return ret;
2041             ++pCur;
2042         }
2043     }
2044     qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
2045     for( i = 0; i < count; ++i )
2046     {
2047         ret = (*fn)( headers[i]._name, headers[i]._nameLen,
2048                     headers[i]._value, headers[i]._valueLen, arg );
2049         if ( ret <= 0 )
2050             return ret;
2051     }
2052     return count;
2053 
2054 }
2055 
2056 
2057 int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
2058             LSAPI_CB_EnvHandler fn, void * arg )
2059 {
2060     int i;
2061     int len = 0;
2062     char * pValue;
2063     int ret;
2064     int count = 0;
2065     if ( !pReq || !fn )
2066         return -1;
2067     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2068     {
2069         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2070         {
2071             len = pReq->m_pHeaderIndex->m_headerLen[i];
2072             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2073             *(pValue + len ) = 0;
2074             ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
2075                         pValue, len, arg );
2076             ++count;
2077             if ( ret <= 0 )
2078                 return ret;
2079         }
2080     }
2081     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2082     {
2083         char achHeaderName[256];
2084         char *p;
2085         char *pKey;
2086         char *pKeyEnd ;
2087         int  keyLen;
2088         struct lsapi_header_offset * pCur, *pEnd;
2089         pCur = pReq->m_pUnknownHeader;
2090         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2091         while( pCur < pEnd )
2092         {
2093             pKey = pReq->m_pHttpHeader + pCur->nameOff;
2094             keyLen = pCur->nameLen;
2095             if ( keyLen > 250 )
2096                 keyLen = 250;
2097             pKeyEnd = pKey + keyLen;
2098             memcpy( achHeaderName, "HTTP_", 5 );
2099             p = &achHeaderName[5];
2100 
2101             while( pKey < pKeyEnd )
2102             {
2103                 char ch = *pKey++;
2104                 if ( ch == '-' )
2105                     *p++ = '_';
2106                 else
2107                     *p++ = toupper( ch );
2108             }
2109             *p = 0;
2110             keyLen += 5;
2111 
2112             pValue = pReq->m_pHttpHeader + pCur->valueOff;
2113             *(pValue + pCur->valueLen ) = 0;
2114             ret = (*fn)( achHeaderName, keyLen,
2115                         pValue, pCur->valueLen, arg );
2116             if ( ret <= 0 )
2117                 return ret;
2118             ++pCur;
2119         }
2120     }
2121     return count + pReq->m_pHeader->m_cntUnknownHeaders;
2122 
2123 }
2124 
2125 static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
2126             int n, LSAPI_CB_EnvHandler fn, void * arg )
2127 {
2128     struct LSAPI_key_value_pair * pEnd = pEnv + n;
2129     int ret;
2130     if ( !pEnv || !fn )
2131         return -1;
2132     while( pEnv < pEnd )
2133     {
2134         ret = (*fn)( pEnv->pKey, pEnv->keyLen,
2135                     pEnv->pValue, pEnv->valLen, arg );
2136         if ( ret <= 0 )
2137             return ret;
2138         ++pEnv;
2139     }
2140     return n;
2141 }
2142 
2143 
2144 
2145 int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
2146             LSAPI_CB_EnvHandler fn, void * arg )
2147 {
2148     if ( !pReq || !fn )
2149         return -1;
2150     if ( pReq->m_pHeader->m_cntEnv > 0 )
2151     {
2152         return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
2153                     fn, arg );
2154     }
2155     return 0;
2156 }
2157 
2158 
2159 
2160 int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
2161             LSAPI_CB_EnvHandler fn, void * arg )
2162 {
2163     if ( !pReq || !fn )
2164         return -1;
2165     if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
2166     {
2167         return EnvForeach( pReq->m_pSpecialEnvList,
2168                 pReq->m_pHeader->m_cntSpecialEnv,
2169                     fn, arg );
2170     }
2171     return 0;
2172 
2173 }
2174 
2175 
2176 
2177 int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2178 {
2179     if ( !pReq || !pReq->m_pIovec )
2180         return -1;
2181     if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
2182         return 0;
2183     pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
2184     if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
2185     {
2186         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
2187         pReq->m_pIovecCur->iov_len  = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
2188         pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
2189         ++pReq->m_pIovecCur;
2190     }
2191 
2192     pReq->m_pIovec->iov_len  = sizeof( struct lsapi_resp_header)
2193             + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
2194     pReq->m_totalLen += pReq->m_pIovec->iov_len;
2195 
2196     lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
2197                     LSAPI_RESP_HEADER, pReq->m_totalLen  );
2198     pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
2199     pReq->m_pIovecToWrite = pReq->m_pIovec;
2200     return 0;
2201 }
2202 
2203 
2204 int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2205                               const char * pHeaderValue )
2206 {
2207     int nameLen, valLen, len;
2208     if ( !pReq || !pHeaderName || !pHeaderValue )
2209         return -1;
2210     if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2211         return -1;
2212     if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2213         return -1;
2214     nameLen = strlen( pHeaderName );
2215     valLen = strlen( pHeaderValue );
2216     if ( nameLen == 0 )
2217         return -1;
2218     while( nameLen > 0 )
2219     {
2220         char ch = *(pHeaderName + nameLen - 1 );
2221         if (( ch == '\n' )||( ch == '\r' ))
2222             --nameLen;
2223         else
2224             break;
2225     }
2226     if ( nameLen <= 0 )
2227         return 0;
2228     while( valLen > 0 )
2229     {
2230         char ch = *(pHeaderValue + valLen - 1 );
2231         if (( ch == '\n' )||( ch == '\r' ))
2232             --valLen;
2233         else
2234             break;
2235     }
2236     len = nameLen + valLen + 1;
2237     if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
2238         return -1;
2239 
2240     if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2241     {
2242         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2243         newlen -= newlen % 4096;
2244         if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2245             return -1;
2246     }
2247     memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
2248     pReq->m_pRespHeaderBufPos += nameLen;
2249     *pReq->m_pRespHeaderBufPos++ = ':';
2250     memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
2251     pReq->m_pRespHeaderBufPos += valLen;
2252     *pReq->m_pRespHeaderBufPos++ = 0;
2253     ++len;  /* add one byte padding for \0 */
2254     pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2255     ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2256     return 0;
2257 }
2258 
2259 
2260 
2261 int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
2262 {
2263     if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
2264         return -1;
2265     if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2266         return -1;
2267     if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2268         return -1;
2269     while( len > 0 )
2270     {
2271         char ch = *(pBuf + len - 1 );
2272         if (( ch == '\n' )||( ch == '\r' ))
2273             --len;
2274         else
2275             break;
2276     }
2277     if ( len <= 0 )
2278         return 0;
2279     if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2280     {
2281         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2282         newlen -= newlen % 4096;
2283         if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2284             return -1;
2285     }
2286     memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
2287     pReq->m_pRespHeaderBufPos += len;
2288     *pReq->m_pRespHeaderBufPos++ = 0;
2289     ++len;  /* add one byte padding for \0 */
2290     pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2291     ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2292     return 0;
2293 }
2294 
2295 
2296 int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
2297 {
2298     int ret;
2299     int fd;
2300     int flag = 1;
2301     int addr_len;
2302 
2303     switch( pServerAddr->sa_family )
2304     {
2305     case AF_INET:
2306         addr_len = 16;
2307         break;
2308     case AF_INET6:
2309         addr_len = sizeof( struct sockaddr_in6 );
2310         break;
2311     case AF_UNIX:
2312         addr_len = sizeof( struct sockaddr_un );
2313         unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
2314         break;
2315     default:
2316         return -1;
2317     }
2318 
2319     fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
2320     if ( fd == -1 )
2321         return -1;
2322 
2323     fcntl( fd, F_SETFD, FD_CLOEXEC );
2324 
2325     if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
2326                 (char *)( &flag ), sizeof(flag)) == 0)
2327     {
2328         ret = bind( fd, pServerAddr, addr_len );
2329         if ( !ret )
2330         {
2331             ret = listen( fd, backlog );
2332             if ( !ret )
2333                 return fd;
2334         }
2335     }
2336 
2337     ret = errno;
2338     close(fd);
2339     errno = ret;
2340     return -1;
2341 
2342 }
2343 
2344 int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2345 {
2346     char achAddr[256];
2347     char * p = achAddr;
2348     char * pEnd;
2349     struct addrinfo *res, hints;
2350     int  doAddrInfo = 0;
2351     int port;
2352 
2353     if ( !pBind )
2354         return -1;
2355 
2356     while( isspace( *pBind ) )
2357         ++pBind;
2358 
2359     strncpy( achAddr, pBind, 256 );
2360 
2361     switch( *p )
2362     {
2363     case '/':
2364         pAddr->sa_family = AF_UNIX;
2365         strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
2366                 sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
2367         return 0;
2368 
2369     case '[':
2370         pAddr->sa_family = AF_INET6;
2371         ++p;
2372         pEnd = strchr( p, ']' );
2373         if ( !pEnd )
2374             return -1;
2375         *pEnd++ = 0;
2376 
2377         if ( *p == '*' )
2378         {
2379             strcpy( achAddr, "::" );
2380             p = achAddr;
2381         }
2382         doAddrInfo = 1;
2383         break;
2384 
2385     default:
2386         pAddr->sa_family = AF_INET;
2387         pEnd = strchr( p, ':' );
2388         if ( !pEnd )
2389             return -1;
2390         *pEnd++ = 0;
2391 
2392         doAddrInfo = 0;
2393         if ( *p == '*' )
2394         {
2395             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
2396         }
2397         else if (!strcasecmp( p, "localhost" ) )
2398             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
2399         else
2400         {
2401             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
2402             if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
2403             {
2404                 doAddrInfo = 1;
2405             }
2406         }
2407         break;
2408     }
2409     if ( *pEnd == ':' )
2410         ++pEnd;
2411 
2412     port = atoi( pEnd );
2413     if (( port <= 0 )||( port > 65535 ))
2414         return -1;
2415     if ( doAddrInfo )
2416     {
2417 
2418         memset(&hints, 0, sizeof(hints));
2419 
2420         hints.ai_family   = pAddr->sa_family;
2421         hints.ai_socktype = SOCK_STREAM;
2422         hints.ai_protocol = IPPROTO_TCP;
2423 
2424         if ( getaddrinfo(p, NULL, &hints, &res) )
2425         {
2426             return -1;
2427         }
2428 
2429         memcpy(pAddr, res->ai_addr, res->ai_addrlen);
2430         freeaddrinfo(res);
2431     }
2432 
2433     if ( pAddr->sa_family == AF_INET )
2434         ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
2435     else
2436         ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
2437     return 0;
2438 
2439 }
2440 
2441 int LSAPI_CreateListenSock( const char * pBind, int backlog )
2442 {
2443     char serverAddr[128];
2444     int ret;
2445     int fd = -1;
2446     ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
2447     if ( !ret )
2448     {
2449         fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
2450     }
2451     return fd;
2452 }
2453 
2454 static fn_select_t g_fnSelect = select;
2455 
2456 typedef struct _lsapi_child_status
2457 {
2458     int     m_pid;
2459     long    m_tmStart;
2460 
2461     volatile short   m_iKillSent;
2462     volatile short   m_inProcess;
2463     volatile int     m_iReqCounter;
2464 
2465     volatile long    m_tmWaitBegin;
2466     volatile long    m_tmReqBegin;
2467     volatile long    m_tmLastCheckPoint;
2468 }
2469 lsapi_child_status;
2470 
2471 static lsapi_child_status * s_pChildStatus = NULL;
2472 
2473 typedef struct _lsapi_prefork_server
2474 {
2475     int m_fd;
2476     int m_iMaxChildren;
2477     int m_iExtraChildren;
2478     int m_iCurChildren;
2479     int m_iMaxIdleChildren;
2480     int m_iServerMaxIdle;
2481     int m_iChildrenMaxIdleTime;
2482     int m_iMaxReqProcessTime;
2483     int m_iAvoidFork;
2484 
2485     lsapi_child_status * m_pChildrenStatus;
2486     lsapi_child_status * m_pChildrenStatusCur;
2487     lsapi_child_status * m_pChildrenStatusEnd;
2488 
2489 }lsapi_prefork_server;
2490 
2491 static lsapi_prefork_server * g_prefork_server = NULL;
2492 
2493 int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2494 {
2495     int pid;
2496     if ( g_prefork_server )
2497         return 0;
2498     if ( max_children <= 1 )
2499         return -1;
2500     if ( max_children >= 10000)
2501         max_children = 10000;
2502 
2503 
2504     g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2505     if ( !g_prefork_server )
2506         return -1;
2507     memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
2508 
2509     if ( fp != NULL )
2510         g_fnSelect = fp;
2511 
2512     s_ppid = getppid();
2513     pid = getpid();
2514     setpgid( pid, pid );
2515     g_prefork_server->m_iAvoidFork = avoidFork;
2516     g_prefork_server->m_iMaxChildren = max_children;
2517 
2518     g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
2519     g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2520     if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2521         g_prefork_server->m_iMaxIdleChildren = 1;
2522     g_prefork_server->m_iChildrenMaxIdleTime = 300;
2523     g_prefork_server->m_iMaxReqProcessTime = 3600;
2524     return 0;
2525 }
2526 
2527 void LSAPI_Set_Server_fd( int fd )
2528 {
2529     if( g_prefork_server )
2530         g_prefork_server->m_fd = fd;
2531 }
2532 
2533 
2534 static int lsapi_accept( int fdListen )
2535 {
2536     int         fd;
2537     int         nodelay = 1;
2538     socklen_t   len;
2539     char        achPeer[128];
2540 
2541     len = sizeof( achPeer );
2542     fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
2543     if ( fd != -1 )
2544     {
2545         if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
2546         {
2547             setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
2548                     (char *)&nodelay, sizeof(nodelay));
2549         }
2550 
2551         //OPTIMIZATION
2552         //if ( s_accept_notify )
2553         //    notify_req_received( fd );
2554     }
2555     return fd;
2556 
2557 }
2558 
2559 
2560 
2561 
2562 static int s_req_processed = 0;
2563 static int s_max_reqs = 10000;
2564 static int s_max_idle_secs = 300;
2565 
2566 static int s_stop;
2567 
2568 static void lsapi_cleanup(int signal)
2569 {
2570     s_stop = signal;
2571 }
2572 
2573 static lsapi_child_status * find_child_status( int pid )
2574 {
2575     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2576     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2577     while( pStatus < pEnd )
2578     {
2579         if ( pStatus->m_pid == pid )
2580         {
2581             if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
2582                 g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
2583             return pStatus;
2584         }
2585         ++pStatus;
2586     }
2587     return NULL;
2588 }
2589 
2590 
2591 
2592 static void lsapi_sigchild( int signal )
2593 {
2594     int status, pid;
2595     lsapi_child_status * child_status;
2596     while( 1 )
2597     {
2598         pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
2599         if ( pid <= 0 )
2600         {
2601             break;
2602         }
2603         if ( WIFSIGNALED( status ))
2604         {
2605             int sig_num = WTERMSIG( status );
2606             int dump = WCOREDUMP( status );
2607             fprintf( stderr, "Child process with pid: %d was killed by signal: %d, core dump: %d\n", pid, sig_num, dump );
2608         }
2609         if ( pid == s_pid_dump_debug_info )
2610         {
2611             pid = 0;
2612             continue;
2613         }
2614         child_status = find_child_status( pid );
2615         if ( child_status )
2616         {
2617             child_status->m_pid = 0;
2618             --g_prefork_server->m_iCurChildren;
2619 
2620         }
2621     }
2622     while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
2623             &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
2624         --g_prefork_server->m_pChildrenStatusCur;
2625 
2626 }
2627 
2628 static int lsapi_init_children_status()
2629 {
2630     int size = 4096;
2631 
2632     char * pBuf;
2633     size = (g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren ) * sizeof( lsapi_child_status ) * 2;
2634     size = (size + 4095 ) / 4096 * 4096;
2635     pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
2636         MAP_ANON | MAP_SHARED, -1, 0 );
2637     if ( pBuf == MAP_FAILED )
2638     {
2639         perror( "Anonymous mmap() failed" );
2640         return -1;
2641     }
2642     memset( pBuf, 0, size );
2643     g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2644     g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
2645     g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + size / sizeof( lsapi_child_status );
2646     return 0;
2647 }
2648 
2649 static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
2650 {
2651     char achCmd[1024];
2652     if ( s_pid_dump_debug_info )
2653     {
2654         if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
2655             return;
2656     }
2657     s_pid_dump_debug_info = fork();
2658 
2659     fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n",
2660                 ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter,
2661                 tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
2662     snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" -ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid );
2663     if ( system( achCmd ) == -1 )
2664         perror( "system()" );
2665     exit( 0 );
2666 }
2667 
2668 static void lsapi_check_child_status( long tmCur )
2669 {
2670     int idle = 0;
2671     int tobekilled;
2672     int dying = 0;
2673     int count = 0;
2674     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2675     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
2676     while( pStatus < pEnd )
2677     {
2678         tobekilled = 0;
2679         if ( pStatus->m_pid != 0 )
2680         {
2681             ++count;
2682             if ( !pStatus->m_inProcess )
2683             {
2684 
2685                 if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
2686                     ( idle > g_prefork_server->m_iMaxIdleChildren ))
2687                 {
2688                     ++pStatus->m_iKillSent;
2689                     //tobekilled = SIGUSR1;
2690                 }
2691                 else
2692                 {
2693                     if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
2694                     {
2695                         ++pStatus->m_iKillSent;
2696                         //tobekilled = SIGUSR1;
2697                     }
2698                 }
2699                 if ( !tobekilled )
2700                     ++idle;
2701             }
2702             else
2703             {
2704                 if ( tmCur - pStatus->m_tmReqBegin >
2705                         g_prefork_server->m_iMaxReqProcessTime )
2706                 {
2707                     if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info ))
2708                         dump_debug_info( pStatus, tmCur );
2709                     if ( pStatus->m_iKillSent > 5 )
2710                     {
2711                         tobekilled = SIGKILL;
2712                         fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid );
2713                     }
2714                     else
2715                     {
2716                         tobekilled = SIGTERM;
2717                         fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid );
2718                     }
2719                 }
2720             }
2721             if ( tobekilled )
2722             {
2723                 if (( kill( pStatus->m_pid, tobekilled ) == -1 )&&( errno == ESRCH ))
2724                 {
2725                     pStatus->m_pid = 0;
2726                     --count;
2727                 }
2728                 else
2729                 {
2730                     ++pStatus->m_iKillSent;
2731                     ++dying;
2732                 }
2733             }
2734         }
2735         ++pStatus;
2736     }
2737     if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
2738     {
2739         fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Children: %d, count: %d, idle: %d, dying: %d\n", getpid(),
2740                 g_prefork_server->m_iCurChildren, count, idle, dying );
2741 
2742     }
2743 }
2744 
2745 static int lsapi_all_children_must_die()
2746 {
2747     int maxWait;
2748     int sec =0;
2749     g_prefork_server->m_iMaxReqProcessTime = 10;
2750     g_prefork_server->m_iMaxIdleChildren = -1;
2751     maxWait = 15;
2752 
2753     while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
2754     {
2755         lsapi_check_child_status(time(NULL));
2756         sleep( 1 );
2757         sec++;
2758     }
2759     if ( g_prefork_server->m_iCurChildren != 0 )
2760         kill( -getpgrp(), SIGKILL );
2761     return 0;
2762 }
2763 
2764 
2765 
2766 static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq )
2767 {
2768     struct sigaction act, old_term, old_quit, old_int,
2769                     old_usr1, old_child;
2770     lsapi_child_status * child_status;
2771     int             wait_secs = 0;
2772     int             ret = 0;
2773     int             pid;
2774     time_t          lastTime = 0;
2775     time_t          curTime = 0;
2776     fd_set          readfds;
2777     struct timeval  timeout;
2778 
2779     sigset_t mask;
2780     sigset_t orig_mask;
2781 
2782     lsapi_init_children_status();
2783 
2784     setsid();
2785 
2786     act.sa_flags = 0;
2787     act.sa_handler = lsapi_sigchild;
2788     if( sigaction( SIGCHLD, &act, &old_child ) )
2789     {
2790         perror( "Can't set signal handler for SIGCHILD" );
2791         return -1;
2792     }
2793 
2794     /* Set up handler to kill children upon exit */
2795     act.sa_flags = 0;
2796     act.sa_handler = lsapi_cleanup;
2797     if( sigaction( SIGTERM, &act, &old_term ) ||
2798         sigaction( SIGINT,  &act, &old_int  ) ||
2799         sigaction( SIGUSR1, &act, &old_usr1 ) ||
2800         sigaction( SIGQUIT, &act, &old_quit ))
2801     {
2802         perror( "Can't set signals" );
2803         return -1;
2804     }
2805     s_stop = 0;
2806     while( !s_stop )
2807     {
2808         curTime = time( NULL );
2809         if (curTime != lastTime )
2810         {
2811             lastTime = curTime;
2812             if (s_ppid && (getppid() != s_ppid ))
2813                 break;
2814             lsapi_check_child_status(curTime );
2815             if (pServer->m_iServerMaxIdle)
2816             {
2817                 if ( pServer->m_iCurChildren <= 0 )
2818                 {
2819                     ++wait_secs;
2820                     if ( wait_secs > pServer->m_iServerMaxIdle )
2821                         return -1;
2822                 }
2823                 else
2824                     wait_secs = 0;
2825             }
2826         }
2827 
2828         if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) )
2829         {
2830             fprintf( stderr, "Reached max children process limit: %d, extra: %d, current: %d, please increase LSAPI_CHILDREN.\n",
2831                                 pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren );
2832             usleep( 100000 );
2833             continue;
2834         }
2835 
2836         FD_ZERO( &readfds );
2837         FD_SET( pServer->m_fd, &readfds );
2838         timeout.tv_sec = 1; timeout.tv_usec = 0;
2839         if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 )
2840         {
2841             /*
2842             if ( pServer->m_iCurChildren >= 0 )
2843             {
2844                 usleep( 10 );
2845                 FD_ZERO( &readfds );
2846                 FD_SET( pServer->m_fd, &readfds );
2847                 timeout.tv_sec = 0; timeout.tv_usec = 0;
2848                 if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 )
2849                     continue;
2850             }*/
2851         }
2852         else if ( ret == -1 )
2853         {
2854             if ( errno == EINTR )
2855                 continue;
2856             /* perror( "select()" ); */
2857             break;
2858         }
2859         else
2860         {
2861             continue;
2862         }
2863 
2864         pReq->m_fd = lsapi_accept( pServer->m_fd );
2865         if ( pReq->m_fd != -1 )
2866         {
2867             child_status = find_child_status( 0 );
2868             if ( child_status )
2869                 memset( child_status, 0, sizeof( *child_status ) );
2870 
2871             sigemptyset( &mask );
2872             sigaddset( &mask, SIGCHLD );
2873 
2874             if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
2875             {
2876                 perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
2877             }
2878 
2879             pid = fork();
2880 
2881             if ( !pid )
2882             {
2883                 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
2884                     perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
2885                 g_prefork_server = NULL;
2886                 s_ppid = getppid();
2887                 s_req_processed = 0;
2888                 s_pChildStatus = child_status;
2889                 lsapi_set_nblock( pReq->m_fd, 0 );
2890                 if ( pReq->m_fdListen != -1 )
2891                 {
2892                     close( pReq->m_fdListen );
2893                     pReq->m_fdListen = -1;
2894                 }
2895                 /* don't catch our signals */
2896                 sigaction( SIGCHLD, &old_child, 0 );
2897                 sigaction( SIGTERM, &old_term, 0 );
2898                 sigaction( SIGQUIT, &old_quit, 0 );
2899                 sigaction( SIGINT,  &old_int,  0 );
2900                 sigaction( SIGUSR1, &old_usr1, 0 );
2901                 //init_conn_key( pReq->m_fd );
2902                 lsapi_notify_pid( pReq->m_fd );
2903                 s_notified_pid = 1;
2904                 //if ( s_accept_notify )
2905                 //    return notify_req_received( pReq->m_fd );
2906                 return 0;
2907             }
2908             else if ( pid == -1 )
2909             {
2910                 perror( "fork() failed, please increase process limit" );
2911             }
2912             else
2913             {
2914                 ++pServer->m_iCurChildren;
2915                 if ( child_status )
2916                 {
2917                     child_status->m_pid = pid;
2918                     child_status->m_tmWaitBegin = curTime;
2919                     child_status->m_tmStart = curTime;
2920                 }
2921             }
2922             close( pReq->m_fd );
2923             pReq->m_fd = -1;
2924 
2925             if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
2926                 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
2927 
2928         }
2929         else
2930         {
2931             if (( errno == EINTR )||( errno == EAGAIN))
2932                 continue;
2933             perror( "accept() failed" );
2934             return -1;
2935         }
2936     }
2937     sigaction( SIGUSR1, &old_usr1, 0 );
2938     //kill( -getpgrp(), SIGUSR1 );
2939     //lsapi_all_children_must_die();  /* Sorry, children ;-) */
2940     return -1;
2941 
2942 }
2943 
2944 void lsapi_error( const char * pMessage, int err_no )
2945 {
2946     fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) );
2947 }
2948 
2949 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2950 {
2951     int             fd;
2952     int             ret;
2953     int             wait_secs;
2954     fd_set          readfds;
2955     struct timeval  timeout;
2956 
2957     LSAPI_Finish_r( pReq );
2958 
2959 
2960     if ( g_prefork_server )
2961     {
2962         if ( g_prefork_server->m_fd != -1 )
2963             if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
2964                 return -1;
2965     }
2966     if ( s_req_processed >= s_max_reqs )
2967         return -1;
2968 
2969     if ( s_pChildStatus )
2970     {
2971         s_pChildStatus->m_tmWaitBegin = time( NULL );
2972     }
2973 
2974 
2975     while( g_running )
2976     {
2977         if ( pReq->m_fd != -1 )
2978         {
2979             fd = pReq->m_fd;
2980         }
2981         else if ( pReq->m_fdListen != -1 )
2982             fd = pReq->m_fdListen;
2983         else
2984         {
2985             break;
2986         }
2987         wait_secs = 0;
2988         while( 1 )
2989         {
2990             if ( !g_running )
2991                 return -1;
2992             if ((s_req_processed)&&( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
2993                 return -1;
2994             FD_ZERO( &readfds );
2995             FD_SET( fd, &readfds );
2996             timeout.tv_sec = 1;
2997             timeout.tv_usec = 0;
2998             ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
2999             if ( ret == 0 )
3000             {
3001                 if ( s_pChildStatus )
3002                 {
3003                     s_pChildStatus->m_inProcess = 0;
3004                 }
3005                 ++wait_secs;
3006                 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
3007                     return -1;
3008                 if ( s_ppid &&( getppid() != s_ppid))
3009                     return -1;
3010             }
3011             else if ( ret == -1 )
3012             {
3013                 if ( errno == EINTR )
3014                     continue;
3015                 else
3016                     return -1;
3017             }
3018             else if ( ret >= 1 )
3019             {
3020                 if (s_req_processed && ( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
3021                     return -1;
3022                 if ( fd == pReq->m_fdListen )
3023                 {
3024                     pReq->m_fd = lsapi_accept( pReq->m_fdListen );
3025                     if ( pReq->m_fd != -1 )
3026                     {
3027                         fd = pReq->m_fd;
3028                         lsapi_set_nblock( fd, 0 );
3029                         //init_conn_key( pReq->m_fd );
3030                         if ( !s_keepListener )
3031                         {
3032                             close( pReq->m_fdListen );
3033                             pReq->m_fdListen = -1;
3034                         }
3035                         if ( s_accept_notify )
3036                             if ( notify_req_received( pReq->m_fd ) == -1 )
3037                                 return -1;
3038                     }
3039                     else
3040                     {
3041                         if (( errno == EINTR )||( errno == EAGAIN))
3042                             continue;
3043                         lsapi_error( "lsapi_accept() error", errno );
3044                         return -1;
3045                     }
3046                 }
3047                 else
3048                     break;
3049             }
3050         }
3051 
3052         if ( !readReq( pReq ) )
3053         {
3054             if ( s_pChildStatus )
3055             {
3056                 s_pChildStatus->m_iKillSent = 0;
3057                 s_pChildStatus->m_inProcess = 1;
3058                 ++s_pChildStatus->m_iReqCounter;
3059                 s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
3060             }
3061             ++s_req_processed;
3062             return 0;
3063         }
3064         lsapi_close( pReq->m_fd );
3065         pReq->m_fd = -1;
3066         LSAPI_Reset_r( pReq );
3067     }
3068     return -1;
3069 
3070 }
3071 
3072 void LSAPI_Set_Max_Reqs( int reqs )
3073 {   s_max_reqs = reqs;          }
3074 
3075 void LSAPI_Set_Max_Idle( int secs )
3076 {   s_max_idle_secs = secs;     }
3077 
3078 void LSAPI_Set_Max_Children( int maxChildren )
3079 {
3080     if ( g_prefork_server )
3081         g_prefork_server->m_iMaxChildren = maxChildren;
3082 }
3083 
3084 void LSAPI_Set_Extra_Children( int extraChildren )
3085 {
3086     if (( g_prefork_server )&&( extraChildren >= 0 ))
3087         g_prefork_server->m_iExtraChildren = extraChildren;
3088 }
3089 
3090 void LSAPI_Set_Max_Process_Time( int secs )
3091 {
3092     if (( g_prefork_server )&&( secs > 0 ))
3093         g_prefork_server->m_iMaxReqProcessTime = secs;
3094 }
3095 
3096 
3097 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
3098 {
3099     if (( g_prefork_server )&&( maxIdleChld > 0 ))
3100         g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
3101 }
3102 
3103 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
3104 {
3105     if ( g_prefork_server )
3106         g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
3107 }
3108 
3109 void LSAPI_Set_Slow_Req_Msecs( int msecs )
3110 {
3111     s_slow_req_msecs = msecs;
3112 }
3113 
3114 int  LSAPI_Get_Slow_Req_Msecs()
3115 {
3116     return s_slow_req_msecs;
3117 }
3118 
3119 
3120 void LSAPI_No_Check_ppid()
3121 {
3122     s_ppid = 0;
3123 }
3124 
3125 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3126 #include <crt_externs.h>
3127 #else
3128 extern char ** environ;
3129 #endif
3130 static void unset_lsapi_envs()
3131 {
3132     char **env;
3133 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3134     env = *_NSGetEnviron();
3135 #else
3136     env = environ;
3137 #endif
3138     while( env != NULL && *env != NULL )
3139     {
3140         if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3141             || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3142         {
3143             char ** del = env;
3144             do
3145                 *del = del[1];
3146             while( *del++ );
3147         }
3148         else
3149             ++env;
3150     }
3151 }
3152 
3153 static int lsapi_initSuEXEC()
3154 {
3155     int i;
3156     struct passwd * pw;
3157     s_defaultUid = 0;
3158     s_defaultGid = 0;
3159     if ( s_uid == 0 )
3160     {
3161         const char * p = getenv( "LSAPI_DEFAULT_UID" );
3162         if ( p )
3163         {
3164             i = atoi( p );
3165             if ( i > 0 )
3166                 s_defaultUid = i;
3167         }
3168         p = getenv( "LSAPI_DEFAULT_GID" );
3169         if ( p )
3170         {
3171             i = atoi( p );
3172             if ( i > 0 )
3173                 s_defaultGid = i;
3174         }
3175         p = getenv( "LSAPI_SECRET" );
3176         if (( !p )||( readSecret(p) == -1 ))
3177                 return -1;
3178         if ( g_prefork_server )
3179         {
3180             if ( g_prefork_server->m_iMaxChildren < 100 )
3181                 g_prefork_server->m_iMaxChildren = 100;
3182             if ( g_prefork_server->m_iExtraChildren < 1000 )
3183                 g_prefork_server->m_iExtraChildren = 1000;
3184         }
3185     }
3186     if ( !s_defaultUid || !s_defaultGid )
3187     {
3188         pw = getpwnam( "nobody" );
3189         if ( pw )
3190         {
3191             if ( !s_defaultUid )
3192                 s_defaultUid = pw->pw_uid;
3193             if ( !s_defaultGid )
3194                 s_defaultGid = pw->pw_gid;
3195         }
3196         else
3197         {
3198             if ( !s_defaultUid )
3199                 s_defaultUid = 10000;
3200             if ( !s_defaultGid )
3201                 s_defaultGid = 10000;
3202         }
3203     }
3204     return 0;
3205 }
3206 
3207 
3208 int LSAPI_Init_Env_Parameters( fn_select_t fp )
3209 {
3210     const char *p;
3211     int n;
3212     int avoidFork = 0;
3213     p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
3214     if ( !p )
3215         p = getenv( "LSAPI_MAX_REQS" );
3216     if ( p )
3217     {
3218         n = atoi( p );
3219         if ( n > 0 )
3220             LSAPI_Set_Max_Reqs( n );
3221     }
3222 
3223     p = getenv( "LSAPI_AVOID_FORK" );
3224     if ( p )
3225     {
3226         avoidFork = atoi( p );
3227     }
3228 
3229     p = getenv( "LSAPI_ACCEPT_NOTIFY" );
3230     if ( p )
3231     {
3232         s_accept_notify = atoi( p );
3233     }
3234 
3235     p = getenv( "LSAPI_SLOW_REQ_MSECS" );
3236     if ( p )
3237     {
3238         n = atoi( p );
3239         LSAPI_Set_Slow_Req_Msecs( n );
3240     }
3241 
3242 #if defined( RLIMIT_CORE )
3243     p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
3244     if ( !p )
3245     {
3246         struct rlimit limit = { 0, 0 };
3247         setrlimit( RLIMIT_CORE, &limit );
3248     }
3249     else
3250         s_enable_core_dump = 1;
3251 
3252 #endif
3253 
3254     p = getenv( "LSAPI_MAX_IDLE" );
3255     if ( p )
3256     {
3257         n = atoi( p );
3258         LSAPI_Set_Max_Idle( n );
3259     }
3260 
3261     p = getenv( "LSAPI_KEEP_LISTEN" );
3262     if ( p )
3263     {
3264         n = atoi( p );
3265         s_keepListener = n;
3266     }
3267 
3268 
3269     if ( LSAPI_Is_Listen() )
3270     {
3271         n = 0;
3272         p = getenv( "PHP_LSAPI_CHILDREN" );
3273         if ( !p )
3274             p = getenv( "LSAPI_CHILDREN" );
3275         if ( p )
3276             n = atoi( p );
3277         if ( n > 1 )
3278         {
3279             LSAPI_Init_Prefork_Server( n, fp, avoidFork );
3280             LSAPI_Set_Server_fd( g_req.m_fdListen );
3281         }
3282 
3283         p = getenv( "LSAPI_EXTRA_CHILDREN" );
3284         if ( p )
3285             LSAPI_Set_Extra_Children( atoi( p ) );
3286 
3287         p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
3288         if ( p )
3289             LSAPI_Set_Max_Idle_Children( atoi( p ) );
3290 
3291         p = getenv( "LSAPI_PGRP_MAX_IDLE" );
3292         if ( p )
3293         {
3294             LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
3295         }
3296 
3297         p = getenv( "LSAPI_MAX_PROCESS_TIME" );
3298         if ( p )
3299             LSAPI_Set_Max_Process_Time( atoi( p ) );
3300 
3301         if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
3302         {
3303             LSAPI_No_Check_ppid();
3304         }
3305 
3306         p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
3307         if ( p )
3308             s_dump_debug_info = atoi( p );
3309 
3310         if ( lsapi_initSuEXEC() == -1 )
3311             return -1;
3312 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3313         lsapi_initLVE();
3314 #endif
3315     }
3316     unset_lsapi_envs();
3317     return 0;
3318 }
3319 
3320 
3321 int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
3322                          const char * pBody, int bodyLen )
3323 {
3324     LSAPI_SetRespStatus_r( pReq, code );
3325     if ( pRespHeaders )
3326     {
3327         while( *pRespHeaders )
3328         {
3329             LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
3330             ++pRespHeaders;
3331         }
3332     }
3333     if ( pBody &&( bodyLen > 0 ))
3334     {
3335         LSAPI_Write_r( pReq, pBody, bodyLen );
3336     }
3337     LSAPI_Finish_r( pReq );
3338     return 0;
3339 }
3340 
3341 
3342 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
3343 
3344 /*
3345  * Note: this code is harmless on little-endian machines.
3346  */
3347 static void byteReverse(unsigned char *buf, unsigned longs)
3348 {
3349     uint32 t;
3350     do {
3351         t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
3352             ((unsigned) buf[1] << 8 | buf[0]);
3353         *(uint32 *) buf = t;
3354         buf += 4;
3355     } while (--longs);
3356 }
3357 
3358 /*
3359  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
3360  * initialization constants.
3361  */
3362 void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
3363 {
3364     ctx->buf[0] = 0x67452301;
3365     ctx->buf[1] = 0xefcdab89;
3366     ctx->buf[2] = 0x98badcfe;
3367     ctx->buf[3] = 0x10325476;
3368 
3369     ctx->bits[0] = 0;
3370     ctx->bits[1] = 0;
3371 }
3372 
3373 /*
3374  * Update context to reflect the concatenation of another buffer full
3375  * of bytes.
3376  */
3377 void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
3378 {
3379     register uint32 t;
3380 
3381     /* Update bitcount */
3382 
3383     t = ctx->bits[0];
3384     if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
3385         ctx->bits[1]++;                /* Carry from low to high */
3386     ctx->bits[1] += len >> 29;
3387 
3388     t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
3389 
3390     /* Handle any leading odd-sized chunks */
3391 
3392     if (t) {
3393         unsigned char *p = (unsigned char *) ctx->in + t;
3394 
3395         t = 64 - t;
3396         if (len < t) {
3397             memmove(p, buf, len);
3398             return;
3399         }
3400         memmove(p, buf, t);
3401         byteReverse(ctx->in, 16);
3402         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3403         buf += t;
3404         len -= t;
3405     }
3406     /* Process data in 64-byte chunks */
3407 
3408     while (len >= 64) {
3409         memmove(ctx->in, buf, 64);
3410         byteReverse(ctx->in, 16);
3411         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3412         buf += 64;
3413         len -= 64;
3414     }
3415 
3416     /* Handle any remaining bytes of data. */
3417 
3418     memmove(ctx->in, buf, len);
3419 }
3420 
3421 /*
3422  * Final wrapup - pad to 64-byte boundary with the bit pattern
3423  * 1 0* (64-bit count of bits processed, MSB-first)
3424  */
3425 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
3426 {
3427     unsigned int count;
3428     unsigned char *p;
3429 
3430     /* Compute number of bytes mod 64 */
3431     count = (ctx->bits[0] >> 3) & 0x3F;
3432 
3433     /* Set the first char of padding to 0x80.  This is safe since there is
3434        always at least one byte free */
3435     p = ctx->in + count;
3436     *p++ = 0x80;
3437 
3438     /* Bytes of padding needed to make 64 bytes */
3439     count = 64 - 1 - count;
3440 
3441     /* Pad out to 56 mod 64 */
3442     if (count < 8) {
3443         /* Two lots of padding:  Pad the first block to 64 bytes */
3444         memset(p, 0, count);
3445         byteReverse(ctx->in, 16);
3446         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3447 
3448         /* Now fill the next block with 56 bytes */
3449         memset(ctx->in, 0, 56);
3450     } else {
3451         /* Pad block to 56 bytes */
3452         memset(p, 0, count - 8);
3453     }
3454     byteReverse(ctx->in, 14);
3455 
3456     /* Append length in bits and transform */
3457     ((uint32 *) ctx->in)[14] = ctx->bits[0];
3458     ((uint32 *) ctx->in)[15] = ctx->bits[1];
3459 
3460     lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3461     byteReverse((unsigned char *) ctx->buf, 4);
3462     memmove(digest, ctx->buf, 16);
3463     memset(ctx, 0, sizeof(*ctx));        /* In case it's sensitive */
3464 }
3465 
3466 /* The four core functions - F1 is optimized somewhat */
3467 
3468 /* #define F1(x, y, z) (x & y | ~x & z) */
3469 #define F1(x, y, z) (z ^ (x & (y ^ z)))
3470 #define F2(x, y, z) F1(z, x, y)
3471 #define F3(x, y, z) (x ^ y ^ z)
3472 #define F4(x, y, z) (y ^ (x | ~z))
3473 
3474 /* This is the central step in the MD5 algorithm. */
3475 #define MD5STEP(f, w, x, y, z, data, s) \
3476         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
3477 
3478 /*
3479  * The core of the MD5 algorithm, this alters an existing MD5 hash to
3480  * reflect the addition of 16 longwords of new data.  MD5Update blocks
3481  * the data and converts bytes into longwords for this routine.
3482  */
3483 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
3484 {
3485     register uint32 a, b, c, d;
3486 
3487     a = buf[0];
3488     b = buf[1];
3489     c = buf[2];
3490     d = buf[3];
3491 
3492     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
3493     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
3494     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
3495     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
3496     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
3497     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
3498     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
3499     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
3500     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
3501     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
3502     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
3503     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
3504     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
3505     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
3506     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
3507     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
3508 
3509     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
3510     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
3511     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
3512     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
3513     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
3514     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
3515     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
3516     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
3517     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
3518     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
3519     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
3520     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
3521     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
3522     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
3523     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
3524     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
3525 
3526     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
3527     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
3528     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
3529     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
3530     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
3531     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
3532     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
3533     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
3534     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
3535     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
3536     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
3537     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
3538     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
3539     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
3540     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
3541     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
3542 
3543     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
3544     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
3545     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
3546     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
3547     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
3548     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
3549     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
3550     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
3551     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
3552     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
3553     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
3554     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
3555     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
3556     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
3557     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
3558     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
3559 
3560     buf[0] += a;
3561     buf[1] += b;
3562     buf[2] += c;
3563     buf[3] += d;
3564 }
3565 

/* [<][>][^][v][top][bottom][index][help] */