File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / litespeed / lsapi_main.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:04:02 2014 UTC (10 years ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 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: lsapi_main.c,v 1.1.1.4 2014/06/15 20:04:02 misho Exp $ */
   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: 
   74: static int  lsapi_mode       = 1;
   75: static char *php_self        = "";
   76: static char *script_filename = "";
   77: static int  source_highlight = 0;
   78: static char * argv0 = NULL;
   79: static int  engine = 1;
   80: #ifdef ZTS
   81: zend_compiler_globals    *compiler_globals;
   82: zend_executor_globals    *executor_globals;
   83: php_core_globals         *core_globals;
   84: sapi_globals_struct      *sapi_globals;
   85: void ***tsrm_ls;
   86: #endif
   87: 
   88: zend_module_entry litespeed_module_entry;
   89: 
   90: /* {{{ php_lsapi_startup
   91:  */
   92: static 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: 
  110: static 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:  */
  130: static 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:  */
  159: static 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:  */
  172: static 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:  */
  188: static 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: /*
  200: static 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: 
  208: static 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)
  229: static 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:  */
  252: static 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:  */
  289: static 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:  */
  304: static 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:  */
  317: static 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:  */
  354: static 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:  */
  364: static 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: 
  406: static 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: 
  425: static char s_cur_chdir[4096] = "";
  426: 
  427: static 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: 
  461: static 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: 
  481: static 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: 
  506: static 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: 
  529: static 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: 
  554: static void override_ini()
  555: {
  556: 
  557:     LSAPI_ForeachSpecialEnv( alter_ini, NULL );
  558: 
  559: }
  560: 
  561: static 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: 
  586: static 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: 
  614: static 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: 
  659: static 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-2014 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-2014 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: 
  802: static int s_stop;
  803: void litespeed_cleanup(int signal)
  804: {
  805:     s_stop = signal;
  806: }
  807: 
  808: 
  809: void 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>
  864: int 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 */
  992: ZEND_BEGIN_ARG_INFO(arginfo_litespeed__void, 0)
  993: ZEND_END_ARG_INFO()
  994: /* }}} */
  995: 
  996: #else
  997: #define arginfo_litespeed__void NULL
  998: #endif
  999: 
 1000: PHP_FUNCTION(litespeed_request_headers);
 1001: PHP_FUNCTION(litespeed_response_headers);
 1002: 
 1003: PHP_MINFO_FUNCTION(litespeed);
 1004: 
 1005: zend_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: 
 1014: static PHP_MINIT_FUNCTION(litespeed)
 1015: {
 1016:     /* REGISTER_INI_ENTRIES(); */
 1017:     return SUCCESS;
 1018: }
 1019: 
 1020: 
 1021: static PHP_MSHUTDOWN_FUNCTION(litespeed)
 1022: {
 1023:     /* UNREGISTER_INI_ENTRIES(); */
 1024:     return SUCCESS;
 1025: }
 1026: 
 1027: zend_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: 
 1040: static 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 */
 1050: PHP_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 */
 1068: PHP_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: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>