From db81c3d979ca63306d8ab64cb8926fdf0aa2c693 Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Thu, 29 May 2003 15:28:01 +0000 Subject: [PATCH] MFH: new switches and --style switches --- sapi/cli/README | 1 + sapi/cli/getopt.c | 293 +++++++++++++-------------- sapi/cli/php_cli.c | 462 ++++++++++++++++++++++++++++-------------- sapi/cli/php_getopt.h | 33 ++- 4 files changed, 479 insertions(+), 310 deletions(-) diff --git a/sapi/cli/README b/sapi/cli/README index e6bf5cc6c6..9e519e9bd0 100644 --- a/sapi/cli/README +++ b/sapi/cli/README @@ -16,4 +16,5 @@ The main differences between the two: * implicit_flush always on * -r option which allows execution of PHP code directly from the command line (e.g. php -r 'echo md5("test");' ) +* Other more sophisticated command line switches (see: man php) * max_execution_time is set to unlimited, overriding php.ini setting. diff --git a/sapi/cli/getopt.c b/sapi/cli/getopt.c index f5874d577e..01e532b7cb 100644 --- a/sapi/cli/getopt.c +++ b/sapi/cli/getopt.c @@ -1,4 +1,22 @@ -/* Borrowed from Apache NT Port */ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2003 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ #include #include @@ -10,164 +28,129 @@ #define OPTERRARG (3) -char *ap_php_optarg; -int ap_php_optind = 1; -static int ap_php_opterr = 1; - -static int -ap_php_optiserr(int argc, char * const *argv, int oint, const char *optstr, - int optchr, int err) +static int php_opt_error(int argc, char * const *argv, int oint, int optchr, int err, int show_err) { - if (ap_php_opterr) - { - fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1); - switch(err) - { - case OPTERRCOLON: - fprintf(stderr, ": in flags\n"); - break; - case OPTERRNF: - fprintf(stderr, "option not found %c\n", argv[oint][optchr]); - break; - case OPTERRARG: - fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]); - break; - default: - fprintf(stderr, "unknown\n"); - break; - } - } - return('?'); + if (show_err) + { + fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1); + switch(err) + { + case OPTERRCOLON: + fprintf(stderr, ": in flags\n"); + break; + case OPTERRNF: + fprintf(stderr, "option not found %c\n", argv[oint][optchr]); + break; + case OPTERRARG: + fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]); + break; + default: + fprintf(stderr, "unknown\n"); + break; + } + } + return('?'); } - -int ap_php_getopt(int argc, char* const *argv, const char *optstr) -{ - static int optchr = 0; - static int dash = 0; /* have already seen the - */ - char *cp; +int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err) +{ + static int optchr = 0; + static int dash = 0; /* have already seen the - */ + int arg_start = 2; - if (ap_php_optind >= argc) - return(EOF); - if (!dash && (argv[ap_php_optind][0] != '-')) - return(EOF); - if (!dash && (argv[ap_php_optind][0] == '-') && !argv[ap_php_optind][1]) - { - /* - * use to specify stdin. Need to let pgm process this and - * the following args - */ - return(EOF); - } - if ((argv[ap_php_optind][0] == '-') && (argv[ap_php_optind][1] == '-')) - { - /* -- indicates end of args */ - ap_php_optind++; - return(EOF); - } - if (!dash) - { - assert((argv[ap_php_optind][0] == '-') && argv[ap_php_optind][1]); - dash = 1; - optchr = 1; - } + int opts_idx = -1; - /* Check if the guy tries to do a -: kind of flag */ - assert(dash); - if (argv[ap_php_optind][optchr] == ':') - { - dash = 0; - ap_php_optind++; - return(ap_php_optiserr(argc, argv, ap_php_optind-1, optstr, optchr, OPTERRCOLON)); - } - if (!(cp = strchr(optstr, argv[ap_php_optind][optchr]))) - { - int errind = ap_php_optind; - int errchr = optchr; + if (*optind >= argc) { + return(EOF); + } + if (!dash) { + if ((argv[*optind][0] != '-')) { + return(EOF); + } else { + if (!argv[*optind][1]) + { + /* + * use to specify stdin. Need to let pgm process this and + * the following args + */ + return(EOF); + } + } + } + if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) { + /* '--' indicates end of args if not followed by a known long option name */ + while (1) { + opts_idx++; + if (opts[opts_idx].opt_char == '-') { + (*optind)++; + return(EOF); + } else if (opts[opts_idx].opt_name && !strcmp(&argv[*optind][2], opts[opts_idx].opt_name)) { + break; + } + } + optchr = 0; + dash = 1; + arg_start = 2 + strlen(opts[opts_idx].opt_name); + } + if (!dash) { + dash = 1; + optchr = 1; + } - if (!argv[ap_php_optind][optchr+1]) - { - dash = 0; - ap_php_optind++; - } - else - optchr++; - return(ap_php_optiserr(argc, argv, errind, optstr, errchr, OPTERRNF)); - } - if (cp[1] == ':') - { - /* Check for cases where the value of the argument - is in the form - or in the form - */ - dash = 0; - if(!argv[ap_php_optind][2]) { - ap_php_optind++; - if (ap_php_optind == argc) - return(ap_php_optiserr(argc, argv, ap_php_optind-1, optstr, optchr, OPTERRARG)); - ap_php_optarg = argv[ap_php_optind++]; - } - else - { - ap_php_optarg = &argv[ap_php_optind][2]; - ap_php_optind++; - } - return(*cp); - } - else - { - if (!argv[ap_php_optind][optchr+1]) - { - dash = 0; - ap_php_optind++; - } - else - optchr++; - return(*cp); - } - assert(0); - return(0); /* never reached */ + /* Check if the guy tries to do a -: kind of flag */ + if (argv[*optind][optchr] == ':') { + dash = 0; + (*optind)++; + return (php_opt_error(argc, argv, *optind-1, optchr, OPTERRCOLON, show_err)); + } + if (opts_idx < 0) { + while (1) { + opts_idx++; + if (opts[opts_idx].opt_char == '-') { + int errind = *optind; + int errchr = optchr; + + if (!argv[*optind][optchr+1]) { + dash = 0; + (*optind)++; + } else { + optchr++; + } + return(php_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err)); + } else if (argv[*optind][optchr] == opts[opts_idx].opt_char) { + break; + } + } + } + if (opts[opts_idx].need_param) { + /* Check for cases where the value of the argument + is in the form - or in the form - */ + dash = 0; + if(!argv[*optind][arg_start]) { + (*optind)++; + if (*optind == argc) { + return(php_opt_error(argc, argv, *optind-1, optchr, OPTERRARG, show_err)); + } + *optarg = argv[(*optind)++]; + } else { + *optarg = &argv[*optind][arg_start]; + (*optind)++; + } + return opts[opts_idx].opt_char; + } else { + if (arg_start == 2) { + if (!argv[*optind][optchr+1]) + { + dash = 0; + (*optind)++; + } else { + optchr++; + } + } else { + (*optind)++; + } + return opts[opts_idx].opt_char; + } + assert(0); + return(0); /* never reached */ } - -#ifdef TESTGETOPT -int - main (int argc, char **argv) - { - int c; - extern char *ap_php_optarg; - extern int ap_php_optind; - int aflg = 0; - int bflg = 0; - int errflg = 0; - char *ofile = NULL; - - while ((c = ap_php_getopt(argc, argv, "abo:")) != EOF) - switch (c) { - case 'a': - if (bflg) - errflg++; - else - aflg++; - break; - case 'b': - if (aflg) - errflg++; - else - bflg++; - break; - case 'o': - ofile = ap_php_optarg; - (void)printf("ofile = %s\n", ofile); - break; - case '?': - errflg++; - } - if (errflg) { - (void)fprintf(stderr, - "usage: cmd [-a|-b] [-o ] files...\n"); - exit (2); - } - for ( ; ap_php_optind < argc; ap_php_optind++) - (void)printf("%s\n", argv[ap_php_optind]); - return 0; - } - -#endif /* TESTGETOPT */ diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index c28b1886a1..df735d333e 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -89,11 +89,39 @@ #define PHP_MODE_LINT 4 #define PHP_MODE_STRIP 5 #define PHP_MODE_CLI_DIRECT 6 - -extern char *ap_php_optarg; -extern int ap_php_optind; - -#define OPTSTRING "aCc:d:ef:g:hilmnqr:sw?vz:" +#define PHP_MODE_PROCESS_STDIN 7 + +static char *optarg = NULL; +static int optind = 1; + +static const opt_struct OPTIONS[] = { + {'a', 0, "interactive"}, + {'B', 1, "process-begin"}, + {'C', 0, "no-chdir"}, /* for compatibility with CGI (do not chdir to script directory) */ + {'c', 1, "php-ini"}, + {'d', 1, "define"}, + {'E', 1, "process-end"}, + {'e', 0, "profile-info"}, + {'F', 1, "process-file"}, + {'f', 1, "file"}, + {'g', 1, "global"}, + {'h', 0, "help"}, + {'i', 0, "info"}, + {'l', 0, "syntax-check"}, + {'m', 0, "modules"}, + {'n', 0, "no-php-ini"}, + {'q', 0, "no-header"}, /* for compatibility with CGI (do not generate HTTP headers) */ + {'R', 1, "process-code"}, + {'H', 0, "hide-args"}, + {'r', 1, "run"}, + {'s', 0, "syntax-highlight"}, + {'s', 0, "syntax-highlighting"}, + {'w', 0, "strip"}, + {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ + {'v', 0, "version"}, + {'z', 1, "zend-extension"}, + {'-', 0, NULL} /* end of args */ +}; static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC) { @@ -244,10 +272,6 @@ static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) static void sapi_cli_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) { - if (sapi_header) { - PHPWRITE_H(sapi_header->header, sapi_header->header_len); - PHPWRITE_H("\r\n", 2); - } } @@ -334,9 +358,12 @@ static void php_cli_usage(char *argv0) prog = "php"; } - php_printf( "Usage: %s [options] [-f] [args...]\n" - " %s [options] -r [args...]\n" - " %s [options] [-- args...]\n" + php_printf( "Usage: %s [options] [-f] [--] [args...]\n" + " %s [options] -r [--] [args...]\n" + " %s [options] [-B ] -R [-E ] [--] [args...]\n" + " %s [options] [-B ] -F [-E ] [--] [args...]\n" + " %s [options] -- [args...]\n" + "\n" " -a Run interactively\n" " -c | Look for php.ini file in this directory\n" " -n No php.ini file will be used\n" @@ -348,6 +375,11 @@ static void php_cli_usage(char *argv0) " -l Syntax check only (lint)\n" " -m Show compiled in modules\n" " -r Run PHP without using script tags \n" + " -B Run PHP before processing input lines\n" + " -R Run PHP for every input line\n" + " -F Parse and execute for every input line\n" + " -E Run PHP after processing all input lines\n" + " -H Hide any passed arguments from external tools.\n" " -s Display colour syntax highlighted source.\n" " -v Version number\n" " -w Display source with stripped comments and whitespace.\n" @@ -355,7 +387,8 @@ static void php_cli_usage(char *argv0) "\n" " args... Arguments passed to script. Use -- args when first argument \n" " starts with - or script is read from stdin\n" - , prog, prog, prog); + "\n" + , prog, prog, prog, prog, prog); } /* }}} */ @@ -390,6 +423,9 @@ static void php_register_command_line_global_vars(char **arg TSRMLS_DC) efree(*arg); } +static php_stream_context *sc_in_process = NULL; +static php_stream *s_in_process = NULL; + static void cli_register_file_handles(TSRMLS_D) { zval *zin, *zout, *zerr; @@ -409,6 +445,9 @@ static void cli_register_file_handles(TSRMLS_D) return; } + sc_in_process = sc_in; + s_in_process = s_in; + php_stream_to_zval(s_in, zin); php_stream_to_zval(s_out, zout); php_stream_to_zval(s_err, zerr); @@ -436,6 +475,42 @@ static void cli_register_file_handles(TSRMLS_D) FREE_ZVAL(zerr); } +static const char *param_mode_conflict = "Either execute direct code, process stdin or use a file.\n"; + +/* {{{ cli_seek_file_begin + */ +static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file, int *lineno TSRMLS_DC) +{ + int c; + + *lineno = 1; + + if (!(file_handle->handle.fp = VCWD_FOPEN(script_file, "rb"))) { + php_printf("Could not open input file: %s.\n", script_file); + return FAILURE; + } + file_handle->filename = script_file; + /* #!php support */ + c = fgetc(file_handle->handle.fp); + if (c == '#') { + while (c != 10 && c != 13) { + c = fgetc(file_handle->handle.fp); /* skip to end of line */ + } + /* handle situations where line is terminated by \r\n */ + if (c == 13) { + if (fgetc(file_handle->handle.fp) != 10) { + long pos = ftell(file_handle->handle.fp); + fseek(file_handle->handle.fp, pos - 1, SEEK_SET); + } + } + *lineno = -2; + } else { + rewind(file_handle->handle.fp); + } + return SUCCESS; +} +/* }}} */ + /* {{{ main */ int main(int argc, char *argv[]) @@ -445,16 +520,18 @@ int main(int argc, char *argv[]) zend_file_handle file_handle; /* temporary locals */ int behavior=PHP_MODE_STANDARD; - int no_headers=1; - int orig_optind=ap_php_optind; - char *orig_optarg=ap_php_optarg; + int orig_optind=optind; + char *orig_optarg=optarg; char *arg_free=NULL, **arg_excp=&arg_free; char *script_file=NULL; zend_llist global_vars; - int interactive=0, is_hashbang=0; + int interactive=0; int module_started = 0; - char *exec_direct=NULL; - char *param_error=NULL; + int lineno = 0; + char *exec_direct=NULL, *exec_run=NULL, *exec_begin=NULL, *exec_end=NULL; + const char *param_error=NULL; + int scan_input = 0; + int hide_argv = 0; /* end of temporary locals */ #ifdef ZTS zend_compiler_globals *compiler_globals; @@ -493,18 +570,18 @@ int main(int argc, char *argv[]) #endif - while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) { + while ((c = php_getopt(argc, argv, OPTIONS, &optarg, &optind, 0))!=-1) { switch (c) { case 'c': - cli_sapi_module.php_ini_path_override = strdup(ap_php_optarg); + cli_sapi_module.php_ini_path_override = strdup(optarg); break; case 'n': cli_sapi_module.php_ini_ignore = 1; break; } } - ap_php_optind = orig_optind; - ap_php_optarg = orig_optarg; + optind = orig_optind; + optarg = orig_optarg; cli_sapi_module.executable_location = argv[0]; @@ -529,23 +606,66 @@ int main(int argc, char *argv[]) module_started = 1; zend_first_try { - while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) { + zend_llist_init(&global_vars, sizeof(char *), NULL, 0); + + zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */ + CG(in_compilation) = 0; /* not initialized but needed for several options */ + EG(uninitialized_zval_ptr) = NULL; + + if (cli_sapi_module.php_ini_path_override && cli_sapi_module.php_ini_ignore) { + PUTS("You cannot use both -n and -c switch. Use -h for help.\n"); + exit_status=1; + goto out_err; + } + + while ((c = php_getopt(argc, argv, OPTIONS, &optarg, &optind, 0)) != -1) { switch (c) { + + case 'h': /* help & quit */ case '?': - no_headers = 1; php_output_startup(); php_output_activate(TSRMLS_C); SG(headers_sent) = 1; php_cli_usage(argv[0]); php_end_ob_buffers(1 TSRMLS_CC); - exit(1); - break; + exit_status=1; + goto out_err; + + + case 'i': /* php info & quit */ + if (php_request_startup(TSRMLS_C)==FAILURE) { + goto err; } + php_print_info(0xFFFFFFFF TSRMLS_CC); + php_end_ob_buffers(1 TSRMLS_CC); + exit_status=1; + goto out; + + case 'm': /* list compiled in modules */ + php_output_startup(); + php_output_activate(TSRMLS_C); + php_printf("[PHP Modules]\n"); + print_modules(TSRMLS_C); + php_printf("\n[Zend Modules]\n"); + print_extensions(TSRMLS_C); + php_printf("\n"); + php_end_ob_buffers(1 TSRMLS_CC); + exit_status=1; + goto out_err; + + case 'v': /* show php version & quit */ + if (php_request_startup(TSRMLS_C)==FAILURE) { + goto err; } - ap_php_optind = orig_optind; - ap_php_optarg = orig_optarg; + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2003 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + php_end_ob_buffers(1 TSRMLS_CC); + exit_status=1; + goto out; - zend_llist_init(&global_vars, sizeof(char *), NULL, 0); + default: + break; + } + } /* Set some CLI defaults */ SG(options) |= SAPI_OPTION_NO_CHDIR; @@ -555,19 +675,9 @@ int main(int argc, char *argv[]) INI_HARDCODED("implicit_flush", "1"); INI_HARDCODED("max_execution_time", "0"); - zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */ - CG(in_compilation) = 0; /* not initialized but needed for several options */ - EG(uninitialized_zval_ptr) = NULL; - - if (cli_sapi_module.php_ini_path_override && cli_sapi_module.php_ini_ignore) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - PUTS("You cannot use both -n and -c switch. Use -h for help.\n"); - exit_status=1; - goto out_err; - } - - while ((c = ap_php_getopt(argc, argv, OPTSTRING)) != -1) { + optind = orig_optind; + optarg = orig_optarg; + while ((c = php_getopt(argc, argv, OPTIONS, &optarg, &optind, 0)) != -1) { switch (c) { case 'a': /* interactive mode */ @@ -579,80 +689,56 @@ int main(int argc, char *argv[]) /* This is default so NOP */ break; case 'd': /* define ini entries on command line */ - define_command_line_ini_entry(ap_php_optarg); + define_command_line_ini_entry(optarg); break; case 'e': /* enable extended info output */ CG(extended_info) = 1; break; + case 'F': + if (behavior == PHP_MODE_PROCESS_STDIN) { + if (exec_run || script_file) { + param_error = "You can use -R or -F only once.\n"; + break; + } + } else if (behavior != PHP_MODE_STANDARD) { + param_error = param_mode_conflict; + break; + } + behavior=PHP_MODE_PROCESS_STDIN; + script_file = optarg; + break; + case 'f': /* parse file */ - if (behavior == PHP_MODE_CLI_DIRECT) { - param_error = "Either execute direct code or use a file.\n"; + if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) { + param_error = param_mode_conflict; + break; + } else if (script_file) { + param_error = "You can use -f only once.\n"; break; } - script_file = ap_php_optarg; - no_headers = 1; + script_file = optarg; break; case 'g': /* define global variables on command line */ { - char *arg = estrdup(ap_php_optarg); + char *arg = estrdup(optarg); zend_llist_add_element(&global_vars, &arg); } break; - case 'h': /* help & quit */ - case '?': - no_headers = 1; - php_output_startup(); - php_output_activate(TSRMLS_C); - SG(headers_sent) = 1; - php_cli_usage(argv[0]); - php_end_ob_buffers(1 TSRMLS_CC); - exit_status=1; - zend_ini_deactivate(TSRMLS_C); - goto out_err; - - case 'i': /* php info & quit */ - if (php_request_startup(TSRMLS_C)==FAILURE) { - goto err; - } - if (no_headers) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - } - php_print_info(0xFFFFFFFF TSRMLS_CC); - php_end_ob_buffers(1 TSRMLS_CC); - exit_status=1; - goto out; - case 'l': /* syntax check mode */ if (behavior != PHP_MODE_STANDARD) { break; } - no_headers = 1; behavior=PHP_MODE_LINT; break; - case 'm': /* list compiled in modules */ - php_output_startup(); - php_output_activate(TSRMLS_C); - SG(headers_sent) = 1; - php_printf("[PHP Modules]\n"); - print_modules(TSRMLS_C); - php_printf("\n[Zend Modules]\n"); - print_extensions(TSRMLS_C); - php_printf("\n"); - php_end_ob_buffers(1 TSRMLS_CC); - exit_status=1; - zend_ini_deactivate(TSRMLS_C); - goto out_err; - #if 0 /* not yet operational, see also below ... */ case '': /* generate indented source mode*/ - if (behavior == PHP_MODE_CLI_DIRECT) { + if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) { param_error = "Source indenting only works for files.\n"; break; } @@ -665,38 +751,72 @@ int main(int argc, char *argv[]) break; case 'r': /* run code from command line */ - if (behavior != PHP_MODE_STANDARD) { - param_error = "Either execute direct code or use a file.\n"; + if (behavior == PHP_MODE_CLI_DIRECT) { + if (exec_direct || script_file) { + param_error = "You can use -r only once.\n"; + break; + } + } else if (behavior != PHP_MODE_STANDARD) { + param_error = param_mode_conflict; break; } behavior=PHP_MODE_CLI_DIRECT; - exec_direct=ap_php_optarg; + exec_direct=optarg; break; - case 's': /* generate highlighted HTML from source */ - if (behavior == PHP_MODE_CLI_DIRECT) { - param_error = "Source highlighting only works for files.\n"; + case 'R': + if (behavior == PHP_MODE_PROCESS_STDIN) { + if (exec_run || script_file) { + param_error = "You can use -R or -F only once.\n"; break; } - behavior=PHP_MODE_HIGHLIGHT; + } else if (behavior != PHP_MODE_STANDARD) { + param_error = param_mode_conflict; + break; + } + behavior=PHP_MODE_PROCESS_STDIN; + exec_run=optarg; break; - case 'v': /* show php version & quit */ - no_headers = 1; - if (php_request_startup(TSRMLS_C)==FAILURE) { - goto err; + case 'B': + if (behavior == PHP_MODE_PROCESS_STDIN) { + if (exec_begin) { + param_error = "You can use -B only once.\n"; + break; } - if (no_headers) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; + } else if (behavior != PHP_MODE_STANDARD) { + param_error = param_mode_conflict; + break; } - php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2003 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); - php_end_ob_buffers(1 TSRMLS_CC); - exit_status=1; - goto out; + behavior=PHP_MODE_PROCESS_STDIN; + exec_begin=optarg; + break; + + case 'E': + if (behavior == PHP_MODE_PROCESS_STDIN) { + if (exec_end) { + param_error = "You can use -E only once.\n"; + break; + } + } else if (behavior != PHP_MODE_STANDARD) { + param_error = param_mode_conflict; + break; + } + scan_input = 1; + behavior=PHP_MODE_PROCESS_STDIN; + exec_end=optarg; + break; + + case 's': /* generate highlighted HTML from source */ + if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) { + param_error = "Source highlighting only works for files.\n"; + break; + } + behavior=PHP_MODE_HIGHLIGHT; + break; case 'w': - if (behavior == PHP_MODE_CLI_DIRECT) { + if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) { param_error = "Source stripping only works for files.\n"; break; } @@ -704,7 +824,10 @@ int main(int argc, char *argv[]) break; case 'z': /* load extension file */ - zend_load_extension(ap_php_optarg); + zend_load_extension(optarg); + break; + case 'H': + hide_argv = 1; break; default: @@ -723,38 +846,25 @@ int main(int argc, char *argv[]) CG(interactive) = interactive; /* only set script_file if not set already and not in direct mode and not at end of parameter list */ - if (argc > ap_php_optind && !script_file && behavior!=PHP_MODE_CLI_DIRECT && strcmp(argv[ap_php_optind-1],"--")) { - no_headers = 1; - script_file=argv[ap_php_optind]; - ap_php_optind++; + if (argc > optind + && !script_file + && behavior!=PHP_MODE_CLI_DIRECT + && behavior!=PHP_MODE_PROCESS_STDIN + && strcmp(argv[optind-1],"--")) + { + script_file=argv[optind]; + optind++; } if (script_file) { - if (!(file_handle.handle.fp = VCWD_FOPEN(script_file, "rb"))) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - php_printf("Could not open input file: %s.\n", script_file); + if (cli_seek_file_begin(&file_handle, script_file, &lineno TSRMLS_CC) != SUCCESS) { goto err; } - file_handle.filename = script_file; script_filename = script_file; - /* #!php support */ - c = fgetc(file_handle.handle.fp); - if (c == '#') { - while (c != 10 && c != 13) { - c = fgetc(file_handle.handle.fp); /* skip to end of line */ - } - /* handle situations where line is terminated by \r\n */ - if (c == 13) { - if (fgetc(file_handle.handle.fp) != 10) { - long pos = ftell(file_handle.handle.fp); - fseek(file_handle.handle.fp, pos - 1, SEEK_SET); - } - } - is_hashbang = 1; - } else { - rewind(file_handle.handle.fp); - } } else { + /* We could handle PHP_MODE_PROCESS_STDIN in a different manner */ + /* here but this would make things only more complicated. And it */ + /* is consitent with the way -R works where the stdin file handle*/ + /* is also accessible. */ file_handle.filename = "-"; file_handle.handle.fp = stdin; } @@ -763,14 +873,14 @@ int main(int argc, char *argv[]) file_handle.free_filename = 0; php_self = file_handle.filename; - /* before registering argv to modulule exchange the *new* argv[0] */ + /* before registering argv to module exchange the *new* argv[0] */ /* we can achieve this without allocating more memory */ - SG(request_info).argc=argc-ap_php_optind+1; - arg_excp = argv+ap_php_optind-1; - arg_free = argv[ap_php_optind-1]; + SG(request_info).argc=argc-optind+1; + arg_excp = argv+optind-1; + arg_free = argv[optind-1]; SG(request_info).path_translated = file_handle.filename; - argv[ap_php_optind-1] = file_handle.filename; - SG(request_info).argv=argv+ap_php_optind-1; + argv[optind-1] = file_handle.filename; + SG(request_info).argv=argv+optind-1; if (php_request_startup(TSRMLS_C)==FAILURE) { *arg_excp = arg_free; @@ -781,16 +891,14 @@ int main(int argc, char *argv[]) PUTS("Could not startup.\n"); goto err; } - - /* Correct line numbers when #!php is used. This is reset in php_request_startup(). */ - if (is_hashbang) { - CG(zend_lineno) = -2; - } - + CG(zend_lineno) = lineno; *arg_excp = arg_free; /* reconstuct argv */ - if (no_headers) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; + + if (hide_argv) { + int i; + for (i = 1; i < argc; i++) { + memset(argv[i], 0, strlen(argv[i])); + } } /* This actually destructs the elements of the list - ugly hack */ @@ -848,6 +956,58 @@ int main(int argc, char *argv[]) exit_status=254; } break; + + case PHP_MODE_PROCESS_STDIN: + { + char *input; + size_t len, index = 0; + pval *argn, *argi; + + cli_register_file_handles(TSRMLS_C); + + if (exec_begin && zend_eval_string(exec_begin, NULL, "Command line begin code" TSRMLS_CC) == FAILURE) { + exit_status=254; + } + ALLOC_ZVAL(argi); + Z_TYPE_P(argi) = IS_LONG; + Z_LVAL_P(argi) = index; + INIT_PZVAL(argi); + zend_hash_update(&EG(symbol_table), "argi", sizeof("argi"), &argi, sizeof(pval *), NULL); + while (exit_status == SUCCESS && (input=php_stream_gets(s_in_process, NULL, 0)) != NULL) { + len = strlen(input); + while (len-- && (input[len]=='\n' || input[len]=='\r')) { + input[len] = '\0'; + } + ALLOC_ZVAL(argn); + Z_TYPE_P(argn) = IS_STRING; + Z_STRLEN_P(argn) = ++len; + Z_STRVAL_P(argn) = estrndup(input, len); + INIT_PZVAL(argn); + zend_hash_update(&EG(symbol_table), "argn", sizeof("argn"), &argn, sizeof(pval *), NULL); + Z_LVAL_P(argi) = ++index; + if (exec_run) { + if (zend_eval_string(exec_run, NULL, "Command line run code" TSRMLS_CC) == FAILURE) { + exit_status=254; + } + } else { + if (script_file) { + if (cli_seek_file_begin(&file_handle, script_file, &lineno TSRMLS_CC) != SUCCESS) { + exit_status = 1; + } else { + CG(zend_lineno) = lineno; + php_execute_script(&file_handle TSRMLS_CC); + exit_status = EG(exit_status); + } + } + } + efree(input); + } + if (exec_end && zend_eval_string(exec_end, NULL, "Command line end code" TSRMLS_CC) == FAILURE) { + exit_status=254; + } + + break; + } } if (cli_sapi_module.php_ini_path_override) { diff --git a/sapi/cli/php_getopt.h b/sapi/cli/php_getopt.h index 40da432b59..a01fc2ae85 100644 --- a/sapi/cli/php_getopt.h +++ b/sapi/cli/php_getopt.h @@ -1,7 +1,32 @@ -/* Borrowed from Apache NT Port */ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2003 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + #include "php.h" -extern char *ap_php_optarg; -extern int ap_php_optind; +/* Define structure for one recognized option (both single char and long name). + * If short_open is '-' this is the last option. + */ +typedef struct _opt_struct { + const char opt_char; + const int need_param; + const char * opt_name; +} opt_struct; -int ap_php_getopt(int argc, char* const *argv, const char *optstr); +int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err); -- 2.40.0