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: 440 883 49.8 %
Date: 2014-07-27 Functions: 19 31 61.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:42 +0000 (5 days ago)

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