+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2013 The PHP Group |
+ | Copyright (c) 1997-2007 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
+----------------------------------------------------------------------+
*/
-/* $Id$ */
+/* $Id: lsapi_main.c,v 1.57 2013/08/23 14:50:25 gwang Exp $ */
#include "php.h"
#include "SAPI.h"
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;
*/
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;
}
/* }}} */
*/
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();
+ }
+ }
}
/* }}} */
*/
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;
}
/* }}} */
*/
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);
- }
+ }
}
/* }}} */
*/
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;
+ }
}
/* }}} */
*/
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;
+ }
}
/* }}} */
*/
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;
}
*/
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);
}
/* }}} */
*/
static sapi_module_struct lsapi_sapi_module =
{
- "litespeed",
- "LiteSpeed",
+ "litespeed",
+ "LiteSpeed V6.4",
- 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( usage );
#ifdef PHP_OUTPUT_NEWAPI
php_output_end_all(TSRMLS_C);
#else
}
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-2013 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-2004 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-2013 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-2004 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;
}
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;
}
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 );
}
/* }}} */
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
/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2013 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available at through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt. |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: George Wang <gwang@litespeedtech.com> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-
-/*
-Copyright (c) 2007, Lite Speed Technologies Inc.
+Copyright (c) 2013, Lite Speed Technologies Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <lsapilib.h>
+/***************************************************************************
+ lsapilib.c - description
+ -------------------
+ begin : Mon Feb 21 2005
+ copyright : (C) 2005 by George Wang
+ email : gwang@litespeedtech.com
+ ***************************************************************************/
+
#include <ctype.h>
+#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/un.h>
+#include <sys/stat.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#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
#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] =
"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",
"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
};
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;
}
+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 )
{
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;
{
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;
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;
{
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];
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;
}
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;
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;
}
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];
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;
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;
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);
#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();
}
int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
{
- if ( !pReq ) {
+ if ( !pReq )
return -1;
- }
memset( pReq, 0, sizeof( LSAPI_Request ) );
- if ( allocateIovec( pReq, 16 ) == -1 ) {
+ if ( allocateIovec( pReq, 16 ) == -1 )
return -1;
- }
pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
- if ( !pReq->m_pRespBuf ) {
+ if ( !pReq->m_pRespBuf )
return -1;
- }
pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
- if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) {
+ if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
return -1;
- }
- if ( isPipe( fd ) ) {
+ if ( isPipe( fd ) )
+ {
pReq->m_fdListen = -1;
pReq->m_fd = fd;
- } else {
+ }
+ else
+ {
pReq->m_fdListen = fd;
pReq->m_fd = -1;
lsapi_set_nblock( fd, 1 );
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 );
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 );
}
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;
}
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++);
-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;
}
}
-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;
}
-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;
}
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;
++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;
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;
{
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;
}
-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;
}
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;
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;
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;
}
}
{
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 )
{
char * pValue;
int ret;
int count = 0;
- if ( !pReq || !fn ) {
+ struct _headerInfo headers[512];
+ if ( !pReq || !fn )
return -1;
- }
- for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
- if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
+
+ for( i = 0; i < H_TRANSFER_ENCODING; ++i )
+ {
+ if ( pReq->m_pHeaderIndex->m_headerOff[i] )
+ {
len = pReq->m_pHeaderIndex->m_headerLen[i];
pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
*(pValue + len ) = 0;
- ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
- pValue, len, arg );
+ headers[count]._name = HTTP_HEADERS[i];
+ headers[count]._nameLen = HTTP_HEADER_LEN[i];
+ headers[count]._value = pValue;
+ headers[count]._valueLen = len;
++count;
- if ( ret <= 0 ) {
- return ret;
- }
+
+ //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
+ // pValue, len, arg );
+ //if ( ret <= 0 )
+ // return ret;
}
}
- if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
+ if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
+ {
char *pKey;
int keyLen;
struct lsapi_header_offset * pCur, *pEnd;
pCur = pReq->m_pUnknownHeader;
pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
- while( pCur < pEnd ) {
+ while( pCur < pEnd )
+ {
pKey = pReq->m_pHttpHeader + pCur->nameOff;
keyLen = pCur->nameLen;
pValue = pReq->m_pHttpHeader + pCur->valueOff;
*(pValue + pCur->valueLen ) = 0;
- ret = (*fn)( pKey, keyLen,
- pValue, pCur->valueLen, arg );
- if ( ret <= 0 ) {
- return ret;
- }
+ headers[count]._name = pKey;
+ headers[count]._nameLen = keyLen;
+ headers[count]._value = pValue;
+ headers[count]._valueLen = pCur->valueLen;
+ ++count;
+ if ( count == 512 )
+ break;
+ //ret = (*fn)( pKey, keyLen,
+ // pValue, pCur->valueLen, arg );
+ //if ( ret <= 0 )
+ // return ret;
++pCur;
}
}
- return count + pReq->m_pHeader->m_cntUnknownHeaders;
+ qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
+ for( i = 0; i < count; ++i )
+ {
+ ret = (*fn)( headers[i]._name, headers[i]._nameLen,
+ headers[i]._value, headers[i]._valueLen, arg );
+ if ( ret <= 0 )
+ return ret;
+ }
+ return count;
}
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;
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;
*(pValue + pCur->valueLen ) = 0;
ret = (*fn)( achHeaderName, keyLen,
pValue, pCur->valueLen, arg );
- if ( ret <= 0 ) {
+ if ( ret <= 0 )
return ret;
- }
++pCur;
}
}
{
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;
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 );
}
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 );
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;
}
-
-
-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;
int flag = 1;
int addr_len;
- switch( pServerAddr->sa_family ) {
+ switch( pServerAddr->sa_family )
+ {
case AF_INET:
addr_len = 16;
break;
}
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;
- }
}
}
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,
return -1;
*pEnd++ = 0;
- if ( *p == '*' ) {
+ if ( *p == '*' )
+ {
strcpy( achAddr, "::" );
p = achAddr;
}
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));
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
- if ( getaddrinfo(p, NULL, &hints, &res) ) {
+ if ( getaddrinfo(p, NULL, &hints, &res) )
+ {
return -1;
}
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;
}
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;
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;
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;
- }
}
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;
{
lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
- while( pStatus < pEnd ) {
- if ( pStatus->m_pid == pid ) {
+ while( pStatus < pEnd )
+ {
+ if ( pStatus->m_pid == pid )
return pStatus;
- }
++pStatus;
}
return NULL;
{
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;
}
}
size = (size + 4095 ) / 4096 * 4096;
pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_SHARED, -1, 0 );
- if ( pBuf == MAP_FAILED ) {
+ if ( pBuf == MAP_FAILED )
+ {
perror( "Anonymous mmap() failed" );
return -1;
}
memset( pBuf, 0, size );
- g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
+ g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
return 0;
}
+static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
+{
+ char achCmd[1024];
+ if ( s_pid_dump_debug_info )
+ {
+ if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
+ return;
+ }
+ s_pid_dump_debug_info = fork();
+
+ fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n",
+ ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter,
+ tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
+ snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" -ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid );
+ if ( system( achCmd ) == -1 )
+ perror( "system()" );
+ exit( 0 );
+}
+
static void lsapi_check_child_status( long tmCur )
{
int idle = 0;
int tobekilled;
int dying = 0;
+ int count = 0;
lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
- while( pStatus < pEnd ) {
- tobekilled = pStatus->m_iKillSent;
- if ( pStatus->m_pid != 0 ) {
- if ( !tobekilled ) {
- if ( !pStatus->m_inProcess ) {
-
- if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
- ( idle >= g_prefork_server->m_iMaxIdleChildren )) {
-
- tobekilled = 1;
- } else {
- if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 )) {
- tobekilled = 1;
- }
- }
- if ( !tobekilled ) {
- ++idle;
- }
- } else {
- if ( tmCur - pStatus->m_tmReqBegin >
- g_prefork_server->m_iMaxReqProcessTime ) {
- tobekilled = 1;
- }
+ while( pStatus < pEnd )
+ {
+ tobekilled = 0;
+ if ( pStatus->m_pid != 0 )
+ {
+ ++count;
+ if ( !pStatus->m_inProcess )
+ {
+
+ if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
+ ( idle > g_prefork_server->m_iMaxIdleChildren ))
+ {
+ tobekilled = SIGUSR1;
}
- } else {
- if ( pStatus->m_inProcess ) {
- tobekilled = pStatus->m_iKillSent = 0;
+ else
+ {
+ if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
+ {
+ tobekilled = SIGUSR1;
+ }
}
+ if ( !tobekilled )
+ ++idle;
}
- if ( tobekilled ) {
- tobekilled = 0;
- if ( pStatus->m_iKillSent > 5 ) {
- tobekilled = SIGKILL;
- } else {
- if ( pStatus->m_iKillSent == 3 ) {
+ else
+ {
+ if ( tmCur - pStatus->m_tmReqBegin >
+ g_prefork_server->m_iMaxReqProcessTime )
+ {
+ if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info ))
+ dump_debug_info( pStatus, tmCur );
+ if ( pStatus->m_iKillSent > 5 )
+ {
+ tobekilled = SIGKILL;
+ fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid );
+ }
+ else
+ {
tobekilled = SIGTERM;
- } else {
- if ( pStatus->m_iKillSent == 1 ) {
- tobekilled = SIGUSR1;
- }
+ fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid );
}
}
- if ( tobekilled ) {
- kill( pStatus->m_pid, tobekilled );
+ }
+ if ( tobekilled )
+ {
+ if (( kill( pStatus->m_pid, tobekilled ) == -1 )&&( errno == ESRCH ))
+ {
+ pStatus->m_pid = 0;
+ --count;
+ }
+ else
+ {
+ ++pStatus->m_iKillSent;
+ ++dying;
}
- ++pStatus->m_iKillSent;
- ++dying;
}
-
- } else {
- ++dying;
}
++pStatus;
}
+ if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
+ {
+ fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Childen: %d, count: %d, idle: %d, dying: %d\n", getpid(),
+ g_prefork_server->m_iCurChildren, count, idle, dying );
+
+ }
}
static int lsapi_all_children_must_die()
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;
}
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;
}
if( sigaction( SIGTERM, &act, &old_term ) ||
sigaction( SIGINT, &act, &old_int ) ||
sigaction( SIGUSR1, &act, &old_usr1 ) ||
- sigaction( SIGQUIT, &act, &old_quit )) {
+ sigaction( SIGQUIT, &act, &old_quit ))
+ {
perror( "Can't set signals" );
return -1;
}
s_stop = 0;
- while( !s_stop ) {
- if ( ret ) {
- curTime = time( NULL );
- } else {
- ++curTime;
- }
- if (curTime != lastTime ) {
+ while( !s_stop )
+ {
+ curTime = time( NULL );
+ if (curTime != lastTime )
+ {
lastTime = curTime;
- if (s_ppid && (getppid() != s_ppid )) {
+ if (s_ppid && (getppid() != s_ppid ))
break;
- }
lsapi_check_child_status(curTime );
- if (pServer->m_iServerMaxIdle) {
- if ( pServer->m_iCurChildren <= 0 ) {
+ if (pServer->m_iServerMaxIdle)
+ {
+ if ( pServer->m_iCurChildren <= 0 )
+ {
++wait_secs;
- if ( wait_secs > pServer->m_iServerMaxIdle ) {
+ if ( wait_secs > pServer->m_iServerMaxIdle )
return -1;
- }
- } else {
- wait_secs = 0;
}
+ else
+ wait_secs = 0;
}
}
- if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) ) {
+ if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) )
+ {
usleep( 100000 );
continue;
}
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;
}
}
+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;
LSAPI_Finish_r( pReq );
- if ( g_prefork_server ) {
- if ( g_prefork_server->m_fd != -1 ) {
- if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) {
+ if ( g_prefork_server )
+ {
+ if ( g_prefork_server->m_fd != -1 )
+ if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
return -1;
- }
- }
}
- if ( s_req_processed >= s_max_reqs ) {
+ if ( s_req_processed >= s_max_reqs )
return -1;
- }
- if ( s_pChildStatus ) {
+ if ( s_pChildStatus )
+ {
s_pChildStatus->m_tmWaitBegin = time( NULL );
}
+
- while( g_running ) {
- if ( pReq->m_fd != -1 ) {
+ while( g_running )
+ {
+ if ( pReq->m_fd != -1 )
+ {
fd = pReq->m_fd;
- } else {
- if ( pReq->m_fdListen != -1 ) {
- fd = pReq->m_fdListen;
- } else {
- return -1;
- }
+ }
+ else if ( pReq->m_fdListen != -1 )
+ fd = pReq->m_fdListen;
+ else
+ {
+ break;
}
wait_secs = 0;
- while( 1 ) {
- if ( !g_running ) {
+ while( 1 )
+ {
+ if ( !g_running )
return -1;
- }
- if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
+ if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
return -1;
- }
FD_ZERO( &readfds );
FD_SET( fd, &readfds );
timeout.tv_sec = 1;
timeout.tv_usec = 0;
ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
- if ( ret == 0 ) {
- if ( s_pChildStatus ) {
+ if ( ret == 0 )
+ {
+ if ( s_pChildStatus )
+ {
s_pChildStatus->m_inProcess = 0;
}
++wait_secs;
- if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) {
+ if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
return -1;
- }
- if ( s_ppid &&( getppid() != s_ppid)) {
+ if ( s_ppid &&( getppid() != s_ppid))
return -1;
- }
- } else {
- if ( ret == -1 ) {
- if ( errno == EINTR ) {
- continue;
- } else {
- return -1;
- }
- } else {
- if ( ret >= 1 ) {
- if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
- return -1;
+ }
+ else if ( ret == -1 )
+ {
+ if ( errno == EINTR )
+ continue;
+ else
+ return -1;
+ }
+ else if ( ret >= 1 )
+ {
+ if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
+ return -1;
+ if ( fd == pReq->m_fdListen )
+ {
+ pReq->m_fd = lsapi_accept( pReq->m_fdListen );
+ if ( pReq->m_fd != -1 )
+ {
+ fd = pReq->m_fd;
+ lsapi_set_nblock( fd, 0 );
+ //init_conn_key( pReq->m_fd );
+ if ( !s_keepListener )
+ {
+ close( pReq->m_fdListen );
+ pReq->m_fdListen = -1;
}
- if ( fd == pReq->m_fdListen ) {
- pReq->m_fd = lsapi_accept( pReq->m_fdListen );
- if ( pReq->m_fd != -1 ) {
- fd = pReq->m_fd;
- lsapi_set_nblock( fd, 0 );
- } else {
- if (( errno == EINTR )||( errno == EAGAIN)) {
- continue;
- }
+ if ( s_accept_notify )
+ if ( notify_req_received( pReq->m_fd ) == -1 )
return -1;
- }
- } else {
- break;
- }
+ }
+ else
+ {
+ if (( errno == EINTR )||( errno == EAGAIN))
+ continue;
+ lsapi_error( "lsapi_accept() error", errno );
+ return -1;
}
}
+ else
+ break;
}
}
- if ( !readReq( pReq ) ) {
- if ( s_pChildStatus ) {
+
+ if ( !readReq( pReq ) )
+ {
+ if ( s_pChildStatus )
+ {
+ s_pChildStatus->m_iKillSent = 0;
s_pChildStatus->m_inProcess = 1;
+ ++s_pChildStatus->m_iReqCounter;
s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
}
++s_req_processed;
}
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;
}
#else
env = environ;
#endif
- while( env != NULL && *env != NULL ) {
- if ( !strncmp(*env, "LSAPI_", 6) ||
- !strncmp( *env, "PHP_LSAPI_", 10 ) ) {
+ while( env != NULL && *env != NULL )
+ {
+ if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
+ || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
+ {
char ** del = env;
- do {
+ do
*del = del[1];
- } while( *del++ );
- } else {
- ++env;
+ while( *del++ );
}
+ else
+ ++env;
}
}
-void LSAPI_Init_Env_Parameters( fn_select_t fp )
+static int lsapi_initSuEXEC()
+{
+ int i;
+ struct passwd * pw;
+ s_defaultUid = 0;
+ s_defaultGid = 0;
+ if ( s_uid == 0 )
+ {
+ const char * p = getenv( "LSAPI_DEFAULT_UID" );
+ if ( p )
+ {
+ i = atoi( p );
+ if ( i > 0 )
+ s_defaultUid = i;
+ }
+ p = getenv( "LSAPI_DEFAULT_GID" );
+ if ( p )
+ {
+ i = atoi( p );
+ if ( i > 0 )
+ s_defaultGid = i;
+ }
+ p = getenv( "LSAPI_SECRET" );
+ if (( !p )||( readSecret(p) == -1 ))
+ return -1;
+ if ( g_prefork_server )
+ {
+ if ( g_prefork_server->m_iMaxChildren < 100 )
+ g_prefork_server->m_iMaxChildren = 100;
+ }
+ }
+ if ( !s_defaultUid || !s_defaultGid )
+ {
+ pw = getpwnam( "nobody" );
+ if ( !s_defaultUid )
+ s_defaultUid = pw->pw_uid;
+ if ( !s_defaultGid )
+ s_defaultGid = pw->pw_gid;
+ }
+ return 0;
+}
+
+
+int LSAPI_Init_Env_Parameters( fn_select_t fp )
{
const char *p;
int n;
int avoidFork = 0;
p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
- if ( !p ) {
+ if ( !p )
p = getenv( "LSAPI_MAX_REQS" );
- }
- if ( p ) {
+ if ( p )
+ {
n = atoi( p );
- if ( n > 0 ) {
+ if ( n > 0 )
LSAPI_Set_Max_Reqs( n );
- }
}
p = getenv( "LSAPI_AVOID_FORK" );
- if ( p ) {
+ if ( p )
+ {
avoidFork = atoi( p );
}
+ p = getenv( "LSAPI_ACCEPT_NOTIFY" );
+ if ( p )
+ {
+ 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;
+}