Add question to reset execution in run/exec/clean

This commit is contained in:
Bob Weinand 2014-10-26 03:50:28 +01:00
parent 25e3560546
commit cc70ec1e67
7 changed files with 173 additions and 141 deletions

View file

@ -45,6 +45,8 @@
#endif /* }}} */
ZEND_DECLARE_MODULE_GLOBALS(phpdbg);
int phpdbg_startup_run = 0;
char *phpdbg_exec = NULL;
static PHP_INI_MH(OnUpdateEol)
{
@ -487,7 +489,7 @@ static void php_sapi_phpdbg_log_message(char *message TSRMLS_DC) /* {{{ */
case PHPDBG_NEXT:
return;
}
} while (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING));
} while (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING));
}
} else fprintf(stdout, "%s\n", message);
@ -752,7 +754,7 @@ static void phpdbg_welcome(zend_bool cleaning TSRMLS_DC) /* {{{ */
phpdbg_writeln("intro", "help=\"help\"", "To get help using phpdbg type \"help\" and press enter");
phpdbg_notice("intro", "report=\"%s\"", "Please report bugs to <%s>", PHPDBG_ISSUES);
phpdbg_xml("</intros>");
} else {
} else if (phpdbg_startup_run == 0) {
if (!(PHPDBG_G(flags) & PHPDBG_WRITE_XML)) {
phpdbg_notice(NULL, NULL, "Clean Execution Environment");
}
@ -776,7 +778,7 @@ static inline void phpdbg_sigint_handler(int signo) /* {{{ */
if (PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE) {
/* we quit remote consoles on recv SIGINT */
if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) {
PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
PHPDBG_G(flags) |= PHPDBG_IS_STOPPING;
zend_bailout();
}
} else {
@ -961,8 +963,6 @@ int main(int argc, char **argv) /* {{{ */
zend_ulong zend_extensions_len = 0L;
zend_bool ini_ignore;
char *ini_override;
char *exec;
size_t exec_len;
char *init_file;
size_t init_file_len;
zend_bool init_file_default;
@ -973,7 +973,6 @@ int main(int argc, char **argv) /* {{{ */
int php_optind, opt, show_banner = 1;
long cleaning = 0;
zend_bool remote = 0;
int run = 0;
int step = 0;
#ifdef _WIN32
@ -1046,8 +1045,6 @@ phpdbg_main:
ini_override = NULL;
zend_extensions = NULL;
zend_extensions_len = 0L;
exec = NULL;
exec_len = 0;
init_file = NULL;
init_file_len = 0;
init_file_default = 1;
@ -1057,14 +1054,13 @@ phpdbg_main:
php_optarg = NULL;
php_optind = 1;
opt = 0;
run = 0;
step = 0;
sapi_name = NULL;
while ((opt = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
switch (opt) {
case 'r':
run++;
phpdbg_startup_run++;
break;
case 'n':
ini_ignore = 1;
@ -1201,14 +1197,12 @@ phpdbg_main:
}
/* set exec if present on command line */
if ((argc > php_optind) && (strcmp(argv[php_optind-1],"--") != SUCCESS))
{
exec_len = strlen(argv[php_optind]);
if (exec_len) {
if (exec) {
free(exec);
if (!phpdbg_exec && (argc > php_optind) && (strcmp(argv[php_optind-1],"--") != SUCCESS)) {
if (strlen(argv[php_optind])) {
if (phpdbg_exec) {
free(phpdbg_exec);
}
exec = strdup(argv[php_optind]);
phpdbg_exec = strdup(argv[php_optind]);
}
php_optind++;
}
@ -1331,7 +1325,7 @@ phpdbg_main:
for (i = SG(request_info).argc; --i;) {
SG(request_info).argv[i] = estrdup(argv[php_optind - 1 + i]);
}
SG(request_info).argv[i] = exec ? estrndup(exec, exec_len) : estrdup("");
SG(request_info).argv[i] = phpdbg_exec ? estrdup(phpdbg_exec) : estrdup("");
php_hash_environment(TSRMLS_C);
}
@ -1394,11 +1388,12 @@ phpdbg_main:
php_stream_stdio_ops.write = phpdbg_stdiop_write;
#endif
if (exec) { /* set execution context */
PHPDBG_G(exec) = phpdbg_resolve_path(exec TSRMLS_CC);
if (phpdbg_exec) { /* set execution context */
PHPDBG_G(exec) = phpdbg_resolve_path(phpdbg_exec TSRMLS_CC);
PHPDBG_G(exec_len) = strlen(PHPDBG_G(exec));
free(exec);
free(phpdbg_exec);
phpdbg_exec = NULL;
}
if (oplog_file) { /* open oplog */
@ -1448,13 +1443,14 @@ phpdbg_main:
PHPDBG_G(flags) |= PHPDBG_IS_STEPPING;
}
if (run) {
if (phpdbg_startup_run) {
/* no need to try{}, run does it ... */
PHPDBG_COMMAND_HANDLER(run)(NULL TSRMLS_CC);
if (run > 1) {
if (phpdbg_startup_run > 1) {
/* if -r is on the command line more than once just quit */
goto phpdbg_out;
}
phpdbg_startup_run = 0;
}
phpdbg_interact:
@ -1494,7 +1490,7 @@ phpdbg_interact:
}
}
} zend_end_try();
} while(!cleaning && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING));
} while (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING));
/* this must be forced */
CG(unclean_shutdown) = 0;

View file

@ -187,9 +187,10 @@ int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC);
#define PHPDBG_IN_SIGNAL_HANDLER (1<<30)
#define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL|PHPDBG_IN_FINISH|PHPDBG_IN_LEAVE)
#define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP|PHPDBG_HAS_METHOD_OPLINE_BP|PHPDBG_HAS_FILE_OPLINE_BP)
#define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP|PHPDBG_HAS_SYM_BP|PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_OPLINE_BP|PHPDBG_HAS_COND_BP|PHPDBG_HAS_OPCODE_BP|PHPDBG_HAS_FUNCTION_OPLINE_BP|PHPDBG_HAS_METHOD_OPLINE_BP|PHPDBG_HAS_FILE_OPLINE_BP)
#define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL | PHPDBG_IN_FINISH | PHPDBG_IN_LEAVE)
#define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP)
#define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP | PHPDBG_HAS_SYM_BP | PHPDBG_HAS_METHOD_BP | PHPDBG_HAS_OPLINE_BP | PHPDBG_HAS_COND_BP | PHPDBG_HAS_OPCODE_BP | PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP)
#define PHPDBG_IS_STOPPING (PHPDBG_IS_QUITTING | PHPDBG_IS_CLEANING)
#ifndef _WIN32
# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_COLOURED|PHPDBG_IS_BP_ENABLED)

