summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schlüter <johannes@php.net>2011-02-19 16:04:30 +0000
committerJohannes Schlüter <johannes@php.net>2011-02-19 16:04:30 +0000
commit6c734a6b4c9ecf90162cf53fcf5f89864ccabbde (patch)
tree7208c4fd48a2d04612a1877b8ab14e42344a394b
parent430af9a0abe07274597eda9f6fe544e87abb7e45 (diff)
downloadphp-git-6c734a6b4c9ecf90162cf53fcf5f89864ccabbde.tar.gz
- Implement FR#53878 Interactive shell should work with shared readline extension
# This is useful w/ distributors who like to build all things shared or don't # provide the readline extension. Or if a user pefers readline's behavior over # libedit which might be used by the distributor.
-rw-r--r--NEWS1
-rw-r--r--ext/readline/config.m42
-rw-r--r--ext/readline/readline.c21
-rw-r--r--ext/readline/readline_cli.c (renamed from sapi/cli/php_cli_readline.c)240
-rw-r--r--ext/readline/readline_cli.h (renamed from sapi/cli/php_cli_readline.h)9
-rw-r--r--sapi/cli/cli.h52
-rw-r--r--sapi/cli/config.m42
-rw-r--r--sapi/cli/config.w324
-rw-r--r--sapi/cli/php_cli.c170
9 files changed, 309 insertions, 192 deletions
diff --git a/NEWS b/NEWS
index 898b701b79..0694228b90 100644
--- a/NEWS
+++ b/NEWS
@@ -112,6 +112,7 @@ PHP NEWS
. Added "cli.prompt" php.ini setting to configure the shell prompt.
. Added shortcut #inisetting=value to change ini settings at run-time.
. Changed shell not to terminate on fatal errors.
+ . Interactive shell works with shared readline extension. FR #53878.
- Improved FastCGI SAPI: (Dmitry)
. Added apache compatible functions: apache_child_terminate(),
diff --git a/ext/readline/config.m4 b/ext/readline/config.m4
index a99262a659..729033b74f 100644
--- a/ext/readline/config.m4
+++ b/ext/readline/config.m4
@@ -98,6 +98,6 @@ fi
if test "$PHP_READLINE" != "no" || test "$PHP_LIBEDIT" != "no"; then
AC_CHECK_FUNCS([rl_completion_matches])
- PHP_NEW_EXTENSION(readline, readline.c, $ext_shared, cli)
+ PHP_NEW_EXTENSION(readline, readline.c readline_cli.c, $ext_shared, cli)
PHP_SUBST(READLINE_SHARED_LIBADD)
fi
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index e9901bf7a1..c47491c199 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -26,6 +26,7 @@
#include "php.h"
#include "php_readline.h"
+#include "readline_cli.h"
#if HAVE_LIBREADLINE || HAVE_LIBEDIT
@@ -66,7 +67,9 @@ static zval *_readline_completion = NULL;
static zval _readline_array;
PHP_MINIT_FUNCTION(readline);
+PHP_MSHUTDOWN_FUNCTION(readline);
PHP_RSHUTDOWN_FUNCTION(readline);
+PHP_MINFO_FUNCTION(readline);
/* }}} */
@@ -151,11 +154,11 @@ zend_module_entry readline_module_entry = {
"readline",
php_readline_functions,
PHP_MINIT(readline),
- NULL,
+ PHP_MSHUTDOWN(readline),
NULL,
PHP_RSHUTDOWN(readline),
- NULL,
- NO_VERSION_YET,
+ PHP_MINFO(readline),
+ PHP_VERSION,
STANDARD_MODULE_PROPERTIES
};
@@ -166,7 +169,12 @@ ZEND_GET_MODULE(readline)
PHP_MINIT_FUNCTION(readline)
{
using_history();
- return SUCCESS;
+ return PHP_MINIT(cli_readline)(INIT_FUNC_ARGS_PASSTHRU);
+}
+
+PHP_MSHUTDOWN_FUNCTION(readline)
+{
+ return PHP_MSHUTDOWN(cli_readline)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
}
PHP_RSHUTDOWN_FUNCTION(readline)
@@ -186,6 +194,11 @@ PHP_RSHUTDOWN_FUNCTION(readline)
return SUCCESS;
}
+PHP_MINFO_FUNCTION(readline)
+{
+ return PHP_MINFO(cli_readline)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
+}
+
/* }}} */
/* {{{ proto string readline([string prompt])
diff --git a/sapi/cli/php_cli_readline.c b/ext/readline/readline_cli.c
index 96fb934e39..45a43de722 100644
--- a/sapi/cli/php_cli_readline.c
+++ b/ext/readline/readline_cli.c
@@ -21,8 +21,6 @@
#include "php.h"
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
-
#ifndef HAVE_RL_COMPLETION_MATCHES
#define rl_completion_matches completion_matches
#endif
@@ -61,13 +59,47 @@
#include "zend_execute.h"
#include "zend_highlight.h"
#include "zend_indent.h"
+#include "zend_exceptions.h"
+
+#include "sapi/cli/cli.h"
+#include "readline_cli.h"
-#include "php_cli_readline.h"
+#ifdef COMPILE_DL_READLINE
+#include <dlfcn.h>
+#endif
#define DEFAULT_PROMPT "\\b \\> "
ZEND_DECLARE_MODULE_GLOBALS(cli_readline);
+static char php_last_char = '\0';
+static FILE *pager_pipe = NULL;
+
+static size_t readline_shell_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
+{
+ if (CLIR_G(prompt_str)) {
+ smart_str_appendl(CLIR_G(prompt_str), str, str_length);
+ return str_length;
+ }
+
+ if (CLIR_G(pager) && *CLIR_G(pager) && !pager_pipe) {
+ pager_pipe = VCWD_POPEN(CLIR_G(pager), "w");
+ }
+ if (pager_pipe) {
+ return fwrite(str, 1, MIN(str_length, 16384), pager_pipe);
+ }
+
+ return -1;
+}
+/* }}} */
+
+static int readline_shell_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
+{
+ php_last_char = str[str_length-1];
+ return -1;
+}
+/* }}} */
+
static void cli_readline_init_globals(zend_cli_readline_globals *rg TSRMLS_DC)
{
rg->pager = NULL;
@@ -80,36 +112,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("cli.prompt", DEFAULT_PROMPT, PHP_INI_ALL, OnUpdateString, prompt, zend_cli_readline_globals, cli_readline_globals)
PHP_INI_END()
-static PHP_MINIT_FUNCTION(cli_readline)
-{
- ZEND_INIT_MODULE_GLOBALS(cli_readline, cli_readline_init_globals, NULL);
- REGISTER_INI_ENTRIES();
- return SUCCESS;
-}
-static PHP_MSHUTDOWN_FUNCTION(cli_readline)
-{
- UNREGISTER_INI_ENTRIES();
- return SUCCESS;
-}
-
-static PHP_MINFO_FUNCTION(cli_readline)
-{
- DISPLAY_INI_ENTRIES();
-}
-
-zend_module_entry cli_readline_module_entry = {
- STANDARD_MODULE_HEADER,
- "cli-readline",
- NULL,
- PHP_MINIT(cli_readline),
- PHP_MSHUTDOWN(cli_readline),
- NULL,
- NULL,
- PHP_MINFO(cli_readline),
- PHP_VERSION,
- STANDARD_MODULE_PROPERTIES
-};
typedef enum {
body,
@@ -124,7 +127,7 @@ typedef enum {
outside,
} php_code_type;
-char *cli_get_prompt(char *block, char prompt TSRMLS_DC) /* {{{ */
+static char *cli_get_prompt(char *block, char prompt TSRMLS_DC) /* {{{ */
{
smart_str retval = {0};
char *prompt_spec = CLIR_G(prompt) ? CLIR_G(prompt) : DEFAULT_PROMPT;
@@ -192,8 +195,9 @@ char *cli_get_prompt(char *block, char prompt TSRMLS_DC) /* {{{ */
smart_str_0(&retval);
return retval.c;
}
+/* }}} */
-int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC) /* {{{ */
+static int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC) /* {{{ */
{
int valid_end = 1, last_valid_end;
int brackets_count = 0;
@@ -566,13 +570,177 @@ TODO:
return retval;
} /* }}} */
-char **cli_code_completion(const char *text, int start, int end) /* {{{ */
+static char **cli_code_completion(const char *text, int start, int end) /* {{{ */
{
return rl_completion_matches(text, cli_completion_generator);
}
/* }}} */
-#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
+static int readline_shell_run(TSRMLS_D) /* {{{ */
+{
+ char *line;
+ size_t size = 4096, pos = 0, len;
+ char *code = emalloc(size);
+ char *prompt = cli_get_prompt("php", '>' TSRMLS_CC);
+ char *history_file;
+
+ if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
+ zend_file_handle *prepend_file_p;
+ zend_file_handle prepend_file = {0};
+
+ prepend_file.filename = PG(auto_prepend_file);
+ prepend_file.opened_path = NULL;
+ prepend_file.free_filename = 0;
+ prepend_file.type = ZEND_HANDLE_FILENAME;
+ prepend_file_p = &prepend_file;
+
+ zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, prepend_file_p);
+ }
+
+ history_file = tilde_expand("~/.php_history");
+ rl_attempted_completion_function = cli_code_completion;
+ rl_special_prefixes = "$";
+ read_history(history_file);
+
+ EG(exit_status) = 0;
+ while ((line = readline(prompt)) != NULL) {
+ if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) {
+ free(line);
+ break;
+ }
+
+ if (!pos && !*line) {
+ free(line);
+ continue;
+ }
+
+ len = strlen(line);
+
+ if (line[0] == '#') {
+ char *param = strstr(&line[1], "=");
+ if (param) {
+ char *cmd;
+ uint cmd_len;
+ param++;
+ cmd_len = param - &line[1] - 1;
+ cmd = estrndup(&line[1], cmd_len);
+
+ zend_alter_ini_entry_ex(cmd, cmd_len + 1, param, strlen(param), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
+ efree(cmd);
+ add_history(line);
+
+ efree(prompt);
+ /* TODO: This might be wrong! */
+ prompt = cli_get_prompt("php", '>' TSRMLS_CC);
+ continue;
+ }
+ }
+
+ if (pos + len + 2 > size) {
+ size = pos + len + 2;
+ code = erealloc(code, size);
+ }
+ memcpy(&code[pos], line, len);
+ pos += len;
+ code[pos] = '\n';
+ code[++pos] = '\0';
+
+ if (*line) {
+ add_history(line);
+ }
+
+ free(line);
+ efree(prompt);
+
+ if (!cli_is_valid_code(code, pos, &prompt TSRMLS_CC)) {
+ continue;
+ }
+
+ zend_try {
+ zend_eval_stringl(code, pos, NULL, "php shell code" TSRMLS_CC);
+ } zend_end_try();
+
+ pos = 0;
+
+ if (!pager_pipe && php_last_char != '\0' && php_last_char != '\n') {
+ readline_shell_write("\n", 1 TSRMLS_CC);
+ }
+
+ if (EG(exception)) {
+ zend_exception_error(EG(exception), E_WARNING TSRMLS_CC);
+ }
+
+ if (pager_pipe) {
+ fclose(pager_pipe);
+ pager_pipe = NULL;
+ }
+
+ php_last_char = '\0';
+ }
+ write_history(history_file);
+ free(history_file);
+ efree(code);
+ efree(prompt);
+ return EG(exit_status);
+}
+/* }}} */
+
+/*
+#ifdef COMPILE_DL_READLINE
+This dlsym() is always used as even the CGI SAPI is linked against "CLI"-only
+extensions. If that is being changed dlsym() should only be used when building
+this extension sharedto offer compatibility.
+*/
+#define GET_SHELL_CB(cb) \
+ do { \
+ (cb) = NULL; \
+ cli_shell_callbacks_t *(*get_callbacks)(); \
+ get_callbacks = dlsym(RTLD_DEFAULT, "php_cli_get_shell_callbacks"); \
+ if (get_callbacks) { \
+ (cb) = get_callbacks(); \
+ } \
+ } while(0)
+/*#else
+#define GET_SHELL_CB(cb) (cb) = php_cli_get_shell_callbacks()
+#endif*/
+
+PHP_MINIT_FUNCTION(cli_readline)
+{
+ cli_shell_callbacks_t *cb;
+
+ ZEND_INIT_MODULE_GLOBALS(cli_readline, cli_readline_init_globals, NULL);
+ REGISTER_INI_ENTRIES();
+
+ GET_SHELL_CB(cb);
+ if (cb) {
+ cb->cli_shell_write = readline_shell_write;
+ cb->cli_shell_ub_write = readline_shell_ub_write;
+ cb->cli_shell_run = readline_shell_run;
+ }
+
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(cli_readline)
+{
+ cli_shell_callbacks_t *cb;
+
+ UNREGISTER_INI_ENTRIES();
+
+ GET_SHELL_CB(cb);
+ if (cb) {
+ cb->cli_shell_write = NULL;
+ cb->cli_shell_ub_write = NULL;
+ cb->cli_shell_run = NULL;
+ }
+
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(cli_readline)
+{
+ DISPLAY_INI_ENTRIES();
+}
/*
* Local variables:
diff --git a/sapi/cli/php_cli_readline.h b/ext/readline/readline_cli.h
index d4314430e3..943417e367 100644
--- a/sapi/cli/php_cli_readline.h
+++ b/ext/readline/readline_cli.h
@@ -34,11 +34,10 @@ ZEND_END_MODULE_GLOBALS(cli_readline)
# define CLIR_G(v) (cli_readline_globals.v)
#endif
-ZEND_EXTERN_MODULE_GLOBALS(cli_readline)
+extern PHP_MINIT_FUNCTION(cli_readline);
+extern PHP_MSHUTDOWN_FUNCTION(cli_readline);
+extern PHP_MINFO_FUNCTION(cli_readline);
-extern zend_module_entry cli_readline_module_entry;
+ZEND_EXTERN_MODULE_GLOBALS(cli_readline)
-char *cli_get_prompt(char *block, char prompt TSRMLS_DC);
-int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC);
-char **cli_code_completion(const char *text, int start, int end);
diff --git a/sapi/cli/cli.h b/sapi/cli/cli.h
new file mode 100644
index 0000000000..2c069c4491
--- /dev/null
+++ b/sapi/cli/cli.h
@@ -0,0 +1,52 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.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: Johannes Schlueter <johannes@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef CLI_H
+#define CLI_H
+
+#ifdef PHP_WIN32
+# define PHP_CLI_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define PHP_CLI_API __attribute__ ((visibility("default")))
+#else
+# define PHP_CLI_API
+#endif
+
+
+extern PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC);
+
+typedef struct {
+ size_t (*cli_shell_write)(const char *str, uint str_length TSRMLS_DC);
+ int (*cli_shell_ub_write)(const char *str, uint str_length TSRMLS_DC);
+ int (*cli_shell_run)(TSRMLS_D);
+} cli_shell_callbacks_t;
+
+extern PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks();
+
+#endif /* CLI_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/sapi/cli/config.m4 b/sapi/cli/config.m4
index 0a0a66053b..68263639d5 100644
--- a/sapi/cli/config.m4
+++ b/sapi/cli/config.m4
@@ -14,7 +14,7 @@ if test "$PHP_CLI" != "no"; then
SAPI_CLI_PATH=sapi/cli/php
dnl Select SAPI
- PHP_SELECT_SAPI(cli, program, php_cli.c php_cli_readline.c,, '$(SAPI_CLI_PATH)')
+ PHP_SELECT_SAPI(cli, program, php_cli.c,, '$(SAPI_CLI_PATH)')
case $host_alias in
*aix*)
diff --git a/sapi/cli/config.w32 b/sapi/cli/config.w32
index 923aa399e5..d6eac80f68 100644
--- a/sapi/cli/config.w32
+++ b/sapi/cli/config.w32
@@ -6,7 +6,7 @@ ARG_ENABLE('crt-debug', 'Enable CRT memory dumps for debugging sent to STDERR',
ARG_ENABLE('cli-win32', 'Build console-less CLI version of PHP', 'no');
if (PHP_CLI == "yes") {
- SAPI('cli', 'php_cli.c php_cli_readline.c', 'php.exe');
+ SAPI('cli', 'php_cli.c', 'php.exe');
if (PHP_CRT_DEBUG == "yes") {
ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP");
}
@@ -14,7 +14,7 @@ if (PHP_CLI == "yes") {
}
if (PHP_CLI_WIN32 == "yes") {
- SAPI('cli_win32', 'cli_win32.c php_cli_readline.c', 'php-win.exe');
+ SAPI('cli_win32', 'cli_win32.c', 'php-win.exe');
ADD_FLAG("LDFLAGS_CLI_WIN32", "/stack:8388608");
}
diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c
index 0d9f5e7396..2816e67885 100644
--- a/sapi/cli/php_cli.c
+++ b/sapi/cli/php_cli.c
@@ -61,6 +61,7 @@
#include "php_main.h"
#include "fopen_wrappers.h"
#include "ext/standard/php_standard.h"
+#include "cli.h"
#ifdef PHP_WIN32
#include <io.h>
#include <fcntl.h>
@@ -75,16 +76,6 @@
#include <unixlib/local.h>
#endif
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
-#if HAVE_LIBEDIT
-#include <editline/readline.h>
-#else
-#include <readline/readline.h>
-#include <readline/history.h>
-#endif
-#include "php_cli_readline.h"
-#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
-
#include "zend_compile.h"
#include "zend_execute.h"
#include "zend_highlight.h"
@@ -121,6 +112,12 @@ PHPAPI extern char *php_ini_scanned_files;
#define PHP_MODE_REFLECTION_ZEND_EXTENSION 12
#define PHP_MODE_SHOW_INI_CONFIG 13
+cli_shell_callbacks_t cli_shell_callbacks = { NULL, NULL, NULL };
+PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks()
+{
+ return &cli_shell_callbacks;
+}
+
const char HARDCODED_INI[] =
"html_errors=0\n"
"register_argc_argv=1\n"
@@ -131,10 +128,6 @@ const char HARDCODED_INI[] =
static char *php_optarg = NULL;
static int php_optind = 1;
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
-static char php_last_char = '\0';
-static FILE *pager_pipe = NULL;
-#endif
static const opt_struct OPTIONS[] = {
{'a', 0, "interactive"},
@@ -256,25 +249,19 @@ static inline int sapi_cli_select(int fd TSRMLS_DC)
return ret != -1;
}
-static inline size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
+PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
{
#ifdef PHP_WRITE_STDOUT
long ret;
#endif
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
- if (CLIR_G(prompt_str)) {
- smart_str_appendl(CLIR_G(prompt_str), str, str_length);
- return str_length;
- }
-
- if (CLIR_G(pager) && *CLIR_G(pager) && !pager_pipe) {
- pager_pipe = VCWD_POPEN(CLIR_G(pager), "w");
- }
- if (pager_pipe) {
- return fwrite(str, 1, MIN(str_length, 16384), pager_pipe);
+ if (cli_shell_callbacks.cli_shell_write) {
+ size_t shell_wrote;
+ shell_wrote = cli_shell_callbacks.cli_shell_write(str, str_length TSRMLS_CC);
+ if (shell_wrote > -1) {
+ return shell_wrote;
+ }
}
-#endif
#ifdef PHP_WRITE_STDOUT
do {
@@ -301,12 +288,17 @@ static int sapi_cli_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{
uint remaining = str_length;
size_t ret;
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
if (!str_length) {
return 0;
}
- php_last_char = str[str_length-1];
-#endif
+
+ if (cli_shell_callbacks.cli_shell_ub_write) {
+ int ub_wrote;
+ ub_wrote = cli_shell_callbacks.cli_shell_ub_write(str, str_length TSRMLS_CC);
+ if (ub_wrote > -1) {
+ return ub_wrote;
+ }
+ }
while (remaining > 0)
{
@@ -419,11 +411,7 @@ static void sapi_cli_send_header(sapi_header_struct *sapi_header, void *server_c
static int php_cli_startup(sapi_module_struct *sapi_module) /* {{{ */
{
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
- if (php_module_startup(sapi_module, &cli_readline_module_entry, 1)==FAILURE) {
-#else
if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
-#endif
return FAILURE;
}
return SUCCESS;
@@ -1142,117 +1130,13 @@ int main(int argc, char *argv[])
cli_register_file_handles(TSRMLS_C);
}
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
- if (interactive) {
- char *line;
- size_t size = 4096, pos = 0, len;
- char *code = emalloc(size);
- char *prompt = cli_get_prompt("php", '>' TSRMLS_CC);
- char *history_file;
-
- if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
- zend_file_handle *prepend_file_p;
- zend_file_handle prepend_file = {0};
-
- prepend_file.filename = PG(auto_prepend_file);
- prepend_file.opened_path = NULL;
- prepend_file.free_filename = 0;
- prepend_file.type = ZEND_HANDLE_FILENAME;
- prepend_file_p = &prepend_file;
-
- zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, prepend_file_p);
- }
-
- history_file = tilde_expand("~/.php_history");
- rl_attempted_completion_function = cli_code_completion;
- rl_special_prefixes = "$";
- read_history(history_file);
-
- EG(exit_status) = 0;
- while ((line = readline(prompt)) != NULL) {
- if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) {
- free(line);
- break;
- }
-
- if (!pos && !*line) {
- free(line);
- continue;
- }
-
- len = strlen(line);
-
- if (line[0] == '#') {
- char *param = strstr(&line[1], "=");
- if (param) {
- char *cmd;
- uint cmd_len;
- param++;
- cmd_len = param - &line[1] - 1;
- cmd = estrndup(&line[1], cmd_len);
-
- zend_alter_ini_entry_ex(cmd, cmd_len + 1, param, strlen(param), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
- efree(cmd);
- add_history(line);
-
- efree(prompt);
- /* TODO: This might be wrong! */
- prompt = cli_get_prompt("php", '>' TSRMLS_CC);
- continue;
- }
- }
-
- if (pos + len + 2 > size) {
- size = pos + len + 2;
- code = erealloc(code, size);
- }
- memcpy(&code[pos], line, len);
- pos += len;
- code[pos] = '\n';
- code[++pos] = '\0';
-
- if (*line) {
- add_history(line);
- }
-
- free(line);
- efree(prompt);
-
- if (!cli_is_valid_code(code, pos, &prompt TSRMLS_CC)) {
- continue;
- }
-
- zend_try {
- zend_eval_stringl(code, pos, NULL, "php shell code" TSRMLS_CC);
- } zend_end_try();
-
- pos = 0;
-
- if (!pager_pipe && php_last_char != '\0' && php_last_char != '\n') {
- sapi_cli_single_write("\n", 1 TSRMLS_CC);
- }
-
- if (EG(exception)) {
- zend_exception_error(EG(exception), E_WARNING TSRMLS_CC);
- }
-
- if (pager_pipe) {
- fclose(pager_pipe);
- pager_pipe = NULL;
- }
-
- php_last_char = '\0';
- }
- write_history(history_file);
- free(history_file);
- efree(code);
- efree(prompt);
+ if (interactive && cli_shell_callbacks.cli_shell_run) {
+ exit_status = cli_shell_callbacks.cli_shell_run();
+ } else {
+ php_execute_script(&file_handle TSRMLS_CC);
exit_status = EG(exit_status);
- break;
}
-#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
- php_execute_script(&file_handle TSRMLS_CC);
- exit_status = EG(exit_status);
+
break;
case PHP_MODE_LINT:
exit_status = php_lint_script(&file_handle TSRMLS_CC);