]> granicus.if.org Git - php/commitdiff
Update LiteSpeed SAPI code to V6.4
authorGeorge Wang <gwang@php.net>
Tue, 5 Nov 2013 21:14:49 +0000 (16:14 -0500)
committerGeorge Wang <gwang@php.net>
Thu, 10 Jul 2014 18:42:05 +0000 (14:42 -0400)
Conflicts:
sapi/litespeed/lsapi_main.c
sapi/litespeed/lsapidef.h
sapi/litespeed/lsapilib.c
sapi/litespeed/lsapilib.h

sapi/litespeed/lsapi_main.c
sapi/litespeed/lsapidef.h
sapi/litespeed/lsapilib.c
sapi/litespeed/lsapilib.h

index 84e870d6285038c66cf729073de0ea5c282289ec..bc236bafab8f4bf585ed7c7ecf383b9846dbc09d 100644 (file)
@@ -16,8 +16,6 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id$ */
-
 #include "php.h"
 #include "SAPI.h"
 #include "php_main.h"
@@ -75,6 +73,7 @@ static int  lsapi_mode       = 1;
 static char *php_self        = "";
 static char *script_filename = "";
 static int  source_highlight = 0;
+static int  ignore_php_ini   = 0;
 static char * argv0 = NULL;
 static int  engine = 1;
 #ifdef ZTS
@@ -289,7 +288,7 @@ static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC)
 static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
 {
     if ( lsapi_mode ) {
-        return LSAPI_ReadReqBody( buffer, count_bytes );
+        return LSAPI_ReadReqBody( buffer, (unsigned long long)count_bytes );
     } else {
         return 0;
     }
@@ -353,7 +352,14 @@ static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  */
 static void sapi_lsapi_log_message(char *message TSRMLS_DC)
 {
+    char buf[8192];
     int len = strlen( message );
+    if ( *(message + len - 1 ) != '\n' )
+    {
+        snprintf( buf, 8191, "%s\n", message );
+        message = buf;
+        ++len;
+    }
     LSAPI_Write_Stderr( message, len);
 }
 /* }}} */
@@ -364,7 +370,7 @@ static void sapi_lsapi_log_message(char *message TSRMLS_DC)
 static sapi_module_struct lsapi_sapi_module =
 {
     "litespeed",
-    "LiteSpeed V5.5",
+    "LiteSpeed V6.4",
 
     php_lsapi_startup,              /* startup */
     php_module_shutdown_wrapper,    /* shutdown */
@@ -520,7 +526,7 @@ static int lsapi_module_main(int show_source TSRMLS_DC)
     }
     zend_try {
         php_request_shutdown(NULL);
-        *argv0 = 0;
+        memset( argv0, 0, 46 );
     } zend_end_try();
     return 0;
 }
@@ -558,10 +564,12 @@ static void override_ini()
 
 }
 
+
 static int processReq( TSRMLS_D )
 {
     int ret = 0;
     zend_first_try {
+
         /* avoid server_context==NULL checks */
         SG(server_context) = (void *) 1;
 
@@ -587,14 +595,16 @@ static void cli_usage( TSRMLS_D )
 {
     static const char * usage =
         "Usage: php\n"
-        "      php -[b|c|h|i|q|s|v|?] [<file>] [args...]\n"
+        "      php -[b|c|n|h|i|q|s|v|?] [<file>] [args...]\n"
         "  Run in LSAPI mode, only '-b', '-s' and '-c' are effective\n"
         "  Run in Command Line Interpreter mode when parameters are specified\n"
         "\n"
         "  -b <address:port>|<port> Bind Path for external LSAPI Server mode\n"
         "  -c <path>|<file> Look for php.ini file in this directory\n"
+        "  -n    No php.ini file will be used\n"
         "  -h    This help\n"
         "  -i    PHP information\n"
+        "  -l    Syntax check\n"
         "  -q    Quiet-mode.  Suppress HTTP Header output.\n"
         "  -s    Display colour syntax highlighted source.\n"
         "  -v    Version number\n"
@@ -626,7 +636,7 @@ static int parse_opt( int argc, char * argv[], int *climode,
                 fprintf( stderr, "TCP or socket address must be specified following '-b' option.\n");
                 return -1;
             }
-            *php_bind = *p++;
+            *php_bind = strdup(*p++);
             break;
             
         case 'c':
@@ -635,16 +645,22 @@ static int parse_opt( int argc, char * argv[], int *climode,
 
                 return -1;
             }
-            *php_ini_path = *p++;
+            *php_ini_path = strdup( *p++ );
             break;
         case 's':
             source_highlight = 1;
-            break;    
+            break;
+        case 'n':
+            ignore_php_ini = 1;
+            break;
+        case '?':
+            if ( *((*(p-1))+2) == 's' )
+                exit( 99 );
         case 'h':
         case 'i':
+        case 'l':
         case 'q':
         case 'v':
-        case '?':
         default:
             *climode = 1;
             break;
@@ -674,7 +690,7 @@ static int cli_main( int argc, char * argv[] )
     const char ** ini;
     char ** p = &argv[1];
     char ** argend= &argv[argc];
-    int ret = 0;
+    int ret = -1;
     int c;
     lsapi_mode = 0;        /* enter CLI mode */
 
@@ -713,8 +729,8 @@ static int cli_main( int argc, char * argv[] )
                     php_end_ob_buffers(1 TSRMLS_CC);
 #endif
                     php_request_shutdown( NULL );
+                    ret = 0;
                 }
-                ret = 1;
                 break;
             case 'v':
                 if (php_request_startup(TSRMLS_C) != FAILURE) {
@@ -729,25 +745,27 @@ static int cli_main( int argc, char * argv[] )
                     php_end_ob_buffers(1 TSRMLS_CC);
 #endif
                     php_request_shutdown( NULL );
+                    ret = 0;
                 }
-                ret = 1;
                 break;
             case 'c':
                 ++p;
             /* fall through */
             case 's':
                 break;
-                
+            case 'l':
+                source_highlight = 2;
+                break;
             case 'h':
             case '?':
             default:
                 cli_usage(TSRMLS_C);
-                ret = 1;
+                ret = 0;
                 break;
 
             }
         }
-        if ( !ret ) {
+        if ( ret == -1 ) {
             if ( *p ) {
                 zend_file_handle file_handle = {0};
 
@@ -766,18 +784,30 @@ static int cli_main( int argc, char * argv[] )
                         fclose( file_handle.handle.fp );
                         ret = 2;
                     } else {
-                        if (source_highlight) {
+                        if (source_highlight == 1) {
                             zend_syntax_highlighter_ini syntax_highlighter_ini;
                     
                             php_get_highlight_struct(&syntax_highlighter_ini);
                             highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC);
+                        } else if (source_highlight == 2) {
+                            file_handle.filename = *p;
+                            file_handle.free_filename = 0;
+                            file_handle.opened_path = NULL;
+                            ret = php_lint_script(&file_handle TSRMLS_CC);
+                            if (ret==SUCCESS) {
+                                zend_printf("No syntax errors detected in %s\n", file_handle.filename);
+                            } else {
+                                zend_printf("Errors parsing %s\n", file_handle.filename);
+                            }
+                            
                         } else {
                             file_handle.filename = *p;
                             file_handle.free_filename = 0;
                             file_handle.opened_path = NULL;
 
                             php_execute_script(&file_handle TSRMLS_CC);
-                        }
+                            ret = EG(exit_status);
+                       }
 
                         php_request_shutdown( NULL );
                     }
@@ -858,7 +888,25 @@ void start_children( int children )
     exit( 0 );
 }
 
-
+void setArgv0( int argc, char * argv[] )
+{
+    char * p;
+    int i;
+    argv0 = argv[0] + strlen( argv[0] );
+    p = argv0;
+    while(( p > argv[0] )&&( p[-1] != '/'))
+        --p;
+    if ( p > argv[0] )
+    {
+        memmove( argv[0], p, argv0 - p );
+        memset( argv[0] + ( argv0 - p ), 0, p - argv[0] );
+        argv0 = argv[0] + (argv0 - p);
+    }
+    for( i = 1; i < argc; ++i )
+    {
+        memset( argv[i], 0, strlen( argv[i] ) );
+    }
+}
 
 #include <fcntl.h>
 int main( int argc, char * argv[] )
@@ -868,7 +916,6 @@ int main( int argc, char * argv[] )
 
     char * php_ini_path = NULL;
     char * php_bind     = NULL;
-    char * p;
     int n;
     int climode = 0;
     struct timeval tv_req_begin;
@@ -894,8 +941,10 @@ int main( int argc, char * argv[] )
     }
     if ( climode ) {
         lsapi_sapi_module.phpinfo_as_text = 1;
+    } else {
+        setArgv0(argc, argv );
     }
-    argv0 = argv[0] + strlen( argv[0] );
+
     sapi_startup(&lsapi_sapi_module);
 
 #ifdef ZTS
@@ -909,6 +958,9 @@ int main( int argc, char * argv[] )
 #endif
 
     lsapi_sapi_module.executable_location = argv[0];
+    
+    if ( ignore_php_ini )
+        lsapi_sapi_module.php_ini_ignore = 1;
 
     if ( php_ini_path ) {
         lsapi_sapi_module.php_ini_path_override = php_ini_path;
@@ -949,6 +1001,8 @@ int main( int argc, char * argv[] )
 
     if ( php_bind ) {
         LSAPI_No_Check_ppid();
+        free( php_bind );
+        php_bind = NULL;
     }
 
     while( LSAPI_Prefork_Accept_r( &g_req ) >= 0 ) {
@@ -986,27 +1040,23 @@ int main( int argc, char * argv[] )
 
 /*   LiteSpeed PHP module starts here */
 
-#if PHP_MAJOR_VERSION > 4
-
 /* {{{ arginfo */
 ZEND_BEGIN_ARG_INFO(arginfo_litespeed__void, 0)
 ZEND_END_ARG_INFO()
 /* }}} */
 
-#else
-#define arginfo_litespeed__void NULL
-#endif
-
 PHP_FUNCTION(litespeed_request_headers);
 PHP_FUNCTION(litespeed_response_headers);
+PHP_FUNCTION(apache_get_modules);
 
 PHP_MINFO_FUNCTION(litespeed);
 
 zend_function_entry litespeed_functions[] = {
-    PHP_FE(litespeed_request_headers,     arginfo_litespeed__void)
-    PHP_FE(litespeed_response_headers,     arginfo_litespeed__void)
-    PHP_FALIAS(getallheaders,             litespeed_request_headers,     arginfo_litespeed__void)
-    PHP_FALIAS(apache_request_headers,     litespeed_request_headers,     arginfo_litespeed__void)
+    PHP_FE(litespeed_request_headers,   arginfo_litespeed__void)
+    PHP_FE(litespeed_response_headers,  arginfo_litespeed__void)
+    PHP_FE(apache_get_modules,          arginfo_litespeed__void)
+    PHP_FALIAS(getallheaders,           litespeed_request_headers,  arginfo_litespeed__void)
+    PHP_FALIAS(apache_request_headers,  litespeed_request_headers,  arginfo_litespeed__void)
     PHP_FALIAS(apache_response_headers, litespeed_response_headers, arginfo_litespeed__void)
     {NULL, NULL, NULL}
 };
@@ -1055,8 +1105,7 @@ PHP_FUNCTION(litespeed_request_headers)
     }
     array_init(return_value);
 
-    if ( lsapi_mode )
-        LSAPI_ForeachOrgHeader( add_associate_array, return_value );
+    LSAPI_ForeachOrgHeader( add_associate_array, return_value );
 
 }
 /* }}} */
@@ -1106,6 +1155,23 @@ PHP_FUNCTION(litespeed_response_headers)
 /* }}} */
 
 
+/* {{{ proto array apache_get_modules(void)
+   Fetch all loaded module names  */
+PHP_FUNCTION(apache_get_modules)
+{
+    /* TODO: */
+    if (ZEND_NUM_ARGS() > 0) {
+        WRONG_PARAM_COUNT;
+    }
+    array_init(return_value);
+    add_next_index_string(return_value, "mod_rewrite", 1);
+    add_next_index_string(return_value, "mod_mime", 1);
+    add_next_index_string(return_value, "mod_headers", 1);
+    add_next_index_string(return_value, "mod_expires", 1);
+}
+/* }}} */
+
+
 /*
  * Local variables:
  * tab-width: 4
index 3bdadac1d1c434557609723bbddc03f0c0e0d720..fb75d01a176251acd0a574a5929d9caaa6975daf 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
    +----------------------------------------------------------------------+
    | PHP Version 5                                                        |
@@ -17,9 +16,8 @@
    +----------------------------------------------------------------------+
 */
 
-
 /*
-Copyright (c) 2007, Lite Speed Technologies Inc.
+Copyright (c) 2002-2014, Lite Speed Technologies Inc.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -113,12 +111,14 @@ enum
 #define LSAPI_RESP_END              5
 #define LSAPI_STDERR_STREAM         6
 #define LSAPI_REQ_RECEIVED          7
+#define LSAPI_CONN_CLOSE            8
+#define LSAPI_INTERNAL_ERROR        9
 
 
 #define LSAPI_MAX_HEADER_LEN        65535
 #define LSAPI_MAX_DATA_PACKET_LEN   16384
 
-#define LSAPI_RESP_HTTP_HEADER_MAX  4096
+#define LSAPI_RESP_HTTP_HEADER_MAX  32768
 #define LSAPI_PACKET_HEADER_LEN     8
 
 
index 1bb16b3268d7ec680fb12feb1ef8029bf7ae6b86..8a10ac62cdc9fba0b927ed4e6ac339ccbaa25f2c 100644 (file)
    +----------------------------------------------------------------------+
 */
 