View file

@ -796,80 +796,30 @@ PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, zend_bool allow_async
PHPDBG_API char *phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */
{
char buf[PHPDBG_MAX_CMD];
char *cmd = NULL;
char *buffer = NULL;
if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) && (buffered == NULL) && !phpdbg_active_sigsafe_mem(TSRMLS_C)) {
fflush(PHPDBG_G(io)[PHPDBG_STDOUT].ptr);
}
if (buffered == NULL) {
if (0) {
disconnect:
PHPDBG_G(flags) |= (PHPDBG_IS_QUITTING|PHPDBG_IS_DISCONNECTED);
zend_bailout();
return NULL;
}
#define USE_LIB_STAR (defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT))
/* note: EOF makes readline write prompt again in local console mode - and ignored if compiled without readline */
/* strongly assuming to be in blocking mode... */
#if USE_LIB_STAR
readline:
if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE)
#endif
{
char buf[PHPDBG_MAX_CMD];
int bytes = PHPDBG_G(input_buflen), len = 0;
if (PHPDBG_G(input_buflen)) {
memcpy(buf, PHPDBG_G(input_buffer), bytes);
}
phpdbg_write("prompt", "", "%s", phpdbg_get_prompt(TSRMLS_C));
PHPDBG_G(last_was_newline) = 1;
do {
int i;
if (bytes <= 0) {
continue;
}
for (i = len; i < len + bytes; i++) {
if (buf[i] == '\x03') {
if (i != len + bytes - 1) {
memmove(buf + i, buf + i + 1, len + bytes - i - 1);
}
len--;
i--;
continue;
}
if (buf[i] == '\n') {
PHPDBG_G(input_buflen) = len + bytes - 1 - i;
if (PHPDBG_G(input_buflen)) {
memcpy(PHPDBG_G(input_buffer), buf + i + 1, PHPDBG_G(input_buflen));
}
if (i != PHPDBG_MAX_CMD - 1) {
buf[i + 1] = 0;
}
cmd = buf;
goto end;
}
}
len += bytes;
/* XXX export the timeout through INI??*/
} while ((bytes = phpdbg_mixed_read(PHPDBG_G(io)[PHPDBG_STDIN].fd, buf + len, PHPDBG_MAX_CMD - len, -1 TSRMLS_CC)) > 0);
if (bytes <= 0) {
goto disconnect;
}
cmd = buf;
phpdbg_consume_stdin_line(cmd = buf TSRMLS_CC);
}
#if USE_LIB_STAR
else {
cmd = readline(phpdbg_get_prompt(TSRMLS_C));
PHPDBG_G(last_was_newline) = 1;
}
if (!cmd) {
@ -883,8 +833,7 @@ readline:
} else {
cmd = buffered;
}
end:
PHPDBG_G(last_was_newline) = 1;
buffer = estrdup(cmd);
#if USE_LIB_STAR
@ -922,3 +871,24 @@ PHPDBG_API void phpdbg_destroy_input(char **input TSRMLS_DC) /*{{{ */
{
efree(*input);
} /* }}} */
PHPDBG_API int phpdbg_ask_user_permission(const char *question TSRMLS_DC) {
if (!(PHPDBG_G(flags) & PHPDBG_WRITE_XML)) {
char buf[PHPDBG_MAX_CMD];
phpdbg_out("%s", question);
phpdbg_out(" (type y or n): ");
while (1) {
phpdbg_consume_stdin_line(buf TSRMLS_CC);
if (buf[1] == '\n' && (buf[0] == 'y' || buf[0] == 'n')) {
if (buf[0] == 'y') {
return SUCCESS;
}
return FAILURE;
}
phpdbg_out("Please enter either y (yes) or n (no): ");
}
}
return SUCCESS;
}

