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