summaryrefslogtreecommitdiff
path: root/sapi/phpdbg/phpdbg_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/phpdbg/phpdbg_cmd.c')
-rw-r--r--sapi/phpdbg/phpdbg_cmd.c327
1 files changed, 161 insertions, 166 deletions
diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c
index a170d52955..5290639dcb 100644
--- a/sapi/phpdbg/phpdbg_cmd.c
+++ b/sapi/phpdbg/phpdbg_cmd.c
@@ -23,7 +23,6 @@
#include "phpdbg_utils.h"
#include "phpdbg_set.h"
#include "phpdbg_prompt.h"
-#include "phpdbg_io.h"
ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
@@ -40,7 +39,7 @@ static inline const char *phpdbg_command_name(const phpdbg_command_t *command, c
memcpy(&buffer[pos], command->name, command->name_len);
pos += command->name_len;
buffer[pos] = 0;
-
+
return buffer;
}
@@ -159,12 +158,12 @@ PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t* src, phpdbg_param_t* des
case STACK_PARAM:
/* nope */
break;
-
+
case STR_PARAM:
dest->str = estrndup(src->str, src->len);
dest->len = src->len;
break;
-
+
case OP_PARAM:
dest->str = estrndup(src->str, src->len);
dest->len = src->len;
@@ -204,7 +203,7 @@ PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t* src, phpdbg_param_t* des
break;
case EMPTY_PARAM: { /* do nothing */ } break;
-
+
default: {
/* not yet */
}
@@ -219,7 +218,7 @@ PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *param TSRMLS_DC) /
case STACK_PARAM:
/* nope */
break;
-
+
case STR_PARAM:
hash += zend_inline_hash_func(param->str, param->len);
break;
@@ -257,7 +256,7 @@ PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *param TSRMLS_DC) /
break;
case EMPTY_PARAM: { /* do nothing */ } break;
-
+
default: {
/* not yet */
}
@@ -275,7 +274,7 @@ PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *l, const phpdbg_pa
/* nope, or yep */
return 1;
break;
-
+
case NUMERIC_FUNCTION_PARAM:
if (l->num != r->num) {
break;
@@ -330,7 +329,7 @@ PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *l, const phpdbg_pa
case EMPTY_PARAM:
return 1;
-
+
default: {
/* not yet */
}
@@ -347,43 +346,43 @@ PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg)
case STR_PARAM:
fprintf(stderr, "%s STR_PARAM(%s=%lu)\n", msg, param->str, param->len);
break;
-
+
case ADDR_PARAM:
fprintf(stderr, "%s ADDR_PARAM(%lu)\n", msg, param->addr);
break;
-
+
case NUMERIC_FILE_PARAM:
fprintf(stderr, "%s NUMERIC_FILE_PARAM(%s:#%lu)\n", msg, param->file.name, param->file.line);
break;
-
+
case FILE_PARAM:
fprintf(stderr, "%s FILE_PARAM(%s:%lu)\n", msg, param->file.name, param->file.line);
break;
-
+
case METHOD_PARAM:
fprintf(stderr, "%s METHOD_PARAM(%s::%s)\n", msg, param->method.class, param->method.name);
break;
-
+
case NUMERIC_METHOD_PARAM:
fprintf(stderr, "%s NUMERIC_METHOD_PARAM(%s::%s)\n", msg, param->method.class, param->method.name);
break;
-
+
case NUMERIC_FUNCTION_PARAM:
fprintf(stderr, "%s NUMERIC_FUNCTION_PARAM(%s::%ld)\n", msg, param->str, param->num);
break;
-
+
case NUMERIC_PARAM:
fprintf(stderr, "%s NUMERIC_PARAM(%ld)\n", msg, param->num);
break;
-
+
case COND_PARAM:
fprintf(stderr, "%s COND_PARAM(%s=%lu)\n", msg, param->str, param->len);
break;
-
+
case OP_PARAM:
fprintf(stderr, "%s OP_PARAM(%s=%lu)\n", msg, param->str, param->len);
break;
-
+
default: {
/* not yet */
}
@@ -395,13 +394,13 @@ PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg)
PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack) {
if (stack && stack->next) {
phpdbg_param_t *remove = stack->next;
-
+
while (remove) {
phpdbg_param_t *next = NULL;
-
+
if (remove->next)
next = remove->next;
-
+
switch (remove->type) {
case NUMERIC_METHOD_PARAM:
case METHOD_PARAM:
@@ -415,30 +414,29 @@ PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack) {
case STR_PARAM:
case OP_PARAM:
if (remove->str)
- free(remove->str);
+ free(remove->str);
break;
-
+
case NUMERIC_FILE_PARAM:
case FILE_PARAM:
if (remove->file.name)
free(remove->file.name);
break;
-
+
default: {
/* nothing */
}
}
-
+
free(remove);
remove = NULL;
-
+
if (next)
- remove = next;
+ remove = next;
else break;
}
}
-
-
+
stack->next = NULL;
} /* }}} */
@@ -466,29 +464,30 @@ PHPDBG_API void phpdbg_stack_push(phpdbg_param_t *stack, phpdbg_param_t *param)
stack->len++;
} /* }}} */
-PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param_t **stack TSRMLS_DC) {
+PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param_t **stack, char **why TSRMLS_DC) {
if (command) {
char buffer[128] = {0,};
const phpdbg_param_t *top = (stack != NULL) ? *stack : NULL;
const char *arg = command->args;
size_t least = 0L,
- received = 0L,
- current = 0L;
+ received = 0L,
+ current = 0L;
zend_bool optional = 0;
-
+
/* check for arg spec */
if (!(arg) || !(*arg)) {
if (!top) {
return SUCCESS;
}
-
- phpdbg_error("command", "type=\"toomanyargs\" command=\"%s\" expected=\"0\"", "The command \"%s\" expected no arguments",
+
+ asprintf(why,
+ "The command \"%s\" expected no arguments",
phpdbg_command_name(command, buffer));
return FAILURE;
}
-
+
least = 0L;
-
+
/* count least amount of arguments */
while (arg && *arg) {
if (arg[0] == '|') {
@@ -497,19 +496,21 @@ PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param
least++;
arg++;
}
-
+
arg = command->args;
#define verify_arg(e, a, t) if (!(a)) { \
if (!optional) { \
- phpdbg_error("command", "type=\"noarg\" command=\"%s\" expected=\"%s\" num=\"%lu\"", "The command \"%s\" expected %s and got nothing at parameter %lu", \
+ asprintf(why, \
+ "The command \"%s\" expected %s and got nothing at parameter %lu", \
phpdbg_command_name(command, buffer), \
(e), \
current); \
return FAILURE;\
} \
} else if ((a)->type != (t)) { \
- phpdbg_error("command", "type=\"wrongarg\" command=\"%s\" expected=\"%s\" got=\"%s\" num=\"%lu\"", "The command \"%s\" expected %s and got %s at parameter %lu", \
+ asprintf(why, \
+ "The command \"%s\" expected %s and got %s at parameter %lu", \
phpdbg_command_name(command, buffer), \
(e),\
phpdbg_get_param_type((a) TSRMLS_CC), \
@@ -519,14 +520,14 @@ PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param
while (arg && *arg) {
current++;
-
+
switch (*arg) {
case '|': {
current--;
optional = 1;
arg++;
} continue;
-
+
case 'i': verify_arg("raw input", top, STR_PARAM); break;
case 's': verify_arg("string", top, STR_PARAM); break;
case 'n': verify_arg("number", top, NUMERIC_PARAM); break;
@@ -536,14 +537,14 @@ PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param
case 'c': verify_arg("condition", top, COND_PARAM); break;
case 'o': verify_arg("opcode", top, OP_PARAM); break;
case 'b': verify_arg("boolean", top, NUMERIC_PARAM); break;
-
+
case '*': { /* do nothing */ } break;
}
-
+
if (top ) {
top = top->next;
} else break;
-
+
received++;
arg++;
}
@@ -551,27 +552,28 @@ PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param
#undef verify_arg
if ((received < least)) {
- phpdbg_error("command", "type=\"toofewargs\" command=\"%s\" expected=\"%d\" argtypes=\"%s\" got=\"%d\"", "The command \"%s\" expected at least %lu arguments (%s) and received %lu",
+ asprintf(why,
+ "The command \"%s\" expected at least %lu arguments (%s) and received %lu",
phpdbg_command_name(command, buffer),
least,
- command->args,
+ command->args,
received);
return FAILURE;
}
}
-
+
return SUCCESS;
}
/* {{{ */
-PHPDBG_API const phpdbg_command_t *phpdbg_stack_resolve(const phpdbg_command_t *commands, const phpdbg_command_t *parent, phpdbg_param_t **top TSRMLS_DC) {
+PHPDBG_API const phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *commands, const phpdbg_command_t *parent, phpdbg_param_t **top, char **why) {
const phpdbg_command_t *command = commands;
phpdbg_param_t *name = *top;
const phpdbg_command_t *matched[3] = {NULL, NULL, NULL};
ulong matches = 0L;
-
+
while (command && command->name && command->handler) {
- if (name->len == 1 || command->name_len >= name->len) {
+ if ((name->len == 1) || (command->name_len >= name->len)) {
/* match single letter alias */
if (command->alias && (name->len == 1)) {
if (command->alias == (*name->str)) {
@@ -579,76 +581,85 @@ PHPDBG_API const phpdbg_command_t *phpdbg_stack_resolve(const phpdbg_command_t *
matches++;
}
} else {
+
/* match full, case insensitive, command name */
if (strncasecmp(command->name, name->str, name->len) == SUCCESS) {
if (matches < 3) {
+
/* only allow abbreviating commands that can be aliased */
- if ((name->len != command->name_len && command->alias) || name->len == command->name_len) {
+ if (((name->len != command->name_len) && command->alias) ||
+ (name->len == command->name_len)) {
matched[matches] = command;
matches++;
}
-
+
+
/* exact match */
- if (name->len == command->name_len) {
+ if (name->len == command->name_len)
break;
- }
- } else {
- break;
- }
+ } else break;
}
}
}
-
+
command++;
}
-
+
switch (matches) {
- case 0:
+ case 0: {
if (parent) {
- phpdbg_error("command", "type=\"notfound\" command=\"%s\" subcommand=\"%s\"", "The command \"%s %s\" could not be found", parent->name, name->str);
- } else {
- phpdbg_error("command", "type=\"notfound\" command=\"%s\"", "The command \"%s\" could not be found", name->str);
- }
- return parent;
-
- case 1:
+ asprintf(
+ why,
+ "The command \"%s %s\" could not be found",
+ parent->name, name->str);
+ } else asprintf(
+ why,
+ "The command \"%s\" could not be found",
+ name->str);
+ } return parent;
+
+ case 1: {
(*top) = (*top)->next;
command = matched[0];
- break;
-
+ } break;
+
default: {
char *list = NULL;
zend_uint it = 0;
size_t pos = 0;
-
+
while (it < matches) {
if (!list) {
- list = emalloc(matched[it]->name_len + 1 + (it + 1 < matches ? sizeof(", ") - 1 : 0));
+ list = malloc(
+ matched[it]->name_len + 1 +
+ ((it+1) < matches ? sizeof(", ")-1 : 0));
} else {
- list = erealloc(list, (pos + matched[it]->name_len) + 1 + (it + 1 < matches ? sizeof(", ") - 1 : 0));
+ list = realloc(list,
+ (pos + matched[it]->name_len) + 1 +
+ ((it+1) < matches ? sizeof(", ")-1 : 0));
}
memcpy(&list[pos], matched[it]->name, matched[it]->name_len);
pos += matched[it]->name_len;
- if ((it + 1) < matches) {
- memcpy(&list[pos], ", ", sizeof(", ") - 1);
+ if ((it+1) < matches) {
+ memcpy(&list[pos], ", ", sizeof(", ")-1);
pos += (sizeof(", ") - 1);
}
-
+
list[pos] = 0;
it++;
}
-
- /* ", " separated matches */
- phpdbg_error("command", "type=\"ambiguous\" command=\"%s\" matches=\"%lu\" matched=\"%s\"", "The command \"%s\" is ambigious, matching %lu commands (%s)", name->str, matches, list);
- efree(list);
-
- return NULL;
- }
+
+ asprintf(
+ why,
+ "The command \"%s\" is ambigious, matching %lu commands (%s)",
+ name->str, matches, list);
+ free(list);
+ } return NULL;
}
if (command->subs && (*top) && ((*top)->type == STR_PARAM)) {
- return phpdbg_stack_resolve(command->subs, command, top TSRMLS_CC);
+ return phpdbg_stack_resolve(command->subs, command, top, why);
} else {
return command;
}
@@ -657,97 +668,102 @@ PHPDBG_API const phpdbg_command_t *phpdbg_stack_resolve(const phpdbg_command_t *
} /* }}} */
/* {{{ */
-PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, zend_bool allow_async_unsafe TSRMLS_DC) {
+PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, char **why TSRMLS_DC) {
phpdbg_param_t *top = NULL;
const phpdbg_command_t *handler = NULL;
-
+
if (stack->type != STACK_PARAM) {
- phpdbg_error("command", "type=\"nostack\"", "The passed argument was not a stack !");
+ asprintf(
+ why, "The passed argument was not a stack !!");
return FAILURE;
}
-
+
if (!stack->len) {
- phpdbg_error("command", "type=\"emptystack\"", "The stack contains nothing !");
+ asprintf(
+ why, "The stack contains nothing !!");
return FAILURE;
}
-
- top = (phpdbg_param_t *) stack->next;
-
+
+ top = (phpdbg_param_t*) stack->next;
+
switch (top->type) {
case EVAL_PARAM:
- phpdbg_activate_err_buf(0 TSRMLS_CC);
- phpdbg_free_err_buf(TSRMLS_C);
return PHPDBG_COMMAND_HANDLER(ev)(top TSRMLS_CC);
case RUN_PARAM:
- if (!allow_async_unsafe) {
- phpdbg_error("signalsegv", "command=\"run\"", "run command is disallowed during hard interrupt");
- }
- phpdbg_activate_err_buf(0 TSRMLS_CC);
- phpdbg_free_err_buf(TSRMLS_C);
return PHPDBG_COMMAND_HANDLER(run)(top TSRMLS_CC);
-
+
case SHELL_PARAM:
- if (!allow_async_unsafe) {
- phpdbg_error("signalsegv", "command=\"sh\"", "sh command is disallowed during hard interrupt");
- return FAILURE;
- }
- phpdbg_activate_err_buf(0 TSRMLS_CC);
- phpdbg_free_err_buf(TSRMLS_C);
return PHPDBG_COMMAND_HANDLER(sh)(top TSRMLS_CC);
-
+
case STR_PARAM: {
- handler = phpdbg_stack_resolve(phpdbg_prompt_commands, NULL, &top TSRMLS_CC);
-
+ handler = phpdbg_stack_resolve(
+ phpdbg_prompt_commands, NULL, &top, why);
+
if (handler) {
- if (!allow_async_unsafe && !(handler->flags & PHPDBG_ASYNC_SAFE)) {
- phpdbg_error("signalsegv", "command=\"%s\"", "%s command is disallowed during hard interrupt", handler->name);
- return FAILURE;
- }
-
- if (phpdbg_stack_verify(handler, &top TSRMLS_CC) == SUCCESS) {
- phpdbg_activate_err_buf(0 TSRMLS_CC);
- phpdbg_free_err_buf(TSRMLS_C);
+ if (phpdbg_stack_verify(handler, &top, why TSRMLS_CC) == SUCCESS) {
return handler->handler(top TSRMLS_CC);
}
}
} return FAILURE;
-
+
default:
- phpdbg_error("command", "type=\"invalidcommand\"", "The first parameter makes no sense !");
+ asprintf(
+ why, "The first parameter makes no sense !!");
return FAILURE;
}
-
+
return SUCCESS;
} /* }}} */
-PHPDBG_API char *phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */
+PHPDBG_API char* phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */
{
- char buf[PHPDBG_MAX_CMD];
char *cmd = NULL;
+#if !defined(HAVE_LIBREADLINE) && !defined(HAVE_LIBEDIT)
+ char buf[PHPDBG_MAX_CMD];
+#endif
char *buffer = NULL;
- if ((PHPDBG_G(flags) & (PHPDBG_IS_STOPPING | PHPDBG_IS_RUNNING)) != 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 (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
+ if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) &&
+ (buffered == NULL)) {
+ fflush(PHPDBG_G(io)[PHPDBG_STDOUT]);
}
if (buffered == 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 */
-#if USE_LIB_STAR
-readline:
- if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE)
-#endif
- {
- phpdbg_write("prompt", "", "%s", phpdbg_get_prompt(TSRMLS_C));
- phpdbg_consume_stdin_line(cmd = buf TSRMLS_CC);
+disconnect:
+ if (0) {
+ PHPDBG_G(flags) |= (PHPDBG_IS_QUITTING|PHPDBG_IS_DISCONNECTED);
+ zend_bailout();
+ return NULL;
}
-#if USE_LIB_STAR
- else {
- cmd = readline(phpdbg_get_prompt(TSRMLS_C));
- PHPDBG_G(last_was_newline) = 1;
+
+#if !defined(HAVE_LIBREADLINE) && !defined(HAVE_LIBEDIT)
+ if (!(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
+ if (!phpdbg_write("%s", phpdbg_get_prompt(TSRMLS_C))) {
+ goto disconnect;
+ }
}
+
+ /* note: EOF is ignored */
+readline:
+ if (!fgets(buf, PHPDBG_MAX_CMD, PHPDBG_G(io)[PHPDBG_STDIN])) {
+ /* the user has gone away */
+ if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
+ goto disconnect;
+ } else goto readline;
+ }
+
+ cmd = buf;
+#else
+ /* note: EOF makes readline write prompt again in local console mode */
+readline:
+ if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
+ char buf[PHPDBG_MAX_CMD];
+ if (fgets(buf, PHPDBG_MAX_CMD, PHPDBG_G(io)[PHPDBG_STDIN])) {
+ cmd = buf;
+ } else goto disconnect;
+ } else cmd = readline(phpdbg_get_prompt(TSRMLS_C));
if (!cmd) {
goto readline;
@@ -757,14 +773,13 @@ readline:
add_history(cmd);
}
#endif
- } else {
- cmd = buffered;
- }
-
+ } else cmd = buffered;
+
buffer = estrdup(cmd);
-#if USE_LIB_STAR
- if (!buffered && cmd && !(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
+#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT)
+ if (!buffered && cmd &&
+ !(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
free(cmd);
}
#endif
@@ -790,7 +805,7 @@ readline:
buffer = estrdup(PHPDBG_G(buffer));
}
}
-
+
return buffer;
} /* }}} */
@@ -799,23 +814,3 @@ 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;
-}