-/* $Id$ */
-
 /*
-Copyright (c) 2007, Lite Speed Technologies Inc.
+Copyright (c) 2002-2014, Lite Speed Technologies Inc.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -50,17 +48,21 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
 
-#include <lsapilib.h>
+/***************************************************************************
+                          lsapilib.c  -  description
+                             -------------------
+    begin                : Mon Feb 21 2005
+    copyright            : (C) 2005 by George Wang
+    email                : gwang@litespeedtech.com
+ ***************************************************************************/
+
 
 #include <ctype.h>
+#include <dlfcn.h>
 #include <errno.h>
 #include <fcntl.h>
 
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/un.h>
+#include <sys/stat.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -71,8 +73,48 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <sys/time.h>
 #include <sys/uio.h>
 #include <sys/wait.h>
+#include <grp.h>
+#include <pwd.h>
 #include <time.h>
 #include <unistd.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/un.h>
+
+#include "lsapilib.h"
+
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+#include <sys/prctl.h>
+#endif
+
+#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
+    || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+#include <sys/sysctl.h>
+#endif
+
+#include <inttypes.h>
+#ifndef uint32
+#define uint32 uint32_t
+#endif
+
+struct lsapi_MD5Context {
+    uint32 buf[4];
+    uint32 bits[2];
+    unsigned char in[64];
+};
+
+void lsapi_MD5Init(struct lsapi_MD5Context *context);
+void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
+           unsigned len);
+void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
+
+/*
+ * This is needed to make RSAREF happy on some MS-DOS compilers.
+ */
+typedef struct lsapi_MD5Context lsapi_MD5_CTX;
+
 
 #define LSAPI_ST_REQ_HEADER     1
 #define LSAPI_ST_REQ_BODY       2
@@ -83,12 +125,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define LSAPI_INIT_RESP_HEADER_LEN 4096
 
 
+
 static int g_inited = 0;
 static int g_running = 1;
 static int s_ppid;
 static int s_slow_req_msecs = 0;
+static int s_keepListener = 0;
+static int s_dump_debug_info = 0;
+static int s_pid_dump_debug_info = 0;
+
 LSAPI_Request g_req = { -1, -1 };
 
+static char         s_pSecret[24];
+
+
 void Flush_RespBuf_r( LSAPI_Request * pReq );
 
 static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
@@ -112,13 +162,13 @@ static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
     "HTTP_TRANSFER_ENCODING"
 };
      
