PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - sapi/cgi - cgi_main.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 500 1061 47.1 %
Date: 2014-10-14 Functions: 20 42 47.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       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 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             :    | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       |
      16             :    |          Stig Bakken <ssb@php.net>                                   |
      17             :    |          Zeev Suraski <zeev@zend.com>                                |
      18             :    | FastCGI: Ben Mansell <php@slimyhorror.com>                           |
      19             :    |          Shane Caraveo <shane@caraveo.com>                           |
      20             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      21             :    +----------------------------------------------------------------------+
      22             : */
      23             : 
      24             : /* $Id$ */
      25             : 
      26             : #include "php.h"
      27             : #include "php_globals.h"
      28             : #include "php_variables.h"
      29             : #include "zend_modules.h"
      30             : 
      31             : #include "SAPI.h"
      32             : 
      33             : #include <stdio.h>
      34             : #include "php.h"
      35             : 
      36             : #ifdef PHP_WIN32
      37             : # include "win32/time.h"
      38             : # include "win32/signal.h"
      39             : # include <process.h>
      40             : #endif
      41             : 
      42             : #if HAVE_SYS_TIME_H
      43             : # include <sys/time.h>
      44             : #endif
      45             : 
      46             : #if HAVE_UNISTD_H
      47             : # include <unistd.h>
      48             : #endif
      49             : 
      50             : #if HAVE_SIGNAL_H
      51             : # include <signal.h>
      52             : #endif
      53             : 
      54             : #if HAVE_SETLOCALE
      55             : # include <locale.h>
      56             : #endif
      57             : 
      58             : #if HAVE_SYS_TYPES_H
      59             : # include <sys/types.h>
      60             : #endif
      61             : 
      62             : #if HAVE_SYS_WAIT_H
      63             : # include <sys/wait.h>
      64             : #endif
      65             : 
      66             : #include "zend.h"
      67             : #include "zend_extensions.h"
      68             : #include "php_ini.h"
      69             : #include "php_globals.h"
      70             : #include "php_main.h"
      71             : #include "fopen_wrappers.h"
      72             : #include "ext/standard/php_standard.h"
      73             : #include "ext/standard/url.h"
      74             : 
      75             : #ifdef PHP_WIN32
      76             : # include <io.h>
      77             : # include <fcntl.h>
      78             : # include "win32/php_registry.h"
      79             : #endif
      80             : 
      81             : #ifdef __riscos__
      82             : # include <unixlib/local.h>
      83             : int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
      84             : #endif
      85             : 
      86             : #include "zend_compile.h"
      87             : #include "zend_execute.h"
      88             : #include "zend_highlight.h"
      89             : #include "zend_indent.h"
      90             : 
      91             : #include "php_getopt.h"
      92             : 
      93             : #include "fastcgi.h"
      94             : 
      95             : #ifndef PHP_WIN32
      96             : /* XXX this will need to change later when threaded fastcgi is implemented.  shane */
      97             : struct sigaction act, old_term, old_quit, old_int;
      98             : #endif
      99             : 
     100             : static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC);
     101             : 
     102             : #ifndef PHP_WIN32
     103             : /* these globals used for forking children on unix systems */
     104             : /**
     105             :  * Number of child processes that will get created to service requests
     106             :  */
     107             : static int children = 0;
     108             : 
     109             : 
     110             : /**
     111             :  * Set to non-zero if we are the parent process
     112             :  */
     113             : static int parent = 1;
     114             : 
     115             : /* Did parent received exit signals SIG_TERM/SIG_INT/SIG_QUIT */
     116             : static int exit_signal = 0;
     117             : 
     118             : /* Is Parent waiting for children to exit */
     119             : static int parent_waiting = 0;
     120             : 
     121             : /**
     122             :  * Process group
     123             :  */
     124             : static pid_t pgroup;
     125             : #endif
     126             : 
     127             : #define PHP_MODE_STANDARD       1
     128             : #define PHP_MODE_HIGHLIGHT      2
     129             : #define PHP_MODE_INDENT         3
     130             : #define PHP_MODE_LINT           4
     131             : #define PHP_MODE_STRIP          5
     132             : 
     133             : static char *php_optarg = NULL;
     134             : static int php_optind = 1;
     135             : static zend_module_entry cgi_module_entry;
     136             : 
     137             : static const opt_struct OPTIONS[] = {
     138             :         {'a', 0, "interactive"},
     139             :         {'b', 1, "bindpath"},
     140             :         {'C', 0, "no-chdir"},
     141             :         {'c', 1, "php-ini"},
     142             :         {'d', 1, "define"},
     143             :         {'e', 0, "profile-info"},
     144             :         {'f', 1, "file"},
     145             :         {'h', 0, "help"},
     146             :         {'i', 0, "info"},
     147             :         {'l', 0, "syntax-check"},
     148             :         {'m', 0, "modules"},
     149             :         {'n', 0, "no-php-ini"},
     150             :         {'q', 0, "no-header"},
     151             :         {'s', 0, "syntax-highlight"},
     152             :         {'s', 0, "syntax-highlighting"},
     153             :         {'w', 0, "strip"},
     154             :         {'?', 0, "usage"},/* help alias (both '?' and 'usage') */
     155             :         {'v', 0, "version"},
     156             :         {'z', 1, "zend-extension"},
     157             :         {'T', 1, "timing"},
     158             :         {'-', 0, NULL} /* end of args */
     159             : };
     160             : 
     161             : typedef struct _php_cgi_globals_struct {
     162             :         HashTable user_config_cache;
     163             :         char *redirect_status_env;
     164             :         zend_bool rfc2616_headers;
     165             :         zend_bool nph;
     166             :         zend_bool check_shebang_line;
     167             :         zend_bool fix_pathinfo;
     168             :         zend_bool force_redirect;
     169             :         zend_bool discard_path;
     170             :         zend_bool fcgi_logging;
     171             : #ifdef PHP_WIN32
     172             :         zend_bool impersonate;
     173             : #endif
     174             : } php_cgi_globals_struct;
     175             : 
     176             : /* {{{ user_config_cache
     177             :  *
     178             :  * Key for each cache entry is dirname(PATH_TRANSLATED).
     179             :  *
     180             :  * NOTE: Each cache entry config_hash contains the combination from all user ini files found in
     181             :  *       the path starting from doc_root throught to dirname(PATH_TRANSLATED).  There is no point
     182             :  *       storing per-file entries as it would not be possible to detect added / deleted entries
     183             :  *       between separate files.
     184             :  */
     185             : typedef struct _user_config_cache_entry {
     186             :         time_t expires;
     187             :         HashTable *user_config;
     188             : } user_config_cache_entry;
     189             : 
     190           0 : static void user_config_cache_entry_dtor(zval *el)
     191             : {
     192           0 :         user_config_cache_entry *entry = (user_config_cache_entry *)Z_PTR_P(el);
     193           0 :         zend_hash_destroy(entry->user_config);
     194           0 :         free(entry->user_config);
     195           0 :         free(entry);
     196           0 : }
     197             : /* }}} */
     198             : 
     199             : #ifdef ZTS
     200             : static int php_cgi_globals_id;
     201             : #define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v)
     202             : #else
     203             : static php_cgi_globals_struct php_cgi_globals;
     204             : #define CGIG(v) (php_cgi_globals.v)
     205             : #endif
     206             : 
     207             : #ifdef PHP_WIN32
     208             : #define TRANSLATE_SLASHES(path) \
     209             :         { \
     210             :                 char *tmp = path; \
     211             :                 while (*tmp) { \
     212             :                         if (*tmp == '\\') *tmp = '/'; \
     213             :                         tmp++; \
     214             :                 } \
     215             :         }
     216             : #else
     217             : #define TRANSLATE_SLASHES(path)
     218             : #endif
     219             : 
     220           0 : static int print_module_info(zval *element TSRMLS_DC)
     221             : {
     222           0 :         zend_module_entry *module = Z_PTR_P(element);
     223           0 :         php_printf("%s\n", module->name);
     224           0 :         return ZEND_HASH_APPLY_KEEP;
     225             : }
     226             : 
     227           0 : static int module_name_cmp(const void *a, const void *b TSRMLS_DC)
     228             : {
     229           0 :         Bucket *f = (Bucket *) a;
     230           0 :         Bucket *s = (Bucket *) b;
     231             : 
     232           0 :         return strcasecmp(      ((zend_module_entry *)Z_PTR(f->val))->name,
     233           0 :                                                 ((zend_module_entry *)Z_PTR(s->val))->name);
     234             : }
     235             : 
     236           0 : static void print_modules(TSRMLS_D)
     237             : {
     238             :         HashTable sorted_registry;
     239             : 
     240           0 :         zend_hash_init(&sorted_registry, 64, NULL, NULL, 1);
     241           0 :         zend_hash_copy(&sorted_registry, &module_registry, NULL);
     242           0 :         zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC);
     243           0 :         zend_hash_apply(&sorted_registry, print_module_info TSRMLS_CC);
     244           0 :         zend_hash_destroy(&sorted_registry);
     245           0 : }
     246             : 
     247           0 : static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC)
     248             : {
     249           0 :         php_printf("%s\n", ext->name);
     250           0 :         return 0;
     251             : }
     252             : 
     253           0 : static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s TSRMLS_DC)
     254             : {
     255           0 :         return strcmp(  ((zend_extension *)(*f)->data)->name,
     256           0 :                                         ((zend_extension *)(*s)->data)->name);
     257             : }
     258             : 
     259           0 : static void print_extensions(TSRMLS_D)
     260             : {
     261             :         zend_llist sorted_exts;
     262             : 
     263           0 :         zend_llist_copy(&sorted_exts, &zend_extensions);
     264           0 :         sorted_exts.dtor = NULL;
     265           0 :         zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC);
     266           0 :         zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC);
     267           0 :         zend_llist_destroy(&sorted_exts);
     268           0 : }
     269             : 
     270             : #ifndef STDOUT_FILENO
     271             : #define STDOUT_FILENO 1
     272             : #endif
     273             : 
     274        7682 : static inline size_t sapi_cgi_single_write(const char *str, uint str_length TSRMLS_DC)
     275             : {
     276             : #ifdef PHP_WRITE_STDOUT
     277             :         int ret;
     278             : 
     279        7682 :         ret = write(STDOUT_FILENO, str, str_length);
     280        7682 :         if (ret <= 0) return 0;
     281        7682 :         return ret;
     282             : #else
     283             :         size_t ret;
     284             : 
     285             :         ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
     286             :         return ret;
     287             : #endif
     288             : }
     289             : 
     290        7682 : static size_t sapi_cgi_ub_write(const char *str, size_t str_length TSRMLS_DC)
     291             : {
     292        7682 :         const char *ptr = str;
     293        7682 :         size_t remaining = str_length;
     294             :         size_t ret;
     295             : 
     296       23046 :         while (remaining > 0) {
     297        7682 :                 ret = sapi_cgi_single_write(ptr, remaining TSRMLS_CC);
     298        7682 :                 if (!ret) {
     299           0 :                         php_handle_aborted_connection();
     300           0 :                         return str_length - remaining;
     301             :                 }
     302        7682 :                 ptr += ret;
     303        7682 :                 remaining -= ret;
     304             :         }
     305             : 
     306        7682 :         return str_length;
     307             : }
     308             : 
     309           0 : static size_t sapi_fcgi_ub_write(const char *str, size_t str_length TSRMLS_DC)
     310             : {
     311           0 :         const char *ptr = str;
     312           0 :         size_t remaining = str_length;
     313           0 :         fcgi_request *request = (fcgi_request*) SG(server_context);
     314             : 
     315           0 :         while (remaining > 0) {
     316           0 :                 zend_long ret = fcgi_write(request, FCGI_STDOUT, ptr, remaining);
     317             : 
     318           0 :                 if (ret <= 0) {
     319           0 :                         php_handle_aborted_connection();
     320           0 :                         return str_length - remaining;
     321             :                 }
     322           0 :                 ptr += ret;
     323           0 :                 remaining -= ret;
     324             :         }
     325             : 
     326           0 :         return str_length;
     327             : }
     328             : 
     329         803 : static void sapi_cgi_flush(void *server_context TSRMLS_DC)
     330             : {
     331         803 :         if (fflush(stdout) == EOF) {
     332           0 :                 php_handle_aborted_connection();
     333             :         }
     334         803 : }
     335             : 
     336           0 : static void sapi_fcgi_flush(void *server_context TSRMLS_DC)
     337             : {
     338           0 :         fcgi_request *request = (fcgi_request*) server_context;
     339             : 
     340           0 :         if (
     341             : #ifndef PHP_WIN32
     342           0 :                 !parent &&
     343             : #endif
     344           0 :                 request && !fcgi_flush(request, 0)) {
     345             : 
     346           0 :                 php_handle_aborted_connection();
     347             :         }
     348           0 : }
     349             : 
     350             : #define SAPI_CGI_MAX_HEADER_LENGTH 1024
     351             : 
     352             : typedef struct _http_error {
     353             :   int code;
     354             :   const char* msg;
     355             : } http_error;
     356             : 
     357             : static const http_error http_error_codes[] = {
     358             :         {100, "Continue"},
     359             :         {101, "Switching Protocols"},
     360             :         {200, "OK"},
     361             :         {201, "Created"},
     362             :         {202, "Accepted"},
     363             :         {203, "Non-Authoritative Information"},
     364             :         {204, "No Content"},
     365             :         {205, "Reset Content"},
     366             :         {206, "Partial Content"},
     367             :         {300, "Multiple Choices"},
     368             :         {301, "Moved Permanently"},
     369             :         {302, "Moved Temporarily"},
     370             :         {303, "See Other"},
     371             :         {304, "Not Modified"},
     372             :         {305, "Use Proxy"},
     373             :         {400, "Bad Request"},
     374             :         {401, "Unauthorized"},
     375             :         {402, "Payment Required"},
     376             :         {403, "Forbidden"},
     377             :         {404, "Not Found"},
     378             :         {405, "Method Not Allowed"},
     379             :         {406, "Not Acceptable"},
     380             :         {407, "Proxy Authentication Required"},
     381             :         {408, "Request Time-out"},
     382             :         {409, "Conflict"},
     383             :         {410, "Gone"},
     384             :         {411, "Length Required"},
     385             :         {412, "Precondition Failed"},
     386             :         {413, "Request Entity Too Large"},
     387             :         {414, "Request-URI Too Large"},
     388             :         {415, "Unsupported Media Type"},
     389             :         {428, "Precondition Required"},
     390             :         {429, "Too Many Requests"},
     391             :         {431, "Request Header Fields Too Large"},
     392             :         {500, "Internal Server Error"},
     393             :         {501, "Not Implemented"},
     394             :         {502, "Bad Gateway"},
     395             :         {503, "Service Unavailable"},
     396             :         {504, "Gateway Time-out"},
     397             :         {505, "HTTP Version not supported"},
     398             :         {511, "Network Authentication Required"},
     399             :         {0,   NULL}
     400             : };
     401             : 
     402         238 : static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
     403             : {
     404             :         char buf[SAPI_CGI_MAX_HEADER_LENGTH];
     405             :         sapi_header_struct *h;
     406             :         zend_llist_position pos;
     407         238 :         zend_bool ignore_status = 0;
     408         238 :         int response_status = SG(sapi_headers).http_response_code;
     409             : 
     410         238 :         if (SG(request_info).no_headers == 1) {
     411           0 :                 return  SAPI_HEADER_SENT_SUCCESSFULLY;
     412             :         }
     413             : 
     414         238 :         if (CGIG(nph) || SG(sapi_headers).http_response_code != 200)
     415             :         {
     416             :                 int len;
     417          43 :                 zend_bool has_status = 0;
     418             : 
     419          43 :                 if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
     420             :                         char *s;
     421           0 :                         len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line);
     422           0 :                         if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
     423           0 :                                 response_status = atoi((s + 1));
     424             :                         }
     425             : 
     426           0 :                         if (len > SAPI_CGI_MAX_HEADER_LENGTH) {
     427           0 :                                 len = SAPI_CGI_MAX_HEADER_LENGTH;
     428             :                         }
     429             : 
     430             :                 } else {
     431             :                         char *s;
     432             : 
     433         191 :                         if (SG(sapi_headers).http_status_line &&
     434          37 :                                 (s = strchr(SG(sapi_headers).http_status_line, ' ')) != 0 &&
     435          37 :                                 (s - SG(sapi_headers).http_status_line) >= 5 &&
     436          37 :                                 strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
     437             :                         ) {
     438          37 :                                 len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s);
     439          37 :                                 response_status = atoi((s + 1));
     440             :                         } else {
     441           6 :                                 h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
     442          28 :                                 while (h) {
     443          32 :                                         if (h->header_len > sizeof("Status:")-1 &&
     444          16 :                                                 strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
     445             :                                         ) {
     446           0 :                                                 has_status = 1;
     447           0 :                                                 break;
     448             :                                         }
     449          16 :                                         h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
     450             :                                 }
     451           6 :                                 if (!has_status) {
     452           6 :                                         http_error *err = (http_error*)http_error_codes;
     453             : 
     454         110 :                                         while (err->code != 0) {
     455         104 :                                                 if (err->code == SG(sapi_headers).http_response_code) {
     456           6 :                                                         break;
     457             :                                                 }
     458          98 :                                                 err++;
     459             :                                         }
     460           6 :                                         if (err->msg) {
     461           6 :                                                 len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->msg);
     462             :                                         } else {
     463           0 :                                                 len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code);
     464             :                                         }
     465             :                                 }
     466             :                         }
     467             :                 }
     468             : 
     469          43 :                 if (!has_status) {
     470          43 :                         PHPWRITE_H(buf, len);
     471          43 :                         ignore_status = 1;
     472             :                 }
     473             :         }
     474             : 
     475         238 :         h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
     476        1071 :         while (h) {
     477             :                 /* prevent CRLFCRLF */
     478         595 :                 if (h->header_len) {
     479        1192 :                         if (h->header_len > sizeof("Status:")-1 && 
     480         595 :                                 strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
     481             :                         ) {
     482           2 :                                 if (!ignore_status) {
     483           1 :                                         ignore_status = 1;
     484           1 :                                         PHPWRITE_H(h->header, h->header_len);
     485           1 :                                         PHPWRITE_H("\r\n", 2);
     486             :                                 }
     487         596 :                         } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 &&
     488           3 :                                 strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0
     489             :                         ) {
     490           1 :                                 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
     491           1 :                                 continue;
     492             :                         } else {
     493         592 :                                 PHPWRITE_H(h->header, h->header_len);
     494         592 :                                 PHPWRITE_H("\r\n", 2);
     495             :                         }
     496             :                 }
     497         594 :                 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
     498             :         }
     499         238 :         PHPWRITE_H("\r\n", 2);
     500             : 
     501         238 :         return SAPI_HEADER_SENT_SUCCESSFULLY;
     502             : }
     503             : 
     504             : #ifndef STDIN_FILENO
     505             : # define STDIN_FILENO 0
     506             : #endif
     507             : 
     508         703 : static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes TSRMLS_DC)
     509             : {
     510         703 :         size_t read_bytes = 0;
     511             :         int tmp_read_bytes;
     512             : 
     513         703 :         count_bytes = MIN(count_bytes, SG(request_info).content_length - SG(read_post_bytes));
     514        1486 :         while (read_bytes < count_bytes) {
     515          80 :                 tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
     516          80 :                 if (tmp_read_bytes <= 0) {
     517           0 :                         break;
     518             :                 }
     519          80 :                 read_bytes += tmp_read_bytes;
     520             :         }
     521         703 :         return read_bytes;
     522             : }
     523             : 
     524           0 : static size_t sapi_fcgi_read_post(char *buffer, size_t count_bytes TSRMLS_DC)
     525             : {
     526           0 :         size_t read_bytes = 0;
     527             :         int tmp_read_bytes;
     528           0 :         fcgi_request *request = (fcgi_request*) SG(server_context);
     529           0 :         size_t remaining = SG(request_info).content_length - SG(read_post_bytes);
     530             : 
     531           0 :         if (remaining < count_bytes) {
     532           0 :                 count_bytes = remaining;
     533             :         }
     534           0 :         while (read_bytes < count_bytes) {
     535           0 :                 tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
     536           0 :                 if (tmp_read_bytes <= 0) {
     537           0 :                         break;
     538             :                 }
     539           0 :                 read_bytes += tmp_read_bytes;
     540             :         }
     541           0 :         return read_bytes;
     542             : }
     543             : 
     544           8 : static char *sapi_cgi_getenv(char *name, size_t name_len TSRMLS_DC)
     545             : {
     546           8 :         return getenv(name);
     547             : }
     548             : 
     549           0 : static char *sapi_fcgi_getenv(char *name, size_t name_len TSRMLS_DC)
     550             : {
     551             :         /* when php is started by mod_fastcgi, no regular environment
     552             :          * is provided to PHP.  It is always sent to PHP at the start
     553             :          * of a request.  So we have to do our own lookup to get env
     554             :          * vars.  This could probably be faster somehow.  */
     555           0 :         fcgi_request *request = (fcgi_request*) SG(server_context);
     556           0 :         char *ret = fcgi_getenv(request, name, name_len);
     557             : 
     558           0 :         if (ret) return ret;
     559             :         /*  if cgi, or fastcgi and not found in fcgi env
     560             :                 check the regular environment */
     561           0 :         return getenv(name);
     562             : }
     563             : 
     564          12 : static char *_sapi_cgi_putenv(char *name, int name_len, char *value)
     565             : {
     566             : #if !HAVE_SETENV || !HAVE_UNSETENV
     567             :         int len;
     568             :         char *buf;
     569             : #endif
     570             : 
     571             : #if HAVE_SETENV
     572          12 :         if (value) {
     573           8 :                 setenv(name, value, 1);
     574             :         }
     575             : #endif
     576             : #if HAVE_UNSETENV
     577          12 :         if (!value) {
     578           4 :                 unsetenv(name);
     579             :         }
     580             : #endif
     581             : 
     582             : #if !HAVE_SETENV || !HAVE_UNSETENV
     583             :         /*  if cgi, or fastcgi and not found in fcgi env
     584             :                 check the regular environment
     585             :                 this leaks, but it's only cgi anyway, we'll fix
     586             :                 it for 5.0
     587             :         */
     588             :         len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2;
     589             :         buf = (char *) malloc(len);
     590             :         if (buf == NULL) {
     591             :                 return getenv(name);
     592             :         }
     593             : #endif
     594             : #if !HAVE_SETENV
     595             :         if (value) {
     596             :                 len = slprintf(buf, len - 1, "%s=%s", name, value);
     597             :                 putenv(buf);
     598             :         }
     599             : #endif
     600             : #if !HAVE_UNSETENV
     601             :         if (!value) {
     602             :                 len = slprintf(buf, len - 1, "%s=", name);
     603             :                 putenv(buf);
     604             :         }
     605             : #endif
     606          12 :         return getenv(name);
     607             : }
     608             : 
     609         404 : static char *sapi_cgi_read_cookies(TSRMLS_D)
     610             : {
     611         404 :         return getenv("HTTP_COOKIE");
     612             : }
     613             : 
     614           0 : static char *sapi_fcgi_read_cookies(TSRMLS_D)
     615             : {
     616           0 :         fcgi_request *request = (fcgi_request*) SG(server_context);
     617             : 
     618           0 :         return FCGI_GETENV(request, "HTTP_COOKIE");
     619             : }
     620             : 
     621           0 : static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC)
     622             : {
     623           0 :         zval *array_ptr = (zval*)arg;   
     624           0 :         int filter_arg = (Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))?PARSE_ENV:PARSE_SERVER;
     625             :         size_t new_val_len;
     626             : 
     627           0 :         if (sapi_module.input_filter(filter_arg, var, &val, strlen(val), &new_val_len TSRMLS_CC)) {
     628           0 :                 php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
     629             :         }
     630           0 : }
     631             : 
     632           0 : static void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
     633             : {
     634           0 :         if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
     635           0 :                 Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_ENV]) &&
     636           0 :                 zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_ENV])) > 0
     637             :         ) {
     638             :                 zval_dtor(array_ptr);
     639           0 :                 ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_ENV]);
     640           0 :                 return;
     641           0 :         } else if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
     642           0 :                 Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_SERVER]) &&
     643           0 :                 zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])) > 0
     644             :         ) {
     645             :                 zval_dtor(array_ptr);
     646           0 :                 ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_SERVER]);
     647           0 :                 return;
     648             :         }
     649             : 
     650             :         /* call php's original import as a catch-all */
     651           0 :         php_php_import_environment_variables(array_ptr TSRMLS_CC);
     652             : 
     653           0 :         if (fcgi_is_fastcgi()) {
     654           0 :                 fcgi_request *request = (fcgi_request*) SG(server_context);
     655           0 :                 fcgi_loadenv(request, cgi_php_load_env_var, array_ptr TSRMLS_CC);
     656             :         }
     657             : }
     658             : 
     659         111 : static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
     660             : {
     661             :         size_t php_self_len;
     662             :         char *php_self;
     663             : 
     664             :         /* In CGI mode, we consider the environment to be a part of the server
     665             :          * variables
     666             :          */
     667         111 :         php_import_environment_variables(track_vars_array TSRMLS_CC);
     668             : 
     669         111 :         if (CGIG(fix_pathinfo)) {
     670         111 :                 char *script_name = SG(request_info).request_uri;
     671             :                 char *path_info;
     672             :                 int free_php_self;
     673             :                 ALLOCA_FLAG(use_heap)
     674             : 
     675         111 :                 if (fcgi_is_fastcgi()) {
     676           0 :                         fcgi_request *request = (fcgi_request*) SG(server_context);
     677             : 
     678           0 :                         path_info = FCGI_GETENV(request, "PATH_INFO");
     679             :                 } else {
     680         111 :                         path_info = getenv("PATH_INFO");
     681             :                 }
     682             : 
     683         111 :                 if (path_info) {
     684          82 :                         unsigned int path_info_len = strlen(path_info);
     685             : 
     686          82 :                         if (script_name) {
     687          82 :                                 unsigned int script_name_len = strlen(script_name);
     688             : 
     689          82 :                                 php_self_len = script_name_len + path_info_len;
     690          82 :                                 php_self = do_alloca(php_self_len + 1, use_heap);
     691          82 :                                 memcpy(php_self, script_name, script_name_len + 1);
     692          82 :                                 memcpy(php_self + script_name_len, path_info, path_info_len + 1);
     693          82 :                                 free_php_self = 1;
     694             :                         }  else {
     695           0 :                                 php_self = path_info;
     696           0 :                                 php_self_len = path_info_len;
     697           0 :                                 free_php_self = 0;
     698             :                         }
     699          29 :                 } else if (script_name) {
     700          10 :                         php_self = script_name;
     701          10 :                         php_self_len = strlen(script_name);
     702          10 :                         free_php_self = 0;
     703             :                 } else {
     704          19 :                         php_self = "";
     705          19 :                         php_self_len = 0;
     706          19 :                         free_php_self = 0;
     707             :                 }
     708             : 
     709             :                 /* Build the special-case PHP_SELF variable for the CGI version */
     710         111 :                 if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) {
     711           0 :                         php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC);
     712             :                 }
     713         111 :                 if (free_php_self) {
     714          82 :                         free_alloca(php_self, use_heap);
     715             :                 }
     716             :         } else {
     717           0 :                 php_self = SG(request_info).request_uri ? SG(request_info).request_uri : "";
     718           0 :                 php_self_len = strlen(php_self);
     719           0 :                 if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) {
     720           0 :                         php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC);
     721             :                 }
     722             :         }
     723         111 : }
     724             : 
     725           0 : static void sapi_cgi_log_message(char *message TSRMLS_DC)
     726             : {
     727           0 :         if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) {
     728             :                 fcgi_request *request;
     729             : 
     730           0 :                 request = (fcgi_request*) SG(server_context);
     731           0 :                 if (request) {
     732           0 :                         int len = strlen(message);
     733           0 :                         char *buf = malloc(len+2);
     734             : 
     735           0 :                         memcpy(buf, message, len);
     736           0 :                         memcpy(buf + len, "\n", sizeof("\n"));
     737           0 :                         fcgi_write(request, FCGI_STDERR, buf, len+1);
     738           0 :                         free(buf);
     739             :                 } else {
     740           0 :                         fprintf(stderr, "%s\n", message);
     741             :                 }
     742             :                 /* ignore return code */
     743             :         } else {
     744           0 :                 fprintf(stderr, "%s\n", message);
     745             :         }
     746           0 : }
     747             : 
     748             : /* {{{ php_cgi_ini_activate_user_config
     749             :  */
     750           0 : static void php_cgi_ini_activate_user_config(char *path, int path_len, const char *doc_root, int doc_root_len, int start TSRMLS_DC)
     751             : {
     752             :         char *ptr;
     753             :         user_config_cache_entry *new_entry, *entry;
     754           0 :         time_t request_time = sapi_get_request_time(TSRMLS_C);
     755             : 
     756             :         /* Find cached config entry: If not found, create one */
     757           0 :         if ((entry = zend_hash_str_find_ptr(&CGIG(user_config_cache), path, path_len)) == NULL) {
     758           0 :                 new_entry = pemalloc(sizeof(user_config_cache_entry), 1);
     759           0 :                 new_entry->expires = 0;
     760           0 :                 new_entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1);
     761           0 :                 zend_hash_init(new_entry->user_config, 8, NULL, (dtor_func_t) config_zval_dtor, 1);
     762           0 :                 entry = zend_hash_str_update_ptr(&CGIG(user_config_cache), path, path_len, new_entry);
     763             :         }
     764             : 
     765             :         /* Check whether cache entry has expired and rescan if it is */
     766           0 :         if (request_time > entry->expires) {
     767           0 :                 char *real_path = NULL;
     768             :                 int real_path_len;
     769             :                 char *s1, *s2;
     770             :                 int s_len;
     771             : 
     772             :                 /* Clear the expired config */
     773           0 :                 zend_hash_clean(entry->user_config);
     774             : 
     775           0 :                 if (!IS_ABSOLUTE_PATH(path, path_len)) {
     776           0 :                         real_path = tsrm_realpath(path, NULL TSRMLS_CC);
     777           0 :                         if (real_path == NULL) {
     778           0 :                                 return;
     779             :                         }
     780           0 :                         real_path_len = strlen(real_path);
     781           0 :                         path = real_path;
     782           0 :                         path_len = real_path_len;
     783             :                 }
     784             : 
     785           0 :                 if (path_len > doc_root_len) {
     786           0 :                         s1 = (char *) doc_root;
     787           0 :                         s2 = path;
     788           0 :                         s_len = doc_root_len;
     789             :                 } else {
     790           0 :                         s1 = path;
     791           0 :                         s2 = (char *) doc_root;
     792           0 :                         s_len = path_len;
     793             :                 }
     794             : 
     795             :                 /* we have to test if path is part of DOCUMENT_ROOT.
     796             :                   if it is inside the docroot, we scan the tree up to the docroot 
     797             :                         to find more user.ini, if not we only scan the current path.
     798             :                   */
     799             : #ifdef PHP_WIN32
     800             :                 if (strnicmp(s1, s2, s_len) == 0) {
     801             : #else 
     802           0 :                 if (strncmp(s1, s2, s_len) == 0) {
     803             : #endif
     804           0 :                         ptr = s2 + start;  /* start is the point where doc_root ends! */
     805           0 :                         while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) {
     806           0 :                                 *ptr = 0;
     807           0 :                                 php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC);
     808           0 :                                 *ptr = '/';
     809           0 :                                 ptr++;
     810             :                         }
     811             :                 } else {
     812           0 :                         php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC);
     813             :                 }
     814             : 
     815           0 :                 if (real_path) {
     816           0 :                         efree(real_path);
     817             :                 }
     818           0 :                 entry->expires = request_time + PG(user_ini_cache_ttl);
     819             :         }
     820             : 
     821             :         /* Activate ini entries with values from the user config hash */
     822           0 :         php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS TSRMLS_CC);
     823             : }
     824             : /* }}} */
     825             : 
     826         404 : static int sapi_cgi_activate(TSRMLS_D)
     827             : {
     828             :         char *path, *doc_root, *server_name;
     829             :         uint path_len, doc_root_len, server_name_len;
     830             : 
     831             :         /* PATH_TRANSLATED should be defined at this stage but better safe than sorry :) */
     832         404 :         if (!SG(request_info).path_translated) {
     833           3 :                 return FAILURE;
     834             :         }
     835             : 
     836         401 :         if (php_ini_has_per_host_config()) {
     837             :                 /* Activate per-host-system-configuration defined in php.ini and stored into configuration_hash during startup */
     838           0 :                 if (fcgi_is_fastcgi()) {
     839           0 :                         fcgi_request *request = (fcgi_request*) SG(server_context);
     840             : 
     841           0 :                         server_name = FCGI_GETENV(request, "SERVER_NAME");
     842             :                 } else {
     843           0 :                         server_name = getenv("SERVER_NAME");
     844             :                 }
     845             :                 /* SERVER_NAME should also be defined at this stage..but better check it anyway */
     846           0 :                 if (server_name) {
     847           0 :                         server_name_len = strlen(server_name);
     848           0 :                         server_name = estrndup(server_name, server_name_len);
     849           0 :                         zend_str_tolower(server_name, server_name_len);
     850           0 :                         php_ini_activate_per_host_config(server_name, server_name_len TSRMLS_CC);
     851           0 :                         efree(server_name);
     852             :                 }
     853             :         }
     854             : 
     855        1203 :         if (php_ini_has_per_dir_config() ||
     856         802 :                 (PG(user_ini_filename) && *PG(user_ini_filename))
     857             :         ) {
     858             :                 /* Prepare search path */
     859         401 :                 path_len = strlen(SG(request_info).path_translated);
     860             : 
     861             :                 /* Make sure we have trailing slash! */
     862         401 :                 if (!IS_SLASH(SG(request_info).path_translated[path_len])) {
     863         401 :                         path = emalloc(path_len + 2);
     864         401 :                         memcpy(path, SG(request_info).path_translated, path_len + 1);
     865         401 :                         path_len = zend_dirname(path, path_len);
     866         401 :                         path[path_len++] = DEFAULT_SLASH;
     867             :                 } else {
     868           0 :                         path = estrndup(SG(request_info).path_translated, path_len);
     869           0 :                         path_len = zend_dirname(path, path_len);
     870             :                 }
     871         401 :                 path[path_len] = 0;
     872             : 
     873             :                 /* Activate per-dir-system-configuration defined in php.ini and stored into configuration_hash during startup */
     874         401 :                 php_ini_activate_per_dir_config(path, path_len TSRMLS_CC); /* Note: for global settings sake we check from root to path */
     875             : 
     876             :                 /* Load and activate user ini files in path starting from DOCUMENT_ROOT */
     877         401 :                 if (PG(user_ini_filename) && *PG(user_ini_filename)) {
     878         401 :                         if (fcgi_is_fastcgi()) {
     879           0 :                                 fcgi_request *request = (fcgi_request*) SG(server_context);
     880             : 
     881           0 :                                 doc_root = FCGI_GETENV(request, "DOCUMENT_ROOT");
     882             :                         } else {
     883         401 :                                 doc_root = getenv("DOCUMENT_ROOT");
     884             :                         }
     885             :                         /* DOCUMENT_ROOT should also be defined at this stage..but better check it anyway */
     886         401 :                         if (doc_root) {
     887           0 :                                 doc_root_len = strlen(doc_root);
     888           0 :                                 if (doc_root_len > 0 && IS_SLASH(doc_root[doc_root_len - 1])) {
     889           0 :                                         --doc_root_len;
     890             :                                 }
     891             : #ifdef PHP_WIN32
     892             :                                 /* paths on windows should be case-insensitive */
     893             :                                 doc_root = estrndup(doc_root, doc_root_len);
     894             :                                 zend_str_tolower(doc_root, doc_root_len);
     895             : #endif
     896           0 :                                 php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len, doc_root_len - 1 TSRMLS_CC);
     897             :                                 
     898             : #ifdef PHP_WIN32
     899             :                                 efree(doc_root);
     900             : #endif
     901             :                         }
     902             :                 }
     903             : 
     904         401 :                 efree(path);
     905             :         }
     906             : 
     907         401 :         return SUCCESS;
     908             : }
     909             : 
     910         805 : static int sapi_cgi_deactivate(TSRMLS_D)
     911             : {
     912             :         /* flush only when SAPI was started. The reasons are:
     913             :                 1. SAPI Deactivate is called from two places: module init and request shutdown
     914             :                 2. When the first call occurs and the request is not set up, flush fails on FastCGI.
     915             :         */
     916         805 :         if (SG(sapi_started)) {
     917         401 :                 if (fcgi_is_fastcgi()) {
     918           0 :                         if (
     919             : #ifndef PHP_WIN32
     920           0 :                                 !parent &&
     921             : #endif
     922           0 :                                 !fcgi_finish_request((fcgi_request*)SG(server_context), 0)) {
     923           0 :                                 php_handle_aborted_connection();
     924             :                         }
     925             :                 } else {
     926         401 :                         sapi_cgi_flush(SG(server_context) TSRMLS_CC);
     927             :                 }
     928             :         }
     929         805 :         return SUCCESS;
     930             : }
     931             : 
     932         404 : static int php_cgi_startup(sapi_module_struct *sapi_module)
     933             : {
     934         404 :         if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
     935           0 :                 return FAILURE;
     936             :         }
     937         404 :         return SUCCESS;
     938             : }
     939             : 
     940             : /* {{{ sapi_module_struct cgi_sapi_module
     941             :  */
     942             : static sapi_module_struct cgi_sapi_module = {
     943             :         "cgi-fcgi",                                           /* name */
     944             :         "CGI/FastCGI",                                        /* pretty name */
     945             : 
     946             :         php_cgi_startup,                                /* startup */
     947             :         php_module_shutdown_wrapper,    /* shutdown */
     948             : 
     949             :         sapi_cgi_activate,                              /* activate */
     950             :         sapi_cgi_deactivate,                    /* deactivate */
     951             : 
     952             :         sapi_cgi_ub_write,                              /* unbuffered write */
     953             :         sapi_cgi_flush,                                 /* flush */
     954             :         NULL,                                                   /* get uid */
     955             :         sapi_cgi_getenv,                                /* getenv */
     956             : 
     957             :         php_error,                                              /* error handler */
     958             : 
     959             :         NULL,                                                   /* header handler */
     960             :         sapi_cgi_send_headers,                  /* send headers handler */
     961             :         NULL,                                                   /* send header handler */
     962             : 
     963             :         sapi_cgi_read_post,                             /* read POST data */
     964             :         sapi_cgi_read_cookies,                  /* read Cookies */
     965             : 
     966             :         sapi_cgi_register_variables,    /* register server variables */
     967             :         sapi_cgi_log_message,                   /* Log message */
     968             :         NULL,                                                   /* Get request time */
     969             :         NULL,                                                   /* Child terminate */
     970             : 
     971             :         STANDARD_SAPI_MODULE_PROPERTIES
     972             : };
     973             : /* }}} */
     974             : 
     975             : /* {{{ arginfo ext/standard/dl.c */
     976             : ZEND_BEGIN_ARG_INFO(arginfo_dl, 0)
     977             :         ZEND_ARG_INFO(0, extension_filename)
     978             : ZEND_END_ARG_INFO()
     979             : /* }}} */
     980             : 
     981             : static const zend_function_entry additional_functions[] = {
     982             :         ZEND_FE(dl, arginfo_dl)
     983             :         {NULL, NULL, NULL}
     984             : };
     985             : 
     986             : /* {{{ php_cgi_usage
     987             :  */
     988           0 : static void php_cgi_usage(char *argv0)
     989             : {
     990             :         char *prog;
     991             : 
     992           0 :         prog = strrchr(argv0, '/');
     993           0 :         if (prog) {
     994           0 :                 prog++;
     995             :         } else {
     996           0 :                 prog = "php";
     997             :         }
     998             : 
     999           0 :         php_printf(     "Usage: %s [-q] [-h] [-s] [-v] [-i] [-f <file>]\n"
    1000             :                                 "       %s <file> [args...]\n"
    1001             :                                 "  -a               Run interactively\n"
    1002             :                                 "  -b <address:port>|<port> Bind Path for external FASTCGI Server mode\n"
    1003             :                                 "  -C               Do not chdir to the script's directory\n"
    1004             :                                 "  -c <path>|<file> Look for php.ini file in this directory\n"
    1005             :                                 "  -n               No php.ini file will be used\n"
    1006             :                                 "  -d foo[=bar]     Define INI entry foo with value 'bar'\n"
    1007             :                                 "  -e               Generate extended information for debugger/profiler\n"
    1008             :                                 "  -f <file>        Parse <file>.  Implies `-q'\n"
    1009             :                                 "  -h               This help\n"
    1010             :                                 "  -i               PHP information\n"
    1011             :                                 "  -l               Syntax check only (lint)\n"
    1012             :                                 "  -m               Show compiled in modules\n"
    1013             :                                 "  -q               Quiet-mode.  Suppress HTTP Header output.\n"
    1014             :                                 "  -s               Display colour syntax highlighted source.\n"
    1015             :                                 "  -v               Version number\n"
    1016             :                                 "  -w               Display source with stripped comments and whitespace.\n"
    1017             :                                 "  -z <file>        Load Zend extension <file>.\n"
    1018             :                                 "  -T <count>       Measure execution time of script repeated <count> times.\n",
    1019             :                                 prog, prog);
    1020           0 : }
    1021             : /* }}} */
    1022             : 
    1023             : /* {{{ is_valid_path
    1024             :  *
    1025             :  * some server configurations allow '..' to slip through in the
    1026             :  * translated path.   We'll just refuse to handle such a path.
    1027             :  */
    1028         217 : static int is_valid_path(const char *path)
    1029             : {
    1030         217 :         const char *p = path;
    1031             : 
    1032         217 :         if (UNEXPECTED(!p)) {
    1033           0 :                 return 0;
    1034             :         }
    1035         217 :         if (UNEXPECTED(*p == '.') && *(p+1) == '.' && (!*(p+2) || IS_SLASH(*(p+2)))) {
    1036           0 :                 return 0;
    1037             :         }
    1038       12049 :         while (*p) {
    1039       11615 :                 if (IS_SLASH(*p)) {
    1040        1540 :                         p++;
    1041        1540 :                         if (UNEXPECTED(*p == '.')) {
    1042           0 :                                 p++;
    1043           0 :                                 if (UNEXPECTED(*p == '.')) {
    1044           0 :                                         p++;
    1045           0 :                                         if (UNEXPECTED(!*p) || UNEXPECTED(IS_SLASH(*p))) {
    1046           0 :                                                 return 0;
    1047             :                                         }                                                                                       
    1048             :                                 }
    1049             :                         }
    1050             :                 }
    1051       11615 :                 p++;
    1052             :         }
    1053         217 :         return 1;
    1054             : }
    1055             : /* }}} */
    1056             : 
    1057             : #define CGI_GETENV(name) \
    1058             :         ((request) ? \
    1059             :                 FCGI_GETENV(request, name) : \
    1060             :         getenv(name))
    1061             : 
    1062             : #define CGI_PUTENV(name, value) \
    1063             :         ((request) ? \
    1064             :                 FCGI_PUTENV(request, name, value) : \
    1065             :                 _sapi_cgi_putenv(name, sizeof(name)-1, value))
    1066             : 
    1067             : /* {{{ init_request_info
    1068             : 
    1069             :   initializes request_info structure
    1070             : 
    1071             :   specificly in this section we handle proper translations
    1072             :   for:
    1073             : 
    1074             :   PATH_INFO
    1075             :         derived from the portion of the URI path following
    1076             :         the script name but preceding any query data
    1077             :         may be empty
    1078             : 
    1079             :   PATH_TRANSLATED
    1080             :     derived by taking any path-info component of the
    1081             :         request URI and performing any virtual-to-physical
    1082             :         translation appropriate to map it onto the server's
    1083             :         document repository structure
    1084             : 
    1085             :         empty if PATH_INFO is empty
    1086             : 
    1087             :         The env var PATH_TRANSLATED **IS DIFFERENT** than the
    1088             :         request_info.path_translated variable, the latter should
    1089             :         match SCRIPT_FILENAME instead.
    1090             : 
    1091             :   SCRIPT_NAME
    1092             :     set to a URL path that could identify the CGI script
    1093             :         rather than the interpreter.  PHP_SELF is set to this
    1094             : 
    1095             :   REQUEST_URI
    1096             :     uri section following the domain:port part of a URI
    1097             : 
    1098             :   SCRIPT_FILENAME
    1099             :     The virtual-to-physical translation of SCRIPT_NAME (as per
    1100             :         PATH_TRANSLATED)
    1101             : 
    1102             :   These settings are documented at
    1103             :   http://cgi-spec.golux.com/
    1104             : 
    1105             : 
    1106             :   Based on the following URL request:
    1107             : 
    1108             :   http://localhost/info.php/test?a=b
    1109             : 
    1110             :   should produce, which btw is the same as if
    1111             :   we were running under mod_cgi on apache (ie. not
    1112             :   using ScriptAlias directives):
    1113             : 
    1114             :   PATH_INFO=/test
    1115             :   PATH_TRANSLATED=/docroot/test
    1116             :   SCRIPT_NAME=/info.php
    1117             :   REQUEST_URI=/info.php/test?a=b
    1118             :   SCRIPT_FILENAME=/docroot/info.php
    1119             :   QUERY_STRING=a=b
    1120             : 
    1121             :   but what we get is (cgi/mod_fastcgi under apache):
    1122             : 
    1123             :   PATH_INFO=/info.php/test
    1124             :   PATH_TRANSLATED=/docroot/info.php/test
    1125             :   SCRIPT_NAME=/php/php-cgi  (from the Action setting I suppose)
    1126             :   REQUEST_URI=/info.php/test?a=b
    1127             :   SCRIPT_FILENAME=/path/to/php/bin/php-cgi  (Action setting translated)
    1128             :   QUERY_STRING=a=b
    1129             : 
    1130             :   Comments in the code below refer to using the above URL in a request
    1131             : 
    1132             :  */
    1133         404 : static void init_request_info(fcgi_request *request TSRMLS_DC)
    1134             : {
    1135         404 :         char *env_script_filename = CGI_GETENV("SCRIPT_FILENAME");
    1136         404 :         char *env_path_translated = CGI_GETENV("PATH_TRANSLATED");
    1137         404 :         char *script_path_translated = env_script_filename;
    1138             : 
    1139             :         /* some broken servers do not have script_filename or argv0
    1140             :          * an example, IIS configured in some ways.  then they do more
    1141             :          * broken stuff and set path_translated to the cgi script location */
    1142         404 :         if (!script_path_translated && env_path_translated) {
    1143           0 :                 script_path_translated = env_path_translated;
    1144             :         }
    1145             : 
    1146             :         /* initialize the defaults */
    1147         404 :         SG(request_info).path_translated = NULL;
    1148         404 :         SG(request_info).request_method = NULL;
    1149         404 :         SG(request_info).proto_num = 1000;
    1150         404 :         SG(request_info).query_string = NULL;
    1151         404 :         SG(request_info).request_uri = NULL;
    1152         404 :         SG(request_info).content_type = NULL;
    1153         404 :         SG(request_info).content_length = 0;
    1154         404 :         SG(sapi_headers).http_response_code = 200;
    1155             : 
    1156             :         /* script_path_translated being set is a good indication that
    1157             :          * we are running in a cgi environment, since it is always
    1158             :          * null otherwise.  otherwise, the filename
    1159             :          * of the script will be retreived later via argc/argv */
    1160         404 :         if (script_path_translated) {
    1161             :                 const char *auth;
    1162         217 :                 char *content_length = CGI_GETENV("CONTENT_LENGTH");
    1163         217 :                 char *content_type = CGI_GETENV("CONTENT_TYPE");
    1164         217 :                 char *env_path_info = CGI_GETENV("PATH_INFO");
    1165         217 :                 char *env_script_name = CGI_GETENV("SCRIPT_NAME");
    1166             : 
    1167             : #ifdef PHP_WIN32
    1168             :                 /* Hack for buggy IIS that sets incorrect PATH_INFO */
    1169             :                 char *env_server_software = CGI_GETENV("SERVER_SOFTWARE");
    1170             : 
    1171             :                 if (env_server_software &&
    1172             :                         env_script_name &&
    1173             :                         env_path_info &&
    1174             :                         strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 &&
    1175             :                         strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0
    1176             :                 ) {
    1177             :                         env_path_info = CGI_PUTENV("ORIG_PATH_INFO", env_path_info);
    1178             :                         env_path_info += strlen(env_script_name);
    1179             :                         if (*env_path_info == 0) {
    1180             :                                 env_path_info = NULL;
    1181             :                         }
    1182             :                         env_path_info = CGI_PUTENV("PATH_INFO", env_path_info);
    1183             :                 }
    1184             : #endif
    1185             : 
    1186         217 :                 if (CGIG(fix_pathinfo)) {
    1187             :                         zend_stat_t st;
    1188         217 :                         char *real_path = NULL;
    1189         217 :                         char *env_redirect_url = CGI_GETENV("REDIRECT_URL");
    1190         217 :                         char *env_document_root = CGI_GETENV("DOCUMENT_ROOT");
    1191         217 :                         char *orig_path_translated = env_path_translated;
    1192         217 :                         char *orig_path_info = env_path_info;
    1193         217 :                         char *orig_script_name = env_script_name;
    1194         217 :                         char *orig_script_filename = env_script_filename;
    1195             :                         int script_path_translated_len;
    1196             : 
    1197         217 :                         if (!env_document_root && PG(doc_root)) {
    1198           0 :                                 env_document_root = CGI_PUTENV("DOCUMENT_ROOT", PG(doc_root));
    1199             :                                 /* fix docroot */
    1200             :                                 TRANSLATE_SLASHES(env_document_root);
    1201             :                         }
    1202             : 
    1203         217 :                         if (env_path_translated != NULL && env_redirect_url != NULL &&
    1204             :                             env_path_translated != script_path_translated &&
    1205           0 :                             strcmp(env_path_translated, script_path_translated) != 0) {
    1206             :                                 /*
    1207             :                                  * pretty much apache specific.  If we have a redirect_url
    1208             :                                  * then our script_filename and script_name point to the
    1209             :                                  * php executable
    1210             :                                  */
    1211           0 :                                 script_path_translated = env_path_translated;
    1212             :                                 /* we correct SCRIPT_NAME now in case we don't have PATH_INFO */
    1213           0 :                                 env_script_name = env_redirect_url;
    1214             :                         }
    1215             : 
    1216             : #ifdef __riscos__
    1217             :                         /* Convert path to unix format*/
    1218             :                         __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR;
    1219             :                         script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0);
    1220             : #endif
    1221             : 
    1222             :                         /*
    1223             :                          * if the file doesn't exist, try to extract PATH_INFO out
    1224             :                          * of it by stat'ing back through the '/'
    1225             :                          * this fixes url's like /info.php/test
    1226             :                          */
    1227         872 :                         if (script_path_translated &&
    1228         217 :                                 (script_path_translated_len = strlen(script_path_translated)) > 0 &&
    1229         217 :                                 (script_path_translated[script_path_translated_len-1] == '/' ||
    1230             : #ifdef PHP_WIN32
    1231             :                                 script_path_translated[script_path_translated_len-1] == '\\' ||
    1232             : #endif
    1233         217 :                                 (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL)
    1234             :                         ) {
    1235           4 :                                 char *pt = estrndup(script_path_translated, script_path_translated_len);
    1236           4 :                                 int len = script_path_translated_len;
    1237             :                                 char *ptr;
    1238             : 
    1239           8 :                                 while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) {
    1240           4 :                                         *ptr = 0;
    1241           4 :                                         if (zend_stat(pt, &st) == 0 && S_ISREG(st.st_mode)) {
    1242             :                                                 /*
    1243             :                                                  * okay, we found the base script!
    1244             :                                                  * work out how many chars we had to strip off;
    1245             :                                                  * then we can modify PATH_INFO
    1246             :                                                  * accordingly
    1247             :                                                  *
    1248             :                                                  * we now have the makings of
    1249             :                                                  * PATH_INFO=/test
    1250             :                                                  * SCRIPT_FILENAME=/docroot/info.php
    1251             :                                                  *
    1252             :                                                  * we now need to figure out what docroot is.
    1253             :                                                  * if DOCUMENT_ROOT is set, this is easy, otherwise,
    1254             :                                                  * we have to play the game of hide and seek to figure
    1255             :                                                  * out what SCRIPT_NAME should be
    1256             :                                                  */
    1257           4 :                                                 int slen = len - strlen(pt);
    1258           4 :                                                 int pilen = env_path_info ? strlen(env_path_info) : 0;
    1259           4 :                                                 char *path_info = env_path_info ? env_path_info + pilen - slen : NULL;
    1260             : 
    1261           4 :                                                 if (orig_path_info != path_info) {
    1262           0 :                                                         if (orig_path_info) {
    1263             :                                                                 char old;
    1264             : 
    1265           0 :                                                                 CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
    1266           0 :                                                                 old = path_info[0];
    1267           0 :                                                                 path_info[0] = 0;
    1268           0 :                                                                 if (!orig_script_name ||
    1269           0 :                                                                         strcmp(orig_script_name, env_path_info) != 0) {
    1270           0 :                                                                         if (orig_script_name) {
    1271           0 :                                                                                 CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
    1272             :                                                                         }
    1273           0 :                                                                         SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_path_info);
    1274             :                                                                 } else {
    1275           0 :                                                                         SG(request_info).request_uri = orig_script_name;
    1276             :                                                                 }
    1277           0 :                                                                 path_info[0] = old;
    1278             :                                                         }
    1279           0 :                                                         env_path_info = CGI_PUTENV("PATH_INFO", path_info);
    1280             :                                                 }
    1281           8 :                                                 if (!orig_script_filename ||
    1282           4 :                                                         strcmp(orig_script_filename, pt) != 0) {
    1283           4 :                                                         if (orig_script_filename) {
    1284           4 :                                                                 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
    1285             :                                                         }
    1286           4 :                                                         script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", pt);
    1287             :                                                 }
    1288             :                                                 TRANSLATE_SLASHES(pt);
    1289             : 
    1290             :                                                 /* figure out docroot
    1291             :                                                  * SCRIPT_FILENAME minus SCRIPT_NAME
    1292             :                                                  */
    1293           4 :                                                 if (env_document_root) {
    1294           0 :                                                         int l = strlen(env_document_root);
    1295           0 :                                                         int path_translated_len = 0;
    1296           0 :                                                         char *path_translated = NULL;
    1297             : 
    1298           0 :                                                         if (l && env_document_root[l - 1] == '/') {
    1299           0 :                                                                 --l;
    1300             :                                                         }
    1301             : 
    1302             :                                                         /* we have docroot, so we should have:
    1303             :                                                          * DOCUMENT_ROOT=/docroot
    1304             :                                                          * SCRIPT_FILENAME=/docroot/info.php
    1305             :                                                          */
    1306             : 
    1307             :                                                         /* PATH_TRANSLATED = DOCUMENT_ROOT + PATH_INFO */
    1308           0 :                                                         path_translated_len = l + (env_path_info ? strlen(env_path_info) : 0);
    1309           0 :                                                         path_translated = (char *) emalloc(path_translated_len + 1);
    1310           0 :                                                         memcpy(path_translated, env_document_root, l);
    1311           0 :                                                         if (env_path_info) {
    1312           0 :                                                                 memcpy(path_translated + l, env_path_info, (path_translated_len - l));
    1313             :                                                         }
    1314           0 :                                                         path_translated[path_translated_len] = '\0';
    1315           0 :                                                         if (orig_path_translated) {
    1316           0 :                                                                 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
    1317             :                                                         }
    1318           0 :                                                         env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
    1319           0 :                                                         efree(path_translated);
    1320           4 :                                                 } else if (     env_script_name &&
    1321             :                                                                         strstr(pt, env_script_name)
    1322           0 :                                                 ) {
    1323             :                                                         /* PATH_TRANSLATED = PATH_TRANSLATED - SCRIPT_NAME + PATH_INFO */
    1324           0 :                                                         int ptlen = strlen(pt) - strlen(env_script_name);
    1325           0 :                                                         int path_translated_len = ptlen + (env_path_info ? strlen(env_path_info) : 0);
    1326           0 :                                                         char *path_translated = NULL;
    1327             : 
    1328           0 :                                                         path_translated = (char *) emalloc(path_translated_len + 1);
    1329           0 :                                                         memcpy(path_translated, pt, ptlen);
    1330           0 :                                                         if (env_path_info) {
    1331           0 :                                                                 memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen);
    1332             :                                                         }
    1333           0 :                                                         path_translated[path_translated_len] = '\0';
    1334           0 :                                                         if (orig_path_translated) {
    1335           0 :                                                                 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
    1336             :                                                         }
    1337           0 :                                                         env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
    1338           0 :                                                         efree(path_translated);
    1339             :                                                 }
    1340           4 :                                                 break;
    1341             :                                         }
    1342             :                                 }
    1343           4 :                                 if (!ptr) {
    1344             :                                         /*
    1345             :                                          * if we stripped out all the '/' and still didn't find
    1346             :                                          * a valid path... we will fail, badly. of course we would
    1347             :                                          * have failed anyway... we output 'no input file' now.
    1348             :                                          */
    1349           0 :                                         if (orig_script_filename) {
    1350           0 :                                                 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
    1351             :                                         }
    1352           0 :                                         script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", NULL);
    1353           0 :                                         SG(sapi_headers).http_response_code = 404;
    1354             :                                 }
    1355           4 :                                 if (!SG(request_info).request_uri) {
    1356           8 :                                         if (!orig_script_name ||
    1357           0 :                                                 strcmp(orig_script_name, env_script_name) != 0) {
    1358           4 :                                                 if (orig_script_name) {
    1359           0 :                                                         CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
    1360             :                                                 }
    1361           4 :                                                 SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
    1362             :                                         } else {
    1363           0 :                                                 SG(request_info).request_uri = orig_script_name;
    1364             :                                         }
    1365             :                                 }
    1366           4 :                                 if (pt) {
    1367           4 :                                         efree(pt);
    1368             :                                 }
    1369             :                         } else {
    1370             :                                 /* make sure path_info/translated are empty */
    1371         213 :                                 if (!orig_script_filename ||
    1372             :                                         (script_path_translated != orig_script_filename &&
    1373           0 :                                         strcmp(script_path_translated, orig_script_filename) != 0)) {
    1374           0 :                                         if (orig_script_filename) {
    1375           0 :                                                 CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
    1376             :                                         }
    1377           0 :                                         script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", script_path_translated);
    1378             :                                 }
    1379         213 :                                 if (env_redirect_url) {
    1380           0 :                                         if (orig_path_info) {
    1381           0 :                                                 CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
    1382           0 :                                                 CGI_PUTENV("PATH_INFO", NULL);
    1383             :                                         }
    1384           0 :                                         if (orig_path_translated) {
    1385           0 :                                                 CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
    1386           0 :                                                 CGI_PUTENV("PATH_TRANSLATED", NULL);
    1387             :                                         }
    1388             :                                 }
    1389         213 :                                 if (env_script_name != orig_script_name) {
    1390           0 :                                         if (orig_script_name) {
    1391           0 :                                                 CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
    1392             :                                         }
    1393           0 :                                         SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
    1394             :                                 } else {
    1395         213 :                                         SG(request_info).request_uri = env_script_name;
    1396             :                                 }
    1397         213 :                                 efree(real_path);
    1398             :                         }
    1399             :                 } else {
    1400             :                         /* pre 4.3 behaviour, shouldn't be used but provides BC */
    1401           0 :                         if (env_path_info) {
    1402           0 :                                 SG(request_info).request_uri = env_path_info;
    1403             :                         } else {
    1404           0 :                                 SG(request_info).request_uri = env_script_name;
    1405             :                         }
    1406           0 :                         if (!CGIG(discard_path) && env_path_translated) {
    1407           0 :                                 script_path_translated = env_path_translated;
    1408             :                         }
    1409             :                 }
    1410             : 
    1411         217 :                 if (is_valid_path(script_path_translated)) {
    1412         217 :                         SG(request_info).path_translated = estrdup(script_path_translated);
    1413             :                 }
    1414             : 
    1415         217 :                 SG(request_info).request_method = CGI_GETENV("REQUEST_METHOD");
    1416             :                 /* FIXME - Work out proto_num here */
    1417         217 :                 SG(request_info).query_string = CGI_GETENV("QUERY_STRING");
    1418         217 :                 SG(request_info).content_type = (content_type ? content_type : "" );
    1419         217 :                 SG(request_info).content_length = (content_length ? atol(content_length) : 0);
    1420             : 
    1421             :                 /* The CGI RFC allows servers to pass on unvalidated Authorization data */
    1422         217 :                 auth = CGI_GETENV("HTTP_AUTHORIZATION");
    1423         217 :                 php_handle_auth_data(auth TSRMLS_CC);
    1424             :         }
    1425         404 : }
    1426             : /* }}} */
    1427             : 
    1428             : #ifndef PHP_WIN32
    1429             : /**
    1430             :  * Clean up child processes upon exit
    1431             :  */
    1432           0 : void fastcgi_cleanup(int signal)
    1433             : {
    1434             : #ifdef DEBUG_FASTCGI
    1435             :         fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid());
    1436             : #endif
    1437             : 
    1438           0 :         sigaction(SIGTERM, &old_term, 0);
    1439             : 
    1440             :         /* Kill all the processes in our process group */
    1441           0 :         kill(-pgroup, SIGTERM);
    1442             : 
    1443           0 :         if (parent && parent_waiting) {
    1444           0 :                 exit_signal = 1;
    1445             :         } else {
    1446           0 :                 exit(0);
    1447             :         }
    1448           0 : }
    1449             : #endif
    1450             : 
    1451             : PHP_INI_BEGIN()
    1452             :         STD_PHP_INI_ENTRY("cgi.rfc2616_headers",     "0",  PHP_INI_ALL,    OnUpdateBool,   rfc2616_headers, php_cgi_globals_struct, php_cgi_globals)
    1453             :         STD_PHP_INI_ENTRY("cgi.nph",                 "0",  PHP_INI_ALL,    OnUpdateBool,   nph, php_cgi_globals_struct, php_cgi_globals)
    1454             :         STD_PHP_INI_ENTRY("cgi.check_shebang_line",  "1",  PHP_INI_SYSTEM, OnUpdateBool,   check_shebang_line, php_cgi_globals_struct, php_cgi_globals)
    1455             :         STD_PHP_INI_ENTRY("cgi.force_redirect",      "1",  PHP_INI_SYSTEM, OnUpdateBool,   force_redirect, php_cgi_globals_struct, php_cgi_globals)
    1456             :         STD_PHP_INI_ENTRY("cgi.redirect_status_env", NULL, PHP_INI_SYSTEM, OnUpdateString, redirect_status_env, php_cgi_globals_struct, php_cgi_globals)
    1457             :         STD_PHP_INI_ENTRY("cgi.fix_pathinfo",        "1",  PHP_INI_SYSTEM, OnUpdateBool,   fix_pathinfo, php_cgi_globals_struct, php_cgi_globals)
    1458             :         STD_PHP_INI_ENTRY("cgi.discard_path",        "0",  PHP_INI_SYSTEM, OnUpdateBool,   discard_path, php_cgi_globals_struct, php_cgi_globals)
    1459             :         STD_PHP_INI_ENTRY("fastcgi.logging",         "1",  PHP_INI_SYSTEM, OnUpdateBool,   fcgi_logging, php_cgi_globals_struct, php_cgi_globals)
    1460             : #ifdef PHP_WIN32
    1461             :         STD_PHP_INI_ENTRY("fastcgi.impersonate",     "0",  PHP_INI_SYSTEM, OnUpdateBool,   impersonate, php_cgi_globals_struct, php_cgi_globals)
    1462             : #endif
    1463             : PHP_INI_END()
    1464             : 
    1465             : /* {{{ php_cgi_globals_ctor
    1466             :  */
    1467         404 : static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC)
    1468             : {
    1469         404 :         php_cgi_globals->rfc2616_headers = 0;
    1470         404 :         php_cgi_globals->nph = 0;
    1471         404 :         php_cgi_globals->check_shebang_line = 1;
    1472         404 :         php_cgi_globals->force_redirect = 1;
    1473         404 :         php_cgi_globals->redirect_status_env = NULL;
    1474         404 :         php_cgi_globals->fix_pathinfo = 1;
    1475         404 :         php_cgi_globals->discard_path = 0;
    1476         404 :         php_cgi_globals->fcgi_logging = 1;
    1477             : #ifdef PHP_WIN32
    1478             :         php_cgi_globals->impersonate = 0;
    1479             : #endif
    1480         404 :         zend_hash_init(&php_cgi_globals->user_config_cache, 8, NULL, user_config_cache_entry_dtor, 1);
    1481         404 : }
    1482             : /* }}} */
    1483             : 
    1484             : /* {{{ PHP_MINIT_FUNCTION
    1485             :  */
    1486         404 : static PHP_MINIT_FUNCTION(cgi)
    1487             : {
    1488             : #ifdef ZTS
    1489             :         ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL);
    1490             : #else
    1491         404 :         php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC);
    1492             : #endif
    1493         404 :         REGISTER_INI_ENTRIES();
    1494         404 :         return SUCCESS;
    1495             : }
    1496             : /* }}} */
    1497             : 
    1498             : /* {{{ PHP_MSHUTDOWN_FUNCTION
    1499             :  */
    1500         401 : static PHP_MSHUTDOWN_FUNCTION(cgi)
    1501             : {
    1502         401 :         zend_hash_destroy(&CGIG(user_config_cache));
    1503             : 
    1504         401 :         UNREGISTER_INI_ENTRIES();
    1505         401 :         return SUCCESS;
    1506             : }
    1507             : /* }}} */
    1508             : 
    1509             : /* {{{ PHP_MINFO_FUNCTION
    1510             :  */
    1511           1 : static PHP_MINFO_FUNCTION(cgi)
    1512             : {
    1513           1 :         DISPLAY_INI_ENTRIES();
    1514           1 : }
    1515             : /* }}} */
    1516             : 
    1517           0 : PHP_FUNCTION(apache_child_terminate) /* {{{ */
    1518             : {
    1519           0 :         if (ZEND_NUM_ARGS() > 0) {
    1520           0 :                 WRONG_PARAM_COUNT;
    1521             :         }
    1522           0 :         if (fcgi_is_fastcgi()) {
    1523           0 :                 fcgi_terminate();
    1524             :         }
    1525             : }
    1526             : /* }}} */
    1527             : 
    1528           0 : static void add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC) /* {{{ */
    1529             : {
    1530           0 :         zval *return_value = (zval*)arg;
    1531           0 :         char *str = NULL;
    1532             :         char *p;
    1533             :         ALLOCA_FLAG(use_heap)
    1534             : 
    1535           0 :         if (var_len > 5 &&
    1536           0 :             var[0] == 'H' &&
    1537           0 :             var[1] == 'T' &&
    1538           0 :             var[2] == 'T' &&
    1539           0 :             var[3] == 'P' &&
    1540           0 :             var[4] == '_') {
    1541             : 
    1542           0 :                 var_len -= 5;
    1543           0 :                 p = var + 5;
    1544           0 :                 var = str = do_alloca(var_len + 1, use_heap);
    1545           0 :                 *str++ = *p++;
    1546           0 :                 while (*p) {
    1547           0 :                         if (*p == '_') {
    1548           0 :                                 *str++ = '-';
    1549           0 :                                 p++;
    1550           0 :                                 if (*p) {
    1551           0 :                                         *str++ = *p++;
    1552             :                                 }
    1553           0 :                         } else if (*p >= 'A' && *p <= 'Z') {
    1554           0 :                                 *str++ = (*p++ - 'A' + 'a');
    1555             :                         } else {
    1556           0 :                                 *str++ = *p++;
    1557             :                         }
    1558             :                 }
    1559           0 :                 *str = 0;
    1560           0 :         } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
    1561           0 :                    memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
    1562           0 :                 var = "Content-Type";
    1563           0 :         } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
    1564           0 :                    memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
    1565           0 :                 var = "Content-Length";
    1566             :         } else {
    1567           0 :                 return;
    1568             :         }
    1569           0 :         add_assoc_stringl_ex(return_value, var, var_len+1, val, val_len);
    1570           0 :         if (str) {
    1571           0 :                 free_alloca(var, use_heap);
    1572             :         }
    1573             : }
    1574             : /* }}} */
    1575             : 
    1576           4 : PHP_FUNCTION(apache_request_headers) /* {{{ */
    1577             : {
    1578           4 :         if (ZEND_NUM_ARGS() > 0) {
    1579           0 :                 WRONG_PARAM_COUNT;
    1580             :         }
    1581           4 :         array_init(return_value);
    1582           4 :         if (fcgi_is_fastcgi()) {
    1583           0 :                 fcgi_request *request = (fcgi_request*) SG(server_context);
    1584             : 
    1585           0 :                 fcgi_loadenv(request, add_request_header, return_value TSRMLS_CC);
    1586             :         } else {
    1587             :                 char buf[128];
    1588           4 :                 char **env, *p, *q, *var, *val, *t = buf;
    1589           4 :                 size_t alloc_size = sizeof(buf);
    1590             :                 zend_ulong var_len;
    1591             : 
    1592         187 :                 for (env = environ; env != NULL && *env != NULL; env++) {
    1593         183 :                         val = strchr(*env, '=');
    1594         183 :                         if (!val) {                             /* malformed entry? */
    1595           0 :                                 continue;
    1596             :                         }
    1597         183 :                         var_len = val - *env;
    1598         183 :                         if (var_len >= alloc_size) {
    1599           0 :                                 alloc_size = var_len + 64;
    1600           0 :                                 t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
    1601             :                         }
    1602         183 :                         var = *env;
    1603         345 :                         if (var_len > 5 &&
    1604         147 :                             var[0] == 'H' &&
    1605           3 :                             var[1] == 'T' &&
    1606           3 :                             var[2] == 'T' &&
    1607           3 :                             var[3] == 'P' &&
    1608           3 :                             var[4] == '_') {
    1609             : 
    1610           3 :                                 var_len -= 5;
    1611             : 
    1612           3 :                                 if (var_len >= alloc_size) {
    1613           0 :                                         alloc_size = var_len + 64;
    1614           0 :                                         t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
    1615             :                                 }
    1616           3 :                                 p = var + 5;
    1617             : 
    1618           3 :                                 var = q = t;
    1619             :                                 /* First char keep uppercase */
    1620           3 :                                 *q++ = *p++;
    1621          16 :                                 while (*p) {
    1622          13 :                                         if (*p == '=') {
    1623             :                                                 /* End of name */
    1624           3 :                                                 break;
    1625          10 :                                         } else if (*p == '_') {
    1626           3 :                                                 *q++ = '-';
    1627           3 :                                                 p++;
    1628             :                                                 /* First char after - keep uppercase */
    1629           3 :                                                 if (*p && *p!='=') {
    1630           2 :                                                         *q++ = *p++;
    1631             :                                                 }
    1632          14 :                                         } else if (*p >= 'A' && *p <= 'Z') {
    1633             :                                                 /* lowercase */
    1634           7 :                                                 *q++ = (*p++ - 'A' + 'a');
    1635             :                                         } else {
    1636           0 :                                                 *q++ = *p++;
    1637             :                                         }
    1638             :                                 }
    1639           3 :                                 *q = 0;
    1640         184 :                         } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
    1641           4 :                                    memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
    1642           0 :                                 var = "Content-Type";
    1643         188 :                         } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
    1644           8 :                                    memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
    1645           0 :                                 var = "Content-Length";
    1646             :                         } else {
    1647         180 :                                 continue;
    1648             :                         }
    1649           3 :                         val++;
    1650           3 :                         add_assoc_string_ex(return_value, var, var_len, val);
    1651             :                 }
    1652           4 :                 if (t != buf && t != NULL) {
    1653           0 :                         efree(t);
    1654             :                 }
    1655             :         }
    1656             : }
    1657             : /* }}} */
    1658             : 
    1659           0 : static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS_DC) /* {{{ */
    1660             : {
    1661             :         char *s, *p;
    1662             :         int  len;
    1663             :         ALLOCA_FLAG(use_heap)
    1664             : 
    1665           0 :         if (h->header_len > 0) {
    1666           0 :                 p = strchr(h->header, ':');
    1667           0 :                 len = p - h->header;
    1668           0 :                 if (p && (len > 0)) {
    1669           0 :                         while (len > 0 && (h->header[len-1] == ' ' || h->header[len-1] == '\t')) {
    1670           0 :                                 len--;
    1671             :                         }
    1672           0 :                         if (len) {
    1673           0 :                                 s = do_alloca(len + 1, use_heap);
    1674           0 :                                 memcpy(s, h->header, len);
    1675           0 :                                 s[len] = 0;
    1676             :                                 do {
    1677           0 :                                         p++;
    1678           0 :                                 } while (*p == ' ' || *p == '\t');
    1679           0 :                                 add_assoc_stringl_ex(return_value, s, len, p, h->header_len - (p - h->header));
    1680           0 :                                 free_alloca(s, use_heap);
    1681             :                         }
    1682             :                 }
    1683             :         }
    1684           0 : }
    1685             : /* }}} */
    1686             : 
    1687           0 : PHP_FUNCTION(apache_response_headers) /* {{{ */
    1688             : {
    1689           0 :         if (zend_parse_parameters_none() == FAILURE) {
    1690           0 :                 return;
    1691             :         }
    1692             : 
    1693           0 :         if (!&SG(sapi_headers).headers) {
    1694             :                 RETURN_FALSE;
    1695             :         }
    1696           0 :         array_init(return_value);
    1697           0 :         zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value TSRMLS_CC);
    1698             : }
    1699             : /* }}} */
    1700             : 
    1701             : ZEND_BEGIN_ARG_INFO(arginfo_no_args, 0)
    1702             : ZEND_END_ARG_INFO()
    1703             : 
    1704             : const zend_function_entry cgi_functions[] = {
    1705             :         PHP_FE(apache_child_terminate, arginfo_no_args)
    1706             :         PHP_FE(apache_request_headers, arginfo_no_args)
    1707             :         PHP_FE(apache_response_headers, arginfo_no_args)
    1708             :         PHP_FALIAS(getallheaders, apache_request_headers, arginfo_no_args)
    1709             :         {NULL, NULL, NULL}
    1710             : };
    1711             : 
    1712             : static zend_module_entry cgi_module_entry = {
    1713             :         STANDARD_MODULE_HEADER,
    1714             :         "cgi-fcgi",
    1715             :         cgi_functions,
    1716             :         PHP_MINIT(cgi),
    1717             :         PHP_MSHUTDOWN(cgi),
    1718             :         NULL,
    1719             :         NULL,
    1720             :         PHP_MINFO(cgi),
    1721             :         NO_VERSION_YET,
    1722             :         STANDARD_MODULE_PROPERTIES
    1723             : };
    1724             : 
    1725             : /* {{{ main
    1726             :  */
    1727         404 : int main(int argc, char *argv[])
    1728             : {
    1729         404 :         int free_query_string = 0;
    1730         404 :         int exit_status = SUCCESS;
    1731         404 :         int cgi = 0, c, i, len;
    1732             :         zend_file_handle file_handle;
    1733             :         char *s;
    1734             : 
    1735             :         /* temporary locals */
    1736         404 :         int behavior = PHP_MODE_STANDARD;
    1737         404 :         int no_headers = 0;
    1738         404 :         int orig_optind = php_optind;
    1739         404 :         char *orig_optarg = php_optarg;
    1740         404 :         char *script_file = NULL;
    1741         404 :         int ini_entries_len = 0;
    1742             :         /* end of temporary locals */
    1743             : 
    1744             : #ifdef ZTS
    1745             :         void ***tsrm_ls;
    1746             : #endif
    1747             : 
    1748         404 :         int max_requests = 500;
    1749         404 :         int requests = 0;
    1750             :         int fastcgi;
    1751         404 :         char *bindpath = NULL;
    1752         404 :         int fcgi_fd = 0;
    1753         404 :         fcgi_request *request = NULL;
    1754         404 :         int warmup_repeats = 0;
    1755         404 :         int repeats = 1;
    1756         404 :         int benchmark = 0;
    1757             : #if HAVE_GETTIMEOFDAY
    1758             :         struct timeval start, end;
    1759             : #else
    1760             :         time_t start, end;
    1761             : #endif
    1762             : #ifndef PHP_WIN32
    1763         404 :         int status = 0;
    1764             : #endif
    1765             :         char *query_string;
    1766             :         char *decoded_query_string;
    1767         404 :         int skip_getopt = 0;
    1768             : 
    1769             : #if 0 && defined(PHP_DEBUG)
    1770             :         /* IIS is always making things more difficult.  This allows
    1771             :          * us to stop PHP and attach a debugger before much gets started */
    1772             :         {
    1773             :                 char szMessage [256];
    1774             :                 wsprintf (szMessage, "Please attach a debugger to the process 0x%X [%d] (%s) and click OK", GetCurrentProcessId(), GetCurrentProcessId(), argv[0]);
    1775             :                 MessageBox(NULL, szMessage, "CGI Debug Time!", MB_OK|MB_SERVICE_NOTIFICATION);
    1776             :         }
    1777             : #endif
    1778             : 
    1779             : #ifdef HAVE_SIGNAL_H
    1780             : #if defined(SIGPIPE) && defined(SIG_IGN)
    1781         404 :         signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
    1782             :                                                                 that sockets created via fsockopen()
    1783             :                                                                 don't kill PHP if the remote site
    1784             :                                                                 closes it.  in apache|apxs mode apache
    1785             :                                                                 does that for us!  thies@thieso.net
    1786             :                                                                 20000419 */
    1787             : #endif
    1788             : #endif
    1789             : 
    1790             : #ifdef ZTS
    1791             :         tsrm_startup(1, 1, 0, NULL);
    1792             :         tsrm_ls = ts_resource(0);
    1793             : #endif
    1794             : 
    1795         404 :         sapi_startup(&cgi_sapi_module);
    1796         404 :         fastcgi = fcgi_is_fastcgi();
    1797         404 :         cgi_sapi_module.php_ini_path_override = NULL;
    1798             : 
    1799             : #ifdef PHP_WIN32
    1800             :         _fmode = _O_BINARY; /* sets default for file streams to binary */
    1801             :         setmode(_fileno(stdin),  O_BINARY);     /* make the stdio mode be binary */
    1802             :         setmode(_fileno(stdout), O_BINARY);     /* make the stdio mode be binary */
    1803             :         setmode(_fileno(stderr), O_BINARY);     /* make the stdio mode be binary */
    1804             : #endif
    1805             : 
    1806         404 :         if (!fastcgi) {
    1807             :                 /* Make sure we detect we are a cgi - a bit redundancy here,
    1808             :                  * but the default case is that we have to check only the first one. */
    1809        1616 :                 if (getenv("SERVER_SOFTWARE") ||
    1810         404 :                         getenv("SERVER_NAME") ||
    1811         404 :                         getenv("GATEWAY_INTERFACE") ||
    1812             :                         getenv("REQUEST_METHOD")
    1813         404 :                 ) {
    1814         213 :                         cgi = 1;
    1815             :                 }
    1816             :         }
    1817             : 
    1818         404 :         if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
    1819             :                 /* we've got query string that has no = - apache CGI will pass it to command line */
    1820             :                 unsigned char *p;
    1821           5 :                 decoded_query_string = strdup(query_string);
    1822           5 :                 php_url_decode(decoded_query_string, strlen(decoded_query_string));
    1823           5 :                 for (p = (unsigned char *)decoded_query_string; *p &&  *p <= ' '; p++) {
    1824             :                         /* skip all leading spaces */
    1825             :                 }
    1826           5 :                 if(*p == '-') {
    1827           0 :                         skip_getopt = 1;
    1828             :                 }
    1829           5 :                 free(decoded_query_string);
    1830             :         }
    1831             : 
    1832       14531 :         while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
    1833       13723 :                 switch (c) {
    1834             :                         case 'c':
    1835         366 :                                 if (cgi_sapi_module.php_ini_path_override) {
    1836           0 :                                         free(cgi_sapi_module.php_ini_path_override);
    1837             :                                 }
    1838         366 :                                 cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
    1839         366 :                                 break;
    1840             :                         case 'n':
    1841         404 :                                 cgi_sapi_module.php_ini_ignore = 1;
    1842         404 :                                 break;
    1843             :                         case 'd': {
    1844             :                                 /* define ini entries on command line */
    1845       12198 :                                 int len = strlen(php_optarg);
    1846             :                                 char *val;
    1847             : 
    1848       12198 :                                 if ((val = strchr(php_optarg, '='))) {
    1849       12198 :                                         val++;
    1850       13355 :                                         if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
    1851        1157 :                                                 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
    1852        1157 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
    1853        1157 :                                                 ini_entries_len += (val - php_optarg);
    1854        1157 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1);
    1855        1157 :                                                 ini_entries_len++;
    1856        1157 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg));
    1857        1157 :                                                 ini_entries_len += len - (val - php_optarg);
    1858        1157 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
    1859        1157 :                                                 ini_entries_len += sizeof("\n\0\"") - 2;
    1860             :                                         } else {
    1861       11041 :                                                 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0"));
    1862       11041 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
    1863       11041 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
    1864       11041 :                                                 ini_entries_len += len + sizeof("\n\0") - 2;
    1865             :                                         }
    1866             :                                 } else {
    1867           0 :                                         cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
    1868           0 :                                         memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
    1869           0 :                                         memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
    1870           0 :                                         ini_entries_len += len + sizeof("=1\n\0") - 2;
    1871             :                                 }
    1872       12198 :                                 break;
    1873             :                         }
    1874             :                         /* if we're started on command line, check to see if
    1875             :                          * we are being started as an 'external' fastcgi
    1876             :                          * server by accepting a bindpath parameter. */
    1877             :                         case 'b':
    1878           0 :                                 if (!fastcgi) {
    1879           0 :                                         bindpath = strdup(php_optarg);
    1880             :                                 }
    1881           0 :                                 break;
    1882             :                         case 's': /* generate highlighted HTML from source */
    1883           3 :                                 behavior = PHP_MODE_HIGHLIGHT;
    1884             :                                 break;
    1885             :                 }
    1886             :         }
    1887         404 :         php_optind = orig_optind;
    1888         404 :         php_optarg = orig_optarg;
    1889             : 
    1890         404 :         if (fastcgi || bindpath) {
    1891             :                 /* Override SAPI callbacks */
    1892           0 :                 cgi_sapi_module.ub_write     = sapi_fcgi_ub_write;
    1893           0 :                 cgi_sapi_module.flush        = sapi_fcgi_flush;
    1894           0 :                 cgi_sapi_module.read_post    = sapi_fcgi_read_post;
    1895           0 :                 cgi_sapi_module.getenv       = sapi_fcgi_getenv;
    1896           0 :                 cgi_sapi_module.read_cookies = sapi_fcgi_read_cookies;
    1897             :         }
    1898             : 
    1899             : #ifdef ZTS
    1900             :         SG(request_info).path_translated = NULL;
    1901             : #endif
    1902             : 
    1903         404 :         cgi_sapi_module.executable_location = argv[0];
    1904         404 :         if (!cgi && !fastcgi && !bindpath) {
    1905         191 :                 cgi_sapi_module.additional_functions = additional_functions;
    1906             :         }
    1907             : 
    1908             :         /* startup after we get the above ini override se we get things right */
    1909         404 :         if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
    1910             : #ifdef ZTS
    1911             :                 tsrm_shutdown();
    1912             : #endif
    1913           0 :                 return FAILURE;
    1914             :         }
    1915             : 
    1916             :         /* check force_cgi after startup, so we have proper output */
    1917         404 :         if (cgi && CGIG(force_redirect)) {
    1918             :                 /* Apache will generate REDIRECT_STATUS,
    1919             :                  * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS.
    1920             :                  * redirect.so and installation instructions available from
    1921             :                  * http://www.koehntopp.de/php.
    1922             :                  *   -- kk@netuse.de
    1923             :                  */
    1924         213 :                 if (!getenv("REDIRECT_STATUS") &&
    1925           0 :                         !getenv ("HTTP_REDIRECT_STATUS") &&
    1926             :                         /* this is to allow a different env var to be configured
    1927             :                          * in case some server does something different than above */
    1928           0 :                         (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
    1929             :                 ) {
    1930           0 :                         zend_try {
    1931           0 :                                 SG(sapi_headers).http_response_code = 400;
    1932           0 :                                 PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
    1933             : <p>This PHP CGI binary was compiled with force-cgi-redirect enabled.  This\n\
    1934             : means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
    1935             : set, e.g. via an Apache Action directive.</p>\n\
    1936             : <p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"http://php.net/security.cgi-bin\">\
    1937             : manual page for CGI security</a>.</p>\n\
    1938             : <p>For more information about changing this behaviour or re-enabling this webserver,\n\
    1939             : consult the installation file that came with this distribution, or visit \n\
    1940             : <a href=\"http://php.net/install.windows\">the manual page</a>.</p>\n");
    1941           0 :                         } zend_catch {
    1942           0 :                         } zend_end_try();
    1943             : #if defined(ZTS) && !defined(PHP_DEBUG)
    1944             :                         /* XXX we're crashing here in msvc6 debug builds at
    1945             :                          * php_message_handler_for_zend:839 because
    1946             :                          * SG(request_info).path_translated is an invalid pointer.
    1947             :                          * It still happens even though I set it to null, so something
    1948             :                          * weird is going on.
    1949             :                          */
    1950             :                         tsrm_shutdown();
    1951             : #endif
    1952           0 :                         return FAILURE;
    1953             :                 }
    1954             :         }
    1955             : 
    1956         404 :         if (bindpath) {
    1957           0 :                 int backlog = 128;
    1958           0 :                 if (getenv("PHP_FCGI_BACKLOG")) {
    1959           0 :                         backlog = atoi(getenv("PHP_FCGI_BACKLOG"));
    1960             :                 }
    1961           0 :                 fcgi_fd = fcgi_listen(bindpath, backlog);
    1962           0 :                 if (fcgi_fd < 0) {
    1963           0 :                         fprintf(stderr, "Couldn't create FastCGI listen socket on port %s\n", bindpath);
    1964             : #ifdef ZTS
    1965             :                         tsrm_shutdown();
    1966             : #endif
    1967           0 :                         return FAILURE;
    1968             :                 }
    1969           0 :                 fastcgi = fcgi_is_fastcgi();
    1970             :         }
    1971         404 :         if (fastcgi) {
    1972             :                 /* How many times to run PHP scripts before dying */
    1973           0 :                 if (getenv("PHP_FCGI_MAX_REQUESTS")) {
    1974           0 :                         max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
    1975           0 :                         if (max_requests < 0) {
    1976           0 :                                 fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n");
    1977           0 :                                 return FAILURE;
    1978             :                         }
    1979             :                 }
    1980             : 
    1981             :                 /* make php call us to get _ENV vars */
    1982           0 :                 php_php_import_environment_variables = php_import_environment_variables;
    1983           0 :                 php_import_environment_variables = cgi_php_import_environment_variables;
    1984             : 
    1985             :                 /* library is already initialized, now init our request */
    1986           0 :                 request = fcgi_init_request(fcgi_fd);
    1987             : 
    1988             : #ifndef PHP_WIN32
    1989             :         /* Pre-fork, if required */
    1990           0 :         if (getenv("PHP_FCGI_CHILDREN")) {
    1991           0 :                 char * children_str = getenv("PHP_FCGI_CHILDREN");
    1992           0 :                 children = atoi(children_str);
    1993           0 :                 if (children < 0) {
    1994           0 :                         fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
    1995           0 :                         return FAILURE;
    1996             :                 }
    1997           0 :                 fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
    1998             :                 /* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
    1999           0 :                 fcgi_set_mgmt_var("FCGI_MAX_REQS",  sizeof("FCGI_MAX_REQS")-1,  children_str, strlen(children_str));
    2000             :         } else {
    2001           0 :                 fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
    2002           0 :                 fcgi_set_mgmt_var("FCGI_MAX_REQS",  sizeof("FCGI_MAX_REQS")-1,  "1", sizeof("1")-1);
    2003             :         }
    2004             : 
    2005           0 :         if (children) {
    2006           0 :                 int running = 0;
    2007             :                 pid_t pid;
    2008             : 
    2009             :                 /* Create a process group for ourself & children */
    2010           0 :                 setsid();
    2011           0 :                 pgroup = getpgrp();
    2012             : #ifdef DEBUG_FASTCGI
    2013             :                 fprintf(stderr, "Process group %d\n", pgroup);
    2014             : #endif
    2015             : 
    2016             :                 /* Set up handler to kill children upon exit */
    2017           0 :                 act.sa_flags = 0;
    2018           0 :                 act.sa_handler = fastcgi_cleanup;
    2019           0 :                 if (sigaction(SIGTERM, &act, &old_term) ||
    2020           0 :                         sigaction(SIGINT,  &act, &old_int)  ||
    2021             :                         sigaction(SIGQUIT, &act, &old_quit)
    2022           0 :                 ) {
    2023           0 :                         perror("Can't set signals");
    2024           0 :                         exit(1);
    2025             :                 }
    2026             : 
    2027           0 :                 if (fcgi_in_shutdown()) {
    2028           0 :                         goto parent_out;
    2029             :                 }
    2030             : 
    2031           0 :                 while (parent) {
    2032             :                         do {
    2033             : #ifdef DEBUG_FASTCGI
    2034             :                                 fprintf(stderr, "Forking, %d running\n", running);
    2035             : #endif
    2036           0 :                                 pid = fork();
    2037           0 :                                 switch (pid) {
    2038             :                                 case 0:
    2039             :                                         /* One of the children.
    2040             :                                          * Make sure we don't go round the
    2041             :                                          * fork loop any more
    2042             :                                          */
    2043           0 :                                         parent = 0;
    2044             : 
    2045             :                                         /* don't catch our signals */
    2046           0 :                                         sigaction(SIGTERM, &old_term, 0);
    2047           0 :                                         sigaction(SIGQUIT, &old_quit, 0);
    2048           0 :                                         sigaction(SIGINT,  &old_int,  0);
    2049           0 :                                         break;
    2050             :                                 case -1:
    2051           0 :                                         perror("php (pre-forking)");
    2052           0 :                                         exit(1);
    2053             :                                         break;
    2054             :                                 default:
    2055             :                                         /* Fine */
    2056           0 :                                         running++;
    2057             :                                         break;
    2058             :                                 }
    2059           0 :                         } while (parent && (running < children));
    2060             : 
    2061           0 :                         if (parent) {
    2062             : #ifdef DEBUG_FASTCGI
    2063             :                                 fprintf(stderr, "Wait for kids, pid %d\n", getpid());
    2064             : #endif
    2065           0 :                                 parent_waiting = 1;
    2066             :                                 while (1) {
    2067           0 :                                         if (wait(&status) >= 0) {
    2068           0 :                                                 running--;
    2069           0 :                                                 break;
    2070           0 :                                         } else if (exit_signal) {
    2071           0 :                                                 break;
    2072             :                                         }
    2073           0 :                                 }
    2074           0 :                                 if (exit_signal) {
    2075             : #if 0
    2076             :                                         while (running > 0) {
    2077             :                                                 while (wait(&status) < 0) {
    2078             :                                                 }
    2079             :                                                 running--;
    2080             :                                         }
    2081             : #endif
    2082           0 :                                         goto parent_out;
    2083             :                                 }
    2084             :                         }
    2085             :                 }
    2086             :         } else {
    2087           0 :                 parent = 0;
    2088             :         }
    2089             : 
    2090             : #endif /* WIN32 */
    2091             :         }
    2092             : 
    2093         404 :         zend_first_try {
    2094       14531 :                 while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1, 2)) != -1) {
    2095       13723 :                         switch (c) {
    2096             :                                 case 'T':
    2097           0 :                                         benchmark = 1;
    2098             :                                         {
    2099           0 :                                                 char *comma = strchr(php_optarg, ',');
    2100           0 :                                                 if (comma) {
    2101           0 :                                                         warmup_repeats = atoi(php_optarg);
    2102           0 :                                                         repeats = atoi(comma + 1);
    2103             :                                                 } else {
    2104           0 :                                                         repeats = atoi(php_optarg);
    2105             :                                                 }
    2106             :                                         }
    2107             : #ifdef HAVE_GETTIMEOFDAY
    2108           0 :                                         gettimeofday(&start, NULL);
    2109             : #else
    2110             :                                         time(&start);
    2111             : #endif
    2112           0 :                                         break;
    2113             :                                 case 'h':
    2114             :                                 case '?':
    2115           0 :                                         if (request) {
    2116           0 :                                                 fcgi_destroy_request(request);
    2117             :                                         }
    2118           0 :                                         fcgi_shutdown();
    2119           0 :                                         no_headers = 1;
    2120           0 :                                         SG(headers_sent) = 1;
    2121           0 :                                         php_cgi_usage(argv[0]);
    2122           0 :                                         php_output_end_all(TSRMLS_C);
    2123           0 :                                         exit_status = 0;
    2124           0 :                                         goto out;
    2125             :                         }
    2126             :                 }
    2127         404 :                 php_optind = orig_optind;
    2128         404 :                 php_optarg = orig_optarg;
    2129             : 
    2130             :                 /* start of FAST CGI loop */
    2131             :                 /* Initialise FastCGI request structure */
    2132             : #ifdef PHP_WIN32
    2133             :                 /* attempt to set security impersonation for fastcgi
    2134             :                  * will only happen on NT based OS, others will ignore it. */
    2135             :                 if (fastcgi && CGIG(impersonate)) {
    2136             :                         fcgi_impersonate();
    2137             :                 }
    2138             : #endif
    2139         808 :                 while (!fastcgi || fcgi_accept_request(request) >= 0) {
    2140         404 :                         SG(server_context) = fastcgi ? (void *) request : (void *) 1;
    2141         404 :                         init_request_info(request TSRMLS_CC);
    2142             : 
    2143         404 :                         if (!cgi && !fastcgi) {
    2144        6283 :                                 while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
    2145        5902 :                                         switch (c) {
    2146             : 
    2147             :                                                 case 'a':       /* interactive mode */
    2148           2 :                                                         printf("Interactive mode enabled\n\n");
    2149           2 :                                                         break;
    2150             : 
    2151             :                                                 case 'C': /* don't chdir to the script directory */
    2152         153 :                                                         SG(options) |= SAPI_OPTION_NO_CHDIR;
    2153         153 :                                                         break;
    2154             : 
    2155             :                                                 case 'e': /* enable extended info output */
    2156           0 :                                                         CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
    2157           0 :                                                         break;
    2158             : 
    2159             :                                                 case 'f': /* parse file */
    2160           6 :                                                         if (script_file) {
    2161           1 :                                                                 efree(script_file);
    2162             :                                                         }
    2163           6 :                                                         script_file = estrdup(php_optarg);
    2164           6 :                                                         no_headers = 1;
    2165           6 :                                                         break;
    2166             : 
    2167             :                                                 case 'i': /* php info & quit */
    2168           0 :                                                         if (script_file) {
    2169           0 :                                                                 efree(script_file);
    2170             :                                                         }
    2171           0 :                                                         if (php_request_startup(TSRMLS_C) == FAILURE) {
    2172           0 :                                                                 SG(server_context) = NULL;
    2173           0 :                                                                 php_module_shutdown(TSRMLS_C);
    2174           0 :                                                                 return FAILURE;
    2175             :                                                         }
    2176           0 :                                                         if (no_headers) {
    2177           0 :                                                                 SG(headers_sent) = 1;
    2178           0 :                                                                 SG(request_info).no_headers = 1;
    2179             :                                                         }
    2180           0 :                                                         php_print_info(0xFFFFFFFF TSRMLS_CC);
    2181           0 :                                                         php_request_shutdown((void *) 0);
    2182           0 :                                                         fcgi_shutdown();
    2183           0 :                                                         exit_status = 0;
    2184           0 :                                                         goto out;
    2185             : 
    2186             :                                                 case 'l': /* syntax check mode */
    2187           4 :                                                         no_headers = 1;
    2188           4 :                                                         behavior = PHP_MODE_LINT;
    2189           4 :                                                         break;
    2190             : 
    2191             :                                                 case 'm': /* list compiled in modules */
    2192           0 :                                                         if (script_file) {
    2193           0 :                                                                 efree(script_file);
    2194             :                                                         }
    2195           0 :                                                         SG(headers_sent) = 1;
    2196           0 :                                                         php_printf("[PHP Modules]\n");
    2197           0 :                                                         print_modules(TSRMLS_C);
    2198           0 :                                                         php_printf("\n[Zend Modules]\n");
    2199           0 :                                                         print_extensions(TSRMLS_C);
    2200           0 :                                                         php_printf("\n");
    2201           0 :                                                         php_output_end_all(TSRMLS_C);
    2202           0 :                                                         fcgi_shutdown();
    2203           0 :                                                         exit_status = 0;
    2204           0 :                                                         goto out;
    2205             : 
    2206             : #if 0 /* not yet operational, see also below ... */
    2207             :                                                 case '': /* generate indented source mode*/
    2208             :                                                         behavior=PHP_MODE_INDENT;
    2209             :                                                         break;
    2210             : #endif
    2211             : 
    2212             :                                                 case 'q': /* do not generate HTTP headers */
    2213         156 :                                                         no_headers = 1;
    2214         156 :                                                         break;
    2215             : 
    2216             :                                                 case 'v': /* show php version & quit */
    2217           1 :                                                         if (script_file) {
    2218           0 :                                                                 efree(script_file);
    2219             :                                                         }
    2220           1 :                                                         no_headers = 1;
    2221           1 :                                                         if (php_request_startup(TSRMLS_C) == FAILURE) {
    2222           0 :                                                                 SG(server_context) = NULL;
    2223           0 :                                                                 php_module_shutdown(TSRMLS_C);
    2224           0 :                                                                 return FAILURE;
    2225             :                                                         }
    2226           1 :                                                         if (no_headers) {
    2227           1 :                                                                 SG(headers_sent) = 1;
    2228           1 :                                                                 SG(request_info).no_headers = 1;
    2229             :                                                         }
    2230             : #if ZEND_DEBUG
    2231             :                                                         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());
    2232             : #else
    2233           1 :                                                         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());
    2234             : #endif
    2235           1 :                                                         php_request_shutdown((void *) 0);
    2236           1 :                                                         fcgi_shutdown();
    2237           1 :                                                         exit_status = 0;
    2238           1 :                                                         goto out;
    2239             : 
    2240             :                                                 case 'w':
    2241           4 :                                                         behavior = PHP_MODE_STRIP;
    2242           4 :                                                         break;
    2243             : 
    2244             :                                                 case 'z': /* load extension file */
    2245           0 :                                                         zend_load_extension(php_optarg TSRMLS_CC);
    2246             :                                                         break;
    2247             : 
    2248             :                                                 default:
    2249             :                                                         break;
    2250             :                                         }
    2251             :                                 }
    2252             : 
    2253         190 :                                 if (script_file) {
    2254             :                                         /* override path_translated if -f on command line */
    2255           5 :                                         if (SG(request_info).path_translated) efree(SG(request_info).path_translated);
    2256           5 :                                         SG(request_info).path_translated = script_file;
    2257             :                                         /* before registering argv to module exchange the *new* argv[0] */
    2258             :                                         /* we can achieve this without allocating more memory */
    2259           5 :                                         SG(request_info).argc = argc - (php_optind - 1);
    2260           5 :                                         SG(request_info).argv = &argv[php_optind - 1];
    2261           5 :                                         SG(request_info).argv[0] = script_file;
    2262         185 :                                 } else if (argc > php_optind) {
    2263             :                                         /* file is on command line, but not in -f opt */
    2264         183 :                                         if (SG(request_info).path_translated) efree(SG(request_info).path_translated);
    2265         183 :                                         SG(request_info).path_translated = estrdup(argv[php_optind]);
    2266             :                                         /* arguments after the file are considered script args */
    2267         183 :                                         SG(request_info).argc = argc - php_optind;
    2268         183 :                                         SG(request_info).argv = &argv[php_optind];
    2269             :                                 }
    2270             : 
    2271         190 :                                 if (no_headers) {
    2272         165 :                                         SG(headers_sent) = 1;
    2273         165 :                                         SG(request_info).no_headers = 1;
    2274             :                                 }
    2275             : 
    2276             :                                 /* all remaining arguments are part of the query string
    2277             :                                  * this section of code concatenates all remaining arguments
    2278             :                                  * into a single string, seperating args with a &
    2279             :                                  * this allows command lines like:
    2280             :                                  *
    2281             :                                  *  test.php v1=test v2=hello+world!
    2282             :                                  *  test.php "v1=test&v2=hello world!"
    2283             :                                  *  test.php v1=test "v2=hello world!"
    2284             :                                 */
    2285         190 :                                 if (!SG(request_info).query_string && argc > php_optind) {
    2286         183 :                                         int slen = strlen(PG(arg_separator).input);
    2287         183 :                                         len = 0;
    2288         366 :                                         for (i = php_optind; i < argc; i++) {
    2289         183 :                                                 if (i < (argc - 1)) {
    2290           0 :                                                         len += strlen(argv[i]) + slen;
    2291             :                                                 } else {
    2292         183 :                                                         len += strlen(argv[i]);
    2293             :                                                 }
    2294             :                                         }
    2295             : 
    2296         183 :                                         len += 2;
    2297         183 :                                         s = malloc(len);
    2298         183 :                                         *s = '\0';                      /* we are pretending it came from the environment  */
    2299         366 :                                         for (i = php_optind; i < argc; i++) {
    2300         183 :                                                 strlcat(s, argv[i], len);
    2301         183 :                                                 if (i < (argc - 1)) {
    2302           0 :                                                         strlcat(s, PG(arg_separator).input, len);
    2303             :                                                 }
    2304             :                                         }
    2305         183 :                                         SG(request_info).query_string = s;
    2306         183 :                                         free_query_string = 1;
    2307             :                                 }
    2308             :                         } /* end !cgi && !fastcgi */
    2309             : 
    2310             :                         /*
    2311             :                                 we never take stdin if we're (f)cgi, always
    2312             :                                 rely on the web server giving us the info
    2313             :                                 we need in the environment.
    2314             :                         */
    2315         804 :                         if (SG(request_info).path_translated || cgi || fastcgi) {
    2316         401 :                                 file_handle.type = ZEND_HANDLE_FILENAME;
    2317         401 :                                 file_handle.filename = SG(request_info).path_translated;
    2318         401 :                                 file_handle.handle.fp = NULL;
    2319             :                         } else {
    2320           2 :                                 file_handle.filename = "-";
    2321           2 :                                 file_handle.type = ZEND_HANDLE_FP;
    2322           2 :                                 file_handle.handle.fp = stdin;
    2323             :                         }
    2324             : 
    2325         403 :                         file_handle.opened_path = NULL;
    2326         403 :                         file_handle.free_filename = 0;
    2327             : 
    2328             :                         /* request startup only after we've done all we can to
    2329             :                          * get path_translated */
    2330         403 :                         if (php_request_startup(TSRMLS_C) == FAILURE) {
    2331           0 :                                 if (fastcgi) {
    2332           0 :                                         fcgi_finish_request(request, 1);
    2333             :                                 }
    2334           0 :                                 SG(server_context) = NULL;
    2335           0 :                                 php_module_shutdown(TSRMLS_C);
    2336           0 :                                 return FAILURE;
    2337             :                         }
    2338         403 :                         if (no_headers) {
    2339         165 :                                 SG(headers_sent) = 1;
    2340         165 :                                 SG(request_info).no_headers = 1;
    2341             :                         }
    2342             : 
    2343             :                         /*
    2344             :                                 at this point path_translated will be set if:
    2345             :                                 1. we are running from shell and got filename was there
    2346             :                                 2. we are running as cgi or fastcgi
    2347             :                         */
    2348         403 :                         if (cgi || fastcgi || SG(request_info).path_translated) {
    2349         401 :                                 if (php_fopen_primary_script(&file_handle TSRMLS_CC) == FAILURE) {
    2350           7 :                                         zend_try {
    2351           7 :                                                 if (errno == EACCES) {
    2352           0 :                                                         SG(sapi_headers).http_response_code = 403;
    2353           0 :                                                         PUTS("Access denied.\n");
    2354             :                                                 } else {
    2355           7 :                                                         SG(sapi_headers).http_response_code = 404;
    2356           7 :                                                         PUTS("No input file specified.\n");
    2357             :                                                 }
    2358           0 :                                         } zend_catch {
    2359           7 :                                         } zend_end_try();
    2360             :                                         /* we want to serve more requests if this is fastcgi
    2361             :                                          * so cleanup and continue, request shutdown is
    2362             :                                          * handled later */
    2363           7 :                                         if (fastcgi) {
    2364           0 :                                                 goto fastcgi_request_done;
    2365             :                                         }
    2366             : 
    2367           7 :                                         if (SG(request_info).path_translated) efree(SG(request_info).path_translated);
    2368             : 
    2369           7 :                                         if (free_query_string && SG(request_info).query_string) {
    2370           3 :                                                 free(SG(request_info).query_string);
    2371           3 :                                                 SG(request_info).query_string = NULL;
    2372             :                                         }
    2373             : 
    2374           7 :                                         php_request_shutdown((void *) 0);
    2375           7 :                                         SG(server_context) = NULL;
    2376           7 :                                         php_module_shutdown(TSRMLS_C);
    2377           7 :                                         sapi_shutdown();
    2378             : #ifdef ZTS
    2379             :                                         tsrm_shutdown();
    2380             : #endif
    2381           7 :                                         return FAILURE;
    2382             :                                 }
    2383             :                         }
    2384             : 
    2385         396 :                         if (CGIG(check_shebang_line)) {
    2386             :                                 /* #!php support */
    2387         396 :                                 switch (file_handle.type) {
    2388             :                                         case ZEND_HANDLE_FD:
    2389           0 :                                                 if (file_handle.handle.fd < 0) {
    2390           0 :                                                         break;
    2391             :                                                 }
    2392           0 :                                                 file_handle.type = ZEND_HANDLE_FP;
    2393           0 :                                                 file_handle.handle.fp = fdopen(file_handle.handle.fd, "rb");
    2394             :                                                 /* break missing intentionally */
    2395             :                                         case ZEND_HANDLE_FP:
    2396           4 :                                                 if (!file_handle.handle.fp ||
    2397           2 :                                                     (file_handle.handle.fp == stdin)) {
    2398             :                                                         break;
    2399             :                                                 }
    2400           0 :                                                 c = fgetc(file_handle.handle.fp);
    2401           0 :                                                 if (c == '#') {
    2402           0 :                                                         while (c != '\n' && c != '\r' && c != EOF) {
    2403           0 :                                                                 c = fgetc(file_handle.handle.fp);       /* skip to end of line */
    2404             :                                                         }
    2405             :                                                         /* handle situations where line is terminated by \r\n */
    2406           0 :                                                         if (c == '\r') {
    2407           0 :                                                                 if (fgetc(file_handle.handle.fp) != '\n') {
    2408           0 :                                                                         zend_long pos = zend_ftell(file_handle.handle.fp);
    2409           0 :                                                                         zend_fseek(file_handle.handle.fp, pos - 1, SEEK_SET);
    2410             :                                                                 }
    2411             :                                                         }
    2412           0 :                                                         CG(start_lineno) = 2;
    2413             :                                                 } else {
    2414           0 :                                                         rewind(file_handle.handle.fp);
    2415             :                                                 }
    2416           0 :                                                 break;
    2417             :                                         case ZEND_HANDLE_STREAM:
    2418           1 :                                                 c = php_stream_getc((php_stream*)file_handle.handle.stream.handle);
    2419           1 :                                                 if (c == '#') {
    2420           0 :                                                         while (c != '\n' && c != '\r' && c != EOF) {
    2421           0 :                                                                 c = php_stream_getc((php_stream*)file_handle.handle.stream.handle);     /* skip to end of line */
    2422             :                                                         }
    2423             :                                                         /* handle situations where line is terminated by \r\n */
    2424           0 :                                                         if (c == '\r') {
    2425           0 :                                                                 if (php_stream_getc((php_stream*)file_handle.handle.stream.handle) != '\n') {
    2426           0 :                                                                         zend_off_t pos = php_stream_tell((php_stream*)file_handle.handle.stream.handle);
    2427           0 :                                                                         php_stream_seek((php_stream*)file_handle.handle.stream.handle, pos - 1, SEEK_SET);
    2428             :                                                                 }
    2429             :                                                         }
    2430           0 :                                                         CG(start_lineno) = 2;
    2431             :                                                 } else {
    2432           1 :                                                         php_stream_rewind((php_stream*)file_handle.handle.stream.handle);
    2433             :                                                 }
    2434           1 :                                                 break;
    2435             :                                         case ZEND_HANDLE_MAPPED:
    2436         393 :                                                 if (file_handle.handle.stream.mmap.buf[0] == '#') {
    2437           0 :                                                     int i = 1;
    2438             : 
    2439           0 :                                                     c = file_handle.handle.stream.mmap.buf[i++];
    2440           0 :                                                         while (c != '\n' && c != '\r' && c != EOF) {
    2441           0 :                                                                 c = file_handle.handle.stream.mmap.buf[i++];
    2442             :                                                         }
    2443           0 :                                                         if (c == '\r') {
    2444           0 :                                                                 if (file_handle.handle.stream.mmap.buf[i] == '\n') {
    2445           0 :                                                                         i++;
    2446             :                                                                 }
    2447             :                                                         }
    2448           0 :                                                         file_handle.handle.stream.mmap.buf += i;
    2449           0 :                                                         file_handle.handle.stream.mmap.len -= i;
    2450             :                                                 }
    2451             :                                                 break;
    2452             :                                         default:
    2453             :                                                 break;
    2454             :                                 }
    2455             :                         }
    2456             : 
    2457         396 :                         switch (behavior) {
    2458             :                                 case PHP_MODE_STANDARD:
    2459         390 :                                         php_execute_script(&file_handle TSRMLS_CC);
    2460         390 :                                         break;
    2461             :                                 case PHP_MODE_LINT:
    2462           3 :                                         PG(during_request_startup) = 0;
    2463           3 :                                         exit_status = php_lint_script(&file_handle TSRMLS_CC);
    2464           3 :                                         if (exit_status == SUCCESS) {
    2465           2 :                                                 zend_printf("No syntax errors detected in %s\n", file_handle.filename);
    2466             :                                         } else {
    2467           1 :                                                 zend_printf("Errors parsing %s\n", file_handle.filename);
    2468             :                                         }
    2469           3 :                                         break;
    2470             :                                 case PHP_MODE_STRIP:
    2471           2 :                                         if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
    2472           2 :                                                 zend_strip(TSRMLS_C);
    2473           2 :                                                 zend_file_handle_dtor(&file_handle TSRMLS_CC);
    2474           2 :                                                 php_output_teardown();
    2475             :                                         }
    2476           2 :                                         return SUCCESS;
    2477             :                                         break;
    2478             :                                 case PHP_MODE_HIGHLIGHT:
    2479             :                                         {
    2480             :                                                 zend_syntax_highlighter_ini syntax_highlighter_ini;
    2481             : 
    2482           1 :                                                 if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
    2483           1 :                                                         php_get_highlight_struct(&syntax_highlighter_ini);
    2484           1 :                                                         zend_highlight(&syntax_highlighter_ini TSRMLS_CC);
    2485           1 :                                                         if (fastcgi) {
    2486           0 :                                                                 goto fastcgi_request_done;
    2487             :                                                         }
    2488           1 :                                                         zend_file_handle_dtor(&file_handle TSRMLS_CC);
    2489           1 :                                                         php_output_teardown();
    2490             :                                                 }
    2491           1 :                                                 return SUCCESS;
    2492             :                                         }
    2493             :                                         break;
    2494             : #if 0
    2495             :                                 /* Zeev might want to do something with this one day */
    2496             :                                 case PHP_MODE_INDENT:
    2497             :                                         open_file_for_scanning(&file_handle TSRMLS_CC);
    2498             :                                         zend_indent(TSRMLS_C);
    2499             :                                         zend_file_handle_dtor(&file_handle TSRMLS_CC);
    2500             :                                         php_output_teardown();
    2501             :                                         return SUCCESS;
    2502             :                                         break;
    2503             : #endif
    2504             :                         }
    2505             : 
    2506             : fastcgi_request_done:
    2507             :                         {
    2508         393 :                                 if (SG(request_info).path_translated) efree(SG(request_info).path_translated);
    2509             : 
    2510         393 :                                 php_request_shutdown((void *) 0);
    2511             : 
    2512         393 :                                 if (exit_status == 0) {
    2513         392 :                                         exit_status = EG(exit_status);
    2514             :                                 }
    2515             : 
    2516         393 :                                 if (free_query_string && SG(request_info).query_string) {
    2517         178 :                                         free(SG(request_info).query_string);
    2518         178 :                                         SG(request_info).query_string = NULL;
    2519             :                                 }
    2520             :                         }
    2521             : 
    2522         393 :                         if (!fastcgi) {
    2523         393 :                                 if (benchmark) {
    2524           0 :                                         if (warmup_repeats) {
    2525           0 :                                                 warmup_repeats--;
    2526           0 :                                                 if (!warmup_repeats) {
    2527             : #ifdef HAVE_GETTIMEOFDAY
    2528           0 :                                                         gettimeofday(&start, NULL);
    2529             : #else
    2530             :                                                         time(&start);                                               
    2531             : #endif
    2532             :                                                 }
    2533           0 :                                                 continue;
    2534             :                                         } else {
    2535           0 :                                                 repeats--;
    2536           0 :                                                 if (repeats > 0) {
    2537           0 :                                                         script_file = NULL;
    2538           0 :                                                         php_optind = orig_optind;
    2539           0 :                                                         php_optarg = orig_optarg;
    2540           0 :                                                         continue;
    2541             :                                                 }
    2542             :                                         }
    2543             :                                 }
    2544         393 :                                 break;
    2545             :                         }
    2546             : 
    2547             :                         /* only fastcgi will get here */
    2548           0 :                         requests++;
    2549           0 :                         if (max_requests && (requests == max_requests)) {
    2550           0 :                                 fcgi_finish_request(request, 1);
    2551           0 :                                 if (bindpath) {
    2552           0 :                                         free(bindpath);
    2553             :                                 }
    2554           0 :                                 if (max_requests != 1) {
    2555             :                                         /* no need to return exit_status of the last request */
    2556           0 :                                         exit_status = 0;
    2557             :                                 }
    2558           0 :                                 break;
    2559             :                         }
    2560             :                         /* end of fastcgi loop */
    2561             :                 }
    2562         393 :                 if (request) {
    2563           0 :                         fcgi_destroy_request(request);
    2564             :                 }
    2565         393 :                 fcgi_shutdown();
    2566             : 
    2567         393 :                 if (cgi_sapi_module.php_ini_path_override) {
    2568         366 :                         free(cgi_sapi_module.php_ini_path_override);
    2569             :                 }
    2570         393 :                 if (cgi_sapi_module.ini_entries) {
    2571         381 :                         free(cgi_sapi_module.ini_entries);
    2572             :                 }
    2573           0 :         } zend_catch {
    2574           0 :                 exit_status = 255;
    2575         393 :         } zend_end_try();
    2576             : 
    2577             : out:
    2578         394 :         if (benchmark) {
    2579             :                 int sec;
    2580             : #ifdef HAVE_GETTIMEOFDAY
    2581             :                 int usec;
    2582             : 
    2583           0 :                 gettimeofday(&end, NULL);
    2584           0 :                 sec = (int)(end.tv_sec - start.tv_sec);
    2585           0 :                 if (end.tv_usec >= start.tv_usec) {
    2586           0 :                         usec = (int)(end.tv_usec - start.tv_usec);
    2587             :                 } else {
    2588           0 :                         sec -= 1;
    2589           0 :                         usec = (int)(end.tv_usec + 1000000 - start.tv_usec);
    2590             :                 }
    2591           0 :                 fprintf(stderr, "\nElapsed time: %d.%06d sec\n", sec, usec);
    2592             : #else
    2593             :                 time(&end);
    2594             :                 sec = (int)(end - start);
    2595             :                 fprintf(stderr, "\nElapsed time: %d sec\n", sec);
    2596             : #endif
    2597             :         }
    2598             : 
    2599             : #ifndef PHP_WIN32
    2600             : parent_out:
    2601             : #endif
    2602             : 
    2603         394 :         SG(server_context) = NULL;
    2604         394 :         php_module_shutdown(TSRMLS_C);
    2605         394 :         sapi_shutdown();
    2606             : 
    2607             : #ifdef ZTS
    2608             :         tsrm_shutdown();
    2609             : #endif
    2610             : 
    2611             : #if defined(PHP_WIN32) && ZEND_DEBUG && 0
    2612             :         _CrtDumpMemoryLeaks();
    2613             : #endif
    2614             : 
    2615         394 :         return exit_status;
    2616             : }
    2617             : /* }}} */
    2618             : 
    2619             : /*
    2620             :  * Local variables:
    2621             :  * tab-width: 4
    2622             :  * c-basic-offset: 4
    2623             :  * End:
    2624             :  * vim600: sw=4 ts=4 fdm=marker
    2625             :  * vim<600: sw=4 ts=4
    2626             :  */

Generated by: LCOV version 1.10

Generated at Tue, 14 Oct 2014 07:25:56 +0000 (7 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.