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