-static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = {
-     11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
-     22, 13, 18, 13, 24, 15, 10, 20, 8, 22 
-};
+static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
+{    11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
+     22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
 
 
-static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = {
+static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
+{
     "Accept", "Accept-Charset",
     "Accept-Encoding",
     "Accept-Language", "Authorization",
@@ -138,8 +188,8 @@ static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = {
     "Transfer-Encoding"
 };
 
-static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = {
-    6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, /* user-agent */
+static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
+{   6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
     13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
 };
      
@@ -161,7 +211,8 @@ static void lsapi_signal(int signo, sighandler_t handler)
 
     sigaction(signo, NULL, &sa);
 
-    if (sa.sa_handler == SIG_DFL) {
+    if (sa.sa_handler == SIG_DFL)
+    {
         sigemptyset(&sa.sa_mask);
         sa.sa_flags = 0;
         sa.sa_handler = handler;
@@ -170,6 +221,34 @@ static void lsapi_signal(int signo, sighandler_t handler)
 }
 
 
+static int s_enable_core_dump = 0;
+static void lsapi_enable_core_dump()
+{
+#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
+    || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+    int  mib[2];
+    size_t len;    
+
+    len = 2;
+    if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
+    {
+        len = sizeof(s_enable_core_dump);
+        if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
+            perror( "sysctl: Failed to set 'kern.sugid_coredump', "
+                    "core dump may not be available!");
+    }
+
+    
+#endif
+
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+    if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
+        perror( "prctl: Failed to set dumpable, "
+                    "core dump may not be available!");
+#endif
+}
+
+
 static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
                                 char type, int len )
 {
@@ -200,75 +279,115 @@ static  int lsapi_set_nblock( int fd, int nonblock )
     return 0;
 }
 
-
 static int lsapi_close( int fd )
 {
     int ret;
-    while( 1 ) {
+    while( 1 )
+    {
         ret = close( fd );
-        if (( ret == -1 )&&( errno == EINTR )&&(g_running)) {
+        if (( ret == -1 )&&( errno == EINTR )&&(g_running))
             continue;
-        }
         return ret;
     }
 }
 
-static inline int lsapi_read( int fd, void * pBuf, int len )
+static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
 {
-    int ret;
-    while( 1 ) {
+    ssize_t ret;
+    while( 1 )
+    {
         ret = read( fd, (char *)pBuf, len );
-        if (( ret == -1 )&&( errno == EINTR )&&(g_running)) {
+        if (( ret == -1 )&&( errno == EINTR )&&(g_running))
             continue;
-        }
         return ret;
     }
 }
 
+/*
+static int lsapi_write( int fd, const void * pBuf, int len )
+{
+   int ret;
+   const char * pCur;
+   const char * pEnd;
+   if ( len == 0 )
+       return 0;
+   pCur = (const char *)pBuf;
+   pEnd = pCur + len;
+   while( g_running && (pCur < pEnd) )
+   {
+       ret = write( fd, pCur, pEnd - pCur );
+       if ( ret >= 0)
+           pCur += ret;
+       else if (( ret == -1 )&&( errno != EINTR ))
+           return ret;
+   }
+   return pCur - (const char *)pBuf;
+}
+*/
 
 static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
 {
     int ret;
     int left = totalLen;
     int n = count;
-    while(( left > 0 )&&g_running ) {
+    while(( left > 0 )&&g_running )
+    {
         ret = writev( fd, *pVec, n );
-        if ( ret > 0 ) {
+        if ( ret > 0 )
+        {
             left -= ret;
-            if (( left <= 0)||( !g_running )) {
+            if (( left <= 0)||( !g_running ))
                 return totalLen - left;
-            }
-            while( ret > 0 ) {
-                if ( (*pVec)->iov_len <= ret ) {
+            while( ret > 0 )
+            {
+                if ( (*pVec)->iov_len <= (unsigned int )ret )
+                {
                     ret -= (*pVec)->iov_len;
                     ++(*pVec);
-                } else {
+                }
+                else
+                {
                     (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
                     (*pVec)->iov_len -= ret;
                     break;
                 }
             }
-        } else if ( ret == -1 ) {
-            if ( errno == EAGAIN ) {
-                if ( totalLen - left > 0 ) {
+        }
+        else if ( ret == -1 )
+        {
+            if ( errno == EAGAIN )
+            {
+                if ( totalLen - left > 0 )
                     return totalLen - left;
-                } else {
+                else
                     return -1;
-                }
-            } else {
-                if ( errno != EINTR ) {
-                    return ret;
-                }
             }
+            else if ( errno != EINTR )
+                return ret;
         }
     }
     return totalLen - left;
 }
 
+/*
+static int getTotalLen( struct iovec * pVec, int count )
+{
+   struct iovec * pEnd = pVec + count;
+   int total = 0;
+   while( pVec < pEnd )
+   {
+       total += pVec->iov_len;
+       ++pVec;
+   }
+   return total;
+}
+*/
+
 static inline int allocateBuf( LSAPI_Request * pReq, int size )
 {
     char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
-    if ( pBuf ) {
+    if ( pBuf )
+    {
         pReq->m_pReqBuf = pBuf;
         pReq->m_reqBufSize = size;
         pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
@@ -282,9 +401,8 @@ static int allocateIovec( LSAPI_Request * pReq, int n )
 {
     struct iovec * p = (struct iovec *)realloc(
                 pReq->m_pIovec, sizeof(struct iovec) * n );
-    if ( !p ) {
+    if ( !p )
         return -1;
-    }
     pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
     pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
     pReq->m_pIovec = p;
@@ -295,9 +413,8 @@ static int allocateIovec( LSAPI_Request * pReq, int n )
 static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
 {
     char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
-    if ( !p ) {
+    if ( !p )
         return -1;
-    }
     pReq->m_pRespHeaderBufPos   = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
     pReq->m_pRespHeaderBuf      = p;
     pReq->m_pRespHeaderBufEnd   = p + size;
@@ -309,10 +426,10 @@ static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktTy
 {
     if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
         ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
-        ( pktType != pHeader->m_type )) {
+        ( pktType != pHeader->m_type ))
         return -1;
-    }
-    if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) {
+    if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
+    {
         register char b;
         b = pHeader->m_packetLen.m_bytes[0];
         pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
@@ -328,21 +445,20 @@ static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
                         int *curSize, int newSize )
 {
     struct LSAPI_key_value_pair * pBuf;
-    if ( *curSize >= newSize ) {
+        if ( *curSize >= newSize )
         return 0;
-    }
-    if ( newSize > 8192 ) {
+    if ( newSize > 8192 )
         return -1;
-    }
     pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
                     sizeof(struct LSAPI_key_value_pair) );
-    if ( pBuf ) {
+    if ( pBuf )
+    {
         *pEnvList = pBuf;
         *curSize  = newSize;
         return 0;
-    } else {
-        return -1;
     }
+    else
+        return -1;
 
 }
 
@@ -351,36 +467,32 @@ static inline int isPipe( int fd )
     char        achPeer[128];
     socklen_t   len = 128;
     if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
-        ( errno == ENOTCONN )) {
+        ( errno == ENOTCONN ))
         return 0;
-    } else {
+    else
         return 1;
-    }
 }
 
 static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
             char **pBegin, char * pEnd )
 {
     struct LSAPI_key_value_pair * pEnvEnd;
-    int keyLen = 0, valLen = 0;
-    if ( count > 8192 ) {
+        int keyLen = 0, valLen = 0;
+    if ( count > 8192 )
         return -1;
-    }
     pEnvEnd = pEnvList + count;
-    while( pEnvList != pEnvEnd ) {
-        if ( pEnd - *pBegin < 4 ) {
+    while( pEnvList != pEnvEnd )
+    {
+        if ( pEnd - *pBegin < 4 )
             return -1;
-        }
         keyLen = *((unsigned char *)((*pBegin)++));
         keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
         valLen = *((unsigned char *)((*pBegin)++));
         valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
-        if ( *pBegin + keyLen + valLen > pEnd ) {
+        if ( *pBegin + keyLen + valLen > pEnd )
             return -1;
-        }
-        if (( !keyLen )||( !valLen )) {
+        if (( !keyLen )||( !valLen ))
             return -1;
-        }
 
         pEnvList->pKey = *pBegin;
         *pBegin += keyLen;
@@ -391,9 +503,8 @@ static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
         pEnvList->valLen = valLen - 1;
         ++pEnvList;
     }
-    if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) {
+    if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
         return -1;
-    }
     *pBegin += 4;
     return 0;
 }
@@ -428,8 +539,10 @@ static inline void fixEndian( LSAPI_Request * pReq )
 static void fixHeaderIndexEndian( LSAPI_Request * pReq )
 {
     int i;
-    for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
-        if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
+    for( i = 0; i < H_TRANSFER_ENCODING; ++i )
+    {
+        if ( pReq->m_pHeaderIndex->m_headerOff[i] )
+        {
             register char b;
             char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
             b = p[0];
@@ -438,20 +551,434 @@ static void fixHeaderIndexEndian( LSAPI_Request * pReq )
             swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
         }
     }
-    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
+    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
+    {
         struct lsapi_header_offset * pCur, *pEnd;
         pCur = pReq->m_pUnknownHeader;
         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
-        while( pCur < pEnd ) {
+        while( pCur < pEnd )
+        {
             swapIntEndian( &pCur->nameOff );
             swapIntEndian( &pCur->nameLen );
             swapIntEndian( &pCur->valueOff );
             swapIntEndian( &pCur->valueLen );
             ++pCur;
         }
-    }    
+    }
+}
+
+static uid_t s_uid = 0;
+static uid_t s_defaultUid;  //web server need set this
+static gid_t s_defaultGid;
+
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+
+#define LSAPI_LVE_DISABLED  0
+#define LSAPI_LVE_ENABLED   1
+#define LSAPI_CAGEFS_ENABLED 2
+#define LSAPI_CAGEFS_NO_SUEXEC 3
+struct liblve;
+static int s_enable_lve = LSAPI_LVE_DISABLED;
+static struct liblve * s_lve = NULL;
+
+static void *s_liblve;
+static int (*fp_lve_is_available)(void) = NULL;
+static int (*fp_lve_instance_init)(struct liblve *) = NULL;
+static int (*fp_lve_destroy)(struct liblve *) = NULL;
+static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
+static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
+static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
+static int lsapi_load_lve_lib()
+{
+    s_liblve = dlopen("liblve.so.0", RTLD_LAZY);
+    if (s_liblve)
+    {
+        fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
+        if (dlerror() == NULL) 
+        {
+            if ( !(*fp_lve_is_available)() )
+            {
+                int uid = getuid();
+                if ( uid )
+                {
+                    setreuid( s_uid, uid );
+                    if ( !(*fp_lve_is_available)() )
+                        s_enable_lve = 0;
+                    setreuid( uid, s_uid );
+                }
+            }
+        }
+    }
+    else
+    {
+        s_enable_lve = LSAPI_LVE_DISABLED;
+    }
+    return (s_liblve)? 0 : -1;
+}
+
+static int init_lve_ex()
+{
+    int rc;
+    if ( !s_liblve )
+        return -1; 
+    fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
+    fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
+    fp_lve_enter = dlsym(s_liblve, "lve_enter");
+    fp_lve_leave = dlsym(s_liblve, "lve_leave");
+    if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
+        fp_lve_jail = dlsym(s_liblve, "jail" );
+
+    if ( s_lve == NULL ) 
+    {
+        rc = (*fp_lve_instance_init)(NULL);
+        s_lve = malloc(rc);
+    }
+    rc = (*fp_lve_instance_init)(s_lve);
+    if (rc != 0) 
+    {
+        perror( "LSAPI: Unable to initialize LVE" );
+        free( s_lve );
+        s_lve = NULL;
+        return -1;
+    }
+    return 0;
+    
+}
+
+#endif
+
+
+
+static int readSecret( const char * pSecretFile )
+{
+    struct stat st;
+    int fd = open( pSecretFile, O_RDONLY , 0600 );
+    if ( fd == -1 )
+    {
+        fprintf( stderr, "LSAPI: failed to open secret file: %s!\n", pSecretFile );
+        return -1;
+    }
+    if ( fstat( fd, &st ) == -1 )
+    {
+        fprintf( stderr, "LSAPI: failed to check state of file: %s!\n", pSecretFile );
+        close( fd );
+        return -1;
+    }
+/*
+    if ( st.st_uid != s_uid )
+    {
+        fprintf( stderr, "LSAPI: file owner check failure: %s!\n", pSecretFile );
+        close( fd );
+        return -1;
+    }
+*/
+    if ( st.st_mode & 0077 )
+    {
+        fprintf( stderr, "LSAPI: file permission check failure: %s\n", pSecretFile );
+        close( fd );
+        return -1;
+    }
+    if ( read( fd, s_pSecret, 16 ) < 16 )
+    {
+        fprintf( stderr, "LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
+        close( fd );
+        return -1;
+    }
+    close( fd );
+    return 0;
+}
+
+int LSAPI_is_suEXEC_Daemon()
+{
+    if (( !s_uid )&&( s_pSecret[0] ))
+        return 1;
+    else
+        return 0;
+}
+
+static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
+{
+    char achError[1024];
+    int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) );
+    if ( pReq )
+        LSAPI_Write_Stderr_r( pReq, achError, n );
+    else
+        write( STDERR_FILENO, achError, n );
+    return 0;
+}
+
+static int lsapi_lve_error( LSAPI_Request * pReq )
+{
+    static const char * headers[] = 
+    {
+        "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
+        "Pragma: no-cache",
+        "Retry-After: 60",
+        "Content-Type: text/html",
+        NULL
+    };
+    static const char achBody[] =
+        "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
+        "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
+        "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
+        "The website is temporarily unable to service your request as it exceeded resource limit.\n"
+        "Please try again later.\n"
+        "<HR>\n"
+        "</BODY></HTML>\n";
+     
+    LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
+    return 0;
+}
+
+static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
+{
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+    if ( s_lve && uid ) //root user should not do that
+    {
+        uint32_t cookie;
+        int ret = -1;
+        ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
+        if ( ret < 0 )
+        {
+            fprintf( stderr, "Pid (%d): enter LVE (%d) : ressult: %d !\n", getpid(), uid, ret );
+            LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
+            lsapi_lve_error( pReq );
+            return -1;
+        }
+    }
+#endif
+
+    return 0;
+}
+
+static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
+{
+    int ret = 0;
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+    char  error_msg[1024] = "";
+    ret = (*fp_lve_jail)( pw, error_msg );
+    if ( ret < 0 )
+    {
+        fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n", 
+                        getpid(), uid, ret, error_msg );
+        LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
+        return -1;
+    }
+#endif
+    return ret;
+}
+
+
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+static int lsapi_initLVE()
+{
+    const char * pEnv;
+    if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
+    {
+        s_enable_lve = atol( pEnv );
+        pEnv = NULL;
+    }
+    else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
+    {
+        s_enable_lve = atol( pEnv );
+        pEnv = NULL;
+    }
+    if ( s_enable_lve && !s_uid )
+    {
+        lsapi_load_lve_lib();
+        if ( s_enable_lve )
+        {
+            return init_lve_ex();
+        }
+
+    }
+    return 0;
+}
+#endif
+
+
+static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
+{
+    int rv;
+    struct passwd * pw;
+    pw = getpwuid( uid );
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+    if ( s_lve )
+    { 
+        if( lsapi_enterLVE( pReq, uid ) == -1 )
+            return -1;
+        if ( pw && fp_lve_jail)
+        {
+            rv = lsapi_jailLVE( pReq, uid, pw );
+            if ( rv == -1 )
+                return -1;
+            if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC ))    //this mode only use cageFS, does not use suEXEC
+            {
+                uid = s_defaultUid;
+                gid = s_defaultGid;
+                pw = getpwuid( uid );
+            }
+        }
+    }
+#endif
+    //if ( !uid || !gid )  //do not allow root 
+    //{
+    //    return -1;
+    //}
+
+#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
+    || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+    if ( s_enable_core_dump )
+        lsapi_enable_core_dump();
+#endif
+
+    rv = setgid(gid);
+    if (rv == -1)
+    {
+        LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
+        return -1;
+    }
+    if ( pw && (pw->pw_gid == gid ))
+    {
+        rv = initgroups( pw->pw_name, gid );
+        if (rv == -1)
+        {
+            LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
+            return -1;
+        }
+    }
+    else
+    {
+        rv = setgroups(1, &gid);
+        if (rv == -1)
+        {
+            LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
+        }
+    }
+    if ( pChroot )
+    {
+        rv = chroot( pChroot );
+        if ( rv == -1 )
+        {
+            LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
+            return -1;
+        }
+    }
+    rv = setuid(uid);
+    if (rv == -1)
+    {
+        LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
+        return -1;
+    }
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+    if ( s_enable_core_dump )
+        lsapi_enable_core_dump();
+#endif
+    return 0;
+}
+
+static int lsapi_suexec_auth( LSAPI_Request *pReq, 
+            char * pAuth, int len, char * pUgid, int ugidLen )
+{
+    lsapi_MD5_CTX md5ctx;
+    unsigned char achMD5[16];
+    if ( len < 32 )
+        return -1;
+    memmove( achMD5, pAuth + 16, 16 );
+    memmove( pAuth + 16, s_pSecret, 16 );
+    lsapi_MD5Init( &md5ctx );
+    lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
+    lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
+    lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
+    if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
+        return 0;
+    return 1;
+}
+
+
+static int lsapi_changeUGid( LSAPI_Request * pReq )
+{
+    int uid = s_defaultUid;
+    int gid = s_defaultGid;
+    const char * pChroot = NULL;
+    struct LSAPI_key_value_pair * pEnv;
+    struct LSAPI_key_value_pair * pAuth;
+    int i;
+    if ( s_uid )
+        return 0;
+    //with special ID  0x00
+    //authenticate the suEXEC request;
+    //first one should be MD5( nonce + lscgid secret )
+    //remember to clear the secret after verification 
+    //it should be set at the end of special env
+    i = pReq->m_pHeader->m_cntSpecialEnv - 1;
+    if ( i >= 0 )
+    {
+        pEnv = pReq->m_pSpecialEnvList + i;
+        if (( *pEnv->pKey == '\000' )&&
+            ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
+        {
+            --pReq->m_pHeader->m_cntSpecialEnv;
+            pAuth = pEnv--;
+            if (( *pEnv->pKey == '\000' )&&
+                ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
+            {
+                --pReq->m_pHeader->m_cntSpecialEnv;
+                uid = *(uint32_t *)pEnv->pValue;
+                gid = *(((uint32_t *)pEnv->pValue) + 1 ); 
+                //fprintf( stderr, "LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
+            }
+            else
+            {
+                fprintf( stderr, "LSAPI: missing SUEXEC_UGID env, use default user!\n" );
+                pEnv = NULL;
+            }
+            if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
+            {
+                //read UID, GID from specialEnv 
+                
+            }
+            else
+            {
+                //authentication error
+                fprintf( stderr, "LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
+                uid = 0;
+            }
+        }
+        else
+        {
+            //fprintf( stderr, "LSAPI: no SUEXEC_AUTH env, use default user!\n" );
+        }
+    }
+
+
+    if ( !uid )
+    {
+        uid = s_defaultUid;
+        gid = s_defaultGid;
+    }
+
+    //change uid
+    if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
+    {
+        return -1;
+    }
+
+    s_uid = uid;       
+
+    return 0;
+}
+
+static int parseContentLenFromHeader(LSAPI_Request * pReq)
+{
+    const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
+    if ( pContentLen )
+        pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
+    return 0;
 }
 
+
 static int parseRequest( LSAPI_Request * pReq, int totalLen )
 {
     int shouldFixEndian;
@@ -459,29 +986,28 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen )
     char * pEnd = pReq->m_pReqBuf + totalLen;
     shouldFixEndian = ( LSAPI_ENDIAN != (
                 pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
-    if ( shouldFixEndian ) {
+    if ( shouldFixEndian )
+    {
         fixEndian( pReq );
     }
     if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
             allocateEnvList( &pReq->m_pSpecialEnvList,
-                              &pReq->m_specialEnvListSize,
-                             pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) {
+                &pReq->m_specialEnvListSize,
+                pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
         return -1;
-    }
     if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
             allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
-                             pReq->m_pHeader->m_cntEnv ) == -1 ) {
+                pReq->m_pHeader->m_cntEnv ) == -1 )
         return -1;
-    }
+
     if ( parseEnv( pReq->m_pSpecialEnvList,
-                   pReq->m_pHeader->m_cntSpecialEnv,
-                   &pBegin, pEnd ) == -1 ) {
+                pReq->m_pHeader->m_cntSpecialEnv,
+                &pBegin, pEnd ) == -1 )
         return -1;
-    }
     if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
-                   &pBegin, pEnd ) == -1 ) {
+                &pBegin, pEnd ) == -1 )
         return -1;
-    }
+
     pReq->m_pScriptFile     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
     pReq->m_pScriptName     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
     pReq->m_pQueryString    = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
@@ -497,90 +1023,183 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen )
 
     pReq->m_pHttpHeader = pBegin;
     pBegin += pReq->m_pHeader->m_httpHeaderLen;
-    if ( pBegin != pEnd ) {
+    if ( pBegin != pEnd )
+    {
+        fprintf( stderr, "%d: request header does match total size, total: %d, real: %ld\n", getpid(), totalLen,
+                    pBegin - pReq->m_pReqBuf );
         return -1;
     }
-
-    if ( shouldFixEndian ) {
+    if ( shouldFixEndian )
+    {
         fixHeaderIndexEndian( pReq );
     }
-
+    pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
+    if ( pReq->m_reqBodyLen == -2 )
+    {
+        parseContentLenFromHeader(pReq);
+    }
+    
     return 0;
 }
 
-static int s_accept_notify = 0;
+//OPTIMIZATION
+static char s_accept_notify = 0;
+static char s_schedule_notify = 0;
+static char s_notify_scheduled = 0;
+static char s_notified_pid = 0;
 
-static struct lsapi_packet_header ack = {'L', 'S',
+static struct lsapi_packet_header s_ack = {'L', 'S',
                 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
-static inline int notify_req_received( int fd )
+
+
+static inline int write_req_received_notification( int fd )
 {
-    if ( write( fd, &ack, LSAPI_PACKET_HEADER_LEN )
-         < LSAPI_PACKET_HEADER_LEN ) {
+    if ( write( fd, &s_ack, LSAPI_PACKET_HEADER_LEN )
+                < LSAPI_PACKET_HEADER_LEN )
         return -1;
+    return 0;
+}
+
+static void lsapi_sigalarm( int sig )
+{
+    if ( s_notify_scheduled )
+    {
+        s_notify_scheduled = 0;
+        if ( g_req.m_fd != -1 )
+            write_req_received_notification( g_req.m_fd );
+    }
+}
+
+static inline int lsapi_schedule_notify()
+{
+    if ( !s_notify_scheduled )
+    {
+        alarm( 2 );
+        s_notify_scheduled = 1;
     }
     return 0;
 }
 
+static inline int notify_req_received( int fd )
+{
+    if ( s_schedule_notify )
+        return lsapi_schedule_notify();
+    return write_req_received_notification( fd );
+
+}
+
+
+static inline int lsapi_notify_pid( int fd )
+{
+    char achBuf[16];
+    lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
+                        8 + LSAPI_PACKET_HEADER_LEN );
+    memmove( &achBuf[8], "\0PID", 4 );
+    *((int *)&achBuf[12]) = getpid();
+    
+    if ( write( fd, achBuf, 16 ) < 16 )
+        return -1;
+    return 0;
+}
+
+static char s_conn_key_packet[16];
+static inline int init_conn_key( int fd )
+{
+    struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet;
+    struct timeval tv;
+    int i;
+    gettimeofday( &tv, NULL );
+    srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() );
+    for( i = 8; i < 16; ++i )
+    {
+        s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0));
+    }
+    lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED,
+                        8 + LSAPI_PACKET_HEADER_LEN );
+    if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 )
+                < LSAPI_PACKET_HEADER_LEN+8 )
+        return -1;
+    return 0;
+    
+
+}
 
 static int readReq( LSAPI_Request * pReq )
 {
     int len;
     int packetLen;
-    if ( !pReq ) {
+    if ( !pReq )
         return -1;
-    }
-    if ( pReq->m_reqBufSize < 8192 ) {
-        if ( allocateBuf( pReq, 8192 ) == -1 ) {
+    if ( pReq->m_reqBufSize < 8192 )
+    {
+        if ( allocateBuf( pReq, 8192 ) == -1 )
             return -1;
-        }
     }
 
-    while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) {
+    while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
+    {
         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
-        if ( len <= 0 ) {
+        if ( len <= 0 )
             return -1;
-        }
         pReq->m_bufRead += len;
     }
     pReq->m_reqState = LSAPI_ST_REQ_HEADER;
 
     packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
-    if ( packetLen < 0 ) {
+    if ( packetLen < 0 )
+    {
+        fprintf( stderr, "%d: packetLen < 0\n", getpid() );
         return -1;
     }
-    if ( packetLen > LSAPI_MAX_HEADER_LEN ) {
+    if ( packetLen > LSAPI_MAX_HEADER_LEN )
+    {
+        fprintf( stderr, "%d: packetLen > %d\n", getpid(), LSAPI_MAX_HEADER_LEN );
         return -1;
     }
 
-    if ( packetLen + 1024 > pReq->m_reqBufSize ) {
-        if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) {
+    if ( packetLen + 1024 > pReq->m_reqBufSize )
+    {
+        if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
             return -1;
-        }
     }
-    while( packetLen > pReq->m_bufRead ) {
+    while( packetLen > pReq->m_bufRead )
+    {
         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
-        if ( len <= 0 ) {
+        if ( len <= 0 )
             return -1;
-        }
         pReq->m_bufRead += len;
     }
-    if ( parseRequest( pReq, packetLen ) < 0 ) {
+    if ( parseRequest( pReq, packetLen ) < 0 )
+    {
+        fprintf( stderr, "%d: parseRequest error\n", getpid() );
         return -1;
     }
-    pReq->m_bufProcessed = packetLen;
+
     pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
 
-    if ( !s_accept_notify )
+    if ( !s_uid )
+        if ( lsapi_changeUGid( pReq ) )
+            return -1;
+    pReq->m_bufProcessed = packetLen;
+
+    //OPTIMIZATION
+    if ( !s_accept_notify && !s_notified_pid )
         return notify_req_received( pReq->m_fd );
     else
+    {
+        s_notified_pid = 0;
         return 0;
+    }
 }
 
 
 
 int LSAPI_Init(void)
 {
-    if ( !g_inited ) {
+    if ( !g_inited )
+    {
+        s_uid = geteuid();
+        s_pSecret[0] = 0;
         lsapi_signal(SIGPIPE, lsapi_sigpipe);
         lsapi_signal(SIGUSR1, lsapi_siguser1);
 
@@ -589,11 +1208,9 @@ int LSAPI_Init(void)
 #endif
         /* let STDOUT function as STDERR, 
            just in case writing to STDOUT directly */
-        dup2( 2, 1 );
-
-        if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) {
+        dup2( 2, 1 );  
+        if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
             return -1;
-        }
         g_inited = 1;
         s_ppid = getppid();
     }
@@ -612,28 +1229,27 @@ int LSAPI_IsRunning(void)
 
 int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
 {
-    if ( !pReq ) {
+    if ( !pReq )
         return -1;
-    }
     memset( pReq, 0, sizeof( LSAPI_Request ) );
-    if ( allocateIovec( pReq, 16 ) == -1 ) {
+    if ( allocateIovec( pReq, 16 ) == -1 )
         return -1;
-    }
     pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
-    if ( !pReq->m_pRespBuf ) {
+    if ( !pReq->m_pRespBuf )
         return -1;
-    }
     pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
     pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
     pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
-    if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) {
+    if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
         return -1;
-    }
  
-    if ( isPipe( fd ) ) {
+    if ( isPipe( fd ) )
+    {
         pReq->m_fdListen = -1;
         pReq->m_fd = fd;
-    } else {
+    }
+    else
+    {
         pReq->m_fdListen = fd;
         pReq->m_fd = -1;
         lsapi_set_nblock( fd, 1 );
@@ -659,42 +1275,48 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
     socklen_t   len;
     int         nodelay = 1;
     
-    if ( !pReq ) {
+    if ( !pReq )
         return -1;
-    }
-    if ( LSAPI_Finish_r( pReq ) == -1 ) {
+    if ( LSAPI_Finish_r( pReq ) == -1 )
         return -1;
-    }
-    while( g_running ) {
-        if ( pReq->m_fd == -1 ) {
-            if ( pReq->m_fdListen != -1) {
+    lsapi_set_nblock( pReq->m_fdListen , 0 );
+    while( g_running )
+    {
+        if ( pReq->m_fd == -1 )
+        {
+            if ( pReq->m_fdListen != -1)
+            {
                 len = sizeof( achPeer );
                 pReq->m_fd = accept( pReq->m_fdListen,
                             (struct sockaddr *)&achPeer, &len );
-                if ( pReq->m_fd == -1 ) {
-                    if (( errno == EINTR )||( errno == EAGAIN)) {
+                if ( pReq->m_fd == -1 )
+                {
+                    if (( errno == EINTR )||( errno == EAGAIN))
                         continue;
-                    } else {
+                    else
                         return -1;
-                    }
-                } else {
+                }
+                else
+                {
                     lsapi_set_nblock( pReq->m_fd , 0 );
-                    if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) {    
+                    if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
+                    {    
                         setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
-                                (char *)&nodelay, sizeof(nodelay));
+                                   (char *)&nodelay, sizeof(nodelay));
                     }
-
+                    //init_conn_key( pReq->m_fd );
+                    //OPTIMIZATION
                     if ( s_accept_notify )
-                        return notify_req_received( pReq->m_fd );
-
+                        if ( notify_req_received( pReq->m_fd ) == -1 )
+                                return -1;
                 }
-            } else {
-                return -1;
             }
+            else
+                return -1;
         }
-        if ( !readReq( pReq ) ) {
+        if ( !readReq( pReq ) )
             break;
-        }
+        //abort();
         lsapi_close( pReq->m_fd );
         pReq->m_fd = -1;
         LSAPI_Reset_r( pReq );
@@ -708,15 +1330,18 @@ static struct lsapi_packet_header   finish = {'L', 'S',
 int LSAPI_Finish_r( LSAPI_Request * pReq )
 {
     /* finish req body */
-    if ( !pReq ) {
+    if ( !pReq )
         return -1;
-    }
-    if (pReq->m_reqState) {
-        if ( pReq->m_fd != -1 ) {
-            if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
+    if (pReq->m_reqState)
+    {
+        if ( pReq->m_fd != -1 )
+        {
+            if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
+            {
                 LSAPI_FinalizeRespHeaders_r( pReq );
             }
-            if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
+            if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
+            {
                 Flush_RespBuf_r( pReq );
             }
             
@@ -745,18 +1370,14 @@ void LSAPI_Reset_r( LSAPI_Request * pReq )
 
 int LSAPI_Release_r( LSAPI_Request * pReq )
 {
-    if ( pReq->m_pReqBuf ) {
+    if ( pReq->m_pReqBuf )
         free( pReq->m_pReqBuf );
-    }
-    if ( pReq->m_pSpecialEnvList ) {
+    if ( pReq->m_pSpecialEnvList )
         free( pReq->m_pSpecialEnvList );
-    }
-    if ( pReq->m_pEnvList ) {
+    if ( pReq->m_pEnvList )
         free( pReq->m_pEnvList );
-    }
-    if ( pReq->m_pRespHeaderBuf ) {
+    if ( pReq->m_pRespHeaderBuf )
         free( pReq->m_pRespHeaderBuf );  
-    }
     return 0;
 }
 
@@ -764,55 +1385,48 @@ int LSAPI_Release_r( LSAPI_Request * pReq )
 char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
 {
     int off;
-    if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) {
+    if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
         return NULL;
-    }
     off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
-    if ( !off ) {
+    if ( !off )
         return NULL;
-    }
-    if ( *(pReq->m_pHttpHeader + off + 
-           pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) {
-        *( pReq->m_pHttpHeader + off + 
-            pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
-    }
+        if ( *(pReq->m_pHttpHeader + off + 
+                 pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
+                *( pReq->m_pHttpHeader + off + 
+                        pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
     return pReq->m_pHttpHeader + off;
 }
 
 static int readBodyToReqBuf( LSAPI_Request * pReq )
 {
-    int bodyLeft;
-    int len = pReq->m_bufRead - pReq->m_bufProcessed;
-    if ( len > 0 ) {
+    off_t bodyLeft;
+    ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
+    if ( len > 0 )
         return len;
-    }
     pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
 
-    bodyLeft = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
+    bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
     len = pReq->m_reqBufSize - pReq->m_bufRead;
-    if ( len < 0 ) {
+    if ( len < 0 )
         return -1;
-    }
-    if ( len > bodyLeft ) {
+    if ( len > bodyLeft )
         len = bodyLeft;
-    }
+        
     len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
-    if ( len > 0 ) {
+    if ( len > 0 )
         pReq->m_bufRead += len;
-    }
     return len;
 }
 
 
 int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
 {
-    if (!pReq || (pReq->m_fd ==-1) ) {
+    if (!pReq || (pReq->m_fd ==-1) )
         return EOF;
-    }
-    if ( pReq->m_bufProcessed >= pReq->m_bufRead ) {
-        if ( readBodyToReqBuf( pReq ) <= 0 ) {
+    if ( pReq->m_bufProcessed >= pReq->m_bufRead )
+    {
+        if ( readBodyToReqBuf( pReq ) <= 0 )
             return EOF;
-        }
     }
     ++pReq->m_reqBodyRead;
     return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
@@ -820,42 +1434,43 @@ int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
 
 
 
-int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF )
+int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
 {
-    int len;
-    int left;
+    ssize_t len;
+    ssize_t left;
     char * pBufEnd = pBuf + bufLen - 1;
     char * pBufCur = pBuf;
     char * pCur;
     char * p;
-    if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF ) {
+    if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF )
         return -1;
-    }
     *getLF = 0;
-    while( (left = pBufEnd - pBufCur ) > 0 ) {
+    while( (left = pBufEnd - pBufCur ) > 0 )
+    {
         
         len = pReq->m_bufRead - pReq->m_bufProcessed;
-        if ( len <= 0 ) {
-            if ( (len = readBodyToReqBuf( pReq )) <= 0 ) {
+        if ( len <= 0 )
+        {
+            if ( (len = readBodyToReqBuf( pReq )) <= 0 )
+            {
                 *getLF = 1;
                 break;
             }
         }
-        if ( len > left ) {
+        if ( len > left )
             len = left;
-        }
         pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
         p = memchr( pCur, '\n', len );
-        if ( p ) {
+        if ( p )
             len = p - pCur + 1;
-        }
         memmove( pBufCur, pCur, len );
         pBufCur += len;
         pReq->m_bufProcessed += len;
 
         pReq->m_reqBodyRead += len;
         
-        if ( p ) {
+        if ( p )
+        {
             *getLF = 1;
             break;
         }
@@ -866,48 +1481,47 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *
 }
 
 
-int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
+ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
 {
-    int len;
-    int total;
+    ssize_t len;
+    off_t total;
     /* char *pOldBuf = pBuf; */
-    if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 )) {
+    if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 ))
         return -1;
-    }
-    total = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
+
+    total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
     
-    if ( total <= 0 ) {
+    if ( total <= 0 )
         return 0;
-    }
-    if ( total < bufLen ) {
+    if ( total < bufLen )
         bufLen = total;
-    }
 
     total = 0;
     len = pReq->m_bufRead - pReq->m_bufProcessed;
-    if ( len > 0 ) {
-        if ( len > bufLen ) {
+    if ( len > 0 )
+    {
+        if ( len > bufLen )
             len = bufLen;
-        }
         memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
         pReq->m_bufProcessed += len;
         total += len;
         pBuf += len;
         bufLen -= len;
     }
-    while( bufLen > 0 ) {
+    while( bufLen > 0 )
+    {
         len = lsapi_read( pReq->m_fd, pBuf, bufLen );
-        if ( len > 0 ) {
+        if ( len > 0 )
+        {
             total += len;
             pBuf += len;
             bufLen -= len;
-        } else {
-            if ( len <= 0 ) {
-                if ( !total) {
-                    return -1;
-                }
-                break;
-            }
+        }
+        else if ( len <= 0 )
+        {
+            if ( !total)
+                return -1;
+            break;
         }
     }
     pReq->m_reqBodyRead += total;
@@ -916,37 +1530,52 @@ int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
 }
 
 
-int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
+ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
 {
     struct lsapi_packet_header * pHeader;
     const char * pEnd;
     const char * p;
-    int bufLen;
-    int toWrite;
-    int packetLen;
+    ssize_t bufLen;
+    ssize_t toWrite;
+    ssize_t packetLen;
+    int skip = 0;
     
-    if ( !pReq || !pBuf || (pReq->m_fd == -1) ) {
+    if ( !pReq || !pBuf || (pReq->m_fd == -1) )
         return -1;
+    if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
+    {
+        LSAPI_FinalizeRespHeaders_r( pReq );
+/*
+        if ( *pBuf == '\r' )
+        {
+            ++skip;
+        }
+        if ( *pBuf == '\n' )
+        {
+            ++skip;
+        }
+*/
     }
-    if ( len < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) {
-        memmove( pReq->m_pRespBufPos, pBuf, len );
-        pReq->m_pRespBufPos += len;
+    pReq->m_reqState |= LSAPI_ST_RESP_BODY;
+
+    if ( (len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
+    {
+        memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
+        pReq->m_pRespBufPos += len - skip;
         return len;
     }
     
-    if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
-        LSAPI_FinalizeRespHeaders_r( pReq );
-    }
-    pReq->m_reqState |= LSAPI_ST_RESP_BODY;
     
     pHeader = pReq->m_respPktHeader;
-    p       = pBuf;
+    p       = pBuf + skip;
     pEnd    = pBuf + len;
     bufLen  = pReq->m_pRespBufPos - pReq->m_pRespBuf;
     
-    while( ( toWrite = pEnd - p ) > 0 ) {
+    while( ( toWrite = pEnd - p ) > 0 )
+    {
         packetLen = toWrite + bufLen;
-        if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) {
+        if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
+        {
             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
             toWrite = packetLen - bufLen;
         }
@@ -959,7 +1588,8 @@ int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
         pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
         ++pReq->m_pIovecCur;
         ++pHeader;
-        if ( bufLen > 0 ) {
+        if ( bufLen > 0 )
+        {
             pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
             pReq->m_pIovecCur->iov_len  = bufLen;
             pReq->m_pRespBufPos = pReq->m_pRespBuf;
@@ -972,21 +1602,108 @@ int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
         ++pReq->m_pIovecCur;
         p += toWrite;
 
-        if ( pHeader >= pReq->m_respPktHeaderEnd - 1) {
-            if ( LSAPI_Flush_r( pReq ) == -1 ) {
+        if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
+        {
+            if ( LSAPI_Flush_r( pReq ) == -1 )
                 return -1;
-            }
             pHeader = pReq->m_respPktHeader;
         }
     }
-    if ( pHeader != pReq->m_respPktHeader ) {
-        if ( LSAPI_Flush_r( pReq ) == -1 ) {
+    if ( pHeader != pReq->m_respPktHeader )
+        if ( LSAPI_Flush_r( pReq ) == -1 )
             return -1;
-        }
-    }
     return p - pBuf;
 }
 
+#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) 
+ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
+{
+    ssize_t ret;
+    off_t written;
+    ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
+    if ( written > 0 )
+    {
+        ret = written;
+        *off += ret;
+    }
+    return ret;
+}
+#endif
+
+#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
+{
+    ssize_t ret;
+    off_t len = size;
+    ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
+    if (( ret == 0 )&&( len > 0 ))
+    {
+        ret = len;
+        *off += len;
+    }
+    return ret;
+}
+#endif
+    
+#if defined(sun) || defined(__sun)
+#include <sys/sendfile.h>
+ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
+{
+    int n = 0 ;
+    sendfilevec_t vec[1];
+
+    vec[n].sfv_fd   = fdIn;
+    vec[n].sfv_flag = 0;
+    vec[n].sfv_off  = *off;
+    vec[n].sfv_len  = size;
+    ++n;
+
+    size_t written;
+    ssize_t ret = sendfilev( fdOut, vec, n, &written );
+    if (( !ret )||( errno == EAGAIN ))
+        ret = written;
+    if ( ret > 0 )
+        *off += ret;
+    return ret;
+}
+#endif
+
+#if defined(linux) || defined(__linux) || defined(__linux__) || \
+    defined(__gnu_linux__)
+#include <sys/sendfile.h>
+#define gsendfile sendfile
+#endif
+#if defined(HPUX)
+ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
+{
+    return sendfile( fdOut, fdIn, off, size, NULL, 0 );
+}
+#endif
+
+ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
+{
+    struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
+    if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
+        return -1;
+    if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
+    {
+        LSAPI_FinalizeRespHeaders_r( pReq );
+    }
+    pReq->m_reqState |= LSAPI_ST_RESP_BODY;
+    
+    LSAPI_Flush_r(pReq);
+    
+    lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
+                            size + LSAPI_PACKET_HEADER_LEN );
+   
+
+    if (write(pReq->m_fd,  (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
+        return -1;
+    
+    return gsendfile( pReq->m_fd, fdIn, off, size );
+}
+
+
 void Flush_RespBuf_r( LSAPI_Request * pReq )
 {
     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
@@ -1000,7 +1717,8 @@ void Flush_RespBuf_r( LSAPI_Request * pReq )
     pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
     ++pReq->m_pIovecCur;
     ++pHeader;
-    if ( bufLen > 0 ) {
+    if ( bufLen > 0 )
+    {
         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
         pReq->m_pIovecCur->iov_len  = bufLen;
         pReq->m_pRespBufPos = pReq->m_pRespBuf;
@@ -1016,32 +1734,35 @@ int LSAPI_Flush_r( LSAPI_Request * pReq )
 {
     int ret = 0;
     int n;
-    if ( !pReq ) {
+    if ( !pReq )
         return -1;
-    }
     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
-    if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) {
+    if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
         return 0;
-    }
-    if ( pReq->m_fd == -1 ) {
+    if ( pReq->m_fd == -1 )
+    {
         pReq->m_pRespBufPos = pReq->m_pRespBuf;
         pReq->m_totalLen = 0;
         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
         return -1;
     }
-    if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
+    if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
+    {
         LSAPI_FinalizeRespHeaders_r( pReq );
     }
-    if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
+    if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
+    {
         Flush_RespBuf_r( pReq );
     }
     
     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
-    if ( n > 0 ) {
+    if ( n > 0 )
+    {
         
         ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
                   n, pReq->m_totalLen );
-        if ( ret < pReq->m_totalLen ) {
+        if ( ret < pReq->m_totalLen )
+        {
             lsapi_close( pReq->m_fd );
             pReq->m_fd = -1;
             ret = -1;
@@ -1053,32 +1774,33 @@ int LSAPI_Flush_r( LSAPI_Request * pReq )
 }
 
 
-int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len )
+ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
 {
     struct lsapi_packet_header header;
     const char * pEnd;
     const char * p;
-    int packetLen;
-    int totalLen;
+    ssize_t packetLen;
+    ssize_t totalLen;
     int ret;
     struct iovec iov[2];
     struct iovec *pIov;
     
-    if ( !pReq ) {
+    if ( !pReq )
         return -1;
-    }
-    if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen )) {
+    if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen ))
         return write( 2, pBuf, len );
-    }
-    if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
+    if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
+    {
         LSAPI_Flush_r( pReq );
     }
     
     p       = pBuf;
     pEnd    = pBuf + len;
 
-    while( ( packetLen = pEnd - p ) > 0 ) {
-        if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) {
+    while( ( packetLen = pEnd - p ) > 0 )
+    {
+        if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
+        {
             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
         }
 
@@ -1095,7 +1817,8 @@ int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len )
         pIov = iov;
         ret = lsapi_writev( pReq->m_fd, &pIov,
                   2, totalLen );
-        if ( ret < totalLen ) {
+        if ( ret < totalLen )
+        {
             lsapi_close( pReq->m_fd );
             pReq->m_fd = -1;
             ret = -1;
@@ -1107,14 +1830,16 @@ int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len )
 static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
 {
     int i;
-    for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
-        if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
-            if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) {
+    for( i = 0; i < H_TRANSFER_ENCODING; ++i )
+    {
+        if ( pReq->m_pHeaderIndex->m_headerOff[i] )
+        {
+            if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
                 return pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
-            }
         }
     }
-    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
+    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
+    {
         const char *p;
         char *pKey;
         char *pKeyEnd;
@@ -1122,22 +1847,22 @@ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
         struct lsapi_header_offset * pCur, *pEnd;
         pCur = pReq->m_pUnknownHeader;
         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
-        while( pCur < pEnd ) {
+        while( pCur < pEnd )
+        {
             pKey = pReq->m_pHttpHeader + pCur->nameOff;
             keyLen = pCur->nameLen;
             pKeyEnd = pKey + keyLen;
             p = &name[5];
 
-            while(( pKey < pKeyEnd )&&( *p )) {
+            while(( pKey < pKeyEnd )&&( *p ))
+            {
                 char ch = toupper( *pKey );
-                if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) {
+                if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
                     break;
-                }
                 ++p; ++pKey;
             }
-            if (( pKey == pKeyEnd )&& (!*p )) {
+            if (( pKey == pKeyEnd )&& (!*p ))
                 return pReq->m_pHttpHeader + pCur->valueOff;
-            }
             ++pCur;
         }
     }
@@ -1149,21 +1874,35 @@ char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
 {
     struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
     struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
-    if ( !pReq || !name ) {
+    if ( !pReq || !name )
         return NULL;
-    }
-    if ( strncmp( name, "HTTP_", 5 ) == 0 ) {
+    if ( strncmp( name, "HTTP_", 5 ) == 0 )
+    {
         return GetHeaderVar( pReq, name );
     }
-    while( pBegin < pEnd ) {
-        if ( strcmp( name, pBegin->pKey ) == 0 ) {
+    while( pBegin < pEnd )
+    {
+        if ( strcmp( name, pBegin->pKey ) == 0 )
             return pBegin->pValue;
-        }
         ++pBegin;
     }
     return NULL;
 }
 
+struct _headerInfo
+{
+    const char * _name;
+    int          _nameLen;
+    const char * _value;
+    int          _valueLen;
+};
+
+int compareValueLocation(const void * v1, const void *v2 )
+{
+    return ((const struct _headerInfo *)v1)->_value -
+           ((const struct _headerInfo *)v2)->_value; 
+}
+
 int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
             LSAPI_CB_EnvHandler fn, void * arg )
 {
@@ -1172,43 +1911,66 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
     char * pValue;
     int ret;
     int count = 0;
-    if ( !pReq || !fn ) {
+    struct _headerInfo headers[512];
+    if ( !pReq || !fn )
         return -1;
-    }
-    for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
-        if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
+    
+    for( i = 0; i < H_TRANSFER_ENCODING; ++i )
+    {
+        if ( pReq->m_pHeaderIndex->m_headerOff[i] )
+        {
             len = pReq->m_pHeaderIndex->m_headerLen[i];
             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
             *(pValue + len ) = 0;
-            ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
-                        pValue, len, arg );
+            headers[count]._name = HTTP_HEADERS[i];
+            headers[count]._nameLen = HTTP_HEADER_LEN[i];
+            headers[count]._value = pValue;
+            headers[count]._valueLen = len;
             ++count;
-            if ( ret <= 0 ) {
-                return ret;
-            }
+        
+            //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
+            //            pValue, len, arg );
+            //if ( ret <= 0 )
+            //    return ret;
         }
     }
-    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
+    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
+    {
         char *pKey;
         int  keyLen;
         struct lsapi_header_offset * pCur, *pEnd;
         pCur = pReq->m_pUnknownHeader;
         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
-        while( pCur < pEnd ) {
+        while( pCur < pEnd )
+        {
             pKey = pReq->m_pHttpHeader + pCur->nameOff;
             keyLen = pCur->nameLen;
 
             pValue = pReq->m_pHttpHeader + pCur->valueOff;
             *(pValue + pCur->valueLen ) = 0;
-            ret = (*fn)( pKey, keyLen, 
-                        pValue, pCur->valueLen, arg );
-            if ( ret <= 0 ) {
-                return ret;
-            }
+            headers[count]._name = pKey;
+            headers[count]._nameLen = keyLen;
+            headers[count]._value = pValue;
+            headers[count]._valueLen = pCur->valueLen;
+            ++count;
+            if ( count == 512 )
+                break;
+            //ret = (*fn)( pKey, keyLen, 
+            //            pValue, pCur->valueLen, arg );
+            //if ( ret <= 0 )
+            //    return ret;
             ++pCur;
         }
     }
-    return count + pReq->m_pHeader->m_cntUnknownHeaders;
+    qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
+    for( i = 0; i < count; ++i )
+    {
+        ret = (*fn)( headers[i]._name, headers[i]._nameLen, 
+                    headers[i]._value, headers[i]._valueLen, arg );
+        if ( ret <= 0 )
+            return ret;
+    }
+    return count;
     
 }
 
@@ -1221,23 +1983,24 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
     char * pValue;
     int ret;
     int count = 0;
-    if ( !pReq || !fn ) {
+    if ( !pReq || !fn )
         return -1;
-    }
-    for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
-        if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
+    for( i = 0; i < H_TRANSFER_ENCODING; ++i )
+    {
+        if ( pReq->m_pHeaderIndex->m_headerOff[i] )
+        {
             len = pReq->m_pHeaderIndex->m_headerLen[i];
             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
             *(pValue + len ) = 0;
             ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
                         pValue, len, arg );
             ++count;
-            if ( ret <= 0 ) {
+            if ( ret <= 0 )
                 return ret;
-            }
         }
     }
-    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
+    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
+    {
         char achHeaderName[256];
         char *p;
         char *pKey;
@@ -1246,24 +2009,23 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
         struct lsapi_header_offset * pCur, *pEnd;
         pCur = pReq->m_pUnknownHeader;
         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
-        while( pCur < pEnd ) {
+        while( pCur < pEnd )
+        {
             pKey = pReq->m_pHttpHeader + pCur->nameOff;
             keyLen = pCur->nameLen;
-            if ( keyLen > 250 ) {
+            if ( keyLen > 250 )
                 keyLen = 250;
-            }
-
             pKeyEnd = pKey + keyLen;
             memcpy( achHeaderName, "HTTP_", 5 );
             p = &achHeaderName[5];
 
-            while( pKey < pKeyEnd ) {
+            while( pKey < pKeyEnd )
+            {
                 char ch = *pKey++;
-                if ( ch == '-' ) {
+                if ( ch == '-' )
                     *p++ = '_';
-                } else {
+                else
                     *p++ = toupper( ch );
-                }
             }
             *p = 0;
             keyLen += 5;
@@ -1272,9 +2034,8 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
             *(pValue + pCur->valueLen ) = 0;
             ret = (*fn)( achHeaderName, keyLen, 
                         pValue, pCur->valueLen, arg );
-            if ( ret <= 0 ) {
+            if ( ret <= 0 )
                 return ret;
-            }
             ++pCur;
         }
     }
@@ -1287,15 +2048,14 @@ static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
 {
     struct LSAPI_key_value_pair * pEnd = pEnv + n;
     int ret;
-    if ( !pEnv || !fn ) {
+    if ( !pEnv || !fn )
         return -1;
-    }
-    while( pEnv < pEnd ) {
+    while( pEnv < pEnd )
+    {
         ret = (*fn)( pEnv->pKey, pEnv->keyLen,
                     pEnv->pValue, pEnv->valLen, arg );
-        if ( ret <= 0 ) {
+        if ( ret <= 0 )
             return ret;
-        }
         ++pEnv;
     }
     return n;
@@ -1306,10 +2066,10 @@ static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
 int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
             LSAPI_CB_EnvHandler fn, void * arg )
 {
-    if ( !pReq || !fn ) {
+    if ( !pReq || !fn )
         return -1;
-    }
-    if ( pReq->m_pHeader->m_cntEnv > 0 ) {
+    if ( pReq->m_pHeader->m_cntEnv > 0 )
+    {
         return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
                     fn, arg );
     }
@@ -1321,10 +2081,10 @@ int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
 int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
             LSAPI_CB_EnvHandler fn, void * arg )
 {
-    if ( !pReq || !fn ) {
+    if ( !pReq || !fn )
         return -1;
-    }
-    if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) {
+    if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
+    {
         return EnvForeach( pReq->m_pSpecialEnvList,
                 pReq->m_pHeader->m_cntSpecialEnv,
                     fn, arg );
@@ -1337,14 +2097,13 @@ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
 
 int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
 {
-    if ( !pReq || !pReq->m_pIovec ) {
+    if ( !pReq || !pReq->m_pIovec )
         return -1;
-    }
-    if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) {
+    if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
         return 0;
-    }
     pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
-    if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) {
+    if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
+    {
         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
         pReq->m_pIovecCur->iov_len  = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
         pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
@@ -1363,25 +2122,87 @@ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
 }
 
 
-
-
-int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, char * pBuf, int len )
+int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, 
+                              const char * pHeaderValue )
 {
-    if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) {
+    int nameLen, valLen, len;
+    if ( !pReq || !pHeaderName || !pHeaderValue ) 
+        return -1;
+    if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
         return -1;
+    if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
+        return -1;
+    nameLen = strlen( pHeaderName );
+    valLen = strlen( pHeaderValue );
+    if ( nameLen == 0 )
+        return -1;
+    while( nameLen > 0 )
+    {
+        char ch = *(pHeaderName + nameLen - 1 );
+        if (( ch == '\n' )||( ch == '\r' ))
+            --nameLen;
+        else
+            break;
     }
-    if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) {
+    if ( nameLen <= 0 )
+        return 0;
+    while( valLen > 0 )
+    {
+        char ch = *(pHeaderValue + valLen - 1 );
+        if (( ch == '\n' )||( ch == '\r' ))
+            --valLen;
+        else
+            break;
+    }
+    len = nameLen + valLen + 1;
+    if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
         return -1;
+
+    if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
+    {
+        int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
+        newlen -= newlen % 4096;
+        if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
+            return -1;
     }
-    if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) {
+    memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
+    pReq->m_pRespHeaderBufPos += nameLen;
+    *pReq->m_pRespHeaderBufPos++ = ':';
+    memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
+    pReq->m_pRespHeaderBufPos += valLen;
+    *pReq->m_pRespHeaderBufPos++ = 0;
+    ++len;  /* add one byte padding for \0 */
+    pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
+    ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
+    return 0;
+}
+
+
+
+int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
+{
+    if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
+        return -1;
+    if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
         return -1;
+    if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
+        return -1;
+    while( len > 0 )
+    {
+        char ch = *(pBuf + len - 1 );
+        if (( ch == '\n' )||( ch == '\r' ))
+            --len;
+        else
+            break;
     }
-    if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) {
+    if ( len <= 0 )
+        return 0;
+    if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
+    {
         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
         newlen -= newlen % 4096;
-        if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) {
+        if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
             return -1;
-        }
     }
     memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
     pReq->m_pRespHeaderBufPos += len;
@@ -1400,7 +2221,8 @@ int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
     int flag = 1;
     int addr_len;
 
-    switch( pServerAddr->sa_family ) {
+    switch( pServerAddr->sa_family )
+    {
     case AF_INET:
         addr_len = 16;
         break;
@@ -1416,20 +2238,20 @@ int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
     }
 
     fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
-    if ( fd == -1 ) {
+    if ( fd == -1 )
         return -1;
-    }
 
     fcntl( fd, F_SETFD, FD_CLOEXEC );
 
     if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
-                (char *)( &flag ), sizeof(flag)) == 0) {
+                (char *)( &flag ), sizeof(flag)) == 0)
+    {
         ret = bind( fd, pServerAddr, addr_len );
-        if ( !ret ) {
+        if ( !ret )
+        {
             ret = listen( fd, backlog );
-            if ( !ret ) {
+            if ( !ret )
                 return fd;
-            }
         }
     }
 
@@ -1449,17 +2271,16 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
     int  doAddrInfo = 0;
     int port;
     
-    if ( !pBind ) {
+    if ( !pBind )
         return -1;
-    }
 
-    while( isspace( *pBind ) ) {
+    while( isspace( *pBind ) )
         ++pBind;
-    }
 
     strncpy( achAddr, pBind, 256 );
 
-    switch( *p ) {
+    switch( *p )
+    {
     case '/':
         pAddr->sa_family = AF_UNIX;
         strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
@@ -1474,7 +2295,8 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
             return -1;
         *pEnd++ = 0;
         
-        if ( *p == '*' ) {
+        if ( *p == '*' )
+        {
             strcpy( achAddr, "::" );
             p = achAddr;
         }
@@ -1484,35 +2306,35 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
     default:
         pAddr->sa_family = AF_INET;
         pEnd = strchr( p, ':' );
-        if ( !pEnd ) {
+        if ( !pEnd )
             return -1;
-        }
         *pEnd++ = 0;
         
         doAddrInfo = 0;
-        if ( *p == '*' ) {
+        if ( *p == '*' )
+        {
             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
-        } else {
-            if (!strcasecmp( p, "localhost" ) ) {
-                ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
-            } else  {
-                ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
-                if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) {
-                    doAddrInfo = 1;
-                }
+        }
+        else if (!strcasecmp( p, "localhost" ) )
+            ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
+        else
+        {
+            ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
+            if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
+            {
+                doAddrInfo = 1;
             }
         }
         break;
     }
-    if ( *pEnd == ':' ) {
+    if ( *pEnd == ':' )
         ++pEnd;
-    }
         
     port = atoi( pEnd );
-    if (( port <= 0 )||( port > 65535 )) {
+    if (( port <= 0 )||( port > 65535 ))
         return -1;
-    }
-    if ( doAddrInfo ) {
+    if ( doAddrInfo )
+    {
 
         memset(&hints, 0, sizeof(hints));
 
@@ -1520,7 +2342,8 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
         hints.ai_socktype = SOCK_STREAM;
         hints.ai_protocol = IPPROTO_TCP;
 
-        if ( getaddrinfo(p, NULL, &hints, &res) ) {
+        if ( getaddrinfo(p, NULL, &hints, &res) )
+        {
             return -1;
         }
 
@@ -1528,11 +2351,10 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
         freeaddrinfo(res);
     }
     
-    if ( pAddr->sa_family == AF_INET ) {
+    if ( pAddr->sa_family == AF_INET )
         ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
-    } else {
+    else
         ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
-    }
     return 0;
     
 }
@@ -1543,7 +2365,8 @@ int LSAPI_CreateListenSock( const char * pBind, int backlog )
     int ret;
     int fd = -1;
     ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
-    if ( !ret ) {
+    if ( !ret )
+    {
         fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
     }
     return fd;
@@ -1554,9 +2377,11 @@ static fn_select_t g_fnSelect = select;
 typedef struct _lsapi_child_status
 {
     int     m_pid;
+    long    m_tmStart;
 
     volatile short   m_iKillSent;
     volatile short   m_inProcess;
+    volatile int     m_iReqCounter;
 
     volatile long    m_tmWaitBegin;
     volatile long    m_tmReqBegin;
@@ -1586,43 +2411,42 @@ static lsapi_prefork_server * g_prefork_server = NULL;
 
 int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
 {
-    if ( g_prefork_server ) {
+    int pid;
+    if ( g_prefork_server )
         return 0;
-    }
-    if ( max_children <= 1 ) {
+    if ( max_children <= 1 )
         return -1;
-    }
-    if ( max_children >= 10000) {
+    if ( max_children >= 10000)
         max_children = 10000;
-    }
 
     
     g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
-    if ( !g_prefork_server ) {
+    if ( !g_prefork_server )
         return -1;
-    }
     memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
 
-    if ( fp != NULL ) {
+    if ( fp != NULL )
         g_fnSelect = fp;
-    }
 
     s_ppid = getppid();
+    pid = getpid();
+    setpgid( pid, pid );
     g_prefork_server->m_iAvoidFork = avoidFork;
     g_prefork_server->m_iMaxChildren = max_children;
     
     g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
     g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
+    if ( g_prefork_server->m_iMaxIdleChildren == 0 )
+        g_prefork_server->m_iMaxIdleChildren = 1;
     g_prefork_server->m_iChildrenMaxIdleTime = 300;
-    g_prefork_server->m_iMaxReqProcessTime = 300;
+    g_prefork_server->m_iMaxReqProcessTime = 3600;
     return 0;    
 }
 
 void LSAPI_Set_Server_fd( int fd )
 {
-    if( g_prefork_server ) {
+    if( g_prefork_server )
         g_prefork_server->m_fd = fd;
-    }
 }
 
 
@@ -1635,14 +2459,17 @@ static int lsapi_accept( int fdListen )
 
     len = sizeof( achPeer );
     fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
-    if ( fd != -1 ) {
-        if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) {
+    if ( fd != -1 )
+    {
+        if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
+        {
             setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
                     (char *)&nodelay, sizeof(nodelay));
         }
 
-        if ( s_accept_notify )
-            notify_req_received( fd );
+        //OPTIMIZATION
+        //if ( s_accept_notify )
+        //    notify_req_received( fd );
     }
     return fd;
 
@@ -1666,10 +2493,10 @@ static lsapi_child_status * find_child_status( int pid )
 {
     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
-    while( pStatus < pEnd ) {
-        if ( pStatus->m_pid == pid ) {
+    while( pStatus < pEnd )
+    {
+        if ( pStatus->m_pid == pid )
             return pStatus;
-        }
         ++pStatus;
     }
     return NULL;
@@ -1681,16 +2508,30 @@ static void lsapi_sigchild( int signal )
 {
     int status, pid;
     lsapi_child_status * child_status;
-    while( 1 ) {
+    while( 1 )
+    {
         pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
-        if ( pid <= 0 ) {
+        if ( pid <= 0 )
+        {
             break;
         }
+        if ( WIFSIGNALED( status ))
+        {
+            int sig_num = WTERMSIG( status );
+            int dump = WCOREDUMP( status );
+            fprintf( stderr, "Child process with pid: %d was killed by signal: %d, core dump: %d\n", pid, sig_num, dump );
+        }
+        if ( pid == s_pid_dump_debug_info )
+        {
+            pid = 0;
+            continue;
+        }
         child_status = find_child_status( pid );
-        if ( child_status ) {
+        if ( child_status )
+        {
             child_status->m_pid = 0;
+            --g_prefork_server->m_iCurChildren;
         }
-        --g_prefork_server->m_iCurChildren;
     }
 
 }
@@ -1704,76 +2545,108 @@ static int lsapi_init_children_status()
     size = (size + 4095 ) / 4096 * 4096;
     pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
         MAP_ANON | MAP_SHARED, -1, 0 );
-    if ( pBuf == MAP_FAILED ) {
+    if ( pBuf == MAP_FAILED )
+    {
         perror( "Anonymous mmap() failed" );
         return -1;
     }
     memset( pBuf, 0, size );
-    g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;    
+    g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;        
     return 0;
 }
 
+static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
+{
+    char achCmd[1024];
+    if ( s_pid_dump_debug_info )
+    {
+        if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
+            return;
+    }
+    s_pid_dump_debug_info = fork();
+
+    fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n", 
+                ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter, 
+                tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); 
+    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 );
+    if ( system( achCmd ) == -1 )
+        perror( "system()" );
+    exit( 0 );
+}
+
 static void lsapi_check_child_status( long tmCur )
 {
     int idle = 0;
     int tobekilled;
     int dying = 0;
+    int count = 0;
     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
-    while( pStatus < pEnd ) {
-        tobekilled = pStatus->m_iKillSent;
-        if ( pStatus->m_pid != 0 ) {
-            if ( !tobekilled ) {
-                if ( !pStatus->m_inProcess ) {
-                    
-                    if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
-                        ( idle >= g_prefork_server->m_iMaxIdleChildren )) {
-                    
-                        tobekilled = 1;
-                    } else {
-                        if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 )) {
-                            tobekilled = 1;
-                        }
-                    }
-                    if ( !tobekilled ) {
-                        ++idle;
-                    }
-                } else {
-                    if ( tmCur - pStatus->m_tmReqBegin > 
-                         g_prefork_server->m_iMaxReqProcessTime ) {
-                        tobekilled = 1;
-                    }
+    while( pStatus < pEnd )
+    {
+        tobekilled = 0;
+        if ( pStatus->m_pid != 0 )
+        {
+            ++count;
+            if ( !pStatus->m_inProcess )
+            {
+                
+                if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
+                    ( idle > g_prefork_server->m_iMaxIdleChildren ))
+                {
+                    tobekilled = SIGUSR1;
                 }
-            } else {
-                if ( pStatus->m_inProcess ) {
-                    tobekilled = pStatus->m_iKillSent = 0;
+                else
+                {
+                    if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
+                    {
+                        tobekilled = SIGUSR1;
+                    }
                 }
+                if ( !tobekilled )
+                    ++idle;
             }
-            if ( tobekilled ) {
-                tobekilled = 0;
-                if ( pStatus->m_iKillSent > 5 ) {
-                    tobekilled = SIGKILL;
-                } else {    
-                    if ( pStatus->m_iKillSent == 3 ) {
+            else
+            {
+                if ( tmCur - pStatus->m_tmReqBegin > 
+                        g_prefork_server->m_iMaxReqProcessTime )
+                {
+                    if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info ))
+                        dump_debug_info( pStatus, tmCur );
+                    if ( pStatus->m_iKillSent > 5 )
+                    {
+                        tobekilled = SIGKILL;
+                        fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid );
+                    }
+                    else
+                    {
                         tobekilled = SIGTERM;
-                    } else {
-                        if ( pStatus->m_iKillSent == 1 ) {
-                            tobekilled = SIGUSR1;
-                        }
+                        fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid );
                     }
                 }
-                if ( tobekilled ) {
-                    kill( pStatus->m_pid, tobekilled );
+            }
+            if ( tobekilled )
+            {
+                if (( kill( pStatus->m_pid, tobekilled ) == -1 )&&( errno == ESRCH ))
+                {
+                    pStatus->m_pid = 0;
+                    --count;
+                }
+                else
+                {
+                    ++pStatus->m_iKillSent;
+                    ++dying;
                 }
-                ++pStatus->m_iKillSent;
-                ++dying;
             }
-                
-        } else {
-            ++dying;
         }
         ++pStatus;
     }
+    if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
+    {
+        fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Childen: %d, count: %d, idle: %d, dying: %d\n", getpid(), 
+                g_prefork_server->m_iCurChildren, count, idle, dying );
+
+    }
 }
 
 static int lsapi_all_children_must_die()
@@ -1784,14 +2657,14 @@ static int lsapi_all_children_must_die()
     g_prefork_server->m_iMaxIdleChildren = -1;
     maxWait = 15;
 
-    while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) {
+    while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
+    {
         lsapi_check_child_status(time(NULL));
         sleep( 1 );
         sec++;
     }
-    if ( g_prefork_server->m_iCurChildren != 0 ) {
+    if ( g_prefork_server->m_iCurChildren != 0 )
         kill( -getpgrp(), SIGKILL );
-    }
     return 0;
 }
 
@@ -1810,13 +2683,17 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
     fd_set          readfds;
     struct timeval  timeout;
 
+    sigset_t mask;
+    sigset_t orig_mask;
+
     lsapi_init_children_status();
     
     setsid();
 
     act.sa_flags = 0;
     act.sa_handler = lsapi_sigchild;
-    if( sigaction( SIGCHLD, &act, &old_child ) ) {
+    if( sigaction( SIGCHLD, &act, &old_child ) )
+    {
         perror( "Can't set signal handler for SIGCHILD" );
         return -1;
     }
@@ -1827,36 +2704,36 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
     if( sigaction( SIGTERM, &act, &old_term ) ||
         sigaction( SIGINT,  &act, &old_int  ) ||
         sigaction( SIGUSR1, &act, &old_usr1 ) ||
-        sigaction( SIGQUIT, &act, &old_quit )) {
+        sigaction( SIGQUIT, &act, &old_quit ))
+    {
         perror( "Can't set signals" );
         return -1;
     }
     s_stop = 0;
-    while( !s_stop ) {
-        if ( ret ) {
-            curTime = time( NULL );
-        } else {
-            ++curTime;
-        }
-        if (curTime != lastTime ) {
+    while( !s_stop )
+    {
+        curTime = time( NULL );
+        if (curTime != lastTime )
+        {
             lastTime = curTime;
-            if (s_ppid && (getppid() != s_ppid )) {
+            if (s_ppid && (getppid() != s_ppid ))
                 break;
-            }
             lsapi_check_child_status(curTime );
-            if (pServer->m_iServerMaxIdle) {
-                if ( pServer->m_iCurChildren <= 0 ) {
+            if (pServer->m_iServerMaxIdle)
+            {
+                if ( pServer->m_iCurChildren <= 0 )
+                {
                     ++wait_secs;
-                    if ( wait_secs > pServer->m_iServerMaxIdle ) {
+                    if ( wait_secs > pServer->m_iServerMaxIdle )
                         return -1;
-                    }
-                } else {
-                    wait_secs = 0;
                 }
+                else
+                    wait_secs = 0;
             }
         }
 
-        if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) ) {
+        if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) )
+        {
             usleep( 100000 );
             continue;
         }
@@ -1864,66 +2741,100 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
         FD_ZERO( &readfds );
         FD_SET( pServer->m_fd, &readfds );
         timeout.tv_sec = 1; timeout.tv_usec = 0;
-        if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 ) {
-            if ( pServer->m_iCurChildren >= 0 ) {
+        if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 )
+        {
+            /*
+            if ( pServer->m_iCurChildren >= 0 )
+            {
                 usleep( 10 );
                 FD_ZERO( &readfds );
                 FD_SET( pServer->m_fd, &readfds );
                 timeout.tv_sec = 0; timeout.tv_usec = 0;
-                if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 ) {
-                    continue;
-                }
-            }
-        } else {
-            if ( ret == -1 ) {
-                if ( errno == EINTR ) {
+                if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 )
                     continue;
-                }
-                /* perror( "select()" ); */
-                break;
-            } else {
+            }*/
+        }
+        else if ( ret == -1 )
+        {
+            if ( errno == EINTR )
                 continue;
-            }
+            /* perror( "select()" ); */
+            break;
+        }
+        else
+        {
+            continue;
         }
 
         pReq->m_fd = lsapi_accept( pServer->m_fd );
-        if ( pReq->m_fd != -1 ) {
+        if ( pReq->m_fd != -1 )
+        {
             child_status = find_child_status( 0 );
+            if ( child_status )
+                memset( child_status, 0, sizeof( *child_status ) );
+
+            sigemptyset( &mask );
+            sigaddset( &mask, SIGCHLD );
+            
+            if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 ) 
+            {
+                perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
+            }
+
             pid = fork();
-            if ( !pid ) {
+    
+            if ( !pid )
+            {
+                if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) 
+                    perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
                 g_prefork_server = NULL;
                 s_ppid = getppid();
                 s_req_processed = 0;
                 s_pChildStatus = child_status;
-                child_status->m_iKillSent = 0;
                 lsapi_set_nblock( pReq->m_fd, 0 );
-
+                if ( pReq->m_fdListen != -1 )
+                {
+                    close( pReq->m_fdListen );
+                    pReq->m_fdListen = -1;
+                }
                 /* don't catch our signals */
                 sigaction( SIGCHLD, &old_child, 0 );
                 sigaction( SIGTERM, &old_term, 0 );
                 sigaction( SIGQUIT, &old_quit, 0 );
                 sigaction( SIGINT,  &old_int,  0 );
                 sigaction( SIGUSR1, &old_usr1, 0 );
+                //init_conn_key( pReq->m_fd );
+                lsapi_notify_pid( pReq->m_fd );
+                s_notified_pid = 1;
+                //if ( s_accept_notify )
+                //    return notify_req_received( pReq->m_fd );
                 return 0;
-            } else {
-                if ( pid == -1 ) {
-                    perror( "fork() failed, please increase process limit" );
-                } else {
-                    ++pServer->m_iCurChildren;
-                    if ( child_status ) {
-                        child_status->m_pid = pid;
-                        child_status->m_iKillSent = 0;
-                        child_status->m_tmWaitBegin = time(NULL);
-                    }
+            }
+            else if ( pid == -1 )
+            {
+                perror( "fork() failed, please increase process limit" );
+            }
+            else
+            {
+                ++pServer->m_iCurChildren;
+                if ( child_status )
+                {
+                    child_status->m_pid = pid;
+                    child_status->m_tmWaitBegin = curTime;
+                    child_status->m_tmStart = curTime;
                 }
             }
             close( pReq->m_fd );
             pReq->m_fd = -1;
 
-        } else {
-            if (( errno == EINTR )||( errno == EAGAIN)) {
+            if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) 
+                perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
+
+        }
+        else
+        {
+            if (( errno == EINTR )||( errno == EAGAIN))
                 continue;
-            }
             perror( "accept() failed" );
             return -1;
         }
@@ -1935,6 +2846,11 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
 
 }
 
+void lsapi_error( const char * pMessage, int err_no )
+{
+    fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) );
+}
+
 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
 {
     int             fd;
@@ -1946,88 +2862,105 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
     LSAPI_Finish_r( pReq );
 
 
-    if ( g_prefork_server ) {
-        if ( g_prefork_server->m_fd != -1 ) {
-            if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) {
+    if ( g_prefork_server )
+    {
+        if ( g_prefork_server->m_fd != -1 )
+            if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
                 return -1;
-            }
-        }
     }
-    if ( s_req_processed >= s_max_reqs ) {
+    if ( s_req_processed >= s_max_reqs )
         return -1;
-    }
 
-    if ( s_pChildStatus ) {
+    if ( s_pChildStatus )
+    {
         s_pChildStatus->m_tmWaitBegin = time( NULL );
     }
+
     
-    while( g_running ) {
-        if ( pReq->m_fd != -1 ) {
+    while( g_running )
+    {
+        if ( pReq->m_fd != -1 )
+        {
             fd = pReq->m_fd;
-        } else {
-            if ( pReq->m_fdListen != -1 ) {
-                fd = pReq->m_fdListen;
-            } else {
-                return -1;
-            }
+        }
+        else if ( pReq->m_fdListen != -1 )
+            fd = pReq->m_fdListen;
+        else
+        {
+            break;
         }
         wait_secs = 0;
-        while( 1 ) {
-            if ( !g_running ) {
+        while( 1 )
+        {
+            if ( !g_running )
                 return -1;
-            }
-            if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
+            if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
                 return -1; 
-            }
             FD_ZERO( &readfds );
             FD_SET( fd, &readfds );
             timeout.tv_sec = 1;
             timeout.tv_usec = 0;
             ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
-            if ( ret == 0 ) {
-                if ( s_pChildStatus ) {
+            if ( ret == 0 )
+            {
+                if ( s_pChildStatus )
+                {
                     s_pChildStatus->m_inProcess = 0;
                 }
                 ++wait_secs;
-                if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) {
+                if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
                     return -1;
-                }
-                if ( s_ppid &&( getppid() != s_ppid)) {
+                if ( s_ppid &&( getppid() != s_ppid))
                     return -1;
-                }
-            } else {
-                if ( ret == -1 ) {
-                    if ( errno == EINTR ) {
-                        continue;
-                    } else {
-                        return -1;
-                    }
-                } else {
-                    if ( ret >= 1 ) {
-                        if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
-                            return -1; 
+            }
+            else if ( ret == -1 )
+            {
+                if ( errno == EINTR )
+                    continue;
+                else
+                    return -1;
+            }
+            else if ( ret >= 1 )
+            {
+                if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
+                    return -1; 
+                if ( fd == pReq->m_fdListen )
+                {
+                    pReq->m_fd = lsapi_accept( pReq->m_fdListen );
+                    if ( pReq->m_fd != -1 )
+                    {
+                        fd = pReq->m_fd;
+                        lsapi_set_nblock( fd, 0 );
+                        //init_conn_key( pReq->m_fd );
+                        if ( !s_keepListener )
+                        {
+                            close( pReq->m_fdListen );
+                            pReq->m_fdListen = -1;
                         }
-                        if ( fd == pReq->m_fdListen ) {
-                            pReq->m_fd = lsapi_accept( pReq->m_fdListen );
-                            if ( pReq->m_fd != -1 ) {
-                                fd = pReq->m_fd;
-                                lsapi_set_nblock( fd, 0 );
-                            } else {
-                                if (( errno == EINTR )||( errno == EAGAIN)) {
-                                    continue;
-                                                               }
+                        if ( s_accept_notify )
+                            if ( notify_req_received( pReq->m_fd ) == -1 )
                                 return -1;
-                            }
-                        } else {
-                            break;
-                        }
+                    }
+                    else
+                    {
+                        if (( errno == EINTR )||( errno == EAGAIN))
+                            continue;
+                        lsapi_error( "lsapi_accept() error", errno );
+                        return -1;
                     }
                 }
+                else
+                    break;
             }
         }
-        if ( !readReq( pReq ) ) {
-            if ( s_pChildStatus ) {
+
+        if ( !readReq( pReq ) )
+        {
+            if ( s_pChildStatus )
+            {
+                s_pChildStatus->m_iKillSent = 0;
                 s_pChildStatus->m_inProcess = 1;
+                ++s_pChildStatus->m_iReqCounter;
                 s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
             }
             ++s_req_processed;
@@ -2042,61 +2975,53 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
 }
 
 void LSAPI_Set_Max_Reqs( int reqs )
-{   
-    s_max_reqs = reqs;          
-}
+{   s_max_reqs = reqs;          }
 
 void LSAPI_Set_Max_Idle( int secs )
-{   
-    s_max_idle_secs = secs;     
-}
+{   s_max_idle_secs = secs;     }
 
 void LSAPI_Set_Max_Children( int maxChildren )
 {
-    if ( g_prefork_server ) {
+    if ( g_prefork_server )
         g_prefork_server->m_iMaxChildren = maxChildren;
-    }
 }
 
 void LSAPI_Set_Extra_Children( int extraChildren )
 {
-    if (( g_prefork_server )&&( extraChildren >= 0 )) {
+    if (( g_prefork_server )&&( extraChildren >= 0 ))
         g_prefork_server->m_iExtraChildren = extraChildren;
-    }
 }
 
 void LSAPI_Set_Max_Process_Time( int secs )
 {
-    if (( g_prefork_server )&&( secs > 0 )) {
+    if (( g_prefork_server )&&( secs > 0 ))
         g_prefork_server->m_iMaxReqProcessTime = secs;
-    }
 }
 
 
 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
 {
-    if (( g_prefork_server )&&( maxIdleChld > 0 )) {
+    if (( g_prefork_server )&&( maxIdleChld > 0 ))
         g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
-    }
 }
 
 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
 {
-    if ( g_prefork_server ) {
+    if ( g_prefork_server )
         g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
-    }
 }
 
 void LSAPI_Set_Slow_Req_Msecs( int msecs )
 {
-       s_slow_req_msecs = msecs;
+    s_slow_req_msecs = msecs;
 }
 
 int  LSAPI_Get_Slow_Req_Msecs()
 {
-       return s_slow_req_msecs;
+    return s_slow_req_msecs;
 }
 
+
 void LSAPI_No_Check_ppid()
 {
     s_ppid = 0;
@@ -2115,113 +3040,419 @@ static void unset_lsapi_envs()
 #else
     env = environ;
 #endif
-    while( env != NULL && *env != NULL ) {
-        if ( !strncmp(*env, "LSAPI_", 6) || 
-             !strncmp( *env, "PHP_LSAPI_", 10 ) ) {   
+    while( env != NULL && *env != NULL ) 
+    {
+        if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 ) 
+            || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid))) 
+        {   
             char ** del = env;
-            do {
+            do 
                 *del = del[1];
-            } while( *del++ );
-        } else {
-            ++env;
+            while( *del++ );
         }
+        else
+            ++env;
     }  
 }
 
-void LSAPI_Init_Env_Parameters( fn_select_t fp )
+static int lsapi_initSuEXEC()
+{
+    int i;
+    struct passwd * pw;
+    s_defaultUid = 0;
+    s_defaultGid = 0;
+    if ( s_uid == 0 )
+    {
+        const char * p = getenv( "LSAPI_DEFAULT_UID" );
+        if ( p )
+        {
+            i = atoi( p );
+            if ( i > 0 )
+                s_defaultUid = i;
+        }
+        p = getenv( "LSAPI_DEFAULT_GID" );
+        if ( p )
+        {
+            i = atoi( p );
+            if ( i > 0 )
+                s_defaultGid = i;
+        }
+        p = getenv( "LSAPI_SECRET" );
+        if (( !p )||( readSecret(p) == -1 ))
+                return -1;  
+        if ( g_prefork_server )
+        {
+            if ( g_prefork_server->m_iMaxChildren < 100 )
+                g_prefork_server->m_iMaxChildren = 100;
+        }
+    }
+    if ( !s_defaultUid || !s_defaultGid )
+    {
+        pw = getpwnam( "nobody" );
+        if ( !s_defaultUid )
+            s_defaultUid = pw->pw_uid;
+        if ( !s_defaultGid )
+            s_defaultGid = pw->pw_gid;
+    }
+    return 0;
+}
+
+
+int LSAPI_Init_Env_Parameters( fn_select_t fp )
 {
     const char *p;
     int n;
     int avoidFork = 0;
     p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
-    if ( !p ) {
+    if ( !p )
         p = getenv( "LSAPI_MAX_REQS" );
-    }
-    if ( p ) {
+    if ( p )
+    {
         n = atoi( p );
-        if ( n > 0 ) {
+        if ( n > 0 )
             LSAPI_Set_Max_Reqs( n );
-        }
     }
 
     p = getenv( "LSAPI_AVOID_FORK" );
-    if ( p ) {
+    if ( p )
+    {
         avoidFork = atoi( p );
     }    
 
     p = getenv( "LSAPI_ACCEPT_NOTIFY" );
-    if ( p ) {
+    if ( p )
+    {
         s_accept_notify = atoi( p );
-    }    
+    }
 
     p = getenv( "LSAPI_SLOW_REQ_MSECS" );
-    if ( p ) {
+    if ( p ) 
+    {
         n = atoi( p );
         LSAPI_Set_Slow_Req_Msecs( n );
-    }    
-
+    }
 
 #if defined( RLIMIT_CORE )
     p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
-    if ( !p ) {
+    if ( !p )
+    {
         struct rlimit limit = { 0, 0 };
         setrlimit( RLIMIT_CORE, &limit );
     }
-#endif    
+    else
+        s_enable_core_dump = 1;
+
+#endif
 
     p = getenv( "LSAPI_MAX_IDLE" );
-    if ( p ) {
+    if ( p )
+    {
         n = atoi( p );
         LSAPI_Set_Max_Idle( n );
     }
 
-    if ( LSAPI_Is_Listen() ) {
+    p = getenv( "LSAPI_KEEP_LISTEN" );
+    if ( p )
+    {
+        n = atoi( p );
+        s_keepListener = n;
+    }
+
+
+    if ( LSAPI_Is_Listen() )
+    {
         n = 0;
         p = getenv( "PHP_LSAPI_CHILDREN" );
-        if ( !p ) {
+        if ( !p )
             p = getenv( "LSAPI_CHILDREN" );
-        }
-        if ( p ) {
+        if ( p )
             n = atoi( p );
-        }
-        if ( n > 1 ) {
+        if ( n > 1 )
+        {
             LSAPI_Init_Prefork_Server( n, fp, avoidFork );
             LSAPI_Set_Server_fd( g_req.m_fdListen );
         }
 
         p = getenv( "LSAPI_EXTRA_CHILDREN" );
-        if ( p ) {
+        if ( p )
             LSAPI_Set_Extra_Children( atoi( p ) );
-        }
         
         p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
-        if ( p ) {
+        if ( p )
             LSAPI_Set_Max_Idle_Children( atoi( p ) );
-        }
+        
         p = getenv( "LSAPI_PGRP_MAX_IDLE" );
-        if ( p ) {
+        if ( p )
+        {
             LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
         }
         
         p = getenv( "LSAPI_MAX_PROCESS_TIME" );
-        if ( p ) {     
+        if ( p )       
             LSAPI_Set_Max_Process_Time( atoi( p ) );
-        }
-        if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) {
+        
+        if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
+        {
             LSAPI_No_Check_ppid();
         }
+        
+        p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
+        if ( p )
+            s_dump_debug_info = atoi( p );
+
+        if ( lsapi_initSuEXEC() == -1 )
+            return -1;
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
+        lsapi_initLVE();
+#endif
     }
     unset_lsapi_envs();
+    return 0;
+}
+
+
+int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, 
+                         const char * pBody, int bodyLen )
+{
+    LSAPI_SetRespStatus_r( pReq, code );
+    if ( pRespHeaders )
+    {
+        while( *pRespHeaders )
+        {
+            LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
+            ++pRespHeaders;
+        }
+    }
+    if ( pBody &&( bodyLen > 0 ))
+    {
+        LSAPI_Write_r( pReq, pBody, bodyLen );
+    }
+    LSAPI_Finish_r( pReq );
+    return 0;
+}
+
+
+static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+    uint32 t;
+    do {
+        t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+            ((unsigned) buf[1] << 8 | buf[0]);
+        *(uint32 *) buf = t;
+        buf += 4;
+    } while (--longs);
+}
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bits[0] = 0;
+    ctx->bits[1] = 0;
 }
 
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+    register uint32 t;
+
+    /* Update bitcount */
+
+    t = ctx->bits[0];
+    if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
+        ctx->bits[1]++;                /* Carry from low to high */
+    ctx->bits[1] += len >> 29;
+
+    t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
+
+    /* Handle any leading odd-sized chunks */
+
+    if (t) {
+        unsigned char *p = (unsigned char *) ctx->in + t;
+
+        t = 64 - t;
+        if (len < t) {
+            memmove(p, buf, len);
+            return;
+        }
+        memmove(p, buf, t);
+        byteReverse(ctx->in, 16);
+        lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
+        buf += t;
+        len -= t;
+    }
+    /* Process data in 64-byte chunks */
+
+    while (len >= 64) {
+        memmove(ctx->in, buf, 64);
+        byteReverse(ctx->in, 16);
+        lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
+        buf += 64;
+        len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+
+    memmove(ctx->in, buf, len);
+}
 
 /*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
  */
+void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
+{
+    unsigned int count;
+    unsigned char *p;
 
+    /* Compute number of bytes mod 64 */
+    count = (ctx->bits[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8) {
+        /* Two lots of padding:  Pad the first block to 64 bytes */
+        memset(p, 0, count);
+        byteReverse(ctx->in, 16);
+        lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
+
+        /* Now fill the next block with 56 bytes */
+        memset(ctx->in, 0, 56);
+    } else {
+        /* Pad block to 56 bytes */
+        memset(p, 0, count - 8);
+    }
+    byteReverse(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ((uint32 *) ctx->in)[14] = ctx->bits[0];
+    ((uint32 *) ctx->in)[15] = ctx->bits[1];
+
+    lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
+    byteReverse((unsigned char *) ctx->buf, 4);
+    memmove(digest, ctx->buf, 16);
+    memset(ctx, 0, sizeof(ctx));        /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+        ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
+{
+    register uint32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
 
index 45934ad4643d2edabdbf882ff10c5f8d230599f0..efa1f53dcc2ef5b5311d607ef2b9b4f2b49603db 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
    +----------------------------------------------------------------------+
    | PHP Version 5                                                        |
@@ -18,7 +17,7 @@
 */
 
 /*
-Copyright (c) 2007, Lite Speed Technologies Inc.
+Copyright (c) 2002-2014, Lite Speed Technologies Inc.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -49,6 +48,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
 
+/***************************************************************************
+                          lsapilib.h  -  description
+                             -------------------
+    begin                : Mon Feb 21 2005
+    copyright            : (C) 2005 by George Wang
+    email                : gwang@litespeedtech.com
+ ***************************************************************************/
 
 
 #ifndef  _LSAPILIB_H_
@@ -118,7 +124,8 @@ typedef struct lsapi_request
     char            * m_pRequestMethod;
     int               m_totalLen;
     int               m_reqState;
-    int               m_reqBodyRead;
+    off_t             m_reqBodyLen;
+    off_t             m_reqBodyRead;
     int               m_bufProcessed;
     int               m_bufRead;
     
@@ -126,6 +133,7 @@ typedef struct lsapi_request
     
     struct lsapi_resp_header          m_respHeader;
     short                             m_respHeaderLen[LSAPI_MAX_RESP_HEADERS];
+    void            * m_pAppData;
 
 }LSAPI_Request;
 
@@ -170,22 +178,30 @@ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
 char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name );
             
 
-int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int len );
+ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t len );
 
 int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq );
 
-int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF );
+int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF );
 
 
 int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq );
 
-int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len );
+ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len );
+
+ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size );
 
-int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len );
+ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len );
 
 int LSAPI_Flush_r( LSAPI_Request * pReq );
 
-int LSAPI_AppendRespHeader_r( LSAPI_Request * pHeader, char * pBuf, int len );
+int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len );
+
+int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, 
+                              const char * pHeaderValue );
+
+int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
+                         const char * pBody, int bodyLen );
 
 static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code )
 {
@@ -195,6 +211,21 @@ static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code )
     return 0;
 }
 
+static inline int LSAPI_SetAppData_r( LSAPI_Request * pReq, void * data )
+{
+    if ( !pReq )
+        return -1;
+    pReq->m_pAppData = data;
+    return 0;
+}
+
+static inline void * LSAPI_GetAppData_r( LSAPI_Request * pReq )
+{
+    if ( !pReq )
+        return NULL;
+    return pReq->m_pAppData;
+}
+
 static inline char * LSAPI_GetQueryString_r( LSAPI_Request * pReq )
 {
     if ( pReq )
@@ -228,21 +259,22 @@ static inline char * LSAPI_GetRequestMethod_r( LSAPI_Request * pReq)
 
 
 
-static inline int  LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq )
+static inline off_t LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq )
 {
     if ( pReq )
-        return pReq->m_pHeader->m_reqBodyLen;
+        return pReq->m_reqBodyLen;
     return -1;
 }
 
-static inline int LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq )
+static inline off_t LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq )
 {
     if ( pReq )
-        return pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
+        return pReq->m_reqBodyLen - pReq->m_reqBodyRead;
     return -1;
 }
 
 
+
 int LSAPI_Is_Listen(void);
 
 static inline int LSAPI_Accept( void )
@@ -282,13 +314,13 @@ static inline char * LSAPI_GetScriptName()
 static inline char * LSAPI_GetRequestMethod()
 {   return LSAPI_GetRequestMethod_r( &g_req );              }
 
-static inline int LSAPI_GetReqBodyLen()
+static inline off_t LSAPI_GetReqBodyLen()
 {   return LSAPI_GetReqBodyLen_r( &g_req );                 }
 
-static inline int LSAPI_GetReqBodyRemain()
+static inline off_t LSAPI_GetReqBodyRemain()
 {   return LSAPI_GetReqBodyRemain_r( &g_req );                 }
 
-static inline int LSAPI_ReadReqBody( char * pBuf, int len )
+static inline ssize_t LSAPI_ReadReqBody( char * pBuf, size_t len )
 {   return LSAPI_ReadReqBody_r( &g_req, pBuf, len );        }
 
 static inline int LSAPI_ReqBodyGetChar()
@@ -302,10 +334,15 @@ static inline int LSAPI_ReqBodyGetLine( char * pBuf, int len, int *getLF )
 static inline int LSAPI_FinalizeRespHeaders(void)
 {   return LSAPI_FinalizeRespHeaders_r( &g_req );           }
 
-static inline int LSAPI_Write( const char * pBuf, int len )
+static inline ssize_t LSAPI_Write( const char * pBuf, ssize_t len )
 {   return LSAPI_Write_r( &g_req, pBuf, len );              }
 
-static inline int LSAPI_Write_Stderr( const char * pBuf, int len )
+static inline ssize_t LSAPI_sendfile( int fdIn, off_t* off, size_t size )
+{
+    return LSAPI_sendfile_r(&g_req, fdIn, off, size );          
+}
+
+static inline ssize_t LSAPI_Write_Stderr( const char * pBuf, ssize_t len )
 {   return LSAPI_Write_Stderr_r( &g_req, pBuf, len );       }
 
 static inline int LSAPI_Flush()
@@ -317,6 +354,9 @@ static inline int LSAPI_AppendRespHeader( char * pBuf, int len )
 static inline int LSAPI_SetRespStatus( int code )
 {   return LSAPI_SetRespStatus_r( &g_req, code );           }
 
+static inline int LSAPI_ErrResponse( int code, const char ** pRespHeaders, const char * pBody, int bodyLen )
+{   return LSAPI_ErrResponse_r( &g_req, code, pRespHeaders, pBody, bodyLen );   }
+
 int LSAPI_IsRunning(void);
 
 int LSAPI_CreateListenSock( const char * pBind, int backlog );
@@ -341,12 +381,13 @@ void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle );
 
 void LSAPI_Set_Max_Process_Time( int secs );
 
-void LSAPI_Init_Env_Parameters( fn_select_t fp );
+int LSAPI_Init_Env_Parameters( fn_select_t fp );
 
 void LSAPI_Set_Slow_Req_Msecs( int msecs );
 
 int  LSAPI_Get_Slow_Req_Msecs( );
 
+int LSAPI_is_suEXEC_Daemon();
 
 #if defined (c_plusplus) || defined (__cplusplus)
 }