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