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