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

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_3/sapi/cgi - cgi_main.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 823
Code covered: 50.5 % Executed lines: 416
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:17 +0000 (3 days ago)

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