LTP GCOV extension - code coverage report
Current view: directory - sapi/cgi - cgi_main.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 479
Code covered: 48.2 % Executed lines: 231
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 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,v 1.267.2.15.2.32 2007/03/29 18:47:04 pollita Exp $ */
      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                 : #ifdef PHP_WIN32
      36                 : #include "win32/time.h"
      37                 : #include "win32/signal.h"
      38                 : #include <process.h>
      39                 : #endif
      40                 : #if HAVE_SYS_TIME_H
      41                 : #include <sys/time.h>
      42                 : #endif
      43                 : #if HAVE_UNISTD_H
      44                 : #include <unistd.h>
      45                 : #endif
      46                 : #if HAVE_SIGNAL_H
      47                 : #include <signal.h>
      48                 : #endif
      49                 : #if HAVE_SETLOCALE
      50                 : #include <locale.h>
      51                 : #endif
      52                 : #if HAVE_SYS_TYPES_H
      53                 : #include <sys/types.h>
      54                 : #endif
      55                 : #if HAVE_SYS_WAIT_H
      56                 : #include <sys/wait.h>
      57                 : #endif
      58                 : #include "zend.h"
      59                 : #include "zend_extensions.h"
      60                 : #include "php_ini.h"
      61                 : #include "php_globals.h"
      62                 : #include "php_main.h"
      63                 : #include "fopen_wrappers.h"
      64                 : #include "ext/standard/php_standard.h"
      65                 : #ifdef PHP_WIN32
      66                 : #include <io.h>
      67                 : #include <fcntl.h>
      68                 : #include "win32/php_registry.h"
      69                 : #endif
      70                 : 
      71                 : #ifdef __riscos__
      72                 : #include <unixlib/local.h>
      73                 : int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
      74                 : #endif
      75                 : 
      76                 : #include "zend_compile.h"
      77                 : #include "zend_execute.h"
      78                 : #include "zend_highlight.h"
      79                 : #include "zend_indent.h"
      80                 : 
      81                 : #include "php_getopt.h"
      82                 : 
      83                 : #if PHP_FASTCGI
      84                 : #include "fastcgi.h"
      85                 : 
      86                 : #ifndef PHP_WIN32
      87                 : /* XXX this will need to change later when threaded fastcgi is
      88                 :    implemented.  shane */
      89                 : struct sigaction act, old_term, old_quit, old_int;
      90                 : #endif
      91                 : 
      92                 : static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC);
      93                 : 
      94                 : #ifndef PHP_WIN32
      95                 : /* these globals used for forking children on unix systems */
      96                 : /**
      97                 :  * Number of child processes that will get created to service requests
      98                 :  */
      99                 : static int children = 0;
     100                 : 
     101                 : /**
     102                 :  * Set to non-zero if we are the parent process
     103                 :  */
     104                 : static int parent = 1;
     105                 : 
     106                 : /**
     107                 :  * Process group
     108                 :  */
     109                 : static pid_t pgroup;
     110                 : #endif
     111                 : 
     112                 : #endif
     113                 : 
     114                 : #define PHP_MODE_STANDARD       1
     115                 : #define PHP_MODE_HIGHLIGHT      2
     116                 : #define PHP_MODE_INDENT         3
     117                 : #define PHP_MODE_LINT           4
     118                 : #define PHP_MODE_STRIP          5
     119                 : 
     120                 : static char *php_optarg = NULL;
     121                 : static int php_optind = 1;
     122                 : static zend_module_entry cgi_module_entry;
     123                 : 
     124                 : static const opt_struct OPTIONS[] = {
     125                 :         {'a', 0, "interactive"},
     126                 :         {'b', 1, "bindpath"},
     127                 :         {'C', 0, "no-chdir"},
     128                 :         {'c', 1, "php-ini"},
     129                 :         {'d', 1, "define"},
     130                 :         {'e', 0, "profile-info"},
     131                 :         {'f', 1, "file"},
     132                 :         {'h', 0, "help"},
     133                 :         {'i', 0, "info"},
     134                 :         {'l', 0, "syntax-check"},
     135                 :         {'m', 0, "modules"},
     136                 :         {'n', 0, "no-php-ini"},
     137                 :         {'q', 0, "no-header"},
     138                 :         {'s', 0, "syntax-highlight"},
     139                 :         {'s', 0, "syntax-highlighting"},
     140                 :         {'w', 0, "strip"},
     141                 :         {'?', 0, "usage"},/* help alias (both '?' and 'usage') */
     142                 :         {'v', 0, "version"},
     143                 :         {'z', 1, "zend-extension"},
     144                 :         {'-', 0, NULL} /* end of args */
     145                 : };
     146                 : 
     147                 : typedef struct _php_cgi_globals_struct {
     148                 :         zend_bool rfc2616_headers;
     149                 :         zend_bool nph;
     150                 :         zend_bool check_shebang_line;
     151                 : #if ENABLE_PATHINFO_CHECK
     152                 :         zend_bool fix_pathinfo;
     153                 : #endif
     154                 : #if FORCE_CGI_REDIRECT
     155                 :         zend_bool force_redirect;
     156                 :         char *redirect_status_env;
     157                 : #endif
     158                 : #if PHP_FASTCGI
     159                 :         zend_bool fcgi_logging;
     160                 : # ifdef PHP_WIN32
     161                 :         zend_bool impersonate;
     162                 : # endif
     163                 : #endif
     164                 : } php_cgi_globals_struct;
     165                 : 
     166                 : #ifdef ZTS
     167                 : static int php_cgi_globals_id;
     168                 : #define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v)
     169                 : #else
     170                 : static php_cgi_globals_struct php_cgi_globals;
     171                 : #define CGIG(v) (php_cgi_globals.v)
     172                 : #endif
     173                 : 
     174                 : #ifdef PHP_WIN32
     175                 : #define TRANSLATE_SLASHES(path) \
     176                 :         { \
     177                 :                 char *tmp = path; \
     178                 :                 while (*tmp) { \
     179                 :                         if (*tmp == '\\') *tmp = '/'; \
     180                 :                         tmp++; \
     181                 :                 } \
     182                 :         }
     183                 : #else
     184                 : #define TRANSLATE_SLASHES(path)
     185                 : #endif
     186                 : 
     187                 : static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC)
     188               0 : {
     189               0 :         php_printf("%s\n", module->name);
     190               0 :         return 0;
     191                 : }
     192                 : 
     193                 : static int module_name_cmp(const void *a, const void *b TSRMLS_DC)
     194               0 : {
     195               0 :         Bucket *f = *((Bucket **) a);
     196               0 :         Bucket *s = *((Bucket **) b);
     197                 : 
     198               0 :         return strcasecmp(((zend_module_entry *)f->pData)->name,
     199                 :                                           ((zend_module_entry *)s->pData)->name);
     200                 : }
     201                 : 
     202                 : static void print_modules(TSRMLS_D)
     203               0 : {
     204                 :         HashTable sorted_registry;
     205                 :         zend_module_entry tmp;
     206                 : 
     207               0 :         zend_hash_init(&sorted_registry, 50, NULL, NULL, 1);
     208               0 :         zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry));
     209               0 :         zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC);
     210               0 :         zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC);
     211               0 :         zend_hash_destroy(&sorted_registry);
     212               0 : }
     213                 : 
     214                 : static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC)
     215               0 : {
     216               0 :         php_printf("%s\n", ext->name);
     217               0 :         return 0;
     218                 : }
     219                 : 
     220                 : static int extension_name_cmp(const zend_llist_element **f,
     221                 :                                                           const zend_llist_element **s TSRMLS_DC)
     222               0 : {
     223               0 :         return strcmp(((zend_extension *)(*f)->data)->name,
     224                 :                                   ((zend_extension *)(*s)->data)->name);
     225                 : }
     226                 : 
     227                 : static void print_extensions(TSRMLS_D)
     228               0 : {
     229                 :         zend_llist sorted_exts;
     230                 : 
     231               0 :         zend_llist_copy(&sorted_exts, &zend_extensions);
     232               0 :         zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC);
     233               0 :         zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC);
     234               0 :         zend_llist_destroy(&sorted_exts);
     235               0 : }
     236                 : 
     237                 : #ifndef STDOUT_FILENO
     238                 : #define STDOUT_FILENO 1
     239                 : #endif
     240                 : 
     241                 : static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC)
     242            4457 : {
     243                 : #ifdef PHP_WRITE_STDOUT
     244                 :         long ret;
     245                 : #else
     246                 :         size_t ret;
     247                 : #endif
     248                 : 
     249                 : #if PHP_FASTCGI
     250                 :         if (fcgi_is_fastcgi()) {
     251                 :                 fcgi_request *request = (fcgi_request*) SG(server_context);
     252                 :                 long ret = fcgi_write(request, FCGI_STDOUT, str, str_length);
     253                 :                 if (ret <= 0) {
     254                 :                         return 0;
     255                 :                 }
     256                 :                 return ret;
     257                 :         }
     258                 : #endif
     259                 : #ifdef PHP_WRITE_STDOUT
     260            4457 :         ret = write(STDOUT_FILENO, str, str_length);
     261            4457 :         if (ret <= 0) return 0;
     262            4457 :         return ret;
     263                 : #else
     264                 :         ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
     265                 :         return ret;
     266                 : #endif
     267                 : }
     268                 : 
     269                 : static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC)
     270            4477 : {
     271            4477 :         const char *ptr = str;
     272            4477 :         uint remaining = str_length;
     273                 :         size_t ret;
     274                 : 
     275           13411 :         while (remaining > 0) {
     276            4457 :                 ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC);
     277            4457 :                 if (!ret) {
     278               0 :                         php_handle_aborted_connection();
     279               0 :                         return str_length - remaining;
     280                 :                 }
     281            4457 :                 ptr += ret;
     282            4457 :                 remaining -= ret;
     283                 :         }
     284                 : 
     285            4477 :         return str_length;
     286                 : }
     287                 : 
     288                 : 
     289                 : static void sapi_cgibin_flush(void *server_context)
     290             280 : {
     291                 : #if PHP_FASTCGI
     292                 :         if (fcgi_is_fastcgi()) {
     293                 :                 fcgi_request *request = (fcgi_request*) server_context;
     294                 :                 if (
     295                 : #ifndef PHP_WIN32
     296                 :                 !parent && 
     297                 : #endif
     298                 :                 request && !fcgi_flush(request, 0)) {
     299                 :                         php_handle_aborted_connection();
     300                 :                 }
     301                 :                 return;
     302                 :         }
     303                 : #endif
     304             280 :         if (fflush(stdout) == EOF) {
     305               0 :                 php_handle_aborted_connection();
     306                 :         }
     307             280 : }
     308                 : 
     309                 : #define SAPI_CGI_MAX_HEADER_LENGTH 1024
     310                 : 
     311                 : static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
     312             110 : {
     313                 :         char buf[SAPI_CGI_MAX_HEADER_LENGTH];
     314                 :         sapi_header_struct *h;
     315                 :         zend_llist_position pos;
     316                 : 
     317             110 :         if (SG(request_info).no_headers == 1) {
     318               0 :                 return  SAPI_HEADER_SENT_SUCCESSFULLY;
     319                 :         }
     320                 : 
     321             110 :         if (CGIG(nph) || SG(sapi_headers).http_response_code != 200)
     322                 :         {
     323                 :                 int len;
     324                 : 
     325              22 :                 if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
     326               0 :                         len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH,
     327                 :                                                    "%s\r\n", SG(sapi_headers).http_status_line);
     328                 : 
     329               0 :                         if (len > SAPI_CGI_MAX_HEADER_LENGTH) {
     330               0 :                                 len = SAPI_CGI_MAX_HEADER_LENGTH;
     331                 :                         }
     332                 : 
     333                 :                 } else {
     334              22 :                         len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code);
     335                 :                 }
     336                 : 
     337              22 :                 PHPWRITE_H(buf, len);
     338                 :         }
     339                 : 
     340             110 :         h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
     341             546 :         while (h) {
     342                 :                 /* prevent CRLFCRLF */
     343             326 :                 if (h->header_len) {
     344             326 :                         PHPWRITE_H(h->header, h->header_len);
     345             326 :                         PHPWRITE_H("\r\n", 2);
     346                 :                 }
     347             326 :                 h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
     348                 :         }
     349             110 :         PHPWRITE_H("\r\n", 2);
     350                 : 
     351             110 :         return SAPI_HEADER_SENT_SUCCESSFULLY;
     352                 : }
     353                 : 
     354                 : 
     355                 : static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
     356             218 : {
     357             218 :         int read_bytes=0, tmp_read_bytes;
     358                 : 
     359             218 :         count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes));
     360             436 :         while (read_bytes < count_bytes) {
     361                 : #if PHP_FASTCGI
     362                 :                 if (fcgi_is_fastcgi()) {
     363                 :                         fcgi_request *request = (fcgi_request*) SG(server_context);
     364                 :                         tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
     365                 :                 } else {
     366                 :                         tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes);
     367                 :                 }
     368                 : #else
     369               0 :                 tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes);
     370                 : #endif
     371                 : 
     372               0 :                 if (tmp_read_bytes <= 0) {
     373               0 :                         break;
     374                 :                 }
     375               0 :                 read_bytes += tmp_read_bytes;
     376                 :         }
     377             218 :         return read_bytes;
     378                 : }
     379                 : 
     380                 : static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC)
     381            1773 : {
     382                 : #if PHP_FASTCGI
     383                 :         /* when php is started by mod_fastcgi, no regular environment
     384                 :            is provided to PHP.  It is always sent to PHP at the start
     385                 :            of a request.  So we have to do our own lookup to get env
     386                 :            vars.  This could probably be faster somehow.  */
     387                 :         if (fcgi_is_fastcgi()) {
     388                 :                 fcgi_request *request = (fcgi_request*) SG(server_context);
     389                 :                 return fcgi_getenv(request, name, name_len);
     390                 :         }
     391                 : #endif
     392                 :         /*  if cgi, or fastcgi and not found in fcgi env
     393                 :                 check the regular environment */
     394            1773 :         return getenv(name);
     395                 : }
     396                 : 
     397                 : static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC)
     398             216 : {
     399                 :         int name_len;
     400                 : #if !HAVE_SETENV || !HAVE_UNSETENV
     401                 :         int len;
     402                 :         char *buf;
     403                 : #endif
     404                 : 
     405             216 :         if (!name) {
     406               0 :                 return NULL;
     407                 :         }
     408             216 :         name_len = strlen(name);
     409                 : 
     410                 : #if PHP_FASTCGI
     411                 :         /* when php is started by mod_fastcgi, no regular environment
     412                 :            is provided to PHP.  It is always sent to PHP at the start
     413                 :            of a request.  So we have to do our own lookup to get env
     414                 :            vars.  This could probably be faster somehow.  */
     415                 :         if (fcgi_is_fastcgi()) {
     416                 :                 fcgi_request *request = (fcgi_request*) SG(server_context);
     417                 :                 return fcgi_putenv(request, name, name_len, value);
     418                 :         }
     419                 : #endif
     420                 : #if HAVE_SETENV
     421             216 :         if (value) {
     422             108 :                 setenv(name, value, 1);
     423                 :         }
     424                 : #endif
     425                 : #if HAVE_UNSETENV
     426             216 :         if (!value) {
     427             108 :                 unsetenv(name);
     428                 :         }
     429                 : #endif
     430                 : 
     431                 : #if !HAVE_SETENV || !HAVE_UNSETENV
     432                 :         /*  if cgi, or fastcgi and not found in fcgi env
     433                 :                 check the regular environment 
     434                 :                 this leaks, but it's only cgi anyway, we'll fix
     435                 :                 it for 5.0
     436                 :         */
     437                 :         len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2;
     438                 :         buf = (char *) malloc(len);
     439                 :         if (buf == NULL) {
     440                 :                 return getenv(name);
     441                 :         }
     442                 : #endif
     443                 : #if !HAVE_SETENV
     444                 :         if (value) {
     445                 :                 len = slprintf(buf, len - 1, "%s=%s", name, value);
     446                 :                 putenv(buf);
     447                 :         }
     448                 : #endif
     449                 : #if !HAVE_UNSETENV
     450                 :         if (!value) {
     451                 :                 len = slprintf(buf, len - 1, "%s=", name);
     452                 :                 putenv(buf);
     453                 :         }
     454                 : #endif
     455             216 :         return getenv(name);
     456                 : }
     457                 : 
     458                 : static char *sapi_cgi_read_cookies(TSRMLS_D)
     459             218 : {
     460             218 :         return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC);
     461                 : }
     462                 : 
     463                 : #if PHP_FASTCGI
     464                 : void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
     465                 : {
     466                 :         if (PG(http_globals)[TRACK_VARS_ENV] &&
     467                 :             array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
     468                 :             Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
     469                 :             zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0) {
     470                 :             zval_dtor(array_ptr);
     471                 :             *array_ptr = *PG(http_globals)[TRACK_VARS_ENV];
     472                 :             INIT_PZVAL(array_ptr);
     473                 :             zval_copy_ctor(array_ptr);
     474                 :             return;
     475                 :         } else if (PG(http_globals)[TRACK_VARS_SERVER] &&
     476                 :                 array_ptr != PG(http_globals)[TRACK_VARS_SERVER] &&
     477                 :             Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY &&
     478                 :             zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0) {
     479                 :             zval_dtor(array_ptr);
     480                 :             *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER];
     481                 :             INIT_PZVAL(array_ptr);
     482                 :             zval_copy_ctor(array_ptr);
     483                 :             return;
     484                 :         }
     485                 :         
     486                 :         /* call php's original import as a catch-all */
     487                 :         php_php_import_environment_variables(array_ptr TSRMLS_CC);
     488                 : 
     489                 :         if (fcgi_is_fastcgi()) {
     490                 :                 fcgi_request *request = (fcgi_request*) SG(server_context);
     491                 :                 HashPosition pos;
     492                 :                 int magic_quotes_gpc = PG(magic_quotes_gpc);
     493                 :                 char *var, **val;
     494                 :                 uint var_len;
     495                 :                 ulong idx;
     496                 :                 int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
     497                 : 
     498                 :                 /* turn off magic_quotes while importing environment variables */
     499                 :                 PG(magic_quotes_gpc) = 0;
     500                 :                 for (zend_hash_internal_pointer_reset_ex(&request->env, &pos);
     501                 :                      zend_hash_get_current_key_ex(&request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING &&
     502                 :                      zend_hash_get_current_data_ex(&request->env, (void **) &val, &pos) == SUCCESS;
     503                 :                      zend_hash_move_forward_ex(&request->env, &pos)) {
     504                 :                         unsigned int new_val_len;
     505                 :                         if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) {
     506                 :                                 php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC);
     507                 :                         }
     508                 :                 }
     509                 :                 PG(magic_quotes_gpc) = magic_quotes_gpc;
     510                 :         }
     511                 : }
     512                 : #endif
     513                 : 
     514                 : static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
     515             218 : {
     516                 :         unsigned int new_val_len;
     517             218 :         char *val = SG(request_info).request_uri ? SG(request_info).request_uri : "";
     518                 :         /* In CGI mode, we consider the environment to be a part of the server
     519                 :          * variables
     520                 :          */
     521             218 :         php_import_environment_variables(track_vars_array TSRMLS_CC);
     522                 :         /* Build the special-case PHP_SELF variable for the CGI version */
     523             218 :         if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &val, strlen(val), &new_val_len TSRMLS_CC)) {
     524             218 :                 php_register_variable_safe("PHP_SELF", val, new_val_len, track_vars_array TSRMLS_CC);
     525                 :         }
     526             218 : }
     527                 : 
     528                 : static void sapi_cgi_log_message(char *message)
     529               0 : {
     530                 : #if PHP_FASTCGI
     531                 :         TSRMLS_FETCH();
     532                 : 
     533                 :         if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) {
     534                 :                 fcgi_request *request;
     535                 :                 
     536                 :                 request = (fcgi_request*) SG(server_context);
     537                 :                 if (request) {                  
     538                 :                         int len = strlen(message);
     539                 :                         char *buf = malloc(len+2);
     540                 : 
     541                 :                         memcpy(buf, message, len);
     542                 :                         memcpy(buf + len, "\n", sizeof("\n"));
     543                 :                         fcgi_write(request, FCGI_STDERR, buf, len+1);
     544                 :                         free(buf);
     545                 :                 } else {
     546                 :                         fprintf(stderr, "%s\n", message);
     547                 :                 }
     548                 :                 /* ignore return code */
     549                 :         } else
     550                 : #endif /* PHP_FASTCGI */
     551               0 :         fprintf(stderr, "%s\n", message);
     552               0 : }
     553                 : 
     554                 : static int sapi_cgi_deactivate(TSRMLS_D)
     555             437 : {
     556                 :         /* flush only when SAPI was started. The reasons are:
     557                 :                 1. SAPI Deactivate is called from two places: module init and request shutdown
     558                 :                 2. When the first call occurs and the request is not set up, flush fails on 
     559                 :                         FastCGI.
     560                 :         */
     561             437 :         if (SG(sapi_started)) {
     562               0 :                 sapi_cgibin_flush(SG(server_context));
     563                 :         }
     564             437 :         return SUCCESS;
     565                 : }
     566                 : 
     567                 : static int php_cgi_startup(sapi_module_struct *sapi_module)
     568             219 : {
     569             219 :         if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
     570               0 :                 return FAILURE;
     571                 :         }
     572             219 :         return SUCCESS;
     573                 : }
     574                 : 
     575                 : 
     576                 : /* {{{ sapi_module_struct cgi_sapi_module
     577                 :  */
     578                 : static sapi_module_struct cgi_sapi_module = {
     579                 : #if PHP_FASTCGI
     580                 :         "cgi-fcgi",                                           /* name */
     581                 :         "CGI/FastCGI",                                        /* pretty name */
     582                 : #else
     583                 :         "cgi",                                                        /* name */
     584                 :         "CGI",                                                        /* pretty name */
     585                 : #endif
     586                 : 
     587                 :         php_cgi_startup,                                /* startup */
     588                 :         php_module_shutdown_wrapper,    /* shutdown */
     589                 : 
     590                 :         NULL,                                                   /* activate */
     591                 :         sapi_cgi_deactivate,                    /* deactivate */
     592                 : 
     593                 :         sapi_cgibin_ub_write,                   /* unbuffered write */
     594                 :         sapi_cgibin_flush,                              /* flush */
     595                 :         NULL,                                                   /* get uid */
     596                 :         sapi_cgibin_getenv,                             /* getenv */
     597                 : 
     598                 :         php_error,                                              /* error handler */
     599                 : 
     600                 :         NULL,                                                   /* header handler */
     601                 :         sapi_cgi_send_headers,                  /* send headers handler */
     602                 :         NULL,                                                   /* send header handler */
     603                 : 
     604                 :         sapi_cgi_read_post,                             /* read POST data */
     605                 :         sapi_cgi_read_cookies,                  /* read Cookies */
     606                 : 
     607                 :         sapi_cgi_register_variables,    /* register server variables */
     608                 :         sapi_cgi_log_message,                   /* Log message */
     609                 :         NULL,                                                   /* Get request time */
     610                 : 
     611                 :         STANDARD_SAPI_MODULE_PROPERTIES
     612                 : };
     613                 : /* }}} */
     614                 : 
     615                 : /* {{{ php_cgi_usage
     616                 :  */
     617                 : static void php_cgi_usage(char *argv0)
     618               1 : {
     619                 :         char *prog;
     620                 : 
     621               1 :         prog = strrchr(argv0, '/');
     622               1 :         if (prog) {
     623               1 :                 prog++;
     624                 :         } else {
     625               0 :                 prog = "php";
     626                 :         }
     627                 : 
     628               1 :         php_printf("Usage: %s [-q] [-h] [-s] [-v] [-i] [-f <file>]\n"
     629                 :                            "       %s <file> [args...]\n"
     630                 :                            "  -a               Run interactively\n"
     631                 : #if PHP_FASTCGI
     632                 :                            "  -b <address:port>|<port> Bind Path for external FASTCGI Server mode\n"
     633                 : #endif
     634                 :                            "  -C               Do not chdir to the script's directory\n"
     635                 :                            "  -c <path>|<file> Look for php.ini file in this directory\n"
     636                 :                            "  -n               No php.ini file will be used\n"
     637                 :                            "  -d foo[=bar]     Define INI entry foo with value 'bar'\n"
     638                 :                            "  -e               Generate extended information for debugger/profiler\n"
     639                 :                            "  -f <file>        Parse <file>.  Implies `-q'\n"
     640                 :                            "  -h               This help\n"
     641                 :                            "  -i               PHP information\n"
     642                 :                            "  -l               Syntax check only (lint)\n"
     643                 :                            "  -m               Show compiled in modules\n"
     644                 :                            "  -q               Quiet-mode.  Suppress HTTP Header output.\n"
     645                 :                            "  -s               Display colour syntax highlighted source.\n"
     646                 :                            "  -v               Version number\n"
     647                 :                            "  -w               Display source with stripped comments and whitespace.\n"
     648                 :                            "  -z <file>        Load Zend extension <file>.\n",
     649                 :                            prog, prog);
     650               1 : }
     651                 : /* }}} */
     652                 : 
     653                 : /* {{{ init_request_info
     654                 : 
     655                 :   initializes request_info structure
     656                 : 
     657                 :   specificly in this section we handle proper translations
     658                 :   for:
     659                 : 
     660                 :   PATH_INFO
     661                 :         derived from the portion of the URI path following 
     662                 :         the script name but preceding any query data
     663                 :         may be empty
     664                 : 
     665                 :   PATH_TRANSLATED
     666                 :     derived by taking any path-info component of the 
     667                 :         request URI and performing any virtual-to-physical 
     668                 :         translation appropriate to map it onto the server's 
     669                 :         document repository structure
     670                 : 
     671                 :         empty if PATH_INFO is empty
     672                 : 
     673                 :         The env var PATH_TRANSLATED **IS DIFFERENT** than the
     674                 :         request_info.path_translated variable, the latter should
     675                 :         match SCRIPT_FILENAME instead.
     676                 : 
     677                 :   SCRIPT_NAME
     678                 :     set to a URL path that could identify the CGI script
     679                 :         rather than the interpreter.  PHP_SELF is set to this.
     680                 : 
     681                 :   REQUEST_URI
     682                 :     uri section following the domain:port part of a URI
     683                 : 
     684                 :   SCRIPT_FILENAME
     685                 :     The virtual-to-physical translation of SCRIPT_NAME (as per 
     686                 :         PATH_TRANSLATED)
     687                 : 
     688                 :   These settings are documented at
     689                 :   http://cgi-spec.golux.com/
     690                 : 
     691                 : 
     692                 :   Based on the following URL request:
     693                 :   
     694                 :   http://localhost/info.php/test?a=b 
     695                 :  
     696                 :   should produce, which btw is the same as if
     697                 :   we were running under mod_cgi on apache (ie. not
     698                 :   using ScriptAlias directives):
     699                 :  
     700                 :   PATH_INFO=/test
     701                 :   PATH_TRANSLATED=/docroot/test
     702                 :   SCRIPT_NAME=/info.php
     703                 :   REQUEST_URI=/info.php/test?a=b
     704                 :   SCRIPT_FILENAME=/docroot/info.php
     705                 :   QUERY_STRING=a=b
     706                 :  
     707                 :   but what we get is (cgi/mod_fastcgi under apache):
     708                 :   
     709                 :   PATH_INFO=/info.php/test
     710                 :   PATH_TRANSLATED=/docroot/info.php/test
     711                 :   SCRIPT_NAME=/php/php-cgi  (from the Action setting I suppose)
     712                 :   REQUEST_URI=/info.php/test?a=b
     713                 :   SCRIPT_FILENAME=/path/to/php/bin/php-cgi  (Action setting translated)
     714                 :   QUERY_STRING=a=b
     715                 :  
     716                 :   Comments in the code below refer to using the above URL in a request
     717                 : 
     718                 :  */
     719                 : static void init_request_info(TSRMLS_D)
     720             218 : {
     721             218 :         char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC);
     722             218 :         char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC);
     723             218 :         char *script_path_translated = env_script_filename;
     724                 : 
     725                 : #if !DISCARD_PATH
     726                 :         /* some broken servers do not have script_filename or argv0
     727                 :            an example, IIS configured in some ways.  then they do more
     728                 :            broken stuff and set path_translated to the cgi script location */
     729             218 :         if (!script_path_translated && env_path_translated) {
     730               0 :                 script_path_translated = env_path_translated;
     731                 :         }
     732                 : #endif
     733                 : 
     734                 :         /* initialize the defaults */
     735             218 :         SG(request_info).path_translated = NULL;
     736             218 :         SG(request_info).request_method = NULL;
     737             218 :         SG(request_info).proto_num = 1000;
     738             218 :         SG(request_info).query_string = NULL;
     739             218 :         SG(request_info).request_uri = NULL;
     740             218 :         SG(request_info).content_type = NULL;
     741             218 :         SG(request_info).content_length = 0;
     742             218 :         SG(sapi_headers).http_response_code = 200;
     743                 : 
     744                 :         /* script_path_translated being set is a good indication that
     745                 :            we are running in a cgi environment, since it is always
     746                 :            null otherwise.  otherwise, the filename
     747                 :            of the script will be retreived later via argc/argv */
     748             218 :         if (script_path_translated) {
     749                 :                 const char *auth;
     750             108 :                 char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1 TSRMLS_CC);
     751             108 :                 char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC);
     752             108 :                 char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
     753             108 :                 char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC);
     754                 : #if ENABLE_PATHINFO_CHECK
     755                 :                 struct stat st;
     756             108 :                 char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC);
     757             108 :                 char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
     758                 : 
     759             108 :                 if (CGIG(fix_pathinfo)) {
     760                 :                         char *real_path;
     761             108 :                         char *orig_path_translated = env_path_translated;
     762             108 :                         char *orig_path_info = env_path_info;
     763             108 :                         char *orig_script_name = env_script_name;
     764             108 :                         char *orig_script_filename = env_script_filename;
     765                 : 
     766             108 :                         if (!env_document_root && PG(doc_root)) {
     767               0 :                                 env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root) TSRMLS_CC);
     768                 :                                 /* fix docroot */
     769                 :                                 TRANSLATE_SLASHES(env_document_root);
     770                 :                         }
     771                 : 
     772             108 :                         if (env_path_translated != NULL && env_redirect_url != NULL) {
     773                 :                                 /* 
     774                 :                                    pretty much apache specific.  If we have a redirect_url
     775                 :                                    then our script_filename and script_name point to the
     776                 :                                    php executable
     777                 :                                 */
     778               0 :                                 script_path_translated = env_path_translated;
     779                 :                                 /* we correct SCRIPT_NAME now in case we don't have PATH_INFO */
     780               0 :                                 env_script_name = env_redirect_url;
     781                 :                         }
     782                 : 
     783                 : #ifdef __riscos__
     784                 :                         /* Convert path to unix format*/
     785                 :                         __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR;
     786                 :                         script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0);
     787                 : #endif
     788                 :                         
     789                 :                         /*
     790                 :                          * if the file doesn't exist, try to extract PATH_INFO out
     791                 :                          * of it by stat'ing back through the '/'
     792                 :                          * this fixes url's like /info.php/test
     793                 :                          */
     794             108 :                         if (script_path_translated &&
     795                 :                             (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL) {
     796               0 :                                 char *pt = estrdup(script_path_translated);
     797               0 :                                 int len = strlen(pt);
     798                 :                                 char *ptr;
     799                 : 
     800               0 :                                 while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) {
     801               0 :                                         *ptr = 0;
     802               0 :                                         if (stat(pt, &st) == 0 && S_ISREG(st.st_mode)) {
     803                 :                                                 /*
     804                 :                                                  * okay, we found the base script!
     805                 :                                                  * work out how many chars we had to strip off;
     806                 :                                                  * then we can modify PATH_INFO
     807                 :                                                  * accordingly
     808                 :                                                  *
     809                 :                                                  * we now have the makings of
     810                 :                                                  * PATH_INFO=/test
     811                 :                                                  * SCRIPT_FILENAME=/docroot/info.php
     812                 :                                                  *
     813                 :                                                  * we now need to figure out what docroot is.
     814                 :                                                  * if DOCUMENT_ROOT is set, this is easy, otherwise,
     815                 :                                                  * we have to play the game of hide and seek to figure
     816                 :                                                  * out what SCRIPT_NAME should be
     817                 :                                                  */
     818               0 :                                                 int slen = len - strlen(pt);
     819               0 :                                                 int pilen = strlen(env_path_info);
     820               0 :                                                 char *path_info = env_path_info + pilen - slen;
     821                 : 
     822               0 :                                                 if (orig_path_info != path_info) {
     823               0 :                                                         if (orig_path_info) {
     824               0 :                                                                 _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
     825                 :                                                         }
     826               0 :                                                         env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC);
     827                 :                                                 }
     828               0 :                                                 if (!orig_script_filename ||
     829                 :                                                         strcmp(orig_script_filename, pt) != 0) {
     830               0 :                                                         if (orig_script_filename) {
     831               0 :                                                                 _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
     832                 :                                                         }
     833               0 :                                                         script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC);
     834                 :                                                 }
     835                 :                                                 TRANSLATE_SLASHES(pt);
     836                 : 
     837                 :                                                 /* figure out docroot
     838                 :                                                    SCRIPT_FILENAME minus SCRIPT_NAME
     839                 :                                                 */
     840                 : 
     841               0 :                                                 if (env_document_root)
     842                 :                                                 {
     843               0 :                                                         int l = strlen(env_document_root);
     844               0 :                                                         int path_translated_len = 0;
     845               0 :                                                         char *path_translated = NULL;
     846                 :                                                         
     847               0 :                                                         if (l && env_document_root[l - 1] == '/') {
     848               0 :                                                                 --l;
     849                 :                                                         }
     850                 : 
     851                 :                                                         /* we have docroot, so we should have:
     852                 :                                                          * DOCUMENT_ROOT=/docroot
     853                 :                                                          * SCRIPT_FILENAME=/docroot/info.php
     854                 :                                                          *
     855                 :                                                          * SCRIPT_NAME is the portion of the path beyond docroot
     856                 :                                                          */
     857               0 :                                                         env_script_name = pt + l;
     858                 : 
     859                 :                                                         /* PATH_TRANSATED = DOCUMENT_ROOT + PATH_INFO */
     860               0 :                                                         path_translated_len = l + strlen(env_path_info);
     861               0 :                                                         path_translated = (char *) emalloc(path_translated_len + 1);
     862               0 :                                                         memcpy(path_translated, env_document_root, l);
     863               0 :                                                         memcpy(path_translated + l, env_path_info, (path_translated_len - l));
     864               0 :                                                         path_translated[path_translated_len] = '\0';
     865               0 :                                                         if (orig_path_translated) {
     866               0 :                                                                 _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
     867                 :                                                         }
     868               0 :                                                         env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
     869               0 :                                                         efree(path_translated);
     870               0 :                                                 } else if (env_script_name && 
     871                 :                                                                    strstr(pt, env_script_name)
     872                 :                                                 ) {
     873                 :                                                         /* PATH_TRANSATED = PATH_TRANSATED - SCRIPT_NAME + PATH_INFO */
     874               0 :                                                         int ptlen = strlen(pt) - strlen(env_script_name);
     875               0 :                                                         int path_translated_len = ptlen + strlen(env_path_info);
     876               0 :                                                         char *path_translated = NULL;
     877                 : 
     878               0 :                                                         path_translated = (char *) emalloc(path_translated_len + 1);
     879               0 :                                                         memcpy(path_translated, pt, ptlen);
     880               0 :                                                         memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen);
     881               0 :                                                         path_translated[path_translated_len] = '\0';
     882               0 :                                                         if (orig_path_translated) {
     883               0 :                                                                 _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
     884                 :                                                         }
     885               0 :                                                         env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
     886               0 :                                                         efree(path_translated);
     887                 :                                                 }
     888               0 :                                                 break;
     889                 :                                         }
     890                 :                                 }
     891               0 :                                 if (!ptr) {
     892                 :                                         /*
     893                 :                                          * if we stripped out all the '/' and still didn't find
     894                 :                                          * a valid path... we will fail, badly. of course we would
     895                 :                                          * have failed anyway... we output 'no input file' now.
     896                 :                                          */
     897               0 :                                         if (orig_script_filename) {
     898               0 :                                                 _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
     899                 :                                         }
     900               0 :                                         script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC);
     901               0 :                                         SG(sapi_headers).http_response_code = 404;
     902                 :                                 }
     903               0 :                                 if (!orig_script_name ||
     904                 :                                         strcmp(orig_script_name, env_script_name) != 0) {
     905               0 :                                         if (orig_script_name) {
     906               0 :                                                 _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
     907                 :                                         }
     908               0 :                                         SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
     909                 :                                 } else {
     910               0 :                                         SG(request_info).request_uri = orig_script_name;
     911                 :                                 }
     912               0 :                                 if (pt) {
     913               0 :                                         efree(pt);
     914                 :                                 }
     915                 :                         } else {
     916                 :                                 /* make sure path_info/translated are empty */
     917             108 :                                 if (!orig_script_filename ||
     918                 :                                         (script_path_translated != orig_script_filename) ||
     919                 :                                         strcmp(script_path_translated, orig_script_filename) != 0) {
     920               0 :                                         if (orig_script_filename) {
     921               0 :                                                 _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
     922                 :                                         }
     923               0 :                                         script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC);
     924                 :                                 }
     925             108 :                                 if (orig_path_info) {
     926               0 :                                         _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
     927               0 :                                         _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC);
     928                 :                                 }
     929             108 :                                 if (orig_path_translated) {
     930             108 :                                         _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
     931             108 :                                         _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC);
     932                 :                                 }
     933             108 :                                 if (env_script_name != orig_script_name) {
     934               0 :                                         if (orig_script_name) {
     935               0 :                                                 _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
     936                 :                                         }
     937               0 :                                         SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
     938                 :                                 } else {
     939             108 :                                         SG(request_info).request_uri = env_script_name;
     940                 :                                 }
     941                 :                         }                       
     942             108 :                         free(real_path);
     943                 :                 } else {
     944                 : #endif
     945                 :                         /* pre 4.3 behaviour, shouldn't be used but provides BC */
     946               0 :                         if (env_path_info) {
     947               0 :                                 SG(request_info).request_uri = env_path_info;
     948                 :                         } else {
     949               0 :                                 SG(request_info).request_uri = env_script_name;
     950                 :                         }
     951                 : #if !DISCARD_PATH
     952               0 :                         if (env_path_translated)
     953               0 :                                 script_path_translated = env_path_translated;
     954                 : #endif
     955                 : #if ENABLE_PATHINFO_CHECK
     956                 :                 }
     957                 : #endif
     958             108 :                 SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC);
     959                 :                 /* FIXME - Work out proto_num here */
     960             108 :                 SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC);
     961                 :                 /* some server configurations allow '..' to slip through in the
     962                 :                    translated path.   We'll just refuse to handle such a path. */
     963             108 :                 if (script_path_translated && !strstr(script_path_translated, "..")) {
     964             108 :                         SG(request_info).path_translated = estrdup(script_path_translated);
     965                 :                 }
     966             108 :                 SG(request_info).content_type = (content_type ? content_type : "" );
     967             108 :                 SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
     968                 :                 
     969                 :                 /* The CGI RFC allows servers to pass on unvalidated Authorization data */
     970             108 :                 auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC);
     971             108 :                 php_handle_auth_data(auth TSRMLS_CC);
     972                 :         }
     973             218 : }
     974                 : /* }}} */
     975                 : 
     976                 : #if PHP_FASTCGI
     977                 : /**
     978                 :  * Clean up child processes upon exit
     979                 :  */
     980                 : void fastcgi_cleanup(int signal)
     981                 : {
     982                 : #ifdef DEBUG_FASTCGI
     983                 :         fprintf(stderr, "FastCGI shutdown, pid %d\n", getpid());
     984                 : #endif
     985                 : 
     986                 : #ifndef PHP_WIN32
     987                 :         sigaction(SIGTERM, &old_term, 0);
     988                 : 
     989                 :         /* Kill all the processes in our process group */
     990                 :         kill(-pgroup, SIGTERM);
     991                 : #endif
     992                 : 
     993                 :         /* We should exit at this point, but MacOSX doesn't seem to */
     994                 :         exit(0);
     995                 : }
     996                 : #endif
     997                 : 
     998                 : PHP_INI_BEGIN()
     999                 :         STD_PHP_INI_ENTRY("cgi.rfc2616_headers",     "0",  PHP_INI_ALL,    OnUpdateBool,   rfc2616_headers, php_cgi_globals_struct, php_cgi_globals)
    1000                 :         STD_PHP_INI_ENTRY("cgi.nph",                 "0",  PHP_INI_ALL,    OnUpdateBool,   nph, php_cgi_globals_struct, php_cgi_globals)
    1001                 :         STD_PHP_INI_ENTRY("cgi.check_shebang_line",  "1",  PHP_INI_SYSTEM, OnUpdateBool,   check_shebang_line, php_cgi_globals_struct, php_cgi_globals)
    1002                 : #if FORCE_CGI_REDIRECT
    1003                 :         STD_PHP_INI_ENTRY("cgi.force_redirect",      "1",  PHP_INI_SYSTEM, OnUpdateBool,   force_redirect, php_cgi_globals_struct, php_cgi_globals)
    1004                 :         STD_PHP_INI_ENTRY("cgi.redirect_status_env", NULL, PHP_INI_SYSTEM, OnUpdateString, redirect_status_env, php_cgi_globals_struct, php_cgi_globals)
    1005                 : #endif
    1006                 : #if ENABLE_PATHINFO_CHECK
    1007                 :         STD_PHP_INI_ENTRY("cgi.fix_pathinfo",        "1",  PHP_INI_SYSTEM, OnUpdateBool,   fix_pathinfo, php_cgi_globals_struct, php_cgi_globals)
    1008                 : #endif
    1009                 : #if PHP_FASTCGI
    1010                 :         STD_PHP_INI_ENTRY("fastcgi.logging",         "1",  PHP_INI_SYSTEM, OnUpdateBool,   fcgi_logging, php_cgi_globals_struct, php_cgi_globals)
    1011                 : # ifdef PHP_WIN32
    1012                 :         STD_PHP_INI_ENTRY("fastcgi.impersonate",     "0",  PHP_INI_SYSTEM, OnUpdateBool,   impersonate, php_cgi_globals_struct, php_cgi_globals)
    1013                 : # endif
    1014                 : #endif
    1015                 : PHP_INI_END()
    1016                 : 
    1017                 : /* {{{ php_cgi_globals_ctor
    1018                 :  */
    1019                 : static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC)
    1020             219 : {
    1021             219 :         php_cgi_globals->rfc2616_headers = 0;
    1022             219 :         php_cgi_globals->nph = 0;
    1023             219 :         php_cgi_globals->check_shebang_line = 1;
    1024                 : #if FORCE_CGI_REDIRECT
    1025                 :         php_cgi_globals->force_redirect = 1;
    1026                 :         php_cgi_globals->redirect_status_env = NULL;
    1027                 : #endif
    1028                 : #if ENABLE_PATHINFO_CHECK
    1029             219 :         php_cgi_globals->fix_pathinfo = 1;
    1030                 : #endif
    1031                 : #if PHP_FASTCGI
    1032                 :         php_cgi_globals->fcgi_logging = 1;
    1033                 : # ifdef PHP_WIN32
    1034                 :         php_cgi_globals->impersonate = 0;
    1035                 : # endif
    1036                 : #endif
    1037             219 : }
    1038                 : /* }}} */
    1039                 : 
    1040                 : /* {{{ PHP_MINIT_FUNCTION
    1041                 :  */
    1042                 : static PHP_MINIT_FUNCTION(cgi)
    1043             219 : {
    1044                 : #ifdef ZTS
    1045                 :         ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL);
    1046                 : #else
    1047             219 :         php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC);
    1048                 : #endif
    1049             219 :         REGISTER_INI_ENTRIES();
    1050             219 :         return SUCCESS;
    1051                 : }
    1052                 : /* }}} */
    1053                 : 
    1054                 : /* {{{ PHP_MSHUTDOWN_FUNCTION
    1055                 :  */
    1056                 : static PHP_MSHUTDOWN_FUNCTION(cgi)
    1057             218 : {
    1058             218 :         UNREGISTER_INI_ENTRIES();
    1059             218 :         return SUCCESS;
    1060                 : }
    1061                 : /* }}} */
    1062                 : 
    1063                 : /* {{{ PHP_MINFO_FUNCTION
    1064                 :  */
    1065                 : static PHP_MINFO_FUNCTION(cgi)
    1066               0 : {
    1067               0 :         DISPLAY_INI_ENTRIES();
    1068               0 : }
    1069                 : /* }}} */
    1070                 : 
    1071                 : static zend_module_entry cgi_module_entry = {
    1072                 :         STANDARD_MODULE_HEADER,
    1073                 : #if PHP_FASTCGI
    1074                 :         "cgi-fcgi",
    1075                 : #else
    1076                 :         "cgi",
    1077                 : #endif
    1078                 :         NULL, 
    1079                 :         PHP_MINIT(cgi), 
    1080                 :         PHP_MSHUTDOWN(cgi), 
    1081                 :         NULL, 
    1082                 :         NULL, 
    1083                 :         PHP_MINFO(cgi), 
    1084                 :         NO_VERSION_YET,
    1085                 :         STANDARD_MODULE_PROPERTIES
    1086                 : };
    1087                 : 
    1088                 : /* {{{ main
    1089                 :  */
    1090                 : int main(int argc, char *argv[])
    1091             219 : {
    1092             219 :         int free_query_string = 0;
    1093             219 :         int exit_status = SUCCESS;
    1094             219 :         int cgi = 0, c, i, len;
    1095                 :         zend_file_handle file_handle;
    1096             219 :         int retval = FAILURE;
    1097                 :         char *s;
    1098                 : /* temporary locals */
    1099             219 :         int behavior = PHP_MODE_STANDARD;
    1100             219 :         int no_headers = 0;
    1101             219 :         int orig_optind = php_optind;
    1102             219 :         char *orig_optarg = php_optarg;
    1103             219 :         char *script_file = NULL;
    1104             219 :         int ini_entries_len = 0;
    1105                 : 
    1106                 : /* end of temporary locals */
    1107                 : #ifdef ZTS
    1108                 :         zend_compiler_globals *compiler_globals;
    1109                 :         zend_executor_globals *executor_globals;
    1110                 :         php_core_globals *core_globals;
    1111                 :         sapi_globals_struct *sapi_globals;
    1112                 :         void ***tsrm_ls;
    1113                 : #endif
    1114                 : 
    1115                 : #if PHP_FASTCGI
    1116                 :         int max_requests = 500;
    1117                 :         int requests = 0;
    1118                 :         int fastcgi = fcgi_is_fastcgi();
    1119                 :         char *bindpath = NULL;
    1120                 :         int fcgi_fd = 0;
    1121                 :         fcgi_request request;
    1122                 : #ifndef PHP_WIN32
    1123                 :         int status = 0;
    1124                 : #endif
    1125                 : #endif /* PHP_FASTCGI */
    1126                 : 
    1127                 : #if 0 && defined(PHP_DEBUG)
    1128                 :         /* IIS is always making things more difficult.  This allows
    1129                 :            us to stop PHP and attach a debugger before much gets started */
    1130                 :         {
    1131                 :                 char szMessage [256];
    1132                 :                 wsprintf (szMessage, "Please attach a debugger to the process 0x%X [%d] (%s) and click OK",
    1133                 :                           GetCurrentProcessId(), GetCurrentProcessId(), argv[0]);
    1134                 :                 MessageBox(NULL, szMessage, "CGI Debug Time!", MB_OK|MB_SERVICE_NOTIFICATION);
    1135                 :         }
    1136                 : #endif
    1137                 : 
    1138                 : #ifdef HAVE_SIGNAL_H
    1139                 : #if defined(SIGPIPE) && defined(SIG_IGN)
    1140             219 :         signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
    1141                 :                                                                 that sockets created via fsockopen()
    1142                 :                                                                 don't kill PHP if the remote site
    1143                 :                                                                 closes it.  in apache|apxs mode apache
    1144                 :                                                                 does that for us!  thies@thieso.net
    1145                 :                                                                 20000419 */
    1146                 : #endif
    1147                 : #endif
    1148                 : 
    1149                 : #ifdef ZTS
    1150                 :         tsrm_startup(1, 1, 0, NULL);
    1151                 : #endif
    1152                 : 
    1153             219 :         sapi_startup(&cgi_sapi_module);
    1154                 : 
    1155                 : #ifdef PHP_WIN32
    1156                 :         _fmode = _O_BINARY; /* sets default for file streams to binary */
    1157                 :         setmode(_fileno(stdin),  O_BINARY);     /* make the stdio mode be binary */
    1158                 :         setmode(_fileno(stdout), O_BINARY);     /* make the stdio mode be binary */
    1159                 :         setmode(_fileno(stderr), O_BINARY);     /* make the stdio mode be binary */
    1160                 : #endif
    1161                 : 
    1162                 : #if PHP_FASTCGI
    1163                 :         if (!fastcgi) {
    1164                 : #endif
    1165                 :         /* Make sure we detect we are a cgi - a bit redundancy here,
    1166                 :            but the default case is that we have to check only the first one. */
    1167             219 :         if (getenv("SERVER_SOFTWARE") ||
    1168                 :                 getenv("SERVER_NAME") ||
    1169                 :                 getenv("GATEWAY_INTERFACE") ||
    1170                 :                 getenv("REQUEST_METHOD")
    1171                 :         ) {
    1172             108 :                 cgi = 1;
    1173                 :         }
    1174                 : #if PHP_FASTCGI
    1175                 :         }
    1176                 : #endif
    1177                 : 
    1178            5017 :         while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) {
    1179            4579 :                 switch (c) {
    1180                 :                         case 'c':
    1181               0 :                                 cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
    1182               0 :                                 break;
    1183                 :                         case 'n':
    1184               0 :                                 cgi_sapi_module.php_ini_ignore = 1;
    1185               0 :                                 break;
    1186                 :                         case 'd': { 
    1187                 :                                 /* define ini entries on command line */
    1188            4362 :                                 int len = strlen(php_optarg);
    1189                 :                                 char *val;
    1190                 : 
    1191            4362 :                                 if ((val = strchr(php_optarg, '='))) {
    1192            4362 :                                         val++;
    1193            4582 :                                         if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
    1194             220 :                                                 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
    1195             220 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
    1196             220 :                                                 ini_entries_len += (val - php_optarg);
    1197             220 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1);
    1198             220 :                                                 ini_entries_len++;
    1199             220 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg));
    1200             220 :                                                 ini_entries_len += len - (val - php_optarg);
    1201             220 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
    1202             220 :                                                 ini_entries_len += sizeof("\n\0\"") - 2;
    1203                 :                                         } else {
    1204            4142 :                                                 cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0"));
    1205            4142 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
    1206            4142 :                                                 memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
    1207            4142 :                                                 ini_entries_len += len + sizeof("\n\0") - 2;
    1208                 :                                         }
    1209                 :                                 } else {
    1210               0 :                                         cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
    1211               0 :                                         memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
    1212               0 :                                         memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
    1213               0 :                                         ini_entries_len += len + sizeof("=1\n\0") - 2;
    1214                 :                                 }
    1215                 :                                 break;
    1216                 :                         }
    1217                 : #if PHP_FASTCGI
    1218                 :                         /* if we're started on command line, check to see if
    1219                 :                            we are being started as an 'external' fastcgi
    1220                 :                            server by accepting a bindpath parameter. */
    1221                 :                         case 'b':
    1222                 :                                 if (!fastcgi) {
    1223                 :                                         bindpath = strdup(php_optarg);
    1224                 :                                 }
    1225                 :                                 break;
    1226                 : #endif
    1227                 :                 }
    1228                 : 
    1229                 :         }
    1230             219 :         php_optind = orig_optind;
    1231             219 :         php_optarg = orig_optarg;
    1232                 : 
    1233                 : #ifdef ZTS
    1234                 :         compiler_globals = ts_resource(compiler_globals_id);
    1235                 :         executor_globals = ts_resource(executor_globals_id);
    1236                 :         core_globals = ts_resource(core_globals_id);
    1237                 :         sapi_globals = ts_resource(sapi_globals_id);
    1238                 :         tsrm_ls = ts_resource(0);
    1239                 :         SG(request_info).path_translated = NULL;
    1240                 : #endif
    1241                 : 
    1242             219 :         cgi_sapi_module.executable_location = argv[0];
    1243                 : 
    1244                 :         /* startup after we get the above ini override se we get things right */
    1245             219 :         if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) {
    1246                 : #ifdef ZTS
    1247                 :                 tsrm_shutdown();
    1248                 : #endif
    1249               0 :                 return FAILURE;
    1250                 :         }
    1251                 : 
    1252                 : #if FORCE_CGI_REDIRECT
    1253                 :         /* check force_cgi after startup, so we have proper output */
    1254                 :         if (cgi && CGIG(force_redirect)) {
    1255                 :                 /* Apache will generate REDIRECT_STATUS,
    1256                 :                  * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS.
    1257                 :                  * redirect.so and installation instructions available from
    1258                 :                  * http://www.koehntopp.de/php.
    1259                 :                  *   -- kk@netuse.de
    1260                 :                  */
    1261                 :                 if (!getenv("REDIRECT_STATUS")
    1262                 :                         && !getenv ("HTTP_REDIRECT_STATUS")
    1263                 :                         /* this is to allow a different env var to be configured
    1264                 :                            in case some server does something different than above */
    1265                 :                         && (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
    1266                 :                         ) {
    1267                 :                         SG(sapi_headers).http_response_code = 400;
    1268                 :                         PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
    1269                 : <p>This PHP CGI binary was compiled with force-cgi-redirect enabled.  This\n\
    1270                 : means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\
    1271                 : set, e.g. via an Apache Action directive.</p>\n\
    1272                 : <p>For more information as to <i>why</i> this behaviour exists, see the <a href=\"http://php.net/security.cgi-bin\">\
    1273                 : manual page for CGI security</a>.</p>\n\
    1274                 : <p>For more information about changing this behaviour or re-enabling this webserver,\n\
    1275                 : consult the installation file that came with this distribution, or visit \n\
    1276                 : <a href=\"http://php.net/install.windows\">the manual page</a>.</p>\n");
    1277                 : 
    1278                 : #if defined(ZTS) && !defined(PHP_DEBUG)
    1279                 :                         /* XXX we're crashing here in msvc6 debug builds at
    1280                 :                            php_message_handler_for_zend:839 because
    1281                 :                            SG(request_info).path_translated is an invalid pointer.
    1282                 :                            It still happens even though I set it to null, so something
    1283                 :                            weird is going on.
    1284                 :                         */
    1285                 :                         tsrm_shutdown();
    1286                 : #endif
    1287                 :                         return FAILURE;
    1288                 :                 }
    1289                 :         }
    1290                 : #endif  /* FORCE_CGI_REDIRECT */
    1291                 : 
    1292                 : #if PHP_FASTCGI
    1293                 :         /* for windows, socket listening is broken in the fastcgi library itself
    1294                 :            so dissabling this feature on windows till time is available to fix it */
    1295                 :         if (bindpath) {
    1296                 :                 fcgi_fd = fcgi_listen(bindpath, 128);
    1297                 :                 if (fcgi_fd < 0) {
    1298                 :                         fprintf(stderr, "Couldn't create FastCGI listen socket on port %s\n", bindpath);
    1299                 : #ifdef ZTS
    1300                 :                         tsrm_shutdown();
    1301                 : #endif
    1302                 :                         return FAILURE;
    1303                 :                 }
    1304                 :                 fastcgi = fcgi_is_fastcgi();
    1305                 :         }
    1306                 :         
    1307                 :         if (fastcgi) {
    1308                 :                 /* How many times to run PHP scripts before dying */
    1309                 :                 if (getenv("PHP_FCGI_MAX_REQUESTS")) {
    1310                 :                         max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
    1311                 :                         if (max_requests < 0) {
    1312                 :                                 fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n");
    1313                 :                                 return FAILURE;
    1314                 :                         }
    1315                 :                 }
    1316                 : 
    1317                 :                 /* make php call us to get _ENV vars */
    1318                 :                 php_php_import_environment_variables = php_import_environment_variables;
    1319                 :                 php_import_environment_variables = cgi_php_import_environment_variables;
    1320                 : 
    1321                 :                 /* library is already initialized, now init our request */
    1322                 :                 fcgi_init_request(&request, fcgi_fd);
    1323                 : 
    1324                 : #ifndef PHP_WIN32
    1325                 :         /* Pre-fork, if required */
    1326                 :         if (getenv("PHP_FCGI_CHILDREN")) {
    1327                 :                 children = atoi(getenv("PHP_FCGI_CHILDREN"));
    1328                 :                 if (children < 0) {
    1329                 :                         fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
    1330                 :                         return FAILURE;
    1331                 :                 }
    1332                 :         }
    1333                 : 
    1334                 :         if (children) {
    1335                 :                 int running = 0;
    1336                 :                 pid_t pid;
    1337                 : 
    1338                 :                 /* Create a process group for ourself & children */
    1339                 :                 setsid();
    1340                 :                 pgroup = getpgrp();
    1341                 : #ifdef DEBUG_FASTCGI
    1342                 :                 fprintf(stderr, "Process group %d\n", pgroup);
    1343                 : #endif
    1344                 : 
    1345                 :                 /* Set up handler to kill children upon exit */
    1346                 :                 act.sa_flags = 0;
    1347                 :                 act.sa_handler = fastcgi_cleanup;
    1348                 :                 if (sigaction(SIGTERM, &act, &old_term) ||
    1349                 :                     sigaction(SIGINT,  &act, &old_int) ||
    1350                 :                     sigaction(SIGQUIT, &act, &old_quit)) {
    1351                 :                         perror("Can't set signals");
    1352                 :                         exit(1);
    1353                 :                 }
    1354                 : 
    1355                 :                 if (fcgi_in_shutdown()) {
    1356                 :                         exit(0);
    1357                 :                 }
    1358                 : 
    1359                 :                 while (parent) {
    1360                 :                         do {
    1361                 : #ifdef DEBUG_FASTCGI
    1362                 :                                 fprintf(stderr, "Forking, %d running\n", running);
    1363                 : #endif
    1364                 :                                 pid = fork();
    1365                 :                                 switch (pid) {
    1366                 :                                 case 0:
    1367                 :                                         /* One of the children.
    1368                 :                                          * Make sure we don't go round the
    1369                 :                                          * fork loop any more
    1370                 :                                          */
    1371                 :                                         parent = 0;
    1372                 : 
    1373                 :                                         /* don't catch our signals */
    1374                 :                                         sigaction(SIGTERM, &old_term, 0);
    1375                 :                                         sigaction(SIGQUIT, &old_quit, 0);
    1376                 :                                         sigaction(SIGINT,  &old_int,  0);
    1377                 :                                         break;
    1378                 :                                 case -1:
    1379                 :                                         perror("php (pre-forking)");
    1380                 :                                         exit(1);
    1381                 :                                         break;
    1382                 :                                 default:
    1383                 :                                         /* Fine */
    1384                 :                                         running++;
    1385                 :                                         break;
    1386                 :                                 }
    1387                 :                         } while (parent && (running < children));
    1388                 : 
    1389                 :                         if (parent) {
    1390                 : #ifdef DEBUG_FASTCGI
    1391                 :                                 fprintf(stderr, "Wait for kids, pid %d\n", getpid());
    1392                 : #endif
    1393                 :                                 while (wait(&status) < 0) {
    1394                 :                                 }
    1395                 :                                 running--;
    1396                 :                         }
    1397                 :                 }
    1398                 :         } else {
    1399                 :                 parent = 0;
    1400                 :         }
    1401                 : 
    1402                 : #endif /* WIN32 */
    1403                 :         }
    1404                 : #endif /* FASTCGI */
    1405                 : 
    1406             219 :         zend_first_try {
    1407            5016 :                 while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1)) != -1) {
    1408            4579 :                         switch (c) {
    1409                 :                                 case 'h':
    1410                 :                                 case '?':
    1411               1 :                                         no_headers = 1;
    1412               1 :                                         php_output_startup();
    1413               1 :                                         php_output_activate(TSRMLS_C);
    1414               1 :                                         SG(headers_sent) = 1;
    1415               1 :                                         php_cgi_usage(argv[0]);
    1416               1 :                                         php_end_ob_buffers(1 TSRMLS_CC);
    1417               1 :                                         exit(1);
    1418                 :                                         break;
    1419                 :                         }
    1420                 :                 }
    1421             218 :                 php_optind = orig_optind;
    1422             218 :                 php_optarg = orig_optarg;
    1423                 : 
    1424                 : #if PHP_FASTCGI
    1425                 :                 /* start of FAST CGI loop */
    1426                 :                 /* Initialise FastCGI request structure */
    1427                 : #ifdef PHP_WIN32
    1428                 :                 /* attempt to set security impersonation for fastcgi
    1429                 :                    will only happen on NT based OS, others will ignore it. */
    1430                 :                 if (fastcgi && CGIG(impersonate)) {
    1431                 :                         fcgi_impersonate();
    1432                 :                 }
    1433                 : #endif
    1434                 :                 while (!fastcgi || fcgi_accept_request(&request) >= 0) {
    1435                 : #endif
    1436                 : 
    1437                 : #if PHP_FASTCGI
    1438                 :                 SG(server_context) = (void *) &request;
    1439                 : #else
    1440             218 :                 SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */
    1441                 : #endif
    1442             218 :                 init_request_info(TSRMLS_C);
    1443             218 :                 CG(interactive) = 0;
    1444                 : 
    1445             218 :                 if (!cgi
    1446                 : #if PHP_FASTCGI
    1447                 :                         && !fastcgi
    1448                 : #endif
    1449                 :                 ) {
    1450             110 :                         if (cgi_sapi_module.php_ini_path_override && cgi_sapi_module.php_ini_ignore) {
    1451               0 :                                 no_headers = 1;
    1452               0 :                                 php_output_startup();
    1453               0 :                                 php_output_activate(TSRMLS_C);
    1454               0 :                                 SG(headers_sent) = 1;
    1455               0 :                                 php_printf("You cannot use both -n and -c switch. Use -h for help.\n");
    1456               0 :                                 php_end_ob_buffers(1 TSRMLS_CC);
    1457               0 :                                 exit(1);
    1458                 :                         }
    1459                 : 
    1460            2528 :                         while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) {
    1461            2308 :                                 switch (c) {
    1462                 : 
    1463                 :                                 case 'a':       /* interactive mode */
    1464               0 :                                                 printf("Interactive mode enabled\n\n");
    1465               0 :                                                 CG(interactive) = 1;
    1466               0 :                                                 break;
    1467                 : 
    1468                 :                                 case 'C': /* don't chdir to the script directory */
    1469               0 :                                                 SG(options) |= SAPI_OPTION_NO_CHDIR;
    1470               0 :                                                 break;
    1471                 : 
    1472                 :                                 case 'e': /* enable extended info output */
    1473               0 :                                                 CG(extended_info) = 1;
    1474               0 :                                                 break;
    1475                 : 
    1476                 :                                 case 'f': /* parse file */
    1477               0 :                                                 script_file = estrdup(php_optarg);
    1478               0 :                                                 no_headers = 1;
    1479                 :                                                 /* arguments after the file are considered script args */
    1480               0 :                                                 SG(request_info).argc = argc - (php_optind - 1);
    1481               0 :                                                 SG(request_info).argv = &argv[php_optind - 1];
    1482               0 :                                                 break;
    1483                 : 
    1484                 :                                 case 'i': /* php info & quit */
    1485               0 :                                                 if (php_request_startup(TSRMLS_C) == FAILURE) {
    1486               0 :                                                         SG(server_context) = NULL;
    1487               0 :                                                         php_module_shutdown(TSRMLS_C);
    1488               0 :                                                         return FAILURE;
    1489                 :                                                 }
    1490               0 :                                                 if (no_headers) {
    1491               0 :                                                         SG(headers_sent) = 1;
    1492               0 :                                                         SG(request_info).no_headers = 1;
    1493                 :                                                 }
    1494               0 :                                                 php_print_info(0xFFFFFFFF TSRMLS_CC);
    1495               0 :                                                 php_end_ob_buffers(1 TSRMLS_CC);
    1496               0 :                                                 exit(0);
    1497                 :                                                 break;
    1498                 : 
    1499                 :                                 case 'l': /* syntax check mode */
    1500               0 :                                                 no_headers = 1;
    1501               0 :                                                 behavior = PHP_MODE_LINT;
    1502               0 :                                                 break;
    1503                 : 
    1504                 :                                 case 'm': /* list compiled in modules */
    1505               0 :                                         php_output_startup();
    1506               0 :                                         php_output_activate(TSRMLS_C);
    1507               0 :                                         SG(headers_sent) = 1;
    1508               0 :                                         php_printf("[PHP Modules]\n");
    1509               0 :                                         print_modules(TSRMLS_C);
    1510               0 :                                         php_printf("\n[Zend Modules]\n");
    1511               0 :                                         print_extensions(TSRMLS_C);
    1512               0 :                                         php_printf("\n");
    1513               0 :                                         php_end_ob_buffers(1 TSRMLS_CC);
    1514               0 :                                         exit(0);
    1515                 :                                         break;
    1516                 : 
    1517                 : #if 0 /* not yet operational, see also below ... */
    1518                 :                                 case '': /* generate indented source mode*/
    1519                 :                                                 behavior=PHP_MODE_INDENT;
    1520                 :                                                 break;
    1521                 : #endif
    1522                 : 
    1523                 :                                 case 'q': /* do not generate HTTP headers */
    1524             108 :                                                 no_headers = 1;
    1525             108 :                                                 break;
    1526                 : 
    1527                 :                                 case 's': /* generate highlighted HTML from source */
    1528               0 :                                                 behavior = PHP_MODE_HIGHLIGHT;
    1529               0 :                                                 break;
    1530                 : 
    1531                 :                                 case 'v': /* show php version & quit */
    1532               0 :                                                 no_headers = 1;
    1533               0 :                                                 if (php_request_startup(TSRMLS_C) == FAILURE) {
    1534               0 :                                                         SG(server_context) = NULL;
    1535               0 :                                                         php_module_shutdown(TSRMLS_C);
    1536               0 :                                                         return FAILURE;
    1537                 :                                                 }
    1538               0 :                                                 if (no_headers) {
    1539               0 :                                                         SG(headers_sent) = 1;
    1540               0 :                                                         SG(request_info).no_headers = 1;
    1541                 :                                                 }
    1542                 : #if ZEND_DEBUG
    1543                 :                                                 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2007 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
    1544                 : #else
    1545               0 :                                                 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2007 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
    1546                 : #endif
    1547               0 :                                                 php_end_ob_buffers(1 TSRMLS_CC);
    1548               0 :                                                 exit(0);
    1549                 :                                                 break;
    1550                 : 
    1551                 :                                 case 'w':
    1552               0 :                                                 behavior = PHP_MODE_STRIP;
    1553               0 :                                                 break;
    1554                 : 
    1555                 :                                 case 'z': /* load extension file */
    1556               0 :                                                 zend_load_extension(php_optarg);
    1557                 :                                                 break;
    1558                 : 
    1559                 :                                         default:
    1560                 :                                                 break;
    1561                 :                                 }
    1562                 :                         }
    1563                 : 
    1564             110 :                         if (script_file) {
    1565                 :                                 /* override path_translated if -f on command line */
    1566               0 :                                 STR_FREE(SG(request_info).path_translated);
    1567               0 :                                 SG(request_info).path_translated = script_file;
    1568                 :                         }
    1569                 : 
    1570             110 :                         if (no_headers) {
    1571             108 :                                 SG(headers_sent) = 1;
    1572             108 :                                 SG(request_info).no_headers = 1;
    1573                 :                         }
    1574                 : 
    1575             110 :                         if (!SG(request_info).path_translated && argc > php_optind) {
    1576                 :                                 /* arguments after the file are considered script args */
    1577             110 :                                 SG(request_info).argc = argc - php_optind;
    1578             110 :                                 SG(request_info).argv = &argv[php_optind];
    1579                 :                                 /* file is on command line, but not in -f opt */
    1580             110 :                                 SG(request_info).path_translated = estrdup(argv[php_optind++]);
    1581                 :                         }
    1582                 : 
    1583                 :                         /* all remaining arguments are part of the query string
    1584                 :                            this section of code concatenates all remaining arguments
    1585                 :                            into a single string, seperating args with a &
    1586                 :                            this allows command lines like:
    1587                 : 
    1588                 :                            test.php v1=test v2=hello+world!
    1589                 :                            test.php "v1=test&v2=hello world!"
    1590                 :                            test.php v1=test "v2=hello world!"
    1591                 :                         */
    1592             110 :                         if (!SG(request_info).query_string && argc > php_optind) {
    1593               0 :                                 int slen = strlen(PG(arg_separator).input);
    1594               0 :                                 len = 0;
    1595               0 :                                 for (i = php_optind; i < argc; i++) {
    1596               0 :                                         if (i < (argc - 1)) {
    1597               0 :                                                 len += strlen(argv[i]) + slen;
    1598                 :                                         } else {
    1599               0 :                                                 len += strlen(argv[i]);
    1600                 :                                         }
    1601                 :                                 }
    1602                 : 
    1603               0 :                                 len += 2;
    1604               0 :                                 s = malloc(len);
    1605               0 :                                 *s = '\0';                      /* we are pretending it came from the environment  */
    1606               0 :                                 for (i = php_optind; i < argc; i++) {
    1607               0 :                                         strlcat(s, argv[i], len);
    1608               0 :                                         if (i < (argc - 1)) {
    1609               0 :                                                 strlcat(s, PG(arg_separator).input, len);
    1610                 :                                         }
    1611                 :                                 }
    1612               0 :                                 SG(request_info).query_string = s;
    1613               0 :                                 free_query_string = 1;
    1614                 :                         }
    1615                 :                 } /* end !cgi && !fastcgi */
    1616                 : 
    1617                 :                 /* 
    1618                 :                         we never take stdin if we're (f)cgi, always
    1619                 :                         rely on the web server giving us the info
    1620                 :                         we need in the environment. 
    1621                 :                 */
    1622             436 :                 if (SG(request_info).path_translated || cgi 
    1623                 : #if PHP_FASTCGI
    1624                 :                         || fastcgi
    1625                 : #endif
    1626                 :                 )
    1627                 :                 {
    1628             218 :                         file_handle.type = ZEND_HANDLE_FILENAME;
    1629             218 :                         file_handle.filename = SG(request_info).path_translated;
    1630             218 :                         file_handle.handle.fp = NULL;
    1631                 :                 } else {
    1632               0 :                         file_handle.filename = "-";
    1633               0 :                         file_handle.type = ZEND_HANDLE_FP;
    1634               0 :                         file_handle.handle.fp = stdin;
    1635                 :                 }
    1636                 : 
    1637             218 :                 file_handle.opened_path = NULL;
    1638             218 :                 file_handle.free_filename = 0;
    1639                 : 
    1640                 :                 /* request startup only after we've done all we can to
    1641                 :                    get path_translated */
    1642             218 :                 if (php_request_startup(TSRMLS_C) == FAILURE) {
    1643                 : #if PHP_FASTCGI
    1644                 :                         if (fastcgi) {
    1645                 :                                 fcgi_finish_request(&request);
    1646                 :                         }
    1647                 : #endif
    1648               0 :                         SG(server_context) = NULL;
    1649               0 :                         php_module_shutdown(TSRMLS_C);
    1650               0 :                         return FAILURE;
    1651                 :                 }
    1652             218 :                 if (no_headers) {
    1653             108 :                         SG(headers_sent) = 1;
    1654             108 :                         SG(request_info).no_headers = 1;
    1655                 :                 }
    1656                 : 
    1657                 :                 /* 
    1658                 :                         at this point path_translated will be set if:
    1659                 :                         1. we are running from shell and got filename was there
    1660                 :                         2. we are running as cgi or fastcgi
    1661                 :                 */
    1662             218 :                 retval = FAILURE;
    1663             218 :                 if (cgi || SG(request_info).path_translated) {
    1664             218 :                         retval = php_fopen_primary_script(&file_handle TSRMLS_CC);
    1665                 :                 }
    1666                 :                 /* 
    1667                 :                         if we are unable to open path_translated and we are not
    1668                 :                         running from shell (so fp == NULL), then fail.
    1669                 :                 */
    1670             218 :                 if (retval == FAILURE && file_handle.handle.fp == NULL) {
    1671               0 :                         if (errno == EACCES) {
    1672               0 :                                 SG(sapi_headers).http_response_code = 403;
    1673               0 :                                 PUTS("Access denied.\n");
    1674                 :                         } else {
    1675               0 :                                 SG(sapi_headers).http_response_code = 404;
    1676               0 :                                 PUTS("No input file specified.\n");
    1677                 :                         }
    1678                 : #if PHP_FASTCGI
    1679                 :                         /* we want to serve more requests if this is fastcgi
    1680                 :                            so cleanup and continue, request shutdown is
    1681                 :                            handled later */
    1682                 :                         if (fastcgi) {
    1683                 :                                 goto fastcgi_request_done;
    1684                 :                         }
    1685                 : #endif
    1686               0 :                         php_request_shutdown((void *) 0);
    1687               0 :                         SG(server_context) = NULL;
    1688               0 :                         php_module_shutdown(TSRMLS_C);
    1689               0 :                         return FAILURE;
    1690                 :                 }
    1691                 : 
    1692             218 :                 if (CGIG(check_shebang_line) && file_handle.handle.fp && (file_handle.handle.fp != stdin)) {
    1693                 :                         /* #!php support */
    1694             218 :                         c = fgetc(file_handle.handle.fp);
    1695             218 :                         if (c == '#') {
    1696               0 :                                 while (c != '\n' && c != '\r') {
    1697               0 :                                         c = fgetc(file_handle.handle.fp);       /* skip to end of line */
    1698                 :                                 }
    1699                 :                                 /* handle situations where line is terminated by \r\n */
    1700               0 :                                 if (c == '\r') {
    1701               0 :                                         if (fgetc(file_handle.handle.fp) != '\n') {
    1702               0 :                                                 long pos = ftell(file_handle.handle.fp);
    1703               0 :                                                 fseek(file_handle.handle.fp, pos - 1, SEEK_SET);
    1704                 :                                         }
    1705                 :                                 }
    1706               0 :                                 CG(start_lineno) = 2;
    1707                 :                         } else {
    1708             218 :                                 rewind(file_handle.handle.fp);
    1709                 :                         }
    1710                 :                 }
    1711                 : 
    1712             218 :                 switch (behavior) {
    1713                 :                         case PHP_MODE_STANDARD:
    1714             218 :                                 php_execute_script(&file_handle TSRMLS_CC);
    1715             218 :                                 break;
    1716                 :                         case PHP_MODE_LINT:
    1717               0 :                                 PG(during_request_startup) = 0;
    1718               0 :                                 exit_status = php_lint_script(&file_handle TSRMLS_CC);
    1719               0 :                                 if (exit_status == SUCCESS) {
    1720               0 :                                         zend_printf("No syntax errors detected in %s\n", file_handle.filename);
    1721                 :                                 } else {
    1722               0 :                                         zend_printf("Errors parsing %s\n", file_handle.filename);
    1723                 :                                 }
    1724               0 :                                 break;
    1725                 :                         case PHP_MODE_STRIP:
    1726               0 :                                 if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
    1727               0 :                                         zend_strip(TSRMLS_C);
    1728               0 :                                         fclose(file_handle.handle.fp);
    1729               0 :                                         php_end_ob_buffers(1 TSRMLS_CC);
    1730                 :                                 }
    1731               0 :                                 return SUCCESS;
    1732                 :                                 break;
    1733                 :                         case PHP_MODE_HIGHLIGHT:
    1734                 :                                 {
    1735                 :                                         zend_syntax_highlighter_ini syntax_highlighter_ini;
    1736                 : 
    1737               0 :                                         if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
    1738               0 :                                                 php_get_highlight_struct(&syntax_highlighter_ini);
    1739               0 :                                                 zend_highlight(&syntax_highlighter_ini TSRMLS_CC);
    1740               0 :                                                 fclose(file_handle.handle.fp);
    1741               0 :                                                 php_end_ob_buffers(1 TSRMLS_CC);
    1742                 :                                         }
    1743               0 :                                         return SUCCESS;
    1744                 :                                 }
    1745                 :                                 break;
    1746                 : #if 0
    1747                 :                         /* Zeev might want to do something with this one day */
    1748                 :                         case PHP_MODE_INDENT:
    1749                 :                                 open_file_for_scanning(&file_handle TSRMLS_CC);
    1750                 :                                 zend_indent();
    1751                 :                                 fclose(file_handle.handle.fp);
    1752                 :                                 return SUCCESS;
    1753                 :                                 break;
    1754                 : #endif
    1755                 :                 }
    1756                 : 
    1757                 : #if PHP_FASTCGI
    1758                 : fastcgi_request_done:
    1759                 : #endif
    1760                 :                 {
    1761                 :                         char *path_translated;
    1762                 : 
    1763                 :                         /*      Go through this trouble so that the memory manager doesn't warn
    1764                 :                          *      about SG(request_info).path_translated leaking
    1765                 :                          */
    1766             218 :                         if (SG(request_info).path_translated) {
    1767             218 :                                 path_translated = strdup(SG(request_info).path_translated);
    1768             218 :                                 STR_FREE(SG(request_info).path_translated);
    1769             218 :                                 SG(request_info).path_translated = path_translated;
    1770                 :                         }
    1771                 : 
    1772             218 :                         php_request_shutdown((void *) 0);
    1773             218 :                         if (exit_status == 0) {
    1774             218 :                                 exit_status = EG(exit_status);
    1775                 :                         }
    1776                 : 
    1777             218 :                         if (SG(request_info).path_translated) {
    1778             218 :                                 free(SG(request_info).path_translated);
    1779             218 :                                 SG(request_info).path_translated = NULL;
    1780                 :                         }
    1781             218 :                         if (free_query_string && SG(request_info).query_string) {
    1782               0 :                                 free(SG(request_info).query_string);
    1783               0 :                                 SG(request_info).query_string = NULL;
    1784                 :                         }
    1785                 : 
    1786                 :                 }
    1787                 : 
    1788                 : #if PHP_FASTCGI
    1789                 :                         if (!fastcgi) break;
    1790                 :                         /* only fastcgi will get here */
    1791                 :                         requests++;
    1792                 :                         if (max_requests && (requests == max_requests)) {
    1793                 :                                 fcgi_finish_request(&request);
    1794                 :                                 if (bindpath) {
    1795                 :                                         free(bindpath);
    1796                 :                                 }
    1797                 :                                 break;
    1798                 :                         }
    1799                 :                         /* end of fastcgi loop */
    1800                 :                 }
    1801                 : #endif
    1802                 : 
    1803             218 :                 if (cgi_sapi_module.php_ini_path_override) {
    1804               0 :                         free(cgi_sapi_module.php_ini_path_override);
    1805                 :                 }
    1806             218 :                 if (cgi_sapi_module.ini_entries) {
    1807             218 :                         free(cgi_sapi_module.ini_entries);
    1808                 :                 }
    1809               0 :         } zend_catch {
    1810               0 :                 exit_status = 255;
    1811             218 :         } zend_end_try();
    1812                 : 
    1813             218 :         SG(server_context) = NULL;
    1814             218 :         php_module_shutdown(TSRMLS_C);
    1815             218 :         sapi_shutdown();
    1816                 : 
    1817                 : #ifdef ZTS
    1818                 :         /*tsrm_shutdown();*/
    1819                 : #endif
    1820                 : 
    1821                 : #if defined(PHP_WIN32) && ZEND_DEBUG && 0
    1822                 :         _CrtDumpMemoryLeaks();
    1823                 : #endif
    1824                 : 
    1825             218 :         return exit_status;
    1826                 : }
    1827                 : /* }}} */
    1828                 : 
    1829                 : /*
    1830                 :  * Local variables:
    1831                 :  * tab-width: 4
    1832                 :  * c-basic-offset: 4
    1833                 :  * End:
    1834                 :  * vim600: sw=4 ts=4 fdm=marker
    1835                 :  * vim<600: sw=4 ts=4
    1836                 :  */

Generated by: LTP GCOV extension version 1.5