root/sapi/cli/php_cli.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_cli_get_shell_callbacks
  2. print_module_info
  3. module_name_cmp
  4. print_modules
  5. print_extension_info
  6. extension_name_cmp
  7. print_extensions
  8. sapi_cli_select
  9. sapi_cli_single_write
  10. sapi_cli_ub_write
  11. sapi_cli_flush
  12. sapi_cli_register_variables
  13. sapi_cli_log_message
  14. sapi_cli_deactivate
  15. sapi_cli_read_cookies
  16. sapi_cli_header_handler
  17. sapi_cli_send_headers
  18. sapi_cli_send_header
  19. php_cli_startup
  20. sapi_cli_ini_defaults
  21. php_cli_usage
  22. cli_register_file_handles
  23. cli_seek_file_begin
  24. do_cli
  25. WinMain

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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    | Author: Edin Kadribasic <edink@php.net>                              |
  16    |         Marcus Boerger <helly@php.net>                               |
  17    |         Johannes Schlueter <johannes@php.net>                        |
  18    |         Parts based on CGI SAPI Module by                            |
  19    |         Rasmus Lerdorf, Stig Bakken and Zeev Suraski                 |
  20    +----------------------------------------------------------------------+
  21 */
  22 
  23 /* $Id$ */
  24 
  25 #include "php.h"
  26 #include "php_globals.h"
  27 #include "php_variables.h"
  28 #include "zend_hash.h"
  29 #include "zend_modules.h"
  30 #include "zend_interfaces.h"
  31 
  32 #include "ext/reflection/php_reflection.h"
  33 
  34 #include "SAPI.h"
  35 
  36 #include <stdio.h>
  37 #include "php.h"
  38 #ifdef PHP_WIN32
  39 #include "win32/time.h"
  40 #include "win32/signal.h"
  41 #include <process.h>
  42 #endif
  43 #if HAVE_SYS_TIME_H
  44 #include <sys/time.h>
  45 #endif
  46 #if HAVE_UNISTD_H
  47 #include <unistd.h>
  48 #endif
  49 #if HAVE_SIGNAL_H
  50 #include <signal.h>
  51 #endif
  52 #if HAVE_SETLOCALE
  53 #include <locale.h>
  54 #endif
  55 #include "zend.h"
  56 #include "zend_extensions.h"
  57 #include "php_ini.h"
  58 #include "php_globals.h"
  59 #include "php_main.h"
  60 #include "fopen_wrappers.h"
  61 #include "ext/standard/php_standard.h"
  62 #include "cli.h"
  63 #ifdef PHP_WIN32
  64 #include <io.h>
  65 #include <fcntl.h>
  66 #include "win32/php_registry.h"
  67 #endif
  68 
  69 #if HAVE_SIGNAL_H
  70 #include <signal.h>
  71 #endif
  72 
  73 #ifdef __riscos__
  74 #include <unixlib/local.h>
  75 #endif
  76 
  77 #include "zend_compile.h"
  78 #include "zend_execute.h"
  79 #include "zend_highlight.h"
  80 #include "zend_indent.h"
  81 #include "zend_exceptions.h"
  82 
  83 #include "php_getopt.h"
  84 
  85 #ifndef PHP_CLI_WIN32_NO_CONSOLE
  86 #include "php_cli_server.h"
  87 #endif
  88 
  89 #include "ps_title.h"
  90 #include "php_cli_process_title.h"
  91 
  92 #ifndef PHP_WIN32
  93 # define php_select(m, r, w, e, t)      select(m, r, w, e, t)
  94 #else
  95 # include "win32/select.h"
  96 #endif
  97 
  98 PHPAPI extern char *php_ini_opened_path;
  99 PHPAPI extern char *php_ini_scanned_path;
 100 PHPAPI extern char *php_ini_scanned_files;
 101 
 102 #ifndef O_BINARY
 103 #define O_BINARY 0
 104 #endif
 105 
 106 #define PHP_MODE_STANDARD      1
 107 #define PHP_MODE_HIGHLIGHT     2
 108 #define PHP_MODE_INDENT        3
 109 #define PHP_MODE_LINT          4
 110 #define PHP_MODE_STRIP         5
 111 #define PHP_MODE_CLI_DIRECT    6
 112 #define PHP_MODE_PROCESS_STDIN 7
 113 #define PHP_MODE_REFLECTION_FUNCTION    8
 114 #define PHP_MODE_REFLECTION_CLASS       9
 115 #define PHP_MODE_REFLECTION_EXTENSION   10
 116 #define PHP_MODE_REFLECTION_EXT_INFO    11
 117 #define PHP_MODE_REFLECTION_ZEND_EXTENSION 12
 118 #define PHP_MODE_SHOW_INI_CONFIG        13
 119 
 120 cli_shell_callbacks_t cli_shell_callbacks = { NULL, NULL, NULL };
 121 PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks()
 122 {
 123         return &cli_shell_callbacks;
 124 }
 125 
 126 const char HARDCODED_INI[] =
 127         "html_errors=0\n"
 128         "register_argc_argv=1\n"
 129         "implicit_flush=1\n"
 130         "output_buffering=0\n"
 131         "max_execution_time=0\n"
 132         "max_input_time=-1\n\0";
 133 
 134 
 135 const opt_struct OPTIONS[] = {
 136         {'a', 0, "interactive"},
 137         {'B', 1, "process-begin"},
 138         {'C', 0, "no-chdir"}, /* for compatibility with CGI (do not chdir to script directory) */
 139         {'c', 1, "php-ini"},
 140         {'d', 1, "define"},
 141         {'E', 1, "process-end"},
 142         {'e', 0, "profile-info"},
 143         {'F', 1, "process-file"},
 144         {'f', 1, "file"},
 145         {'h', 0, "help"},
 146         {'i', 0, "info"},
 147         {'l', 0, "syntax-check"},
 148         {'m', 0, "modules"},
 149         {'n', 0, "no-php-ini"},
 150         {'q', 0, "no-header"}, /* for compatibility with CGI (do not generate HTTP headers) */
 151         {'R', 1, "process-code"},
 152         {'H', 0, "hide-args"},
 153         {'r', 1, "run"},
 154         {'s', 0, "syntax-highlight"},
 155         {'s', 0, "syntax-highlighting"},
 156         {'S', 1, "server"},
 157         {'t', 1, "docroot"},
 158         {'w', 0, "strip"},
 159         {'?', 0, "usage"},/* help alias (both '?' and 'usage') */
 160         {'v', 0, "version"},
 161         {'z', 1, "zend-extension"},
 162         {10,  1, "rf"},
 163         {10,  1, "rfunction"},
 164         {11,  1, "rc"},
 165         {11,  1, "rclass"},
 166         {12,  1, "re"},
 167         {12,  1, "rextension"},
 168         {13,  1, "rz"},
 169         {13,  1, "rzendextension"},
 170         {14,  1, "ri"},
 171         {14,  1, "rextinfo"},
 172         {15,  0, "ini"},
 173         {'-', 0, NULL} /* end of args */
 174 };
 175 
 176 static int print_module_info(zend_module_entry *module TSRMLS_DC) /* {{{ */
 177 {
 178         php_printf("%s\n", module->name);
 179         return ZEND_HASH_APPLY_KEEP;
 180 }
 181 /* }}} */
 182 
 183 static int module_name_cmp(const void *a, const void *b TSRMLS_DC) /* {{{ */
 184 {
 185         Bucket *f = *((Bucket **) a);
 186         Bucket *s = *((Bucket **) b);
 187 
 188         return strcasecmp(((zend_module_entry *)f->pData)->name,
 189                                   ((zend_module_entry *)s->pData)->name);
 190 }
 191 /* }}} */
 192 
 193 static void print_modules(TSRMLS_D) /* {{{ */
 194 {
 195         HashTable sorted_registry;
 196         zend_module_entry tmp;
 197 
 198         zend_hash_init(&sorted_registry, 50, NULL, NULL, 1);
 199         zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry));
 200         zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC);
 201         zend_hash_apply(&sorted_registry, (apply_func_t) print_module_info TSRMLS_CC);
 202         zend_hash_destroy(&sorted_registry);
 203 }
 204 /* }}} */
 205 
 206 static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) /* {{{ */
 207 {
 208         php_printf("%s\n", ext->name);
 209         return ZEND_HASH_APPLY_KEEP;
 210 }
 211 /* }}} */
 212 
 213 static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s TSRMLS_DC) /* {{{ */
 214 {
 215         return strcmp(((zend_extension *)(*f)->data)->name,
 216                                   ((zend_extension *)(*s)->data)->name);
 217 }
 218 /* }}} */
 219 
 220 static void print_extensions(TSRMLS_D) /* {{{ */
 221 {
 222         zend_llist sorted_exts;
 223 
 224         zend_llist_copy(&sorted_exts, &zend_extensions);
 225         sorted_exts.dtor = NULL;
 226         zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC);
 227         zend_llist_apply(&sorted_exts, (llist_apply_func_t) print_extension_info TSRMLS_CC);
 228         zend_llist_destroy(&sorted_exts);
 229 }
 230 /* }}} */
 231 
 232 #ifndef STDOUT_FILENO
 233 #define STDOUT_FILENO 1
 234 #endif
 235 
 236 static inline int sapi_cli_select(int fd TSRMLS_DC)
 237 {
 238         fd_set wfd, dfd;
 239         struct timeval tv;
 240         int ret;
 241 
 242         FD_ZERO(&wfd);
 243         FD_ZERO(&dfd);
 244 
 245         PHP_SAFE_FD_SET(fd, &wfd);
 246 
 247         tv.tv_sec = FG(default_socket_timeout);
 248         tv.tv_usec = 0;
 249 
 250         ret = php_select(fd+1, &dfd, &wfd, &dfd, &tv);
 251 
 252         return ret != -1;
 253 }
 254 
 255 PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
 256 {
 257 #ifdef PHP_WRITE_STDOUT
 258         long ret;
 259 #else
 260         size_t ret;
 261 #endif
 262 
 263         if (cli_shell_callbacks.cli_shell_write) {
 264                 size_t shell_wrote;
 265                 shell_wrote = cli_shell_callbacks.cli_shell_write(str, str_length TSRMLS_CC);
 266                 if (shell_wrote > -1) {
 267                         return shell_wrote;
 268                 }
 269         }
 270 
 271 #ifdef PHP_WRITE_STDOUT
 272         do {
 273                 ret = write(STDOUT_FILENO, str, str_length);
 274         } while (ret <= 0 && errno == EAGAIN && sapi_cli_select(STDOUT_FILENO TSRMLS_CC));
 275 
 276         if (ret <= 0) {
 277                 return 0;
 278         }
 279 
 280         return ret;
 281 #else
 282         ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
 283         return ret;
 284 #endif
 285 }
 286 /* }}} */
 287 
 288 static int sapi_cli_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
 289 {
 290         const char *ptr = str;
 291         uint remaining = str_length;
 292         size_t ret;
 293 
 294         if (!str_length) {
 295                 return 0;
 296         }
 297 
 298         if (cli_shell_callbacks.cli_shell_ub_write) {
 299                 int ub_wrote;
 300                 ub_wrote = cli_shell_callbacks.cli_shell_ub_write(str, str_length TSRMLS_CC);
 301                 if (ub_wrote > -1) {
 302                         return ub_wrote;
 303                 }
 304         }
 305 
 306         while (remaining > 0)
 307         {
 308                 ret = sapi_cli_single_write(ptr, remaining TSRMLS_CC);
 309                 if (!ret) {
 310 #ifndef PHP_CLI_WIN32_NO_CONSOLE
 311                         php_handle_aborted_connection();
 312 #endif
 313                         break;
 314                 }
 315                 ptr += ret;
 316                 remaining -= ret;
 317         }
 318 
 319         return (ptr - str);
 320 }
 321 /* }}} */
 322 
 323 static void sapi_cli_flush(void *server_context) /* {{{ */
 324 {
 325         /* Ignore EBADF here, it's caused by the fact that STDIN/STDOUT/STDERR streams
 326          * are/could be closed before fflush() is called.
 327          */
 328         if (fflush(stdout)==EOF && errno!=EBADF) {
 329 #ifndef PHP_CLI_WIN32_NO_CONSOLE
 330                 php_handle_aborted_connection();
 331 #endif
 332         }
 333 }
 334 /* }}} */
 335 
 336 static char *php_self = "";
 337 static char *script_filename = "";
 338 
 339 static void sapi_cli_register_variables(zval *track_vars_array TSRMLS_DC) /* {{{ */
 340 {
 341         unsigned int len;
 342         char   *docroot = "";
 343 
 344         /* In CGI mode, we consider the environment to be a part of the server
 345          * variables
 346          */
 347         php_import_environment_variables(track_vars_array TSRMLS_CC);
 348 
 349         /* Build the special-case PHP_SELF variable for the CLI version */
 350         len = strlen(php_self);
 351         if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, len, &len TSRMLS_CC)) {
 352                 php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC);
 353         }
 354         if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &php_self, len, &len TSRMLS_CC)) {
 355                 php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC);
 356         }
 357         /* filenames are empty for stdin */
 358         len = strlen(script_filename);
 359         if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &script_filename, len, &len TSRMLS_CC)) {
 360                 php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC);
 361         }
 362         if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &script_filename, len, &len TSRMLS_CC)) {
 363                 php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC);
 364         }
 365         /* just make it available */
 366         len = 0U;
 367         if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len, &len TSRMLS_CC)) {
 368                 php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array TSRMLS_CC);
 369         }
 370 }
 371 /* }}} */
 372 
 373 static void sapi_cli_log_message(char *message TSRMLS_DC) /* {{{ */
 374 {
 375         fprintf(stderr, "%s\n", message);
 376 }
 377 /* }}} */
 378 
 379 static int sapi_cli_deactivate(TSRMLS_D) /* {{{ */
 380 {
 381         fflush(stdout);
 382         if(SG(request_info).argv0) {
 383                 free(SG(request_info).argv0);
 384                 SG(request_info).argv0 = NULL;
 385         }
 386         return SUCCESS;
 387 }
 388 /* }}} */
 389 
 390 static char* sapi_cli_read_cookies(TSRMLS_D) /* {{{ */
 391 {
 392         return NULL;
 393 }
 394 /* }}} */
 395 
 396 static int sapi_cli_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s TSRMLS_DC) /* {{{ */
 397 {
 398         return 0;
 399 }
 400 /* }}} */
 401 
 402 static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */
 403 {
 404         /* We do nothing here, this function is needed to prevent that the fallback
 405          * header handling is called. */
 406         return SAPI_HEADER_SENT_SUCCESSFULLY;
 407 }
 408 /* }}} */
 409 
 410 static void sapi_cli_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) /* {{{ */
 411 {
 412 }
 413 /* }}} */
 414 
 415 static int php_cli_startup(sapi_module_struct *sapi_module) /* {{{ */
 416 {
 417         if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
 418                 return FAILURE;
 419         }
 420         return SUCCESS;
 421 }
 422 /* }}} */
 423 
 424 /* {{{ sapi_cli_ini_defaults */
 425 
 426 /* overwriteable ini defaults must be set in sapi_cli_ini_defaults() */
 427 #define INI_DEFAULT(name,value)\
 428         Z_SET_REFCOUNT(tmp, 0);\
 429         Z_UNSET_ISREF(tmp);     \
 430         ZVAL_STRINGL(&tmp, zend_strndup(value, sizeof(value)-1), sizeof(value)-1, 0);\
 431         zend_hash_update(configuration_hash, name, sizeof(name), &tmp, sizeof(zval), NULL);\
 432 
 433 static void sapi_cli_ini_defaults(HashTable *configuration_hash)
 434 {
 435         zval tmp;
 436         INI_DEFAULT("report_zend_debug", "0");
 437         INI_DEFAULT("display_errors", "1");
 438 }
 439 /* }}} */
 440 
 441 /* {{{ sapi_module_struct cli_sapi_module
 442  */
 443 static sapi_module_struct cli_sapi_module = {
 444         "cli",                                                  /* name */
 445         "Command Line Interface",       /* pretty name */
 446 
 447         php_cli_startup,                                /* startup */
 448         php_module_shutdown_wrapper,    /* shutdown */
 449 
 450         NULL,                                                   /* activate */
 451         sapi_cli_deactivate,                    /* deactivate */
 452 
 453         sapi_cli_ub_write,                      /* unbuffered write */
 454         sapi_cli_flush,                             /* flush */
 455         NULL,                                                   /* get uid */
 456         NULL,                                                   /* getenv */
 457 
 458         php_error,                                              /* error handler */
 459 
 460         sapi_cli_header_handler,                /* header handler */
 461         sapi_cli_send_headers,                  /* send headers handler */
 462         sapi_cli_send_header,                   /* send header handler */
 463 
 464         NULL,                                       /* read POST data */
 465         sapi_cli_read_cookies,          /* read Cookies */
 466 
 467         sapi_cli_register_variables,    /* register server variables */
 468         sapi_cli_log_message,                   /* Log message */
 469         NULL,                                                   /* Get request time */
 470         NULL,                                                   /* Child terminate */
 471         
 472         STANDARD_SAPI_MODULE_PROPERTIES
 473 };
 474 /* }}} */
 475 
 476 /* {{{ arginfo ext/standard/dl.c */
 477 ZEND_BEGIN_ARG_INFO(arginfo_dl, 0)
 478         ZEND_ARG_INFO(0, extension_filename)
 479 ZEND_END_ARG_INFO()
 480 /* }}} */
 481 
 482 static const zend_function_entry additional_functions[] = {
 483         ZEND_FE(dl, arginfo_dl)
 484         PHP_FE(cli_set_process_title,        arginfo_cli_set_process_title)
 485         PHP_FE(cli_get_process_title,        arginfo_cli_get_process_title)
 486         {NULL, NULL, NULL}
 487 };
 488 
 489 /* {{{ php_cli_usage
 490  */
 491 static void php_cli_usage(char *argv0)
 492 {
 493         char *prog;
 494 
 495         prog = strrchr(argv0, '/');
 496         if (prog) {
 497                 prog++;
 498         } else {
 499                 prog = "php";
 500         }
 501         
 502         printf( "Usage: %s [options] [-f] <file> [--] [args...]\n"
 503                                 "   %s [options] -r <code> [--] [args...]\n"
 504                                 "   %s [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]\n"
 505                                 "   %s [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]\n"
 506                                 "   %s [options] -S <addr>:<port> [-t docroot]\n"
 507                                 "   %s [options] -- [args...]\n"
 508                                 "   %s [options] -a\n"
 509                                 "\n"
 510 #if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
 511                                 "  -a               Run as interactive shell\n"
 512 #else
 513                                 "  -a               Run interactively\n"
 514 #endif
 515                                 "  -c <path>|<file> Look for php.ini file in this directory\n"
 516                                 "  -n               No php.ini file will be used\n"
 517                                 "  -d foo[=bar]     Define INI entry foo with value 'bar'\n"
 518                                 "  -e               Generate extended information for debugger/profiler\n"
 519                                 "  -f <file>        Parse and execute <file>.\n"
 520                                 "  -h               This help\n"
 521                                 "  -i               PHP information\n"
 522                                 "  -l               Syntax check only (lint)\n"
 523                                 "  -m               Show compiled in modules\n"
 524                                 "  -r <code>        Run PHP <code> without using script tags <?..?>\n"
 525                                 "  -B <begin_code>  Run PHP <begin_code> before processing input lines\n"
 526                                 "  -R <code>        Run PHP <code> for every input line\n"
 527                                 "  -F <file>        Parse and execute <file> for every input line\n"
 528                                 "  -E <end_code>    Run PHP <end_code> after processing all input lines\n"
 529                                 "  -H               Hide any passed arguments from external tools.\n"
 530                                 "  -S <addr>:<port> Run with built-in web server.\n"
 531                                 "  -t <docroot>     Specify document root <docroot> for built-in web server.\n"
 532                                 "  -s               Output HTML syntax highlighted source.\n"
 533                                 "  -v               Version number\n"
 534                                 "  -w               Output source with stripped comments and whitespace.\n"
 535                                 "  -z <file>        Load Zend extension <file>.\n"
 536                                 "\n"
 537                                 "  args...          Arguments passed to script. Use -- args when first argument\n"
 538                                 "                   starts with - or script is read from stdin\n"
 539                                 "\n"
 540                                 "  --ini            Show configuration file names\n"
 541                                 "\n"
 542                                 "  --rf <name>      Show information about function <name>.\n"
 543                                 "  --rc <name>      Show information about class <name>.\n"
 544                                 "  --re <name>      Show information about extension <name>.\n"
 545                                 "  --rz <name>      Show information about Zend extension <name>.\n"
 546                                 "  --ri <name>      Show configuration for extension <name>.\n"
 547                                 "\n"
 548                                 , prog, prog, prog, prog, prog, prog, prog);
 549 }
 550 /* }}} */
 551 
 552 static php_stream *s_in_process = NULL;
 553 
 554 static void cli_register_file_handles(TSRMLS_D) /* {{{ */
 555 {
 556         zval *zin, *zout, *zerr;
 557         php_stream *s_in, *s_out, *s_err;
 558         php_stream_context *sc_in=NULL, *sc_out=NULL, *sc_err=NULL;
 559         zend_constant ic, oc, ec;
 560         
 561         MAKE_STD_ZVAL(zin);
 562         MAKE_STD_ZVAL(zout);
 563         MAKE_STD_ZVAL(zerr);
 564 
 565         s_in  = php_stream_open_wrapper_ex("php://stdin",  "rb", 0, NULL, sc_in);
 566         s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out);
 567         s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err);
 568 
 569         if (s_in==NULL || s_out==NULL || s_err==NULL) {
 570                 FREE_ZVAL(zin);
 571                 FREE_ZVAL(zout);
 572                 FREE_ZVAL(zerr);
 573                 if (s_in) php_stream_close(s_in);
 574                 if (s_out) php_stream_close(s_out);
 575                 if (s_err) php_stream_close(s_err);
 576                 return;
 577         }
 578         
 579 #if PHP_DEBUG
 580         /* do not close stdout and stderr */
 581         s_out->flags |= PHP_STREAM_FLAG_NO_CLOSE;
 582         s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE;
 583 #endif
 584 
 585         s_in_process = s_in;
 586 
 587         php_stream_to_zval(s_in,  zin);
 588         php_stream_to_zval(s_out, zout);
 589         php_stream_to_zval(s_err, zerr);
 590         
 591         ic.value = *zin;
 592         ic.flags = CONST_CS;
 593         ic.name = zend_strndup(ZEND_STRL("STDIN"));
 594         ic.name_len = sizeof("STDIN");
 595         ic.module_number = 0;
 596         zend_register_constant(&ic TSRMLS_CC);
 597 
 598         oc.value = *zout;
 599         oc.flags = CONST_CS;
 600         oc.name = zend_strndup(ZEND_STRL("STDOUT"));
 601         oc.name_len = sizeof("STDOUT");
 602         oc.module_number = 0;
 603         zend_register_constant(&oc TSRMLS_CC);
 604 
 605         ec.value = *zerr;
 606         ec.flags = CONST_CS;
 607         ec.name = zend_strndup(ZEND_STRL("STDERR"));
 608         ec.name_len = sizeof("STDERR");
 609         ec.module_number = 0;
 610         zend_register_constant(&ec TSRMLS_CC);
 611 
 612         FREE_ZVAL(zin);
 613         FREE_ZVAL(zout);
 614         FREE_ZVAL(zerr);
 615 }
 616 /* }}} */
 617 
 618 static const char *param_mode_conflict = "Either execute direct code, process stdin or use a file.\n";
 619 
 620 /* {{{ cli_seek_file_begin
 621  */
 622 static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file, int *lineno TSRMLS_DC)
 623 {
 624         int c;
 625 
 626         *lineno = 1;
 627 
 628         file_handle->type = ZEND_HANDLE_FP;
 629         file_handle->opened_path = NULL;
 630         file_handle->free_filename = 0;
 631         if (!(file_handle->handle.fp = VCWD_FOPEN(script_file, "rb"))) {
 632                 php_printf("Could not open input file: %s\n", script_file);
 633                 return FAILURE;
 634         }
 635         file_handle->filename = script_file;
 636 
 637         /* #!php support */
 638         c = fgetc(file_handle->handle.fp);
 639         if (c == '#' && (c = fgetc(file_handle->handle.fp)) == '!') {
 640                 while (c != '\n' && c != '\r' && c != EOF) {
 641                         c = fgetc(file_handle->handle.fp);      /* skip to end of line */
 642                 }
 643                 /* handle situations where line is terminated by \r\n */
 644                 if (c == '\r') {
 645                         if (fgetc(file_handle->handle.fp) != '\n') {
 646                                 long pos = ftell(file_handle->handle.fp);
 647                                 fseek(file_handle->handle.fp, pos - 1, SEEK_SET);
 648                         }
 649                 }
 650                 *lineno = 2;
 651         } else {
 652                 rewind(file_handle->handle.fp);
 653         }
 654 
 655         return SUCCESS;
 656 }
 657 /* }}} */
 658 
 659 static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */
 660 {
 661         int c;
 662         zend_file_handle file_handle;
 663         int behavior = PHP_MODE_STANDARD;
 664         char *reflection_what = NULL;
 665         volatile int request_started = 0;
 666         volatile int exit_status = 0;
 667         char *php_optarg = NULL, *orig_optarg = NULL;
 668         int php_optind = 1, orig_optind = 1;
 669         char *exec_direct=NULL, *exec_run=NULL, *exec_begin=NULL, *exec_end=NULL;
 670         char *arg_free=NULL, **arg_excp=&arg_free;
 671         char *script_file=NULL, *translated_path = NULL;
 672         int interactive=0;
 673         int lineno = 0;
 674         const char *param_error=NULL;
 675         int hide_argv = 0;
 676 
 677         zend_try {
 678         
 679                 CG(in_compilation) = 0; /* not initialized but needed for several options */
 680                 EG(uninitialized_zval_ptr) = NULL;
 681 
 682                 while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
 683                         switch (c) {
 684 
 685                         case 'i': /* php info & quit */
 686                                 if (php_request_startup(TSRMLS_C)==FAILURE) {
 687                                         goto err;
 688                                 }
 689                                 request_started = 1;
 690                                 php_print_info(0xFFFFFFFF TSRMLS_CC);
 691                                 php_output_end_all(TSRMLS_C);
 692                                 exit_status = (c == '?' && argc > 1 && !strchr(argv[1],  c));
 693                                 goto out;
 694 
 695                         case 'v': /* show php version & quit */
 696                                 php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2016 The PHP Group\n%s",
 697                                         PHP_VERSION, cli_sapi_module.name, __DATE__, __TIME__,
 698 #if ZEND_DEBUG && defined(HAVE_GCOV)
 699                                         "(DEBUG GCOV)",
 700 #elif ZEND_DEBUG
 701                                         "(DEBUG)",
 702 #elif defined(HAVE_GCOV)
 703                                         "(GCOV)",
 704 #else
 705                                         "",
 706 #endif
 707                                         get_zend_version()
 708                                 );
 709                                 sapi_deactivate(TSRMLS_C);
 710                                 goto out;
 711 
 712                         case 'm': /* list compiled in modules */
 713                                 if (php_request_startup(TSRMLS_C)==FAILURE) {
 714                                         goto err;
 715                                 }
 716                                 request_started = 1;
 717                                 php_printf("[PHP Modules]\n");
 718                                 print_modules(TSRMLS_C);
 719                                 php_printf("\n[Zend Modules]\n");
 720                                 print_extensions(TSRMLS_C);
 721                                 php_printf("\n");
 722                                 php_output_end_all(TSRMLS_C);
 723                                 exit_status=0;
 724                                 goto out;
 725 
 726                         default:
 727                                 break;
 728                         }
 729                 }
 730 
 731                 /* Set some CLI defaults */
 732                 SG(options) |= SAPI_OPTION_NO_CHDIR;
 733 
 734                 php_optind = orig_optind;
 735                 php_optarg = orig_optarg;
 736                 while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
 737                         switch (c) {
 738 
 739                         case 'a':       /* interactive mode */
 740                                 if (!interactive) {
 741                                         if (behavior != PHP_MODE_STANDARD) {
 742                                                 param_error = param_mode_conflict;
 743                                                 break;
 744                                         }
 745 
 746                                         interactive=1;
 747                                 }
 748                                 break;
 749 
 750                         case 'C': /* don't chdir to the script directory */
 751                                 /* This is default so NOP */
 752                                 break;
 753 
 754                         case 'F':
 755                                 if (behavior == PHP_MODE_PROCESS_STDIN) {
 756                                         if (exec_run || script_file) {
 757                                                 param_error = "You can use -R or -F only once.\n";
 758                                                 break;
 759                                         }
 760                                 } else if (behavior != PHP_MODE_STANDARD) {
 761                                         param_error = param_mode_conflict;
 762                                         break;
 763                                 }
 764                                 behavior=PHP_MODE_PROCESS_STDIN;
 765                                 script_file = php_optarg;
 766                                 break;
 767 
 768                         case 'f': /* parse file */
 769                                 if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) {
 770                                         param_error = param_mode_conflict;
 771                                         break;
 772                                 } else if (script_file) {
 773                                         param_error = "You can use -f only once.\n";
 774                                         break;
 775                                 }
 776                                 script_file = php_optarg;
 777                                 break;
 778 
 779                         case 'l': /* syntax check mode */
 780                                 if (behavior != PHP_MODE_STANDARD) {
 781                                         break;
 782                                 }
 783                                 behavior=PHP_MODE_LINT;
 784                                 break;
 785 
 786 #if 0 /* not yet operational, see also below ... */
 787                         case '': /* generate indented source mode*/
 788                                 if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) {
 789                                         param_error = "Source indenting only works for files.\n";
 790                                         break;
 791                                 }
 792                                 behavior=PHP_MODE_INDENT;
 793                                 break;
 794 #endif
 795 
 796                         case 'q': /* do not generate HTTP headers */
 797                                 /* This is default so NOP */
 798                                 break;
 799 
 800                         case 'r': /* run code from command line */
 801                                 if (behavior == PHP_MODE_CLI_DIRECT) {
 802                                         if (exec_direct || script_file) {
 803                                                 param_error = "You can use -r only once.\n";
 804                                                 break;
 805                                         }
 806                                 } else if (behavior != PHP_MODE_STANDARD || interactive) {
 807                                         param_error = param_mode_conflict;
 808                                         break;
 809                                 }
 810                                 behavior=PHP_MODE_CLI_DIRECT;
 811                                 exec_direct=php_optarg;
 812                                 break;
 813                         
 814                         case 'R':
 815                                 if (behavior == PHP_MODE_PROCESS_STDIN) {
 816                                         if (exec_run || script_file) {
 817                                                 param_error = "You can use -R or -F only once.\n";
 818                                                 break;
 819                                         }
 820                                 } else if (behavior != PHP_MODE_STANDARD) {
 821                                         param_error = param_mode_conflict;
 822                                         break;
 823                                 }
 824                                 behavior=PHP_MODE_PROCESS_STDIN;
 825                                 exec_run=php_optarg;
 826                                 break;
 827 
 828                         case 'B':
 829                                 if (behavior == PHP_MODE_PROCESS_STDIN) {
 830                                         if (exec_begin) {
 831                                                 param_error = "You can use -B only once.\n";
 832                                                 break;
 833                                         }
 834                                 } else if (behavior != PHP_MODE_STANDARD || interactive) {
 835                                         param_error = param_mode_conflict;
 836                                         break;
 837                                 }
 838                                 behavior=PHP_MODE_PROCESS_STDIN;
 839                                 exec_begin=php_optarg;
 840                                 break;
 841 
 842                         case 'E':
 843                                 if (behavior == PHP_MODE_PROCESS_STDIN) {
 844                                         if (exec_end) {
 845                                                 param_error = "You can use -E only once.\n";
 846                                                 break;
 847                                         }
 848                                 } else if (behavior != PHP_MODE_STANDARD || interactive) {
 849                                         param_error = param_mode_conflict;
 850                                         break;
 851                                 }
 852                                 behavior=PHP_MODE_PROCESS_STDIN;
 853                                 exec_end=php_optarg;
 854                                 break;
 855 
 856                         case 's': /* generate highlighted HTML from source */
 857                                 if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) {
 858                                         param_error = "Source highlighting only works for files.\n";
 859                                         break;
 860                                 }
 861                                 behavior=PHP_MODE_HIGHLIGHT;
 862                                 break;
 863 
 864                         case 'w':
 865                                 if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) {
 866                                         param_error = "Source stripping only works for files.\n";
 867                                         break;
 868                                 }
 869                                 behavior=PHP_MODE_STRIP;
 870                                 break;
 871 
 872                         case 'z': /* load extension file */
 873                                 zend_load_extension(php_optarg);
 874                                 break;
 875                         case 'H':
 876                                 hide_argv = 1;
 877                                 break;
 878                         case 10:
 879                                 behavior=PHP_MODE_REFLECTION_FUNCTION;
 880                                 reflection_what = php_optarg;
 881                                 break;
 882                         case 11:
 883                                 behavior=PHP_MODE_REFLECTION_CLASS;
 884                                 reflection_what = php_optarg;
 885                                 break;
 886                         case 12:
 887                                 behavior=PHP_MODE_REFLECTION_EXTENSION;
 888                                 reflection_what = php_optarg;
 889                                 break;
 890                         case 13:
 891                                 behavior=PHP_MODE_REFLECTION_ZEND_EXTENSION;
 892                                 reflection_what = php_optarg;
 893                                 break;
 894                         case 14:
 895                                 behavior=PHP_MODE_REFLECTION_EXT_INFO;
 896                                 reflection_what = php_optarg;
 897                                 break;
 898                         case 15:
 899                                 behavior = PHP_MODE_SHOW_INI_CONFIG;
 900                                 break;
 901                         default:
 902                                 break;
 903                         }
 904                 }
 905 
 906                 if (param_error) {
 907                         PUTS(param_error);
 908                         exit_status=1;
 909                         goto err;
 910                 }
 911 
 912                 if (interactive) {
 913 #if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
 914                         printf("Interactive shell\n\n");
 915 #else
 916                         printf("Interactive mode enabled\n\n");
 917 #endif
 918                         fflush(stdout);
 919                 }
 920 
 921                 CG(interactive) = interactive;
 922 
 923                 /* only set script_file if not set already and not in direct mode and not at end of parameter list */
 924                 if (argc > php_optind 
 925                   && !script_file 
 926                   && behavior!=PHP_MODE_CLI_DIRECT 
 927                   && behavior!=PHP_MODE_PROCESS_STDIN 
 928                   && strcmp(argv[php_optind-1],"--")) 
 929                 {
 930                         script_file=argv[php_optind];
 931                         php_optind++;
 932                 }
 933                 if (script_file) {
 934                         if (cli_seek_file_begin(&file_handle, script_file, &lineno TSRMLS_CC) != SUCCESS) {
 935                                 goto err;
 936                         } else {
 937                                 char real_path[MAXPATHLEN];
 938                                 if (VCWD_REALPATH(script_file, real_path)) {
 939                                         translated_path = strdup(real_path);
 940                                 }
 941                                 script_filename = script_file;
 942                         }
 943                 } else {
 944                         /* We could handle PHP_MODE_PROCESS_STDIN in a different manner  */
 945                         /* here but this would make things only more complicated. And it */
 946                         /* is consitent with the way -R works where the stdin file handle*/
 947                         /* is also accessible. */
 948                         file_handle.filename = "-";
 949                         file_handle.handle.fp = stdin;
 950                 }
 951                 file_handle.type = ZEND_HANDLE_FP;
 952                 file_handle.opened_path = NULL;
 953                 file_handle.free_filename = 0;
 954                 php_self = (char*)file_handle.filename;
 955 
 956                 /* before registering argv to module exchange the *new* argv[0] */
 957                 /* we can achieve this without allocating more memory */
 958                 SG(request_info).argc=argc-php_optind+1;
 959                 arg_excp = argv+php_optind-1;
 960                 arg_free = argv[php_optind-1];
 961                 SG(request_info).path_translated = translated_path? translated_path: (char*)file_handle.filename;
 962                 argv[php_optind-1] = (char*)file_handle.filename;
 963                 SG(request_info).argv=argv+php_optind-1;
 964 
 965                 if (php_request_startup(TSRMLS_C)==FAILURE) {
 966                         *arg_excp = arg_free;
 967                         fclose(file_handle.handle.fp);
 968                         PUTS("Could not startup.\n");
 969                         goto err;
 970                 }
 971                 request_started = 1;
 972                 CG(start_lineno) = lineno;
 973                 *arg_excp = arg_free; /* reconstuct argv */
 974 
 975                 if (hide_argv) {
 976                         int i;
 977                         for (i = 1; i < argc; i++) {
 978                                 memset(argv[i], 0, strlen(argv[i]));
 979                         }
 980                 }
 981 
 982                 zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
 983 
 984                 PG(during_request_startup) = 0;
 985                 switch (behavior) {
 986                 case PHP_MODE_STANDARD:
 987                         if (strcmp(file_handle.filename, "-")) {
 988                                 cli_register_file_handles(TSRMLS_C);
 989                         }
 990 
 991                         if (interactive && cli_shell_callbacks.cli_shell_run) {
 992                                 exit_status = cli_shell_callbacks.cli_shell_run(TSRMLS_C);
 993                         } else {
 994                                 php_execute_script(&file_handle TSRMLS_CC);
 995                                 exit_status = EG(exit_status);
 996                         }
 997                         break;
 998                 case PHP_MODE_LINT:
 999                         exit_status = php_lint_script(&file_handle TSRMLS_CC);
1000                         if (exit_status==SUCCESS) {
1001                                 zend_printf("No syntax errors detected in %s\n", file_handle.filename);
1002                         } else {
1003                                 zend_printf("Errors parsing %s\n", file_handle.filename);
1004                         }
1005                         break;
1006                 case PHP_MODE_STRIP:
1007                         if (open_file_for_scanning(&file_handle TSRMLS_CC)==SUCCESS) {
1008                                 zend_strip(TSRMLS_C);
1009                         }
1010                         goto out;
1011                         break;
1012                 case PHP_MODE_HIGHLIGHT:
1013                         {
1014                                 zend_syntax_highlighter_ini syntax_highlighter_ini;
1015 
1016                                 if (open_file_for_scanning(&file_handle TSRMLS_CC)==SUCCESS) {
1017                                         php_get_highlight_struct(&syntax_highlighter_ini);
1018                                         zend_highlight(&syntax_highlighter_ini TSRMLS_CC);
1019                                 }
1020                                 goto out;
1021                         }
1022                         break;
1023 #if 0
1024                         /* Zeev might want to do something with this one day */
1025                 case PHP_MODE_INDENT:
1026                         open_file_for_scanning(&file_handle TSRMLS_CC);
1027                         zend_indent();
1028                         zend_file_handle_dtor(file_handle.handle TSRMLS_CC);
1029                         goto out;
1030                         break;
1031 #endif
1032                 case PHP_MODE_CLI_DIRECT:
1033                         cli_register_file_handles(TSRMLS_C);
1034                         if (zend_eval_string_ex(exec_direct, NULL, "Command line code", 1 TSRMLS_CC) == FAILURE) {
1035                                 exit_status=254;
1036                         }
1037                         break;
1038                         
1039                 case PHP_MODE_PROCESS_STDIN:
1040                         {
1041                                 char *input;
1042                                 size_t len, index = 0;
1043                                 zval *argn, *argi;
1044 
1045                                 cli_register_file_handles(TSRMLS_C);
1046 
1047                                 if (exec_begin && zend_eval_string_ex(exec_begin, NULL, "Command line begin code", 1 TSRMLS_CC) == FAILURE) {
1048                                         exit_status=254;
1049                                 }
1050                                 ALLOC_ZVAL(argi);
1051                                 Z_TYPE_P(argi) = IS_LONG;
1052                                 Z_LVAL_P(argi) = index;
1053                                 INIT_PZVAL(argi);
1054                                 zend_hash_update(&EG(symbol_table), "argi", sizeof("argi"), &argi, sizeof(zval *), NULL);
1055                                 while (exit_status == SUCCESS && (input=php_stream_gets(s_in_process, NULL, 0)) != NULL) {
1056                                         len = strlen(input);
1057                                         while (len-- && (input[len]=='\n' || input[len]=='\r')) {
1058                                                 input[len] = '\0';
1059                                         }
1060                                         ALLOC_ZVAL(argn);
1061                                         Z_TYPE_P(argn) = IS_STRING;
1062                                         Z_STRLEN_P(argn) = ++len;
1063                                         Z_STRVAL_P(argn) = estrndup(input, len);
1064                                         INIT_PZVAL(argn);
1065                                         zend_hash_update(&EG(symbol_table), "argn", sizeof("argn"), &argn, sizeof(zval *), NULL);
1066                                         Z_LVAL_P(argi) = ++index;
1067                                         if (exec_run) {
1068                                                 if (zend_eval_string_ex(exec_run, NULL, "Command line run code", 1 TSRMLS_CC) == FAILURE) {
1069                                                         exit_status=254;
1070                                                 }
1071                                         } else {
1072                                                 if (script_file) {
1073                                                         if (cli_seek_file_begin(&file_handle, script_file, &lineno TSRMLS_CC) != SUCCESS) {
1074                                                                 exit_status = 1;
1075                                                         } else {
1076                                                                 CG(start_lineno) = lineno;
1077                                                                 php_execute_script(&file_handle TSRMLS_CC);
1078                                                                 exit_status = EG(exit_status);
1079                                                         }
1080                                                 }
1081                                         }
1082                                         efree(input);
1083                                 }
1084                                 if (exec_end && zend_eval_string_ex(exec_end, NULL, "Command line end code", 1 TSRMLS_CC) == FAILURE) {
1085                                         exit_status=254;
1086                                 }
1087 
1088                                 break;
1089                         }
1090                         case PHP_MODE_REFLECTION_FUNCTION:
1091                         case PHP_MODE_REFLECTION_CLASS:
1092                         case PHP_MODE_REFLECTION_EXTENSION:
1093                         case PHP_MODE_REFLECTION_ZEND_EXTENSION:
1094                                 {
1095                                         zend_class_entry *pce = NULL;
1096                                         zval *arg, *ref;
1097                                         zend_execute_data execute_data;
1098 
1099                                         switch (behavior) {
1100                                                 default:
1101                                                         break;
1102                                                 case PHP_MODE_REFLECTION_FUNCTION:
1103                                                         if (strstr(reflection_what, "::")) {
1104                                                                 pce = reflection_method_ptr;
1105                                                         } else {
1106                                                                 pce = reflection_function_ptr;
1107                                                         }
1108                                                         break;
1109                                                 case PHP_MODE_REFLECTION_CLASS:
1110                                                         pce = reflection_class_ptr;
1111                                                         break;
1112                                                 case PHP_MODE_REFLECTION_EXTENSION:
1113                                                         pce = reflection_extension_ptr;
1114                                                         break;
1115                                                 case PHP_MODE_REFLECTION_ZEND_EXTENSION:
1116                                                         pce = reflection_zend_extension_ptr;
1117                                                         break;
1118                                         }
1119                                         
1120                                         MAKE_STD_ZVAL(arg);
1121                                         ZVAL_STRING(arg, reflection_what, 1);
1122                                         ALLOC_ZVAL(ref);
1123                                         object_init_ex(ref, pce);
1124                                         INIT_PZVAL(ref);
1125 
1126                                         memset(&execute_data, 0, sizeof(zend_execute_data));
1127                                         EG(current_execute_data) = &execute_data;
1128                                         EX(function_state).function = pce->constructor;
1129                                         zend_call_method_with_1_params(&ref, pce, &pce->constructor, "__construct", NULL, arg);
1130 
1131                                         if (EG(exception)) {
1132                                                 zval *msg = zend_read_property(zend_exception_get_default(TSRMLS_C), EG(exception), "message", sizeof("message")-1, 0 TSRMLS_CC);
1133                                                 zend_printf("Exception: %s\n", Z_STRVAL_P(msg));
1134                                                 zval_ptr_dtor(&EG(exception));
1135                                                 EG(exception) = NULL;
1136                                         } else {
1137                                                 zend_call_method_with_1_params(NULL, reflection_ptr, NULL, "export", NULL, ref);
1138                                         }
1139                                         zval_ptr_dtor(&ref);
1140                                         zval_ptr_dtor(&arg);
1141 
1142                                         break;
1143                                 }
1144                         case PHP_MODE_REFLECTION_EXT_INFO:
1145                                 {
1146                                         int len = strlen(reflection_what);
1147                                         char *lcname = zend_str_tolower_dup(reflection_what, len);
1148                                         zend_module_entry *module;
1149 
1150                                         if (zend_hash_find(&module_registry, lcname, len+1, (void**)&module) == FAILURE) {
1151                                                 if (!strcmp(reflection_what, "main")) {
1152                                                         display_ini_entries(NULL);
1153                                                 } else {
1154                                                         zend_printf("Extension '%s' not present.\n", reflection_what);
1155                                                         exit_status = 1;
1156                                                 }
1157                                         } else {
1158                                                 php_info_print_module(module TSRMLS_CC);
1159                                         }
1160                                         
1161                                         efree(lcname);
1162                                         break;
1163                                 }
1164                         case PHP_MODE_SHOW_INI_CONFIG:
1165                                 {
1166                                         zend_printf("Configuration File (php.ini) Path: %s\n", PHP_CONFIG_FILE_PATH);
1167                                         zend_printf("Loaded Configuration File:         %s\n", php_ini_opened_path ? php_ini_opened_path : "(none)");
1168                                         zend_printf("Scan for additional .ini files in: %s\n", php_ini_scanned_path  ? php_ini_scanned_path : "(none)");
1169                                         zend_printf("Additional .ini files parsed:      %s\n", php_ini_scanned_files ? php_ini_scanned_files : "(none)");
1170                                         break;
1171                                 }
1172                 }
1173         } zend_end_try();
1174 
1175 out:
1176         if (request_started) {
1177                 php_request_shutdown((void *) 0);
1178         }
1179         if (translated_path) {
1180                 free(translated_path);
1181         }
1182         if (exit_status == 0) {
1183                 exit_status = EG(exit_status);
1184         }
1185         return exit_status;
1186 err:
1187         sapi_deactivate(TSRMLS_C);
1188         zend_ini_deactivate(TSRMLS_C);
1189         exit_status = 1;
1190         goto out;
1191 }
1192 /* }}} */
1193 
1194 /* {{{ main
1195  */
1196 #ifdef PHP_CLI_WIN32_NO_CONSOLE
1197 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
1198 #else
1199 int main(int argc, char *argv[])
1200 #endif
1201 {
1202 #ifdef ZTS
1203         void ***tsrm_ls;
1204 #endif
1205 #ifdef PHP_CLI_WIN32_NO_CONSOLE
1206         int argc = __argc;
1207         char **argv = __argv;
1208 #endif
1209 
1210         int c;
1211         int exit_status = SUCCESS;
1212         int module_started = 0, sapi_started = 0;
1213         char *php_optarg = NULL;
1214         int php_optind = 1, use_extended_info = 0;
1215         char *ini_path_override = NULL;
1216         char *ini_entries = NULL;
1217         int ini_entries_len = 0;
1218         int ini_ignore = 0;
1219         sapi_module_struct *sapi_module = &cli_sapi_module;
1220 
1221         /*
1222          * Do not move this initialization. It needs to happen before argv is used
1223          * in any way.
1224          */
1225         argv = save_ps_args(argc, argv);
1226 
1227         cli_sapi_module.additional_functions = additional_functions;
1228 
1229 #if defined(PHP_WIN32) && defined(_DEBUG) && defined(PHP_WIN32_DEBUG_HEAP)
1230         {
1231                 int tmp_flag;
1232                 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1233                 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1234                 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1235                 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1236                 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1237                 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1238                 tmp_flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
1239                 tmp_flag |= _CRTDBG_DELAY_FREE_MEM_DF;
1240                 tmp_flag |= _CRTDBG_LEAK_CHECK_DF;
1241 
1242                 _CrtSetDbgFlag(tmp_flag);
1243         }
1244 #endif
1245 
1246 #ifdef HAVE_SIGNAL_H
1247 #if defined(SIGPIPE) && defined(SIG_IGN)
1248         signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
1249                                                                 that sockets created via fsockopen()
1250                                                                 don't kill PHP if the remote site
1251                                                                 closes it.  in apache|apxs mode apache
1252                                                                 does that for us!  thies@thieso.net
1253                                                                 20000419 */
1254 #endif
1255 #endif
1256 
1257 
1258 #ifdef ZTS
1259         tsrm_startup(1, 1, 0, NULL);
1260         tsrm_ls = ts_resource(0);
1261 #endif
1262 
1263 #ifdef PHP_WIN32
1264         _fmode = _O_BINARY;                     /*sets default for file streams to binary */
1265         setmode(_fileno(stdin), O_BINARY);              /* make the stdio mode be binary */
1266         setmode(_fileno(stdout), O_BINARY);             /* make the stdio mode be binary */
1267         setmode(_fileno(stderr), O_BINARY);             /* make the stdio mode be binary */
1268 #endif
1269 
1270         while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2))!=-1) {
1271                 switch (c) {
1272                         case 'c':
1273                                 if (ini_path_override) {
1274                                         free(ini_path_override);
1275                                 }
1276                                 ini_path_override = strdup(php_optarg);
1277                                 break;
1278                         case 'n':
1279                                 ini_ignore = 1;
1280                                 break;
1281                         case 'd': {
1282                                 /* define ini entries on command line */
1283                                 int len = strlen(php_optarg);
1284                                 char *val;
1285 
1286                                 if ((val = strchr(php_optarg, '='))) {
1287                                         val++;
1288                                         if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
1289                                                 ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
1290                                                 memcpy(ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
1291                                                 ini_entries_len += (val - php_optarg);
1292                                                 memcpy(ini_entries + ini_entries_len, "\"", 1);
1293                                                 ini_entries_len++;
1294                                                 memcpy(ini_entries + ini_entries_len, val, len - (val - php_optarg));
1295                                                 ini_entries_len += len - (val - php_optarg);
1296                                                 memcpy(ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
1297                                                 ini_entries_len += sizeof("\n\0\"") - 2;
1298                                         } else {
1299                                                 ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\n\0"));
1300                                                 memcpy(ini_entries + ini_entries_len, php_optarg, len);
1301                                                 memcpy(ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
1302                                                 ini_entries_len += len + sizeof("\n\0") - 2;
1303                                         }
1304                                 } else {
1305                                         ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
1306                                         memcpy(ini_entries + ini_entries_len, php_optarg, len);
1307                                         memcpy(ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
1308                                         ini_entries_len += len + sizeof("=1\n\0") - 2;
1309                                 }
1310                                 break;
1311                         }
1312 #ifndef PHP_CLI_WIN32_NO_CONSOLE
1313                         case 'S':
1314                                 sapi_module = &cli_server_sapi_module;
1315                                 cli_server_sapi_module.additional_functions = server_additional_functions;
1316                                 break;
1317 #endif
1318                         case 'h': /* help & quit */
1319                         case '?':
1320                                 php_cli_usage(argv[0]);
1321                                 goto out;
1322                         case 'i': case 'v': case 'm':
1323                                 sapi_module = &cli_sapi_module;
1324                                 goto exit_loop;
1325                         case 'e': /* enable extended info output */
1326                                 use_extended_info = 1;
1327                                 break;
1328                 }
1329         }
1330 exit_loop:
1331 
1332         sapi_module->ini_defaults = sapi_cli_ini_defaults;
1333         sapi_module->php_ini_path_override = ini_path_override;
1334         sapi_module->phpinfo_as_text = 1;
1335         sapi_module->php_ini_ignore_cwd = 1;
1336         sapi_startup(sapi_module);
1337         sapi_started = 1;
1338 
1339         sapi_module->php_ini_ignore = ini_ignore;
1340 
1341         sapi_module->executable_location = argv[0];
1342 
1343         if (sapi_module == &cli_sapi_module) {
1344                 if (ini_entries) {
1345                         ini_entries = realloc(ini_entries, ini_entries_len + sizeof(HARDCODED_INI));
1346                         memmove(ini_entries + sizeof(HARDCODED_INI) - 2, ini_entries, ini_entries_len + 1);
1347                         memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI) - 2);
1348                 } else {
1349                         ini_entries = malloc(sizeof(HARDCODED_INI));
1350                         memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI));
1351                 }
1352                 ini_entries_len += sizeof(HARDCODED_INI) - 2;
1353         }
1354 
1355         sapi_module->ini_entries = ini_entries;
1356 
1357         /* startup after we get the above ini override se we get things right */
1358         if (sapi_module->startup(sapi_module) == FAILURE) {
1359                 /* there is no way to see if we must call zend_ini_deactivate()
1360                  * since we cannot check if EG(ini_directives) has been initialised
1361                  * because the executor's constructor does not set initialize it.
1362                  * Apart from that there seems no need for zend_ini_deactivate() yet.
1363                  * So we goto out_err.*/
1364                 exit_status = 1;
1365                 goto out;
1366         }
1367         module_started = 1;
1368         
1369         /* -e option */
1370         if (use_extended_info) {
1371                 CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
1372         }
1373 
1374         zend_first_try {
1375 #ifndef PHP_CLI_WIN32_NO_CONSOLE
1376                 if (sapi_module == &cli_sapi_module) {
1377 #endif
1378                         exit_status = do_cli(argc, argv TSRMLS_CC);
1379 #ifndef PHP_CLI_WIN32_NO_CONSOLE
1380                 } else {
1381                         exit_status = do_cli_server(argc, argv TSRMLS_CC);
1382                 }
1383 #endif
1384         } zend_end_try();
1385 out:
1386         if (ini_path_override) {
1387                 free(ini_path_override);
1388         }
1389         if (ini_entries) {
1390                 free(ini_entries);
1391         }
1392         if (module_started) {
1393                 php_module_shutdown(TSRMLS_C);
1394         }
1395         if (sapi_started) {
1396                 sapi_shutdown();
1397         }
1398 #ifdef ZTS
1399         tsrm_shutdown();
1400 #endif
1401 
1402         /*
1403          * Do not move this de-initialization. It needs to happen right before
1404          * exiting.
1405          */
1406         cleanup_ps_args(argv);
1407         exit(exit_status);
1408 }
1409 /* }}} */
1410 
1411 /*
1412  * Local variables:
1413  * tab-width: 4
1414  * c-basic-offset: 4
1415  * End:
1416  * vim600: sw=4 ts=4 fdm=marker
1417  * vim<600: sw=4 ts=4
1418  */

/* [<][>][^][v][top][bottom][index][help] */