summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2014-07-17 12:06:12 +0800
committerXinchen Hui <laruence@php.net>2014-07-17 12:06:12 +0800
commit21654a671f1656ff43274faa6ded773000abac2f (patch)
treede37bcf7a044266c81e70e84b1ee37678a4a505a
parent41eb63e78f8e4a04b3d634cfac6fbc5b3c1adb99 (diff)
parent7446c81aed7d085f05dae0d785c7f49109bc44ec (diff)
downloadphp-git-21654a671f1656ff43274faa6ded773000abac2f.tar.gz
Merge branch 'PHP-5.5' of https://git.php.net/repository/php-src into PHP-5.5
-rw-r--r--NEWS3
-rw-r--r--ext/intl/tests/collator_get_locale.phpt2
-rw-r--r--ext/standard/basic_functions.c3
-rw-r--r--ext/standard/string.c11
-rw-r--r--ext/standard/tests/strings/ucwords_error.phpt6
-rw-r--r--ext/standard/tests/strings/ucwords_variation5.phpt25
-rw-r--r--ext/zlib/tests/bug65391.phpt2
-rw-r--r--sapi/cgi/tests/bug61605.phpt2
-rw-r--r--sapi/cli/php_cli_server.c12
-rw-r--r--sapi/litespeed/Makefile.frag2
-rw-r--r--sapi/litespeed/lsapi_main.c1369
-rw-r--r--sapi/litespeed/lsapidef.h8
-rw-r--r--sapi/litespeed/lsapilib.c2497
-rw-r--r--sapi/litespeed/lsapilib.h76
-rw-r--r--tests/basic/025.phpt1
-rw-r--r--win32/build/Makefile.phpize8
-rw-r--r--win32/build/confutils.js153
-rw-r--r--win32/build/phpize.js.in2
18 files changed, 2980 insertions, 1202 deletions
diff --git a/NEWS b/NEWS
index bd76438534..cea00519e2 100644
--- a/NEWS
+++ b/NEWS
@@ -17,12 +17,15 @@ PHP NEWS
. Fixed bug #67151 (strtr with empty array crashes). (Nikita)
. Fixed bug #67407 (Windows 8.1/Server 2012 R2 reported as Windows 8/Server
2012). (Christian Wenz)
+ . Implemented FR #34407 (ucwords and Title Case). (Tjerk)
- CLI server:
. Implemented FR #67429 (CLI server is missing some new HTTP response codes).
(Adam)
. Fixed bug #66830 (Empty header causes PHP built-in web server to hang).
(Adam)
+ . Fixed bug #67594 (Unable to access to apache_request_headers() elements).
+ (Tjerk)
- FPM:
. Fixed bug #67530 (error_log=syslog ignored). (Remi)
diff --git a/ext/intl/tests/collator_get_locale.phpt b/ext/intl/tests/collator_get_locale.phpt
index 68440f3ee7..e71a020b4b 100644
--- a/ext/intl/tests/collator_get_locale.phpt
+++ b/ext/intl/tests/collator_get_locale.phpt
@@ -3,6 +3,8 @@ get_locale() icu <= 4.2
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '4.3', '<') != 1) print 'skip'; ?>
+--INI--
+precision=6
--FILE--
<?php
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index d23c050ac4..ace6540a04 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -2324,8 +2324,9 @@ ZEND_BEGIN_ARG_INFO(arginfo_lcfirst, 0)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO(arginfo_ucwords, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ucwords, 0, 0, 1)
ZEND_ARG_INFO(0, str)
+ ZEND_ARG_INFO(0, delimiters)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_strtr, 0, 0, 2)
diff --git a/ext/standard/string.c b/ext/standard/string.c
index a63bea09ff..62122cf1dc 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -2743,11 +2743,12 @@ PHP_FUNCTION(lcfirst)
Uppercase the first character of every word in a string */
PHP_FUNCTION(ucwords)
{
- char *str;
+ char *str, *delims = " \t\r\n\f\v";
register char *r, *r_end;
- int str_len;
+ int str_len, delims_len = 6;
+ char mask[256];
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &delims, &delims_len) == FAILURE) {
return;
}
@@ -2755,12 +2756,14 @@ PHP_FUNCTION(ucwords)
RETURN_EMPTY_STRING();
}
+ php_charmask((unsigned char *)delims, delims_len, mask TSRMLS_CC);
+
ZVAL_STRINGL(return_value, str, str_len, 1);
r = Z_STRVAL_P(return_value);
*r = toupper((unsigned char) *r);
for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) {
- if (isspace((int) *(unsigned char *)r++)) {
+ if (mask[(unsigned char)*r++]) {
*r = toupper((unsigned char) *r);
}
}
diff --git a/ext/standard/tests/strings/ucwords_error.phpt b/ext/standard/tests/strings/ucwords_error.phpt
index d79e569cc7..a01c688c4a 100644
--- a/ext/standard/tests/strings/ucwords_error.phpt
+++ b/ext/standard/tests/strings/ucwords_error.phpt
@@ -18,7 +18,7 @@ echo "\n-- Testing ucwords() function with more than expected no. of arguments -
$str = 'string_val';
$extra_arg = 10;
-var_dump( ucwords($str, $extra_arg) );
+var_dump( ucwords($str, $extra_arg, $extra_arg) );
// check if there were any changes made to $str
var_dump($str);
@@ -30,12 +30,12 @@ echo "Done\n";
-- Testing ucwords() function with Zero arguments --
-Warning: ucwords() expects exactly 1 parameter, 0 given in %s on line %d
+Warning: ucwords() expects at least 1 parameter, 0 given in %s on line %d
NULL
-- Testing ucwords() function with more than expected no. of arguments --
-Warning: ucwords() expects exactly 1 parameter, 2 given in %s on line %d
+Warning: ucwords() expects at most 2 parameters, 3 given in %s on line %d
NULL
string(10) "string_val"
Done
diff --git a/ext/standard/tests/strings/ucwords_variation5.phpt b/ext/standard/tests/strings/ucwords_variation5.phpt
new file mode 100644
index 0000000000..985df47c4a
--- /dev/null
+++ b/ext/standard/tests/strings/ucwords_variation5.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Test ucwords() function : usage variations - custom delimiters
+--FILE--
+<?php
+/* Prototype : string ucwords ( string $str )
+ * Description: Uppercase the first character of each word in a string
+ * Source code: ext/standard/string.c
+*/
+
+echo "*** Testing ucwords() : usage variations ***\n";
+
+var_dump(ucwords('testing-dashed-words', '-'));
+var_dump(ucwords('test(braced)words', '()'));
+var_dump(ucwords('testing empty delimiters', ''));
+var_dump(ucwords('testing ranges', 'a..e'));
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing ucwords() : usage variations ***
+string(%d) "Testing-Dashed-Words"
+string(%d) "Test(Braced)Words"
+string(%d) "Testing empty delimiters"
+string(%d) "TeSting raNgeS"
+Done
diff --git a/ext/zlib/tests/bug65391.phpt b/ext/zlib/tests/bug65391.phpt
index 3ba5350810..a93c2c0158 100644
--- a/ext/zlib/tests/bug65391.phpt
+++ b/ext/zlib/tests/bug65391.phpt
@@ -6,6 +6,8 @@ extension_loaded("zlib") or die("skip need zlib");
?>
--GET--
dummy=1
+--INI--
+expose_php=On
--FILE--
<?php
header("Vary: Cookie");
diff --git a/sapi/cgi/tests/bug61605.phpt b/sapi/cgi/tests/bug61605.phpt
index c6e4cf20ca..9c29e6dda2 100644
--- a/sapi/cgi/tests/bug61605.phpt
+++ b/sapi/cgi/tests/bug61605.phpt
@@ -4,6 +4,8 @@ Bug #61605 (header_remove() does not remove all headers)
<?php include "skipif.inc"; ?>
--GET--
foo=bar
+--INI--
+expose_php=On
--FILE--
<?php
header("A: first");
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 15b4f29bf3..6cefa2de9f 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -1685,10 +1685,14 @@ static int php_cli_server_client_read_request_on_header_value(php_http_parser *p
return 1;
}
{
- char *header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len);
- zend_hash_add(&client->request.headers, header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL);
- zend_hash_add(&client->request.headers_original_case, client->current_header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL);
- efree(header_name);
+ /* strip off the colon */
+ char *orig_header_name = estrndup(client->current_header_name, client->current_header_name_len);
+ char *lc_header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len);
+
+ zend_hash_add(&client->request.headers, lc_header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL);
+ zend_hash_add(&client->request.headers_original_case, orig_header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL);
+ efree(lc_header_name);
+ efree(orig_header_name);
}
if (client->current_header_name_allocated) {
diff --git a/sapi/litespeed/Makefile.frag b/sapi/litespeed/Makefile.frag
index b70e5e8702..767c2e5eb1 100644
--- a/sapi/litespeed/Makefile.frag
+++ b/sapi/litespeed/Makefile.frag
@@ -4,6 +4,6 @@ $(SAPI_LITESPEED_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_LITESPEED_OB
$(BUILD_LITESPEED)
install-litespeed: $(SAPI_LITESPEED_PATH)
- @echo "Installing PHP LitSpeed binary: $(INSTALL_ROOT)$(bindir)/"
+ @echo "Installing PHP LiteSpeed binary: $(INSTALL_ROOT)$(bindir)/"
@$(INSTALL) -m 0755 $(SAPI_LITESPEED_PATH) $(INSTALL_ROOT)$(bindir)/lsphp
diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c
index 52c39f1b6c..3413a423ac 100644
--- a/sapi/litespeed/lsapi_main.c
+++ b/sapi/litespeed/lsapi_main.c
@@ -16,8 +16,6 @@
+----------------------------------------------------------------------+
*/
-/* $Id$ */
-
#include "php.h"
#include "SAPI.h"
#include "php_main.h"
@@ -75,7 +73,9 @@ 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
zend_compiler_globals *compiler_globals;
zend_executor_globals *executor_globals;
@@ -90,40 +90,65 @@ zend_module_entry litespeed_module_entry;
*/
static int php_lsapi_startup(sapi_module_struct *sapi_module)
{
- if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
- return FAILURE;
- }
- return SUCCESS;
+ if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
+ return FAILURE;
+ }
+ argv0 = sapi_module->executable_location;
+ return SUCCESS;
}
/* }}} */
+/* {{{ sapi_lsapi_ini_defaults */
+
+/* overwriteable ini defaults must be set in sapi_cli_ini_defaults() */
+#define INI_DEFAULT(name,value)\
+ ZVAL_STRING(tmp, value, 0);\
+ zend_hash_update(configuration_hash, name, sizeof(name), tmp, sizeof(zval), (void**)&entry);\
+ Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry))
+
+static void sapi_lsapi_ini_defaults(HashTable *configuration_hash)
+{
+ zval *tmp, *entry;
+
+#if PHP_MAJOR_VERSION > 4
+/*
+ MAKE_STD_ZVAL(tmp);
+
+ INI_DEFAULT("register_long_arrays", "0");
+
+ FREE_ZVAL(tmp);
+*/
+#endif
+
+}
+/* }}} */
/* {{{ sapi_lsapi_ub_write
*/
static int sapi_lsapi_ub_write(const char *str, uint str_length TSRMLS_DC)
{
- int ret;
- int remain;
- if ( lsapi_mode ) {
- ret = LSAPI_Write( str, str_length );
- if ( ret < str_length ) {
- php_handle_aborted_connection();
- return str_length - ret;
- }
- } else {
- remain = str_length;
- while( remain > 0 ) {
- ret = write( 1, str, remain );
- if ( ret <= 0 ) {
- php_handle_aborted_connection();
- return str_length - remain;
- }
- str += ret;
- remain -= ret;
- }
- }
- return str_length;
+ int ret;
+ int remain;
+ if ( lsapi_mode ) {
+ ret = LSAPI_Write( str, str_length );
+ if ( ret < str_length ) {
+ php_handle_aborted_connection();
+ return str_length - ret;
+ }
+ } else {
+ remain = str_length;
+ while( remain > 0 ) {
+ ret = write( 1, str, remain );
+ if ( ret <= 0 ) {
+ php_handle_aborted_connection();
+ return str_length - remain;
+ }
+ str += ret;
+ remain -= ret;
+ }
+ }
+ return str_length;
}
/* }}} */
@@ -132,11 +157,11 @@ static int sapi_lsapi_ub_write(const char *str, uint str_length TSRMLS_DC)
*/
static void sapi_lsapi_flush( void * server_context )
{
- if ( lsapi_mode ) {
- if ( LSAPI_Flush() == -1) {
- php_handle_aborted_connection();
- }
- }
+ if ( lsapi_mode ) {
+ if ( LSAPI_Flush() == -1) {
+ php_handle_aborted_connection();
+ }
+ }
}
/* }}} */
@@ -145,8 +170,12 @@ static void sapi_lsapi_flush( void * server_context )
*/
static int sapi_lsapi_deactivate(TSRMLS_D)
{
- LSAPI_Finish();
- return SUCCESS;
+ if ( SG(request_info).path_translated )
+ {
+ efree( SG(request_info).path_translated );
+ }
+
+ return SUCCESS;
}
/* }}} */
@@ -157,46 +186,99 @@ static int sapi_lsapi_deactivate(TSRMLS_D)
*/
static char *sapi_lsapi_getenv( char * name, size_t name_len TSRMLS_DC )
{
- if ( lsapi_mode ) {
- return LSAPI_GetEnv( name );
- } else {
- return getenv( name );
- }
+ if ( lsapi_mode ) {
+ return LSAPI_GetEnv( name );
+ } else {
+ return getenv( name );
+ }
}
/* }}} */
+/*
+static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen,
+ void * arg )
+{
+ php_register_variable_safe((char *)pKey, (char *)pValue, valLen, (zval *)arg TSRMLS_CC);
+ return 1;
+}
+*/
static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen,
- void * arg )
+ void * arg )
{
- php_register_variable_safe((char *)pKey, (char *)pValue, valLen, (zval *)arg TSRMLS_CC);
- return 1;
+ zval * gpc_element, **gpc_element_p;
+ HashTable * symtable1 = Z_ARRVAL_P((zval * )arg);
+ register char * pKey1 = (char *)pKey;
+
+ MAKE_STD_ZVAL(gpc_element);
+ Z_STRLEN_P( gpc_element ) = valLen;
+ Z_STRVAL_P( gpc_element ) = estrndup(pValue, valLen);
+ Z_TYPE_P( gpc_element ) = IS_STRING;
+#if PHP_MAJOR_VERSION > 4
+ zend_symtable_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
+#else
+ zend_hash_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
+#endif
+ return 1;
}
+#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
+static int add_variable_magic_quote( const char * pKey, int keyLen, const char * pValue, int valLen,
+ void * arg )
+{
+ zval * gpc_element, **gpc_element_p;
+ HashTable * symtable1 = Z_ARRVAL_P((zval * )arg);
+ register char * pKey1 = (char *)pKey;
+
+ MAKE_STD_ZVAL(gpc_element);
+ Z_STRLEN_P( gpc_element ) = valLen;
+ Z_STRVAL_P( gpc_element ) = php_addslashes((char *)pValue, valLen, &Z_STRLEN_P( gpc_element ), 0 );
+ Z_TYPE_P( gpc_element ) = IS_STRING;
+#if PHP_MAJOR_VERSION > 4
+ zend_symtable_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
+#else
+ zend_hash_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
+#endif
+ return 1;
+}
+
+#endif
/* {{{ sapi_lsapi_register_variables
*/
static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC)
{
+ char * php_self = "";
+ if ( lsapi_mode ) {
+ if ( (SG(request_info).request_uri ) )
+ php_self = (SG(request_info).request_uri );
- if ( lsapi_mode ) {
- LSAPI_ForeachHeader( add_variable, track_vars_array );
- LSAPI_ForeachEnv( add_variable, track_vars_array );
- php_import_environment_variables(track_vars_array TSRMLS_CC);
-
- php_register_variable("PHP_SELF", (SG(request_info).request_uri ? SG(request_info).request_uri:""), track_vars_array TSRMLS_CC);
- } else {
- php_import_environment_variables(track_vars_array TSRMLS_CC);
+#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
+ if (!PG(magic_quotes_gpc)) {
+#endif
+ LSAPI_ForeachHeader( add_variable, track_vars_array );
+ LSAPI_ForeachEnv( add_variable, track_vars_array );
+ add_variable("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array );
+#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
+ } else {
+ LSAPI_ForeachHeader( add_variable_magic_quote, track_vars_array );
+ LSAPI_ForeachEnv( add_variable_magic_quote, track_vars_array );
+ add_variable_magic_quote("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array );
+ }
+#endif
+ php_import_environment_variables(track_vars_array TSRMLS_CC);
+ } else {
+ php_import_environment_variables(track_vars_array TSRMLS_CC);
- php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC);
- php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC);
- php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC);
- php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC);
- php_register_variable("DOCUMENT_ROOT", "", track_vars_array TSRMLS_CC);
+ php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC);
+ php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC);
+ php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC);
+ php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC);
+ php_register_variable("DOCUMENT_ROOT", "", track_vars_array TSRMLS_CC);
- }
+ }
}
/* }}} */
@@ -205,11 +287,11 @@ 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 );
- } else {
- return 0;
- }
+ if ( lsapi_mode ) {
+ return LSAPI_ReadReqBody( buffer, (unsigned long long)count_bytes );
+ } else {
+ return 0;
+ }
}
/* }}} */
@@ -220,11 +302,11 @@ static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
*/
static char *sapi_lsapi_read_cookies(TSRMLS_D)
{
- if ( lsapi_mode ) {
- return LSAPI_GetHeader( H_COOKIE );
- } else {
- return NULL;
- }
+ if ( lsapi_mode ) {
+ return LSAPI_GetHeader( H_COOKIE );
+ } else {
+ return NULL;
+ }
}
/* }}} */
@@ -233,33 +315,33 @@ static char *sapi_lsapi_read_cookies(TSRMLS_D)
*/
static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
- sapi_header_struct *h;
- zend_llist_position pos;
- if ( lsapi_mode ) {
- LSAPI_SetRespStatus( SG(sapi_headers).http_response_code );
-
- h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
- while (h) {
- if ( h->header_len > 0 ) {
- LSAPI_AppendRespHeader(h->header, h->header_len);
- }
- h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
- }
- if (SG(sapi_headers).send_default_content_type) {
- char *hd;
- int len;
- char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
-
- hd = sapi_get_default_content_type(TSRMLS_C);
- len = snprintf( headerBuf, SAPI_LSAPI_MAX_HEADER_LENGTH - 1,
- "Content-type: %s", hd );
- efree(hd);
-
- LSAPI_AppendRespHeader( headerBuf, len );
- }
- }
- LSAPI_FinalizeRespHeaders();
- return SAPI_HEADER_SENT_SUCCESSFULLY;
+ sapi_header_struct *h;
+ zend_llist_position pos;
+ if ( lsapi_mode ) {
+ LSAPI_SetRespStatus( SG(sapi_headers).http_response_code );
+
+ h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
+ while (h) {
+ if ( h->header_len > 0 ) {
+ LSAPI_AppendRespHeader(h->header, h->header_len);
+ }
+ h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
+ }
+ if (SG(sapi_headers).send_default_content_type) {
+ char *hd;
+ int len;
+ char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
+
+ hd = sapi_get_default_content_type(TSRMLS_C);
+ len = snprintf( headerBuf, SAPI_LSAPI_MAX_HEADER_LENGTH - 1,
+ "Content-type: %s", hd );
+ efree(hd);
+
+ LSAPI_AppendRespHeader( headerBuf, len );
+ }
+ }
+ LSAPI_FinalizeRespHeaders();
+ return SAPI_HEADER_SENT_SUCCESSFULLY;
}
@@ -270,8 +352,15 @@ static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
*/
static void sapi_lsapi_log_message(char *message TSRMLS_DC)
{
- int len = strlen( message );
- LSAPI_Write_Stderr( message, len);
+ 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);
}
/* }}} */
@@ -280,158 +369,251 @@ static void sapi_lsapi_log_message(char *message TSRMLS_DC)
*/
static sapi_module_struct lsapi_sapi_module =
{
- "litespeed",
- "LiteSpeed",
+ "litespeed",
+ "LiteSpeed V6.6",
- php_lsapi_startup, /* startup */
- php_module_shutdown_wrapper, /* shutdown */
+ php_lsapi_startup, /* startup */
+ php_module_shutdown_wrapper, /* shutdown */
- NULL, /* activate */
- sapi_lsapi_deactivate, /* deactivate */
+ NULL, /* activate */
+ sapi_lsapi_deactivate, /* deactivate */
- sapi_lsapi_ub_write, /* unbuffered write */
- sapi_lsapi_flush, /* flush */
- NULL, /* get uid */
- sapi_lsapi_getenv, /* getenv */
+ sapi_lsapi_ub_write, /* unbuffered write */
+ sapi_lsapi_flush, /* flush */
+ NULL, /* get uid */
+ sapi_lsapi_getenv, /* getenv */
- php_error, /* error handler */
+ php_error, /* error handler */
- NULL, /* header handler */
- sapi_lsapi_send_headers, /* send headers handler */
- NULL, /* send header handler */
+ NULL, /* header handler */
+ sapi_lsapi_send_headers, /* send headers handler */
+ NULL, /* send header handler */
- sapi_lsapi_read_post, /* read POST data */
- sapi_lsapi_read_cookies, /* read Cookies */
+ sapi_lsapi_read_post, /* read POST data */
+ sapi_lsapi_read_cookies, /* read Cookies */
- sapi_lsapi_register_variables, /* register server variables */
- sapi_lsapi_log_message, /* Log message */
+ sapi_lsapi_register_variables, /* register server variables */
+ sapi_lsapi_log_message, /* Log message */
- NULL, /* php.ini path override */
- NULL, /* block interruptions */
- NULL, /* unblock interruptions */
- NULL, /* default post reader */
- NULL, /* treat data */
- NULL, /* executable location */
+ NULL, /* php.ini path override */
+ NULL, /* block interruptions */
+ NULL, /* unblock interruptions */
+ NULL, /* default post reader */
+ NULL, /* treat data */
+ NULL, /* executable location */
- 0, /* php.ini ignore */
+ 0, /* php.ini ignore */
- STANDARD_SAPI_MODULE_PROPERTIES
+ STANDARD_SAPI_MODULE_PROPERTIES
};
/* }}} */
static int init_request_info( TSRMLS_D )
{
- char * pContentType = LSAPI_GetHeader( H_CONTENT_TYPE );
- char * pAuth;
-
- SG(request_info).content_type = pContentType ? pContentType : "";
- SG(request_info).request_method = LSAPI_GetRequestMethod();
- SG(request_info).query_string = LSAPI_GetQueryString();
- SG(request_info).request_uri = LSAPI_GetScriptName();
- SG(request_info).content_length = LSAPI_GetReqBodyLen();
- SG(request_info).path_translated = LSAPI_GetScriptFileName();
+ char * pContentType = LSAPI_GetHeader( H_CONTENT_TYPE );
+ char * pAuth;
+
+ SG(request_info).content_type = pContentType ? pContentType : "";
+ SG(request_info).request_method = LSAPI_GetRequestMethod();
+ SG(request_info).query_string = LSAPI_GetQueryString();
+ SG(request_info).request_uri = LSAPI_GetScriptName();
+ SG(request_info).content_length = LSAPI_GetReqBodyLen();
+ SG(request_info).path_translated = estrdup( LSAPI_GetScriptFileName());
+
+ /* It is not reset by zend engine, set it to 0. */
+ SG(sapi_headers).http_response_code = 0;
+
+ pAuth = LSAPI_GetHeader( H_AUTHORIZATION );
+ php_handle_auth_data(pAuth TSRMLS_CC);
+}
- /* It is not reset by zend engine, set it to 0. */
- SG(sapi_headers).http_response_code = 0;
-
- pAuth = LSAPI_GetHeader( H_AUTHORIZATION );
- php_handle_auth_data(pAuth TSRMLS_CC);
+static char s_cur_chdir[4096] = "";
+
+static int lsapi_chdir_primary_script( zend_file_handle * file_handle )
+{
+#if PHP_MAJOR_VERSION > 4
+ char * p;
+ char ch;
+
+ SG(options) |= SAPI_OPTION_NO_CHDIR;
+ getcwd( s_cur_chdir, sizeof( s_cur_chdir ) );
+
+ p = strrchr( file_handle->filename, '/' );
+ if ( *p )
+ {
+ *p = 0;
+ if ( strcmp( file_handle->filename, s_cur_chdir ) != 0 ) {
+ chdir( file_handle->filename );
+ }
+ *p++ = '/';
+ ch = *p;
+ *p = 0;
+ if ( !CWDG(cwd).cwd ||
+ ( strcmp( file_handle->filename, CWDG(cwd).cwd ) != 0 ) ) {
+ CWDG(cwd).cwd_length = p - file_handle->filename;
+ CWDG(cwd).cwd = (char *) realloc(CWDG(cwd).cwd, CWDG(cwd).cwd_length+1);
+ memmove( CWDG(cwd).cwd, file_handle->filename, CWDG(cwd).cwd_length+1 );
+ }
+ *p = ch;
+ }
+ /* virtual_file_ex(&CWDG(cwd), file_handle->filename, NULL, CWD_REALPATH); */
+#else
+ VCWD_CHDIR_FILE( file_handle->filename );
+#endif
+ return 0;
}
-static int lsapi_module_main(int show_source TSRMLS_DC)
+static int lsapi_fopen_primary_script( zend_file_handle * file_handle )
+{
+ FILE * fp;
+ char * p;
+ fp = fopen( SG(request_info).path_translated, "rb" );
+ if ( !fp )
+ {
+ return -1;
+ }
+ file_handle->type = ZEND_HANDLE_FP;
+ file_handle->handle.fp = fp;
+ file_handle->filename = SG(request_info).path_translated;
+ file_handle->free_filename = 0;
+ file_handle->opened_path = NULL;
+
+ lsapi_chdir_primary_script( file_handle );
+
+ return 0;
+}
+
+static int lsapi_execute_script( zend_file_handle * file_handle TSRMLS_DC)
{
- zend_file_handle file_handle = {0};
+ char *p;
+ int len;
+ file_handle->type = ZEND_HANDLE_FILENAME;
+ file_handle->handle.fd = 0;
+ file_handle->filename = SG(request_info).path_translated;
+ file_handle->free_filename = 0;
+ file_handle->opened_path = NULL;
+
+ p = argv0;
+ *p++ = ':';
+ len = strlen( SG(request_info).path_translated );
+ if ( len > 45 )
+ len = len - 45;
+ else
+ len = 0;
+ memccpy( p, SG(request_info).path_translated + len, 0, 46 );
+
+ php_execute_script(file_handle TSRMLS_CC);
+ return 0;
- if (php_request_startup(TSRMLS_C) == FAILURE ) {
- return -1;
- }
- if (show_source) {
- 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 {
- file_handle.type = ZEND_HANDLE_FILENAME;
- file_handle.handle.fd = 0;
- file_handle.filename = SG(request_info).path_translated;
- file_handle.free_filename = 0;
- file_handle.opened_path = NULL;
- php_execute_script(&file_handle TSRMLS_CC);
- }
- zend_try {
- php_request_shutdown(NULL);
- } zend_end_try();
- return 0;
+static int lsapi_module_main(int show_source TSRMLS_DC)
+{
+ zend_file_handle file_handle = {0};
+
+ if (php_request_startup(TSRMLS_C) == FAILURE ) {
+ return -1;
+ }
+ if (show_source) {
+ 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 {
+ lsapi_execute_script( &file_handle TSRMLS_CC);
+ }
+ zend_try {
+ php_request_shutdown(NULL);
+ memset( argv0, 0, 46 );
+ } zend_end_try();
+ return 0;
}
static int alter_ini( const char * pKey, int keyLen, const char * pValue, int valLen,
- void * arg )
+ void * arg )
{
- int type = ZEND_INI_PERDIR;
- if ( '\001' == *pKey ) {
- ++pKey;
- if ( *pKey == 4 ) {
- type = ZEND_INI_SYSTEM;
- }
- ++pKey;
- --keyLen;
- zend_alter_ini_entry((char *)pKey, keyLen,
- (char *)pValue, valLen,
- type, PHP_INI_STAGE_ACTIVATE);
- }
- return 1;
+ int type = ZEND_INI_PERDIR;
+ if ( '\001' == *pKey ) {
+ ++pKey;
+ if ( *pKey == 4 ) {
+ type = ZEND_INI_SYSTEM;
+ }
+ ++pKey;
+ --keyLen;
+ if (( keyLen == 7 )&&( strncasecmp( pKey, "engine", 6 )== 0 ))
+ {
+ if ( *pValue == '0' )
+ engine = 0;
+ }
+ else
+ zend_alter_ini_entry((char *)pKey, keyLen,
+ (char *)pValue, valLen,
+ type, PHP_INI_STAGE_ACTIVATE);
+ }
+ return 1;
}
static void override_ini()
{
- LSAPI_ForeachSpecialEnv( alter_ini, NULL );
+ LSAPI_ForeachSpecialEnv( alter_ini, NULL );
}
+
static int processReq( TSRMLS_D )
{
- int ret = 0;
- zend_first_try {
- /* avoid server_context==NULL checks */
- SG(server_context) = (void *) 1;
-
- init_request_info( TSRMLS_C );
-
- override_ini();
-
- if ( lsapi_module_main( source_highlight TSRMLS_CC ) == -1 ) {
- ret = -1;
- }
- } zend_end_try();
- return ret;
+ int ret = 0;
+ zend_first_try {
+
+ /* avoid server_context==NULL checks */
+ SG(server_context) = (void *) 1;
+
+ engine = 1;
+ override_ini();
+
+ if ( engine ) {
+ init_request_info( TSRMLS_C );
+
+ if ( lsapi_module_main( source_highlight TSRMLS_CC ) == -1 ) {
+ ret = -1;
+ }
+ } else {
+ LSAPI_AppendRespHeader( "status: 403", 11 );
+ LSAPI_AppendRespHeader( "content-type: text/html", 23 );
+ LSAPI_Write( "Forbidden: PHP engine is disable.\n", 34 );
+ }
+ } zend_end_try();
+ return ret;
}
static void cli_usage( TSRMLS_D )
{
- static const char * usage =
- "Usage: php\n"
- " php -[b|c|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"
- " -h This help\n"
- " -i PHP information\n"
- " -q Quiet-mode. Suppress HTTP Header output.\n"
- " -s Display colour syntax highlighted source.\n"
- " -v Version number\n"
- " -? This help\n"
- "\n"
- " args... Arguments passed to script.\n";
- php_output_startup();
- php_output_activate(TSRMLS_C);
- php_printf( "%s", usage );
+ static const char * usage =
+ "Usage: php\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"
+ " -? This help\n"
+ "\n"
+ " args... Arguments passed to script.\n";
+ php_output_startup();
+ php_output_activate(TSRMLS_C);
+ php_printf( "%s", usage );
#ifdef PHP_OUTPUT_NEWAPI
php_output_end_all(TSRMLS_C);
#else
@@ -440,349 +622,419 @@ static void cli_usage( TSRMLS_D )
}
static int parse_opt( int argc, char * argv[], int *climode,
- char **php_ini_path, char ** php_bind )
-{
- char ** p = &argv[1];
- char ** argend= &argv[argc];
- int c;
- while (( p < argend )&&(**p == '-' )) {
- c = *((*p)+1);
- ++p;
- switch( c ) {
- case 'b':
- if ( p >= argend ) {
- fprintf( stderr, "TCP or socket address must be specified following '-b' option.\n");
- return -1;
- }
- *php_bind = *p++;
- break;
-
- case 'c':
- if ( p >= argend ) {
- fprintf( stderr, "<path> or <file> must be specified following '-c' option.\n");
-
- return -1;
- }
- *php_ini_path = *p++;
- break;
- case 's':
- source_highlight = 1;
- break;
- case 'h':
- case 'i':
- case 'q':
- case 'v':
- case '?':
- default:
- *climode = 1;
- break;
- }
- }
- if ( p - argv < argc ) {
- *climode = 1;
- }
- return 0;
+ char **php_ini_path, char ** php_bind )
+{
+ char ** p = &argv[1];
+ char ** argend= &argv[argc];
+ int c;
+ while (( p < argend )&&(**p == '-' )) {
+ c = *((*p)+1);
+ ++p;
+ switch( c ) {
+ case 'b':
+ if ( p >= argend ) {
+ fprintf( stderr, "TCP or socket address must be specified following '-b' option.\n");
+ return -1;
+ }
+ *php_bind = strdup(*p++);
+ break;
+
+ case 'c':
+ if ( p >= argend ) {
+ fprintf( stderr, "<path> or <file> must be specified following '-c' option.\n");
+
+ return -1;
+ }
+ *php_ini_path = strdup( *p++ );
+ break;
+ case 's':
+ source_highlight = 1;
+ 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':
+ default:
+ *climode = 1;
+ break;
+ }
+ }
+ if ( p - argv < argc ) {
+ *climode = 1;
+ }
+ return 0;
}
static int cli_main( int argc, char * argv[] )
{
- static const char * ini_defaults[] = {
- "report_zend_debug", "0",
- "display_errors", "1",
- "register_argc_argv", "1",
- "html_errors", "0",
- "implicit_flush", "1",
- "output_buffering", "0",
- "max_execution_time", "0",
- "max_input_time", "-1",
- NULL
- };
-
- const char ** ini;
- char ** p = &argv[1];
- char ** argend= &argv[argc];
- int ret = 0;
- int c;
- lsapi_mode = 0; /* enter CLI mode */
+ static const char * ini_defaults[] = {
+ "report_zend_debug", "0",
+ "display_errors", "1",
+ "register_argc_argv", "1",
+ "html_errors", "0",
+ "implicit_flush", "1",
+ "output_buffering", "0",
+ "max_execution_time", "0",
+ "max_input_time", "-1",
+ NULL
+ };
+
+ const char ** ini;
+ char ** p = &argv[1];
+ char ** argend= &argv[argc];
+ int ret = -1;
+ int c;
+ lsapi_mode = 0; /* enter CLI mode */
#ifdef PHP_WIN32
- _fmode = _O_BINARY; /*sets default for file streams to binary */
- setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */
- setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */
- setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
+ _fmode = _O_BINARY; /*sets default for file streams to binary */
+ setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */
+ setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */
+ setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
#endif
- zend_first_try {
- SG(server_context) = (void *) 1;
-
- zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */
- CG(in_compilation) = 0; /* not initialized but needed for several options */
- EG(uninitialized_zval_ptr) = NULL;
-
- for( ini = ini_defaults; *ini; ini+=2 ) {
- zend_alter_ini_entry( (char *)*ini, strlen( *ini )+1,
- (char *)*(ini+1), strlen( *(ini+1) ),
- PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
- }
-
- while (( p < argend )&&(**p == '-' )) {
- c = *((*p)+1);
- ++p;
- switch( c ) {
- case 'q':
- break;
- case 'i':
- if (php_request_startup(TSRMLS_C) != FAILURE) {
- php_print_info(0xFFFFFFFF TSRMLS_CC);
+ zend_first_try {
+ SG(server_context) = (void *) 1;
+
+ zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */
+ CG(in_compilation) = 0; /* not initialized but needed for several options */
+ EG(uninitialized_zval_ptr) = NULL;
+
+ for( ini = ini_defaults; *ini; ini+=2 ) {
+ zend_alter_ini_entry( (char *)*ini, strlen( *ini )+1,
+ (char *)*(ini+1), strlen( *(ini+1) ),
+ PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
+ }
+
+ while (( p < argend )&&(**p == '-' )) {
+ c = *((*p)+1);
+ ++p;
+ switch( c ) {
+ case 'q':
+ break;
+ case 'i':
+ if (php_request_startup(TSRMLS_C) != FAILURE) {
+ php_print_info(0xFFFFFFFF TSRMLS_CC);
#ifdef PHP_OUTPUT_NEWAPI
php_output_end_all(TSRMLS_C);
#else
php_end_ob_buffers(1 TSRMLS_CC);
#endif
- php_request_shutdown( NULL );
- }
- ret = 1;
- break;
- case 'v':
- if (php_request_startup(TSRMLS_C) != FAILURE) {
+ php_request_shutdown( NULL );
+ ret = 0;
+ }
+ break;
+ case 'v':
+ if (php_request_startup(TSRMLS_C) != FAILURE) {
#if ZEND_DEBUG
- php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#else
- php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#endif
#ifdef PHP_OUTPUT_NEWAPI
php_output_end_all(TSRMLS_C);
#else
php_end_ob_buffers(1 TSRMLS_CC);
#endif
- php_request_shutdown( NULL );
- }
- ret = 1;
- break;
- case 'c':
- ++p;
- /* fall through */
- case 's':
- break;
-
- case 'h':
- case '?':
- default:
- cli_usage(TSRMLS_C);
- ret = 1;
- break;
-
- }
- }
- if ( !ret ) {
- if ( *p ) {
- zend_file_handle file_handle = {0};
-
- file_handle.type = ZEND_HANDLE_FP;
- file_handle.handle.fp = VCWD_FOPEN(*p, "rb");
-
- if ( file_handle.handle.fp ) {
- script_filename = *p;
- php_self = *p;
-
- SG(request_info).path_translated = *p;
- SG(request_info).argc = argc - (p - argv);
- SG(request_info).argv = p;
-
- if (php_request_startup(TSRMLS_C) == FAILURE ) {
- fclose( file_handle.handle.fp );
- ret = 2;
- } else {
- if (source_highlight) {
- 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 {
- file_handle.filename = *p;
- file_handle.free_filename = 0;
- file_handle.opened_path = NULL;
-
- php_execute_script(&file_handle TSRMLS_CC);
- }
-
- php_request_shutdown( NULL );
- }
- } else {
- php_printf("Could not open input file: %s.\n", *p);
- }
- } else {
- cli_usage(TSRMLS_C);
- }
- }
-
- }zend_end_try();
-
- php_module_shutdown(TSRMLS_C);
+ php_request_shutdown( NULL );
+ ret = 0;
+ }
+ break;
+ case 'c':
+ ++p;
+ /* fall through */
+ case 's':
+ break;
+ case 'l':
+ source_highlight = 2;
+ break;
+ case 'h':
+ case '?':
+ default:
+ cli_usage(TSRMLS_C);
+ ret = 0;
+ break;
+
+ }
+ }
+ if ( ret == -1 ) {
+ if ( *p ) {
+ zend_file_handle file_handle = {0};
+
+ file_handle.type = ZEND_HANDLE_FP;
+ file_handle.handle.fp = VCWD_FOPEN(*p, "rb");
+
+ if ( file_handle.handle.fp ) {
+ script_filename = *p;
+ php_self = *p;
+
+ SG(request_info).path_translated = estrdup(*p);
+ SG(request_info).argc = argc - (p - argv);
+ SG(request_info).argv = p;
+
+ if (php_request_startup(TSRMLS_C) == FAILURE ) {
+ fclose( file_handle.handle.fp );
+ ret = 2;
+ } else {
+ 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 );
+ }
+ } else {
+ php_printf("Could not open input file: %s.\n", *p);
+ }
+ } else {
+ cli_usage(TSRMLS_C);
+ }
+ }
+
+ }zend_end_try();
+
+ php_module_shutdown(TSRMLS_C);
#ifdef ZTS
- tsrm_shutdown();
+ tsrm_shutdown();
#endif
- return ret;
+ return ret;
}
static int s_stop;
void litespeed_cleanup(int signal)
{
- s_stop = signal;
+ s_stop = signal;
}
void start_children( int children )
{
- struct sigaction act, old_term, old_quit, old_int, old_usr1;
- int running = 0;
- int status;
- pid_t pid;
-
- /* Create a process group */
- setsid();
-
- /* Set up handler to kill children upon exit */
- act.sa_flags = 0;
- act.sa_handler = litespeed_cleanup;
- if( sigaction( SIGTERM, &act, &old_term ) ||
- sigaction( SIGINT, &act, &old_int ) ||
- sigaction( SIGUSR1, &act, &old_usr1 ) ||
- sigaction( SIGQUIT, &act, &old_quit )) {
- perror( "Can't set signals" );
- exit( 1 );
- }
- s_stop = 0;
- while( 1 ) {
- while((!s_stop )&&( running < children )) {
- pid = fork();
- switch( pid ) {
- case 0: /* children process */
-
- /* don't catch our signals */
- sigaction( SIGTERM, &old_term, 0 );
- sigaction( SIGQUIT, &old_quit, 0 );
- sigaction( SIGINT, &old_int, 0 );
- sigaction( SIGUSR1, &old_usr1, 0 );
- return ;
- case -1:
- perror( "php (pre-forking)" );
- exit( 1 );
- break;
- default: /* parent process */
- running++;
- break;
- }
- }
- if ( s_stop ) {
- break;
- }
- pid = wait( &status );
- running--;
- }
- kill( -getpgrp(), SIGUSR1 );
- exit( 0 );
+ struct sigaction act, old_term, old_quit, old_int, old_usr1;
+ int running = 0;
+ int status;
+ pid_t pid;
+
+ /* Create a process group */
+ setsid();
+
+ /* Set up handler to kill children upon exit */
+ act.sa_flags = 0;
+ act.sa_handler = litespeed_cleanup;
+ if( sigaction( SIGTERM, &act, &old_term ) ||
+ sigaction( SIGINT, &act, &old_int ) ||
+ sigaction( SIGUSR1, &act, &old_usr1 ) ||
+ sigaction( SIGQUIT, &act, &old_quit )) {
+ perror( "Can't set signals" );
+ exit( 1 );
+ }
+ s_stop = 0;
+ while( 1 ) {
+ while((!s_stop )&&( running < children )) {
+ pid = fork();
+ switch( pid ) {
+ case 0: /* children process */
+
+ /* don't catch our signals */
+ sigaction( SIGTERM, &old_term, 0 );
+ sigaction( SIGQUIT, &old_quit, 0 );
+ sigaction( SIGINT, &old_int, 0 );
+ sigaction( SIGUSR1, &old_usr1, 0 );
+ return ;
+ case -1:
+ perror( "php (pre-forking)" );
+ exit( 1 );
+ break;
+ default: /* parent process */
+ running++;
+ break;
+ }
+ }
+ if ( s_stop ) {
+ break;
+ }
+ pid = wait( &status );
+ running--;
+ }
+ kill( -getpgrp(), SIGUSR1 );
+ 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[] )
{
- int ret;
- int bindFd;
-
- char * php_ini_path = NULL;
- char * php_bind = NULL;
- char * p;
- int n;
- int climode = 0;
-
+ int ret;
+ int bindFd;
+
+ char * php_ini_path = NULL;
+ char * php_bind = NULL;
+ int n;
+ int climode = 0;
+ struct timeval tv_req_begin;
+ struct timeval tv_req_end;
+ int slow_script_msec = 0;
+ char time_buf[40];
+
#ifdef HAVE_SIGNAL_H
#if defined(SIGPIPE) && defined(SIG_IGN)
- signal(SIGPIPE, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
#endif
#endif
#ifdef ZTS
- tsrm_startup(1, 1, 0, NULL);
+ tsrm_startup(1, 1, 0, NULL);
#endif
- if (argc > 1 ) {
- if ( parse_opt( argc, argv, &climode,
- &php_ini_path, &php_bind ) == -1 ) {
- return 1;
- }
- }
- if ( climode ) {
- lsapi_sapi_module.phpinfo_as_text = 1;
- }
- sapi_startup(&lsapi_sapi_module);
+ if (argc > 1 ) {
+ if ( parse_opt( argc, argv, &climode,
+ &php_ini_path, &php_bind ) == -1 ) {
+ return 1;
+ }
+ }
+ if ( climode ) {
+ lsapi_sapi_module.phpinfo_as_text = 1;
+ } else {
+ setArgv0(argc, argv );
+ }
+
+ sapi_startup(&lsapi_sapi_module);
#ifdef ZTS
- compiler_globals = ts_resource(compiler_globals_id);
- executor_globals = ts_resource(executor_globals_id);
- core_globals = ts_resource(core_globals_id);
- sapi_globals = ts_resource(sapi_globals_id);
- tsrm_ls = ts_resource(0);
+ compiler_globals = ts_resource(compiler_globals_id);
+ executor_globals = ts_resource(executor_globals_id);
+ core_globals = ts_resource(core_globals_id);
+ sapi_globals = ts_resource(sapi_globals_id);
+ tsrm_ls = ts_resource(0);
- SG(request_info).path_translated = NULL;
+ SG(request_info).path_translated = NULL;
#endif
- lsapi_sapi_module.executable_location = argv[0];
+ 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;
+ }
- if ( php_ini_path ) {
- lsapi_sapi_module.php_ini_path_override = php_ini_path;
- }
- if (php_module_startup(&lsapi_sapi_module, &litespeed_module_entry, 1) == FAILURE) {
+ lsapi_sapi_module.ini_defaults = sapi_lsapi_ini_defaults;
+
+ if (php_module_startup(&lsapi_sapi_module, &litespeed_module_entry, 1) == FAILURE) {
#ifdef ZTS
- tsrm_shutdown();
+ tsrm_shutdown();
#endif
- return FAILURE;
- }
-
- if ( climode ) {
- return cli_main(argc, argv);
- }
-
-
- if ( php_bind ) {
- bindFd = LSAPI_CreateListenSock( php_bind, 10 );
- if ( bindFd == -1 ) {
- fprintf( stderr,
- "Failed to bind socket [%s]: %s\n", php_bind, strerror( errno ) );
- exit( 2 );
- }
- if ( bindFd != 0 ) {
- dup2( bindFd, 0 );
- close( bindFd );
- }
- }
-
- LSAPI_Init();
+ return FAILURE;
+ }
+
+ if ( climode ) {
+ return cli_main(argc, argv);
+ }
+
+ if ( php_bind ) {
+ bindFd = LSAPI_CreateListenSock( php_bind, 10 );
+ if ( bindFd == -1 ) {
+ fprintf( stderr,
+ "Failed to bind socket [%s]: %s\n", php_bind, strerror( errno ) );
+ exit( 2 );
+ }
+ if ( bindFd != 0 ) {
+ dup2( bindFd, 0 );
+ close( bindFd );
+ }
+ }
+
+ LSAPI_Init();
- LSAPI_Init_Env_Parameters( NULL );
-
- if ( php_bind ) {
- LSAPI_No_Check_ppid();
- }
-
- while( LSAPI_Prefork_Accept_r( &g_req ) >= 0 ) {
- ret = processReq(TSRMLS_C);
- LSAPI_Finish();
- if ( ret ) {
- break;
- }
- }
- php_module_shutdown(TSRMLS_C);
+ LSAPI_Init_Env_Parameters( NULL );
+
+ slow_script_msec = LSAPI_Get_Slow_Req_Msecs();
+
+ if ( php_bind ) {
+ LSAPI_No_Check_ppid();
+ free( php_bind );
+ php_bind = NULL;
+ }
+
+ while( LSAPI_Prefork_Accept_r( &g_req ) >= 0 ) {
+ if ( slow_script_msec ) {
+ gettimeofday( &tv_req_begin, NULL );
+ }
+ ret = processReq(TSRMLS_C);
+ if ( slow_script_msec ) {
+ gettimeofday( &tv_req_end, NULL );
+ n = ((long) tv_req_end.tv_sec - tv_req_begin.tv_sec ) * 1000
+ + (tv_req_end.tv_usec - tv_req_begin.tv_usec) / 1000;
+ if ( n > slow_script_msec )
+ {
+ strftime( time_buf, 30, "%d/%b/%Y:%H:%M:%S", localtime( &tv_req_end.tv_sec ) );
+ fprintf( stderr, "[%s] Slow PHP script: %d ms\n URL: %s %s\n Query String: %s\n Script: %s\n",
+ time_buf, n, LSAPI_GetRequestMethod(),
+ LSAPI_GetScriptName(), LSAPI_GetQueryString(),
+ LSAPI_GetScriptFileName() );
+
+ }
+ }
+ LSAPI_Finish();
+ if ( ret ) {
+ break;
+ }
+ }
+ php_module_shutdown(TSRMLS_C);
#ifdef ZTS
- tsrm_shutdown();
+ tsrm_shutdown();
#endif
- return ret;
+ return ret;
}
@@ -795,49 +1047,51 @@ ZEND_END_ARG_INFO()
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_FALIAS(apache_response_headers, litespeed_response_headers, arginfo_litespeed__void)
- {NULL, NULL, NULL}
+ 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}
};
static PHP_MINIT_FUNCTION(litespeed)
{
- /* REGISTER_INI_ENTRIES(); */
- return SUCCESS;
+ /* REGISTER_INI_ENTRIES(); */
+ return SUCCESS;
}
static PHP_MSHUTDOWN_FUNCTION(litespeed)
{
- /* UNREGISTER_INI_ENTRIES(); */
- return SUCCESS;
+ /* UNREGISTER_INI_ENTRIES(); */
+ return SUCCESS;
}
zend_module_entry litespeed_module_entry = {
- STANDARD_MODULE_HEADER,
- "litespeed",
- litespeed_functions,
- PHP_MINIT(litespeed),
- PHP_MSHUTDOWN(litespeed),
- NULL,
- NULL,
- NULL,
- NO_VERSION_YET,
- STANDARD_MODULE_PROPERTIES
+ STANDARD_MODULE_HEADER,
+ "litespeed",
+ litespeed_functions,
+ PHP_MINIT(litespeed),
+ PHP_MSHUTDOWN(litespeed),
+ NULL,
+ NULL,
+ NULL,
+ NO_VERSION_YET,
+ STANDARD_MODULE_PROPERTIES
};
static int add_associate_array( const char * pKey, int keyLen, const char * pValue, int valLen,
- void * arg )
+ void * arg )
{
- add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue, 1 );
- return 1;
+ add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue, 1 );
+ return 1;
}
@@ -845,13 +1099,13 @@ static int add_associate_array( const char * pKey, int keyLen, const char * pVal
Fetch all HTTP request headers */
PHP_FUNCTION(litespeed_request_headers)
{
- /* TODO: */
- if (ZEND_NUM_ARGS() > 0) {
- WRONG_PARAM_COUNT;
- }
- array_init(return_value);
+ /* TODO: */
+ if (ZEND_NUM_ARGS() > 0) {
+ WRONG_PARAM_COUNT;
+ }
+ array_init(return_value);
- LSAPI_ForeachOrgHeader( add_associate_array, return_value );
+ LSAPI_ForeachOrgHeader( add_associate_array, return_value );
}
/* }}} */
@@ -862,45 +1116,62 @@ PHP_FUNCTION(litespeed_request_headers)
Fetch all HTTP response headers */
PHP_FUNCTION(litespeed_response_headers)
{
- sapi_header_struct *h;
- zend_llist_position pos;
- char * p;
- int len;
- char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
-
- if (ZEND_NUM_ARGS() > 0) {
- WRONG_PARAM_COUNT;
- }
-
- if (!&SG(sapi_headers).headers) {
- RETURN_FALSE;
- }
- array_init(return_value);
-
- h = zend_llist_get_first_ex(&SG(sapi_headers).headers, &pos);
- while (h) {
- if ( h->header_len > 0 ) {
- p = strchr( h->header, ':' );
- len = p - h->header;
- if (( p )&&( len > 0 )) {
- memmove( headerBuf, h->header, len );
- while( len > 0 && (isspace( headerBuf[len-1])) ) {
- --len;
- }
- headerBuf[len] = 0;
- if ( len ) {
- while( isspace(*++p));
- add_assoc_string_ex(return_value, headerBuf, len+1, p, 1 );
- }
- }
- }
- h = zend_llist_get_next_ex(&SG(sapi_headers).headers, &pos);
- }
+ sapi_header_struct *h;
+ zend_llist_position pos;
+ char * p;
+ int len;
+ char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
+
+ if (ZEND_NUM_ARGS() > 0) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (!&SG(sapi_headers).headers) {
+ RETURN_FALSE;
+ }
+ array_init(return_value);
+
+ h = zend_llist_get_first_ex(&SG(sapi_headers).headers, &pos);
+ while (h) {
+ if ( h->header_len > 0 ) {
+ p = strchr( h->header, ':' );
+ len = p - h->header;
+ if (( p )&&( len > 0 )) {
+ memmove( headerBuf, h->header, len );
+ while( len > 0 && (isspace( headerBuf[len-1])) ) {
+ --len;
+ }
+ headerBuf[len] = 0;
+ if ( len ) {
+ while( isspace(*++p));
+ add_assoc_string_ex(return_value, headerBuf, len+1, p, 1 );
+ }
+ }
+ }
+ h = zend_llist_get_next_ex(&SG(sapi_headers).headers, &pos);
+ }
}
/* }}} */
+/* {{{ 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
diff --git a/sapi/litespeed/lsapidef.h b/sapi/litespeed/lsapidef.h
index 3bdadac1d1..fb75d01a17 100644
--- a/sapi/litespeed/lsapidef.h
+++ b/sapi/litespeed/lsapidef.h
@@ -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
diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c
index 24b5a7e559..786a3bd20b 100644
--- a/sapi/litespeed/lsapilib.c
+++ b/sapi/litespeed/lsapilib.c
@@ -16,10 +16,8 @@
+----------------------------------------------------------------------+
*/
-/* $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,13 @@ 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>
#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 +65,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,11 +117,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] =
@@ -111,13 +154,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",
@@ -137,8 +180,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
};
@@ -160,7 +203,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;
@@ -169,6 +213,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 )
{
@@ -199,75 +271,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;
@@ -281,9 +393,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;
@@ -294,9 +405,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;
@@ -308,10 +418,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];
@@ -327,21 +437,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;
}
@@ -350,36 +459,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;
@@ -390,9 +495,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;
}
@@ -427,8 +531,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];
@@ -437,20 +543,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;
@@ -458,29 +978,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;
@@ -496,85 +1015,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 struct lsapi_packet_header ack = {'L', 'S',
+//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 s_ack = {'L', 'S',
LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
-static inline int notify_req_received( LSAPI_Request * pReq )
+
+
+static inline int write_req_received_notification( int fd )
{
- if ( write( pReq->m_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;
- return notify_req_received( pReq );
+ 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);
@@ -583,11 +1200,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();
}
@@ -606,28 +1221,35 @@ int LSAPI_IsRunning(void)
int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
{
- if ( !pReq ) {
+ int newfd;
+ 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 ( fd == STDIN_FILENO )
+ {
+ fd = dup( fd );
+ newfd = open( "/dev/null", O_RDWR );
+ dup2( newfd, STDIN_FILENO );
+ }
+
+ 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 );
@@ -653,38 +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 )
+ 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 );
@@ -698,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 );
}
@@ -735,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;
}
@@ -754,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++);
@@ -810,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;
}
@@ -856,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;
@@ -906,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;
}
@@ -949,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;
@@ -962,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;
@@ -990,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;
@@ -1006,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;
@@ -1043,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;
}
@@ -1085,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;
@@ -1097,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;
@@ -1112,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;
}
}
@@ -1139,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 )
{
@@ -1162,43 +1911,67 @@ 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;
+ *(pKey + keyLen ) = 0;
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;
}
@@ -1211,23 +1984,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;
@@ -1236,23 +2010,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 )
+ keyLen = 250;
pKeyEnd = pKey + keyLen;
memcpy( achHeaderName, "HTTP_", 5 );
p = &achHeaderName[5];
- if ( keyLen > 250 ) {
- keyLen = 250;
- }
- while( pKey < pKeyEnd ) {
+ while( pKey < pKeyEnd )
+ {
char ch = *pKey++;
- if ( ch == '-' ) {
+ if ( ch == '-' )
*p++ = '_';
- } else {
+ else
*p++ = toupper( ch );
- }
}
*p = 0;
keyLen += 5;
@@ -1261,9 +2035,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;
}
}
@@ -1276,15 +2049,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;
@@ -1295,10 +2067,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 );
}
@@ -1310,10 +2082,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 );
@@ -1326,14 +2098,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;
@@ -1352,25 +2123,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 ( nameLen <= 0 )
+ return 0;
+ while( valLen > 0 )
+ {
+ char ch = *(pHeaderValue + valLen - 1 );
+ if (( ch == '\n' )||( ch == '\r' ))
+ --valLen;
+ else
+ break;
}
- if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) {
+ 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;
@@ -1389,7 +2222,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;
@@ -1405,20 +2239,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;
- }
}
}
@@ -1438,17 +2272,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,
@@ -1463,7 +2296,8 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
return -1;
*pEnd++ = 0;
- if ( *p == '*' ) {
+ if ( *p == '*' )
+ {
strcpy( achAddr, "::" );
p = achAddr;
}
@@ -1473,35 +2307,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));
@@ -1509,7 +2343,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;
}
@@ -1517,11 +2352,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;
}
@@ -1532,7 +2366,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;
@@ -1543,9 +2378,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;
@@ -1568,6 +2405,8 @@ typedef struct _lsapi_prefork_server
int m_iAvoidFork;
lsapi_child_status * m_pChildrenStatus;
+ lsapi_child_status * m_pChildrenStatusCur;
+ lsapi_child_status * m_pChildrenStatusEnd;
}lsapi_prefork_server;
@@ -1575,43 +2414,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;
- }
}
@@ -1624,11 +2462,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));
}
+
+ //OPTIMIZATION
+ //if ( s_accept_notify )
+ // notify_req_received( fd );
}
return fd;
@@ -1651,9 +2495,13 @@ static void lsapi_cleanup(int signal)
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 ) {
+ lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
+ while( pStatus < pEnd )
+ {
+ if ( pStatus->m_pid == pid )
+ {
+ if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
+ g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
return pStatus;
}
++pStatus;
@@ -1667,17 +2515,35 @@ 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;
}
+ while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
+ &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
+ --g_prefork_server->m_pChildrenStatusCur;
}
@@ -1686,80 +2552,116 @@ static int lsapi_init_children_status()
int size = 4096;
char * pBuf;
- size = g_prefork_server->m_iMaxChildren * sizeof( lsapi_child_status ) * 2;
+ size = (g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren ) * sizeof( lsapi_child_status ) * 2;
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;
+ g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
+ g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + size / sizeof( lsapi_child_status );
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;
- }
+ lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
+ 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 ))
+ {
+ ++pStatus->m_iKillSent;
+ //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 ))
+ {
+ ++pStatus->m_iKillSent;
+ //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()
@@ -1770,14 +2672,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;
}
@@ -1796,13 +2698,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;
}
@@ -1813,36 +2719,38 @@ 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 ) )
+ {
+ fprintf( stderr, "Reached max children process limit: %d, extra: %d, current: %d, please increase LSAPI_CHILDREN.\n",
+ pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren );
usleep( 100000 );
continue;
}
@@ -1850,77 +2758,116 @@ 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;
}
}
sigaction( SIGUSR1, &old_usr1, 0 );
- kill( -getpgrp(), SIGUSR1 );
- lsapi_all_children_must_die(); /* Sorry, children ;-) */
+ //kill( -getpgrp(), SIGUSR1 );
+ //lsapi_all_children_must_die(); /* Sorry, children ;-) */
return -1;
}
+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;
@@ -1932,88 +2879,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_req_processed)&&( 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_req_processed && ( 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;
@@ -2028,49 +2992,50 @@ 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;
+}
+
+int LSAPI_Get_Slow_Req_Msecs()
+{
+ return s_slow_req_msecs;
}
@@ -2092,101 +3057,421 @@ 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 ( g_prefork_server->m_iExtraChildren < 1000 )
+ g_prefork_server->m_iExtraChildren = 1000;
+ }
+ }
+ 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 )
+ {
+ s_accept_notify = atoi( p );
+ }
+
+ p = getenv( "LSAPI_SLOW_REQ_MSECS" );
+ 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;
+}
diff --git a/sapi/litespeed/lsapilib.h b/sapi/litespeed/lsapilib.h
index 9d6255b327..cae1863c79 100644
--- a/sapi/litespeed/lsapilib.h
+++ b/sapi/litespeed/lsapilib.h
@@ -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
@@ -50,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
#ifndef _LSAPILIB_H_
#define _LSAPILIB_H_
@@ -118,7 +116,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 +125,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 +170,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 +203,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 +251,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 +306,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 +326,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 +346,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,7 +373,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)
}
diff --git a/tests/basic/025.phpt b/tests/basic/025.phpt
index 58191bcd61..37561a2a2e 100644
--- a/tests/basic/025.phpt
+++ b/tests/basic/025.phpt
@@ -3,6 +3,7 @@ Test HTTP_RAW_POST_DATA with excessive post length
--INI--
always_populate_raw_post_data=1
post_max_size=1K
+expose_php=On
--POST--
a=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
--FILE--
diff --git a/win32/build/Makefile.phpize b/win32/build/Makefile.phpize
index 17cfc90fbd..44faf7d54b 100644
--- a/win32/build/Makefile.phpize
+++ b/win32/build/Makefile.phpize
@@ -5,10 +5,8 @@ MT="$(MT)"
PHPSDK_DIR=$(PHP_DIR)
PHPLIB=$(PHPSDK_DIR)\lib\$(PHPLIB)
-LDFLAGS=/libpath:"$(PHPSDK_DIR)\lib\;$(PHPSDK_DIR)"
-
-CFLAGS=/nologo /FD $(BASE_INCLUDES) /D _WINDOWS /D ZEND_WIN32=1 /D PHP_WIN32=1 /D WIN32 /D_USE_32BIT_TIME_T=1 /D ZEND_WIN32_FORCE_INLINE /GF /D ZEND_DEBUG=0 /D ZTS=1 /D FD_SETSIZE=256
-CFLAGS_PHP=/D _USRDLL /D PHP5DLLTS_EXPORTS /D PHP_EXPORTS /D TSRM_EXPORTS /D SAPI_EXPORTS /D WINVER=0x500 /D COMPILE_DL_AJAXMIN
+LDFLAGS=$(LDFLAGS) /libpath:"$(PHPSDK_DIR)\lib\;$(PHPSDK_DIR)"
+BUILD_DIR_DEV=$(PHPSDK_DIR)
all: $(EXT_TARGETS) $(PECL_TARGETS)
@@ -36,3 +34,5 @@ _VC_MANIFEST_EMBED_EXE= if exist $@.manifest $(MT) -nologo -manifest $@.manifest
_VC_MANIFEST_EMBED_DLL= if exist $@.manifest $(MT) -nologo -manifest $@.manifest -outputresource:$@;2
!endif
+install: build-headers
+
diff --git a/win32/build/confutils.js b/win32/build/confutils.js
index 136b3bb024..9b1e0fc891 100644
--- a/win32/build/confutils.js
+++ b/win32/build/confutils.js
@@ -1022,6 +1022,11 @@ function is_pgo_desired(mod)
{
var varname = "PHP_" + mod.toUpperCase() + "_PGO";
+ /* XXX enable PGO in phpize mode */
+ if (MODE_PHPIZE) {
+ return false;
+ }
+
/* don't disable if there's no mention of the varname */
if (eval("typeof " + varname + " == 'undefined'")) {
return true;
@@ -1163,11 +1168,6 @@ function ADD_EXTENSION_DEP(extname, dependson, optional)
var dep_present = false;
var dep_shared = false;
- if (MODE_PHPIZE) {
- ext_deps_js = file_get_contents(PHP_DIR + "\\script\\ext_deps.js");
- eval(ext_deps_js);
- }
-
try {
dep_present = eval("PHP_" + DEP);
@@ -1513,7 +1513,7 @@ function output_as_table(header, ar_out)
var min = new Array(l);
var max = new Array(l);
- if (l != ar_out[0].length) {
+ if (!!ar_out[0] && l != ar_out[0].length) {
STDOUT.WriteLine("Invalid header argument, can't output the table " + l + " " + ar_out[0].length );
return;
}
@@ -1651,6 +1651,9 @@ function generate_files()
generate_internal_functions();
generate_config_h();
generate_phpize();
+ } else {
+ generate_config_pickle_h();
+ generate_ext_pickle();
}
STDOUT.WriteLine("Done.");
STDOUT.WriteBlankLines(1);
@@ -1663,6 +1666,140 @@ function generate_files()
}
}
+function generate_ext_pickle()
+{
+ var content;
+ var DEPS = null;
+ var dest;
+ var deps_lines = new Array();
+
+ var build_var_name = function(name) {
+ return "PHP_" + name.toUpperCase();
+ }
+
+ STDOUT.WriteLine("Generating pickle deps");
+ dest = PHP_DIR + "/script/";
+
+ if (!FSO.FolderExists(dest)) {
+ FSO.CreateFolder(dest);
+ }
+
+ if (FSO.FileExists(dest + "/ext_pickle.js")) {
+ DEPS = FSO.OpenTextFile(dest + "/ext_pickle.js", 1);
+
+ while (!DEPS.AtEndOfStream) {
+ var ln = DEPS.ReadLine();
+ var found = false;
+
+ for (var i in extensions_enabled) {
+ var reg0 = new RegExp(build_var_name(extensions_enabled[i][0]) + "\s*=.+", "g");
+ var reg1 = new RegExp(build_var_name(extensions_enabled[i][0]) + "_SHARED" + "\s*=.+", "g");
+
+ if (ln.match(reg1) || ln.match(reg0)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ deps_lines.push(ln);
+ }
+ }
+ }
+
+ for (var i in extensions_enabled) {
+ deps_lines.push(build_var_name(extensions_enabled[i][0]) + "=true;");
+ deps_lines.push(build_var_name(extensions_enabled[i][0]) + "_SHARED=" + (extensions_enabled[i][1] == 'shared' ? 'true' : 'false') + ";");
+ }
+
+ if (!!DEPS) {
+ DEPS.Close();
+ DEPS = null;
+ }
+
+ /* Replace the ext_pickle.js with the new content */
+ DEPS = FSO.CreateTextFile(dest + "/ext_pickle.js", true);
+
+ for (var j in deps_lines) {
+ DEPS.WriteLine(deps_lines[j]);
+ }
+
+ DEPS.Close();
+}
+
+function generate_config_pickle_h()
+{
+ var outfile = null;
+ var lines = new Array();
+ var keys = (new VBArray(configure_hdr.Keys())).toArray();
+ dest = PHP_DIR + "/include/main";
+
+ var ignore_key = function(key) {
+ var ignores = [ "CONFIGURE_COMMAND", "PHP_COMPILER_ID", "COMPILER", "ARCHITECTURE", "HAVE_STRNLEN", "PHP_DIR" ];
+
+ for (var k in ignores) {
+ if (ignores[k] == key) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ STDOUT.WriteLine("Generating main/config.pickle.h");
+
+ if (FSO.FileExists(dest + "/config.pickle.h")) {
+ outfile = FSO.OpenTextFile(dest + "/config.pickle.h", 1);
+
+ while (!outfile.AtEndOfStream) {
+ var found = false;
+ var ln = outfile.ReadLine();
+
+ for (var i in keys) {
+ var reg = new RegExp("#define[\s ]+" + keys[i] + "[\s ]*.*", "g");
+
+ if (ln.match(reg)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ lines.push(ln);
+ }
+ }
+ }
+
+ for (var i in keys) {
+ var item = configure_hdr.Item(keys[i]);
+
+ if (ignore_key(keys[i])) {
+ continue;
+ }
+
+ /* XXX fix comment handling */
+ /*if (!lines[j].match(/^#define.+/g)) {
+ continue;
+ }*/
+
+ lines.push("#define " + keys[i] + " " + item[0]);
+ }
+
+ if (outfile) {
+ outfile.Close();
+ outfile = null;
+ }
+
+ outfile = FSO.CreateTextFile(dest + "/config.pickle.h", true);
+
+ for (var k in lines) {
+ outfile.WriteLine(lines[k]);
+ }
+
+ outfile.Close();
+}
+
function generate_config_h()
{
var infile, outfile;
@@ -1821,7 +1958,9 @@ function generate_makefile()
MFO.Close();
TF = FSO.OpenTextFile("Makefile.objects", 1);
- MF.Write(TF.ReadAll());
+ if (!TF.AtEndOfStream) {
+ MF.Write(TF.ReadAll());
+ }
TF.Close();
MF.Close();
diff --git a/win32/build/phpize.js.in b/win32/build/phpize.js.in
index 4813ec0b5d..235c0816a3 100644
--- a/win32/build/phpize.js.in
+++ b/win32/build/phpize.js.in
@@ -209,6 +209,8 @@ C.WriteLine("/* This file automatically generated from script/confutils.js */");
C.WriteLine("var MODE_PHPIZE = true;");
C.WriteLine("var PHP_DIR = " + '"' + PHP_DIR.replace(new RegExp('(["\\\\])', "g"), '\\$1') + '"');
+C.Write(file_get_contents(PHP_DIR + "//script//ext_deps.js"));
+
C.Write(file_get_contents(PHP_DIR + "/script/confutils.js"));
C.Write(file_get_contents(PHP_DIR + "/script/config.phpize.js"));