View file

@ -131,6 +131,7 @@ typedef struct {
*/
PHPDBG_API char* phpdbg_read_input(char *buffered TSRMLS_DC);
PHPDBG_API void phpdbg_destroy_input(char** TSRMLS_DC);
PHPDBG_API int phpdbg_ask_user_permission(const char *question TSRMLS_DC);
/**
* Stack Management

View file

@ -47,6 +47,55 @@
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
/* is easy to generalize ... but not needed for now */
PHPDBG_API int phpdbg_consume_stdin_line(char *buf TSRMLS_DC) {
int bytes = PHPDBG_G(input_buflen), len = 0;
if (PHPDBG_G(input_buflen)) {
memcpy(buf, PHPDBG_G(input_buffer), bytes);
}
PHPDBG_G(last_was_newline) = 1;
do {
int i;
if (bytes <= 0) {
continue;
}
for (i = len; i < len + bytes; i++) {
if (buf[i] == '\x03') {
if (i != len + bytes - 1) {
memmove(buf + i, buf + i + 1, len + bytes - i - 1);
}
len--;
i--;
continue;
}
if (buf[i] == '\n') {
PHPDBG_G(input_buflen) = len + bytes - 1 - i;
if (PHPDBG_G(input_buflen)) {
memcpy(PHPDBG_G(input_buffer), buf + i + 1, PHPDBG_G(input_buflen));
}
if (i != PHPDBG_MAX_CMD - 1) {
buf[i + 1] = 0;
}
return i;
}
}
len += bytes;
} while ((bytes = phpdbg_mixed_read(PHPDBG_G(io)[PHPDBG_STDIN].fd, buf + len, PHPDBG_MAX_CMD - len, -1 TSRMLS_CC)) > 0);
if (bytes <= 0) {
PHPDBG_G(flags) |= PHPDBG_IS_QUITTING | PHPDBG_IS_DISCONNECTED;
zend_bailout();
return 0;
}
return bytes;
}
PHPDBG_API int phpdbg_consume_bytes(int sock, char *ptr, int len, int tmo TSRMLS_DC) {
int got_now, i = len, j;
char *p = ptr;

View file

@ -21,6 +21,8 @@
#include "phpdbg.h"
PHPDBG_API int phpdbg_consume_stdin_line(char *buf TSRMLS_DC);
PHPDBG_API int phpdbg_consume_bytes(int sock, char *ptr, int len, int tmo TSRMLS_DC);
PHPDBG_API int phpdbg_send_bytes(int sock, const char *ptr, int len);
PHPDBG_API int phpdbg_mixed_read(int sock, char *ptr, int len, int tmo TSRMLS_DC);

View file

@ -43,6 +43,8 @@
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
ZEND_EXTERN_MODULE_GLOBALS(output);
extern int phpdbg_startup_run;
extern char *phpdbg_exec;
#ifdef HAVE_LIBDL
#ifdef PHP_WIN32
@ -355,6 +357,11 @@ PHPDBG_COMMAND(exec) /* {{{ */
size_t res_len = strlen(res);
if ((res_len != PHPDBG_G(exec_len)) || (memcmp(res, PHPDBG_G(exec), res_len) != SUCCESS)) {
if (EG(in_execution)) {
if (phpdbg_ask_user_permission("Do you really want to stop execution to set a new execution context?" TSRMLS_CC) == FAILURE) {
return FAILURE;
}
}
if (PHPDBG_G(exec)) {
phpdbg_notice("exec", "type=\"unset\" context=\"%s\"", "Unsetting old execution context: %s", PHPDBG_G(exec));
@ -378,9 +385,11 @@ PHPDBG_COMMAND(exec) /* {{{ */
phpdbg_notice("exec", "type=\"set\" context=\"%s\"", "Set execution context: %s", PHPDBG_G(exec));
if (phpdbg_compile(TSRMLS_C) == FAILURE) {
phpdbg_error("compile", "type=\"compilefailure\" context=\"%s\"", "Failed to compile %s", PHPDBG_G(exec));
if (EG(in_execution)) {
phpdbg_clean(1 TSRMLS_CC);
}
phpdbg_compile(TSRMLS_C);
} else {
phpdbg_notice("exec", "type=\"unchanged\"", "Execution context not changed");
}
@ -399,20 +408,15 @@ int phpdbg_compile(TSRMLS_D) /* {{{ */
if (!PHPDBG_G(exec)) {
phpdbg_error("inactive", "type=\"nocontext\"", "No execution context");
return SUCCESS;
}
if (EG(in_execution)) {
phpdbg_error("inactive", "type=\"isrunning\"", "Cannot compile while in execution");
return FAILURE;
}
if (php_stream_open_for_zend_ex(PHPDBG_G(exec), &fh, USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC) == SUCCESS) {
PHPDBG_G(ops) = zend_compile_file(&fh, ZEND_INCLUDE TSRMLS_CC);
zend_destroy_file_handle(&fh TSRMLS_CC);
phpdbg_notice("compile", "context=\"%s\"", "Successful compilation of %s", PHPDBG_G(exec));
return SUCCESS;
} else {
phpdbg_error("compile", "type=\"openfailure\" context=\"%s\"", "Could not open file %s", PHPDBG_G(exec));
@ -570,11 +574,6 @@ static inline void phpdbg_handle_exception(TSRMLS_D) /* }}} */
PHPDBG_COMMAND(run) /* {{{ */
{
if (EG(in_execution)) {
phpdbg_error("inactive", "type=\"isrunning\"", "Cannot start another execution while one is in progress");
return SUCCESS;
}
if (PHPDBG_G(ops) || PHPDBG_G(exec)) {
zend_op **orig_opline = EG(opline_ptr);
zend_op_array *orig_op_array = EG(active_op_array);
@ -582,6 +581,14 @@ PHPDBG_COMMAND(run) /* {{{ */
zend_bool restore = 1;
zend_execute_data *ex = EG(current_execute_data);
if (EG(in_execution)) {
if (phpdbg_ask_user_permission("Do you really want to restart execution?" TSRMLS_CC) == SUCCESS) {
phpdbg_startup_run++;
phpdbg_clean(1 TSRMLS_CC);
}
return SUCCESS;
}
if (!PHPDBG_G(ops)) {
if (phpdbg_compile(TSRMLS_C) == FAILURE) {
phpdbg_error("compile", "type=\"compilefailure\" context=\"%s\"", "Failed to compile %s, cannot run", PHPDBG_G(exec));
@ -643,7 +650,7 @@ PHPDBG_COMMAND(run) /* {{{ */
EG(opline_ptr) = orig_opline;
EG(return_value_ptr_ptr) = orig_retval_ptr;
if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
phpdbg_error("stop", "type=\"bailout\"", "Caught exit/error from VM");
restore = 0;
}
@ -1127,7 +1134,7 @@ PHPDBG_COMMAND(register) /* {{{ */
PHPDBG_COMMAND(quit) /* {{{ */
{
/* don't allow this to loop, ever ... */
if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
zend_bailout();
}
@ -1138,9 +1145,10 @@ PHPDBG_COMMAND(quit) /* {{{ */
PHPDBG_COMMAND(clean) /* {{{ */
{
if (EG(in_execution)) {
phpdbg_error("inactive", "type=\"isrunning\"", "Cannot clean environment while executing");
if (phpdbg_ask_user_permission("Do you really want to clean your current environment?" TSRMLS_CC) == FAILURE) {
return SUCCESS;
}
}
phpdbg_out("Cleaning Execution Environment\n");
phpdbg_xml("<cleaninfo %r>");
@ -1227,10 +1235,16 @@ int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC) /* {{{ */
PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE;
input = phpdbg_read_input(NULL TSRMLS_CC);
while (1) {
if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) {
zend_bailout();
}
if (!(input = phpdbg_read_input(NULL TSRMLS_CC))) {
break;
}
if (input) {
do {
phpdbg_init_param(&stack, STACK_PARAM);
if (phpdbg_do_parse(&stack, input TSRMLS_CC) <= 0) {
@ -1244,7 +1258,7 @@ int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC) /* {{{ */
#endif
switch (ret = phpdbg_stack_execute(&stack, allow_async_unsafe TSRMLS_CC)) {
case FAILURE:
if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
if (!allow_async_unsafe || phpdbg_call_register(&stack TSRMLS_CC) == FAILURE) {
phpdbg_output_err_buf(NULL, "%b", "%b" TSRMLS_CC);
}
@ -1257,10 +1271,10 @@ int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC) /* {{{ */
case PHPDBG_NEXT: {
phpdbg_activate_err_buf(0 TSRMLS_CC);
phpdbg_free_err_buf(TSRMLS_C);
if (!EG(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
if (!EG(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
phpdbg_error("command", "type=\"noexec\"", "Not running");
}
goto out;
break;
}
}
@ -1277,10 +1291,8 @@ int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC) /* {{{ */
phpdbg_stack_free(&stack);
phpdbg_destroy_input(&input TSRMLS_CC);
PHPDBG_G(req_id) = 0;
} while ((input = phpdbg_read_input(NULL TSRMLS_CC)));
}
out:
if (input) {
phpdbg_stack_free(&stack);
phpdbg_destroy_input(&input TSRMLS_CC);
@ -1308,6 +1320,7 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */
}
if (full) {
phpdbg_exec = strdup(PHPDBG_G(exec)); /* preserve exec, don't reparse that from cmd */
PHPDBG_G(flags) |= PHPDBG_IS_CLEANING;
zend_bailout();
@ -1593,7 +1606,7 @@ void phpdbg_force_interruption(TSRMLS_D) {
next:
PHPDBG_G(flags) &= ~PHPDBG_IN_SIGNAL_HANDLER;
if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) {
if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) {
zend_bailout();
}
}