1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 The PHP Group | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 3.01 of the PHP license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available at through the world-wide-web at the following url: | 10 | http://www.php.net/license/3_01.txt. | 11 | If you did not receive a copy of the PHP license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@php.net so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Author: George Wang <gwang@litespeedtech.com> | 16 +----------------------------------------------------------------------+ 17*/ 18 19/* $Id$ */ 20 21#include "php.h" 22#include "SAPI.h" 23#include "php_main.h" 24#include "php_ini.h" 25#include "php_variables.h" 26#include "zend_highlight.h" 27#include "zend.h" 28 29#include "lsapilib.h" 30 31#include <stdio.h> 32 33#if HAVE_STDLIB_H 34#include <stdlib.h> 35#endif 36 37#if HAVE_UNISTD_H 38#include <unistd.h> 39#endif 40 41#ifdef PHP_WIN32 42 43#include <io.h> 44#include <fcntl.h> 45#include "win32/php_registry.h" 46 47#else 48 49#include <sys/wait.h> 50 51#endif 52 53#include <sys/stat.h> 54 55#if HAVE_SYS_TYPES_H 56 57#include <sys/types.h> 58 59#endif 60 61#if HAVE_SIGNAL_H 62 63#include <signal.h> 64 65#endif 66 67#include <sys/socket.h> 68#include <arpa/inet.h> 69#include <netinet/in.h> 70 71 72#define SAPI_LSAPI_MAX_HEADER_LENGTH 2048 73 74static int lsapi_mode = 1; 75static char *php_self = ""; 76static char *script_filename = ""; 77static int source_highlight = 0; 78static char * argv0 = NULL; 79static int engine = 1; 80#ifdef ZTS 81zend_compiler_globals *compiler_globals; 82zend_executor_globals *executor_globals; 83php_core_globals *core_globals; 84sapi_globals_struct *sapi_globals; 85void ***tsrm_ls; 86#endif 87 88zend_module_entry litespeed_module_entry; 89 90/* {{{ php_lsapi_startup 91 */ 92static int php_lsapi_startup(sapi_module_struct *sapi_module) 93{ 94 if (php_module_startup(sapi_module, NULL, 0)==FAILURE) { 95 return FAILURE; 96 } 97 argv0 = sapi_module->executable_location; 98 return SUCCESS; 99} 100/* }}} */ 101 102/* {{{ sapi_lsapi_ini_defaults */ 103 104/* overwriteable ini defaults must be set in sapi_cli_ini_defaults() */ 105#define INI_DEFAULT(name,value)\ 106 ZVAL_STRING(tmp, value, 0);\ 107 zend_hash_update(configuration_hash, name, sizeof(name), tmp, sizeof(zval), (void**)&entry);\ 108 Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry)) 109 110static void sapi_lsapi_ini_defaults(HashTable *configuration_hash) 111{ 112 zval *tmp, *entry; 113 114#if PHP_MAJOR_VERSION > 4 115/* 116 MAKE_STD_ZVAL(tmp); 117 118 INI_DEFAULT("register_long_arrays", "0"); 119 120 FREE_ZVAL(tmp); 121*/ 122#endif 123 124} 125/* }}} */ 126 127 128/* {{{ sapi_lsapi_ub_write 129 */ 130static int sapi_lsapi_ub_write(const char *str, uint str_length TSRMLS_DC) 131{ 132 int ret; 133 int remain; 134 if ( lsapi_mode ) { 135 ret = LSAPI_Write( str, str_length ); 136 if ( ret < str_length ) { 137 php_handle_aborted_connection(); 138 return str_length - ret; 139 } 140 } else { 141 remain = str_length; 142 while( remain > 0 ) { 143 ret = write( 1, str, remain ); 144 if ( ret <= 0 ) { 145 php_handle_aborted_connection(); 146 return str_length - remain; 147 } 148 str += ret; 149 remain -= ret; 150 } 151 } 152 return str_length; 153} 154/* }}} */ 155 156 157/* {{{ sapi_lsapi_flush 158 */ 159static void sapi_lsapi_flush( void * server_context ) 160{ 161 if ( lsapi_mode ) { 162 if ( LSAPI_Flush() == -1) { 163 php_handle_aborted_connection(); 164 } 165 } 166} 167/* }}} */ 168 169 170/* {{{ sapi_lsapi_deactivate 171 */ 172static int sapi_lsapi_deactivate(TSRMLS_D) 173{ 174 if ( SG(request_info).path_translated ) 175 { 176 efree( SG(request_info).path_translated ); 177 } 178 179 return SUCCESS; 180} 181/* }}} */ 182 183 184 185 186/* {{{ sapi_lsapi_getenv 187 */ 188static char *sapi_lsapi_getenv( char * name, size_t name_len TSRMLS_DC ) 189{ 190 if ( lsapi_mode ) { 191 return LSAPI_GetEnv( name ); 192 } else { 193 return getenv( name ); 194 } 195} 196/* }}} */ 197 198 199/* 200static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen, 201 void * arg ) 202{ 203 php_register_variable_safe((char *)pKey, (char *)pValue, valLen, (zval *)arg TSRMLS_CC); 204 return 1; 205} 206*/ 207 208static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen, 209 void * arg ) 210{ 211 zval * gpc_element, **gpc_element_p; 212 HashTable * symtable1 = Z_ARRVAL_P((zval * )arg); 213 register char * pKey1 = (char *)pKey; 214 215 MAKE_STD_ZVAL(gpc_element); 216 Z_STRLEN_P( gpc_element ) = valLen; 217 Z_STRVAL_P( gpc_element ) = estrndup(pValue, valLen); 218 Z_TYPE_P( gpc_element ) = IS_STRING; 219#if PHP_MAJOR_VERSION > 4 220 zend_symtable_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p ); 221#else 222 zend_hash_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p ); 223#endif 224 return 1; 225} 226 227 228#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5) 229static int add_variable_magic_quote( const char * pKey, int keyLen, const char * pValue, int valLen, 230 void * arg ) 231{ 232 zval * gpc_element, **gpc_element_p; 233 HashTable * symtable1 = Z_ARRVAL_P((zval * )arg); 234 register char * pKey1 = (char *)pKey; 235 236 MAKE_STD_ZVAL(gpc_element); 237 Z_STRLEN_P( gpc_element ) = valLen; 238 Z_STRVAL_P( gpc_element ) = php_addslashes((char *)pValue, valLen, &Z_STRLEN_P( gpc_element ), 0 ); 239 Z_TYPE_P( gpc_element ) = IS_STRING; 240#if PHP_MAJOR_VERSION > 4 241 zend_symtable_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p ); 242#else 243 zend_hash_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p ); 244#endif 245 return 1; 246} 247 248#endif 249 250/* {{{ sapi_lsapi_register_variables 251 */ 252static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC) 253{ 254 char * php_self = ""; 255 if ( lsapi_mode ) { 256 if ( (SG(request_info).request_uri ) ) 257 php_self = (SG(request_info).request_uri ); 258 259#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5) 260 if (!PG(magic_quotes_gpc)) { 261#endif 262 LSAPI_ForeachHeader( add_variable, track_vars_array ); 263 LSAPI_ForeachEnv( add_variable, track_vars_array ); 264 add_variable("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array ); 265#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5) 266 } else { 267 LSAPI_ForeachHeader( add_variable_magic_quote, track_vars_array ); 268 LSAPI_ForeachEnv( add_variable_magic_quote, track_vars_array ); 269 add_variable_magic_quote("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array ); 270 } 271#endif 272 php_import_environment_variables(track_vars_array TSRMLS_CC); 273 } else { 274 php_import_environment_variables(track_vars_array TSRMLS_CC); 275 276 php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC); 277 php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC); 278 php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC); 279 php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC); 280 php_register_variable("DOCUMENT_ROOT", "", track_vars_array TSRMLS_CC); 281 282 } 283} 284/* }}} */ 285 286 287/* {{{ sapi_lsapi_read_post 288 */ 289static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC) 290{ 291 if ( lsapi_mode ) { 292 return LSAPI_ReadReqBody( buffer, count_bytes ); 293 } else { 294 return 0; 295 } 296} 297/* }}} */ 298 299 300 301 302/* {{{ sapi_lsapi_read_cookies 303 */ 304static char *sapi_lsapi_read_cookies(TSRMLS_D) 305{ 306 if ( lsapi_mode ) { 307 return LSAPI_GetHeader( H_COOKIE ); 308 } else { 309 return NULL; 310 } 311} 312/* }}} */ 313 314 315/* {{{ sapi_lsapi_send_headers 316 */ 317static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) 318{ 319 sapi_header_struct *h; 320 zend_llist_position pos; 321 if ( lsapi_mode ) { 322 LSAPI_SetRespStatus( SG(sapi_headers).http_response_code ); 323 324 h = zend_llist_get_first_ex(&sapi_headers->headers, &pos); 325 while (h) { 326 if ( h->header_len > 0 ) { 327 LSAPI_AppendRespHeader(h->header, h->header_len); 328 } 329 h = zend_llist_get_next_ex(&sapi_headers->headers, &pos); 330 } 331 if (SG(sapi_headers).send_default_content_type) { 332 char *hd; 333 int len; 334 char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH]; 335 336 hd = sapi_get_default_content_type(TSRMLS_C); 337 len = snprintf( headerBuf, SAPI_LSAPI_MAX_HEADER_LENGTH - 1, 338 "Content-type: %s", hd ); 339 efree(hd); 340 341 LSAPI_AppendRespHeader( headerBuf, len ); 342 } 343 } 344 LSAPI_FinalizeRespHeaders(); 345 return SAPI_HEADER_SENT_SUCCESSFULLY; 346 347 348} 349/* }}} */ 350 351 352/* {{{ sapi_lsapi_send_headers 353 */ 354static void sapi_lsapi_log_message(char *message TSRMLS_DC) 355{ 356 int len = strlen( message ); 357 LSAPI_Write_Stderr( message, len); 358} 359/* }}} */ 360 361 362/* {{{ sapi_module_struct cgi_sapi_module 363 */ 364static sapi_module_struct lsapi_sapi_module = 365{ 366 "litespeed", 367 "LiteSpeed V5.5", 368 369 php_lsapi_startup, /* startup */ 370 php_module_shutdown_wrapper, /* shutdown */ 371 372 NULL, /* activate */ 373 sapi_lsapi_deactivate, /* deactivate */ 374 375 sapi_lsapi_ub_write, /* unbuffered write */ 376 sapi_lsapi_flush, /* flush */ 377 NULL, /* get uid */ 378 sapi_lsapi_getenv, /* getenv */ 379 380 php_error, /* error handler */ 381 382 NULL, /* header handler */ 383 sapi_lsapi_send_headers, /* send headers handler */ 384 NULL, /* send header handler */ 385 386 sapi_lsapi_read_post, /* read POST data */ 387 sapi_lsapi_read_cookies, /* read Cookies */ 388 389 sapi_lsapi_register_variables, /* register server variables */ 390 sapi_lsapi_log_message, /* Log message */ 391 392 NULL, /* php.ini path override */ 393 NULL, /* block interruptions */ 394 NULL, /* unblock interruptions */ 395 NULL, /* default post reader */ 396 NULL, /* treat data */ 397 NULL, /* executable location */ 398 399 0, /* php.ini ignore */ 400 401 STANDARD_SAPI_MODULE_PROPERTIES 402 403}; 404/* }}} */ 405 406static int init_request_info( TSRMLS_D ) 407{ 408 char * pContentType = LSAPI_GetHeader( H_CONTENT_TYPE ); 409 char * pAuth; 410 411 SG(request_info).content_type = pContentType ? pContentType : ""; 412 SG(request_info).request_method = LSAPI_GetRequestMethod(); 413 SG(request_info).query_string = LSAPI_GetQueryString(); 414 SG(request_info).request_uri = LSAPI_GetScriptName(); 415 SG(request_info).content_length = LSAPI_GetReqBodyLen(); 416 SG(request_info).path_translated = estrdup( LSAPI_GetScriptFileName()); 417 418 /* It is not reset by zend engine, set it to 0. */ 419 SG(sapi_headers).http_response_code = 0; 420 421 pAuth = LSAPI_GetHeader( H_AUTHORIZATION ); 422 php_handle_auth_data(pAuth TSRMLS_CC); 423} 424 425static char s_cur_chdir[4096] = ""; 426 427static int lsapi_chdir_primary_script( zend_file_handle * file_handle ) 428{ 429#if PHP_MAJOR_VERSION > 4 430 char * p; 431 char ch; 432 433 SG(options) |= SAPI_OPTION_NO_CHDIR; 434 getcwd( s_cur_chdir, sizeof( s_cur_chdir ) ); 435 436 p = strrchr( file_handle->filename, '/' ); 437 if ( *p ) 438 { 439 *p = 0; 440 if ( strcmp( file_handle->filename, s_cur_chdir ) != 0 ) { 441 chdir( file_handle->filename ); 442 } 443 *p++ = '/'; 444 ch = *p; 445 *p = 0; 446 if ( !CWDG(cwd).cwd || 447 ( strcmp( file_handle->filename, CWDG(cwd).cwd ) != 0 ) ) { 448 CWDG(cwd).cwd_length = p - file_handle->filename; 449 CWDG(cwd).cwd = (char *) realloc(CWDG(cwd).cwd, CWDG(cwd).cwd_length+1); 450 memmove( CWDG(cwd).cwd, file_handle->filename, CWDG(cwd).cwd_length+1 ); 451 } 452 *p = ch; 453 } 454 /* virtual_file_ex(&CWDG(cwd), file_handle->filename, NULL, CWD_REALPATH); */ 455#else 456 VCWD_CHDIR_FILE( file_handle->filename ); 457#endif 458 return 0; 459} 460 461static int lsapi_fopen_primary_script( zend_file_handle * file_handle ) 462{ 463 FILE * fp; 464 char * p; 465 fp = fopen( SG(request_info).path_translated, "rb" ); 466 if ( !fp ) 467 { 468 return -1; 469 } 470 file_handle->type = ZEND_HANDLE_FP; 471 file_handle->handle.fp = fp; 472 file_handle->filename = SG(request_info).path_translated; 473 file_handle->free_filename = 0; 474 file_handle->opened_path = NULL; 475 476 lsapi_chdir_primary_script( file_handle ); 477 478 return 0; 479} 480 481static int lsapi_execute_script( zend_file_handle * file_handle TSRMLS_DC) 482{ 483 char *p; 484 int len; 485 file_handle->type = ZEND_HANDLE_FILENAME; 486 file_handle->handle.fd = 0; 487 file_handle->filename = SG(request_info).path_translated; 488 file_handle->free_filename = 0; 489 file_handle->opened_path = NULL; 490 491 p = argv0; 492 *p++ = ':'; 493 len = strlen( SG(request_info).path_translated ); 494 if ( len > 45 ) 495 len = len - 45; 496 else 497 len = 0; 498 memccpy( p, SG(request_info).path_translated + len, 0, 46 ); 499 500 php_execute_script(file_handle TSRMLS_CC); 501 return 0; 502 503} 504 505 506static int lsapi_module_main(int show_source TSRMLS_DC) 507{ 508 zend_file_handle file_handle = {0}; 509 510 if (php_request_startup(TSRMLS_C) == FAILURE ) { 511 return -1; 512 } 513 if (show_source) { 514 zend_syntax_highlighter_ini syntax_highlighter_ini; 515 516 php_get_highlight_struct(&syntax_highlighter_ini); 517 highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC); 518 } else { 519 lsapi_execute_script( &file_handle TSRMLS_CC); 520 } 521 zend_try { 522 php_request_shutdown(NULL); 523 *argv0 = 0; 524 } zend_end_try(); 525 return 0; 526} 527 528 529static int alter_ini( const char * pKey, int keyLen, const char * pValue, int valLen, 530 void * arg ) 531{ 532 int type = ZEND_INI_PERDIR; 533 if ( '\001' == *pKey ) { 534 ++pKey; 535 if ( *pKey == 4 ) { 536 type = ZEND_INI_SYSTEM; 537 } 538 ++pKey; 539 --keyLen; 540 if (( keyLen == 7 )&&( strncasecmp( pKey, "engine", 6 )== 0 )) 541 { 542 if ( *pValue == '0' ) 543 engine = 0; 544 } 545 else 546 zend_alter_ini_entry((char *)pKey, keyLen, 547 (char *)pValue, valLen, 548 type, PHP_INI_STAGE_ACTIVATE); 549 } 550 return 1; 551} 552 553 554static void override_ini() 555{ 556 557 LSAPI_ForeachSpecialEnv( alter_ini, NULL ); 558 559} 560 561static int processReq( TSRMLS_D ) 562{ 563 int ret = 0; 564 zend_first_try { 565 /* avoid server_context==NULL checks */ 566 SG(server_context) = (void *) 1; 567 568 engine = 1; 569 override_ini(); 570 571 if ( engine ) { 572 init_request_info( TSRMLS_C ); 573 574 if ( lsapi_module_main( source_highlight TSRMLS_CC ) == -1 ) { 575 ret = -1; 576 } 577 } else { 578 LSAPI_AppendRespHeader( "status: 403", 11 ); 579 LSAPI_AppendRespHeader( "content-type: text/html", 23 ); 580 LSAPI_Write( "Forbidden: PHP engine is disable.\n", 34 ); 581 } 582 } zend_end_try(); 583 return ret; 584} 585 586static void cli_usage( TSRMLS_D ) 587{ 588 static const char * usage = 589 "Usage: php\n" 590 " php -[b|c|h|i|q|s|v|?] [<file>] [args...]\n" 591 " Run in LSAPI mode, only '-b', '-s' and '-c' are effective\n" 592 " Run in Command Line Interpreter mode when parameters are specified\n" 593 "\n" 594 " -b <address:port>|<port> Bind Path for external LSAPI Server mode\n" 595 " -c <path>|<file> Look for php.ini file in this directory\n" 596 " -h This help\n" 597 " -i PHP information\n" 598 " -q Quiet-mode. Suppress HTTP Header output.\n" 599 " -s Display colour syntax highlighted source.\n" 600 " -v Version number\n" 601 " -? This help\n" 602 "\n" 603 " args... Arguments passed to script.\n"; 604 php_output_startup(); 605 php_output_activate(TSRMLS_C); 606 php_printf( "%s", usage ); 607#ifdef PHP_OUTPUT_NEWAPI 608 php_output_end_all(TSRMLS_C); 609#else 610 php_end_ob_buffers(1 TSRMLS_CC); 611#endif 612} 613 614static int parse_opt( int argc, char * argv[], int *climode, 615 char **php_ini_path, char ** php_bind ) 616{ 617 char ** p = &argv[1]; 618 char ** argend= &argv[argc]; 619 int c; 620 while (( p < argend )&&(**p == '-' )) { 621 c = *((*p)+1); 622 ++p; 623 switch( c ) { 624 case 'b': 625 if ( p >= argend ) { 626 fprintf( stderr, "TCP or socket address must be specified following '-b' option.\n"); 627 return -1; 628 } 629 *php_bind = *p++; 630 break; 631 632 case 'c': 633 if ( p >= argend ) { 634 fprintf( stderr, "<path> or <file> must be specified following '-c' option.\n"); 635 636 return -1; 637 } 638 *php_ini_path = *p++; 639 break; 640 case 's': 641 source_highlight = 1; 642 break; 643 case 'h': 644 case 'i': 645 case 'q': 646 case 'v': 647 case '?': 648 default: 649 *climode = 1; 650 break; 651 } 652 } 653 if ( p - argv < argc ) { 654 *climode = 1; 655 } 656 return 0; 657} 658 659static int cli_main( int argc, char * argv[] ) 660{ 661 662 static const char * ini_defaults[] = { 663 "report_zend_debug", "0", 664 "display_errors", "1", 665 "register_argc_argv", "1", 666 "html_errors", "0", 667 "implicit_flush", "1", 668 "output_buffering", "0", 669 "max_execution_time", "0", 670 "max_input_time", "-1", 671 NULL 672 }; 673 674 const char ** ini; 675 char ** p = &argv[1]; 676 char ** argend= &argv[argc]; 677 int ret = 0; 678 int c; 679 lsapi_mode = 0; /* enter CLI mode */ 680 681#ifdef PHP_WIN32 682 _fmode = _O_BINARY; /*sets default for file streams to binary */ 683 setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ 684 setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ 685 setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ 686#endif 687 688 zend_first_try { 689 SG(server_context) = (void *) 1; 690 691 zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */ 692 CG(in_compilation) = 0; /* not initialized but needed for several options */ 693 EG(uninitialized_zval_ptr) = NULL; 694 695 for( ini = ini_defaults; *ini; ini+=2 ) { 696 zend_alter_ini_entry( (char *)*ini, strlen( *ini )+1, 697 (char *)*(ini+1), strlen( *(ini+1) ), 698 PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); 699 } 700 701 while (( p < argend )&&(**p == '-' )) { 702 c = *((*p)+1); 703 ++p; 704 switch( c ) { 705 case 'q': 706 break; 707 case 'i': 708 if (php_request_startup(TSRMLS_C) != FAILURE) { 709 php_print_info(0xFFFFFFFF TSRMLS_CC); 710#ifdef PHP_OUTPUT_NEWAPI 711 php_output_end_all(TSRMLS_C); 712#else 713 php_end_ob_buffers(1 TSRMLS_CC); 714#endif 715 php_request_shutdown( NULL ); 716 } 717 ret = 1; 718 break; 719 case 'v': 720 if (php_request_startup(TSRMLS_C) != FAILURE) { 721#if ZEND_DEBUG 722 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()); 723#else 724 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()); 725#endif 726#ifdef PHP_OUTPUT_NEWAPI 727 php_output_end_all(TSRMLS_C); 728#else 729 php_end_ob_buffers(1 TSRMLS_CC); 730#endif 731 php_request_shutdown( NULL ); 732 } 733 ret = 1; 734 break; 735 case 'c': 736 ++p; 737 /* fall through */ 738 case 's': 739 break; 740 741 case 'h': 742 case '?': 743 default: 744 cli_usage(TSRMLS_C); 745 ret = 1; 746 break; 747 748 } 749 } 750 if ( !ret ) { 751 if ( *p ) { 752 zend_file_handle file_handle = {0}; 753 754 file_handle.type = ZEND_HANDLE_FP; 755 file_handle.handle.fp = VCWD_FOPEN(*p, "rb"); 756 757 if ( file_handle.handle.fp ) { 758 script_filename = *p; 759 php_self = *p; 760 761 SG(request_info).path_translated = estrdup(*p); 762 SG(request_info).argc = argc - (p - argv); 763 SG(request_info).argv = p; 764 765 if (php_request_startup(TSRMLS_C) == FAILURE ) { 766 fclose( file_handle.handle.fp ); 767 ret = 2; 768 } else { 769 if (source_highlight) { 770 zend_syntax_highlighter_ini syntax_highlighter_ini; 771 772 php_get_highlight_struct(&syntax_highlighter_ini); 773 highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC); 774 } else { 775 file_handle.filename = *p; 776 file_handle.free_filename = 0; 777 file_handle.opened_path = NULL; 778 779 php_execute_script(&file_handle TSRMLS_CC); 780 } 781 782 php_request_shutdown( NULL ); 783 } 784 } else { 785 php_printf("Could not open input file: %s.\n", *p); 786 } 787 } else { 788 cli_usage(TSRMLS_C); 789 } 790 } 791 792 }zend_end_try(); 793 794 php_module_shutdown(TSRMLS_C); 795 796#ifdef ZTS 797 tsrm_shutdown(); 798#endif 799 return ret; 800} 801 802static int s_stop; 803void litespeed_cleanup(int signal) 804{ 805 s_stop = signal; 806} 807 808 809void start_children( int children ) 810{ 811 struct sigaction act, old_term, old_quit, old_int, old_usr1; 812 int running = 0; 813 int status; 814 pid_t pid; 815 816 /* Create a process group */ 817 setsid(); 818 819 /* Set up handler to kill children upon exit */ 820 act.sa_flags = 0; 821 act.sa_handler = litespeed_cleanup; 822 if( sigaction( SIGTERM, &act, &old_term ) || 823 sigaction( SIGINT, &act, &old_int ) || 824 sigaction( SIGUSR1, &act, &old_usr1 ) || 825 sigaction( SIGQUIT, &act, &old_quit )) { 826 perror( "Can't set signals" ); 827 exit( 1 ); 828 } 829 s_stop = 0; 830 while( 1 ) { 831 while((!s_stop )&&( running < children )) { 832 pid = fork(); 833 switch( pid ) { 834 case 0: /* children process */ 835 836 /* don't catch our signals */ 837 sigaction( SIGTERM, &old_term, 0 ); 838 sigaction( SIGQUIT, &old_quit, 0 ); 839 sigaction( SIGINT, &old_int, 0 ); 840 sigaction( SIGUSR1, &old_usr1, 0 ); 841 return ; 842 case -1: 843 perror( "php (pre-forking)" ); 844 exit( 1 ); 845 break; 846 default: /* parent process */ 847 running++; 848 break; 849 } 850 } 851 if ( s_stop ) { 852 break; 853 } 854 pid = wait( &status ); 855 running--; 856 } 857 kill( -getpgrp(), SIGUSR1 ); 858 exit( 0 ); 859} 860 861 862 863#include <fcntl.h> 864int main( int argc, char * argv[] ) 865{ 866 int ret; 867 int bindFd; 868 869 char * php_ini_path = NULL; 870 char * php_bind = NULL; 871 char * p; 872 int n; 873 int climode = 0; 874 struct timeval tv_req_begin; 875 struct timeval tv_req_end; 876 int slow_script_msec = 0; 877 char time_buf[40]; 878 879#ifdef HAVE_SIGNAL_H 880#if defined(SIGPIPE) && defined(SIG_IGN) 881 signal(SIGPIPE, SIG_IGN); 882#endif 883#endif 884 885#ifdef ZTS 886 tsrm_startup(1, 1, 0, NULL); 887#endif 888 889 if (argc > 1 ) { 890 if ( parse_opt( argc, argv, &climode, 891 &php_ini_path, &php_bind ) == -1 ) { 892 return 1; 893 } 894 } 895 if ( climode ) { 896 lsapi_sapi_module.phpinfo_as_text = 1; 897 } 898 argv0 = argv[0] + strlen( argv[0] ); 899 sapi_startup(&lsapi_sapi_module); 900 901#ifdef ZTS 902 compiler_globals = ts_resource(compiler_globals_id); 903 executor_globals = ts_resource(executor_globals_id); 904 core_globals = ts_resource(core_globals_id); 905 sapi_globals = ts_resource(sapi_globals_id); 906 tsrm_ls = ts_resource(0); 907 908 SG(request_info).path_translated = NULL; 909#endif 910 911 lsapi_sapi_module.executable_location = argv[0]; 912 913 if ( php_ini_path ) { 914 lsapi_sapi_module.php_ini_path_override = php_ini_path; 915 } 916 917 918 lsapi_sapi_module.ini_defaults = sapi_lsapi_ini_defaults; 919 920 if (php_module_startup(&lsapi_sapi_module, &litespeed_module_entry, 1) == FAILURE) { 921#ifdef ZTS 922 tsrm_shutdown(); 923#endif 924 return FAILURE; 925 } 926 927 if ( climode ) { 928 return cli_main(argc, argv); 929 } 930 931 if ( php_bind ) { 932 bindFd = LSAPI_CreateListenSock( php_bind, 10 ); 933 if ( bindFd == -1 ) { 934 fprintf( stderr, 935 "Failed to bind socket [%s]: %s\n", php_bind, strerror( errno ) ); 936 exit( 2 ); 937 } 938 if ( bindFd != 0 ) { 939 dup2( bindFd, 0 ); 940 close( bindFd ); 941 } 942 } 943 944 LSAPI_Init(); 945 946 LSAPI_Init_Env_Parameters( NULL ); 947 948 slow_script_msec = LSAPI_Get_Slow_Req_Msecs(); 949 950 if ( php_bind ) { 951 LSAPI_No_Check_ppid(); 952 } 953 954 while( LSAPI_Prefork_Accept_r( &g_req ) >= 0 ) { 955 if ( slow_script_msec ) { 956 gettimeofday( &tv_req_begin, NULL ); 957 } 958 ret = processReq(TSRMLS_C); 959 if ( slow_script_msec ) { 960 gettimeofday( &tv_req_end, NULL ); 961 n = ((long) tv_req_end.tv_sec - tv_req_begin.tv_sec ) * 1000 962 + (tv_req_end.tv_usec - tv_req_begin.tv_usec) / 1000; 963 if ( n > slow_script_msec ) 964 { 965 strftime( time_buf, 30, "%d/%b/%Y:%H:%M:%S", localtime( &tv_req_end.tv_sec ) ); 966 fprintf( stderr, "[%s] Slow PHP script: %d ms\n URL: %s %s\n Query String: %s\n Script: %s\n", 967 time_buf, n, LSAPI_GetRequestMethod(), 968 LSAPI_GetScriptName(), LSAPI_GetQueryString(), 969 LSAPI_GetScriptFileName() ); 970 971 } 972 } 973 LSAPI_Finish(); 974 if ( ret ) { 975 break; 976 } 977 } 978 php_module_shutdown(TSRMLS_C); 979 980#ifdef ZTS 981 tsrm_shutdown(); 982#endif 983 return ret; 984} 985 986 987/* LiteSpeed PHP module starts here */ 988 989#if PHP_MAJOR_VERSION > 4 990 991/* {{{ arginfo */ 992ZEND_BEGIN_ARG_INFO(arginfo_litespeed__void, 0) 993ZEND_END_ARG_INFO() 994/* }}} */ 995 996#else 997#define arginfo_litespeed__void NULL 998#endif 999 1000PHP_FUNCTION(litespeed_request_headers); 1001PHP_FUNCTION(litespeed_response_headers); 1002 1003PHP_MINFO_FUNCTION(litespeed); 1004 1005zend_function_entry litespeed_functions[] = { 1006 PHP_FE(litespeed_request_headers, arginfo_litespeed__void) 1007 PHP_FE(litespeed_response_headers, arginfo_litespeed__void) 1008 PHP_FALIAS(getallheaders, litespeed_request_headers, arginfo_litespeed__void) 1009 PHP_FALIAS(apache_request_headers, litespeed_request_headers, arginfo_litespeed__void) 1010 PHP_FALIAS(apache_response_headers, litespeed_response_headers, arginfo_litespeed__void) 1011 {NULL, NULL, NULL} 1012}; 1013 1014static PHP_MINIT_FUNCTION(litespeed) 1015{ 1016 /* REGISTER_INI_ENTRIES(); */ 1017 return SUCCESS; 1018} 1019 1020 1021static PHP_MSHUTDOWN_FUNCTION(litespeed) 1022{ 1023 /* UNREGISTER_INI_ENTRIES(); */ 1024 return SUCCESS; 1025} 1026 1027zend_module_entry litespeed_module_entry = { 1028 STANDARD_MODULE_HEADER, 1029 "litespeed", 1030 litespeed_functions, 1031 PHP_MINIT(litespeed), 1032 PHP_MSHUTDOWN(litespeed), 1033 NULL, 1034 NULL, 1035 NULL, 1036 NO_VERSION_YET, 1037 STANDARD_MODULE_PROPERTIES 1038}; 1039 1040static int add_associate_array( const char * pKey, int keyLen, const char * pValue, int valLen, 1041 void * arg ) 1042{ 1043 add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue, 1 ); 1044 return 1; 1045} 1046 1047 1048/* {{{ proto array litespeed_request_headers(void) 1049 Fetch all HTTP request headers */ 1050PHP_FUNCTION(litespeed_request_headers) 1051{ 1052 /* TODO: */ 1053 if (ZEND_NUM_ARGS() > 0) { 1054 WRONG_PARAM_COUNT; 1055 } 1056 array_init(return_value); 1057 1058 if ( lsapi_mode ) 1059 LSAPI_ForeachOrgHeader( add_associate_array, return_value ); 1060 1061} 1062/* }}} */ 1063 1064 1065 1066/* {{{ proto array litespeed_response_headers(void) 1067 Fetch all HTTP response headers */ 1068PHP_FUNCTION(litespeed_response_headers) 1069{ 1070 sapi_header_struct *h; 1071 zend_llist_position pos; 1072 char * p; 1073 int len; 1074 char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH]; 1075 1076 if (ZEND_NUM_ARGS() > 0) { 1077 WRONG_PARAM_COUNT; 1078 } 1079 1080 if (!&SG(sapi_headers).headers) { 1081 RETURN_FALSE; 1082 } 1083 array_init(return_value); 1084 1085 h = zend_llist_get_first_ex(&SG(sapi_headers).headers, &pos); 1086 while (h) { 1087 if ( h->header_len > 0 ) { 1088 p = strchr( h->header, ':' ); 1089 len = p - h->header; 1090 if (( p )&&( len > 0 )) { 1091 memmove( headerBuf, h->header, len ); 1092 while( len > 0 && (isspace( headerBuf[len-1])) ) { 1093 --len; 1094 } 1095 headerBuf[len] = 0; 1096 if ( len ) { 1097 while( isspace(*++p)); 1098 add_assoc_string_ex(return_value, headerBuf, len+1, p, 1 ); 1099 } 1100 } 1101 } 1102 h = zend_llist_get_next_ex(&SG(sapi_headers).headers, &pos); 1103 } 1104} 1105 1106/* }}} */ 1107 1108 1109/* 1110 * Local variables: 1111 * tab-width: 4 1112 * c-basic-offset: 4 1113 * End: 1114 * vim600: sw=4 ts=4 fdm=marker 1115 * vim<600: sw=4 ts=4 1116 */ 1117 1118 1119