root/sapi/phpdbg/phpdbg_cmd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. phpdbg_command_name
  2. phpdbg_get_param_type
  3. phpdbg_clear_param
  4. phpdbg_param_tostring
  5. phpdbg_copy_param
  6. phpdbg_hash_param
  7. phpdbg_match_param
  8. phpdbg_param_debug
  9. phpdbg_stack_free
  10. phpdbg_stack_push
  11. phpdbg_stack_verify
  12. phpdbg_stack_resolve
  13. phpdbg_stack_execute
  14. phpdbg_read_input
  15. phpdbg_destroy_input

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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    | Authors: Felipe Pena <felipe@php.net>                                |
  16    | Authors: Joe Watkins <joe.watkins@live.co.uk>                        |
  17    | Authors: Bob Weinand <bwoebi@php.net>                                |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 #include "phpdbg.h"
  22 #include "phpdbg_cmd.h"
  23 #include "phpdbg_utils.h"
  24 #include "phpdbg_set.h"
  25 #include "phpdbg_prompt.h"
  26 
  27 ZEND_EXTERN_MODULE_GLOBALS(phpdbg);
  28 
  29 static inline const char *phpdbg_command_name(const phpdbg_command_t *command, char *buffer) {
  30         size_t pos = 0;
  31 
  32         if (command->parent) {
  33                 memcpy(&buffer[pos], command->parent->name, command->parent->name_len);
  34                 pos += command->parent->name_len;
  35                 memcpy(&buffer[pos], " ", sizeof(" ")-1);
  36                 pos += (sizeof(" ")-1);
  37         }
  38 
  39         memcpy(&buffer[pos], command->name, command->name_len);
  40         pos += command->name_len;
  41         buffer[pos] = 0;
  42         
  43         return buffer;
  44 }
  45 
  46 PHPDBG_API const char *phpdbg_get_param_type(const phpdbg_param_t *param TSRMLS_DC) /* {{{ */
  47 {
  48         switch (param->type) {
  49                 case STACK_PARAM:
  50                         return "stack";
  51                 case EMPTY_PARAM:
  52                         return "empty";
  53                 case ADDR_PARAM:
  54                         return "address";
  55                 case NUMERIC_PARAM:
  56                         return "numeric";
  57                 case METHOD_PARAM:
  58                         return "method";
  59                 case NUMERIC_FUNCTION_PARAM:
  60                         return "function opline";
  61                 case NUMERIC_METHOD_PARAM:
  62                         return "method opline";
  63                 case FILE_PARAM:
  64                         return "file or file opline";
  65                 case STR_PARAM:
  66                         return "string";
  67                 default: /* this is bad */
  68                         return "unknown";
  69         }
  70 }
  71 
  72 PHPDBG_API void phpdbg_clear_param(phpdbg_param_t *param TSRMLS_DC) /* {{{ */
  73 {
  74         if (param) {
  75                 switch (param->type) {
  76                         case FILE_PARAM:
  77                                 efree(param->file.name);
  78                                 break;
  79                         case METHOD_PARAM:
  80                                 efree(param->method.class);
  81                                 efree(param->method.name);
  82                                 break;
  83                         case STR_PARAM:
  84                                 efree(param->str);
  85                                 break;
  86                         default:
  87                                 break;
  88                 }
  89         }
  90 
  91 } /* }}} */
  92 
  93 PHPDBG_API char* phpdbg_param_tostring(const phpdbg_param_t *param, char **pointer TSRMLS_DC) /* {{{ */
  94 {
  95         switch (param->type) {
  96                 case STR_PARAM:
  97                         asprintf(pointer,
  98                                 "%s", param->str);
  99                 break;
 100 
 101                 case ADDR_PARAM:
 102                         asprintf(pointer,
 103                                 "%#lx", param->addr);
 104                 break;
 105 
 106                 case NUMERIC_PARAM:
 107                         asprintf(pointer,
 108                                 "%li",
 109                                 param->num);
 110                 break;
 111 
 112                 case METHOD_PARAM:
 113                         asprintf(pointer,
 114                                 "%s::%s",
 115                                 param->method.class,
 116                                 param->method.name);
 117                 break;
 118 
 119                 case FILE_PARAM:
 120                         if (param->num) {
 121                                 asprintf(pointer,
 122                                         "%s:%lu#%lu",
 123                                         param->file.name,
 124                                         param->file.line,
 125                                         param->num);
 126                         } else {
 127                                 asprintf(pointer,
 128                                         "%s:%lu",
 129                                         param->file.name,
 130                                         param->file.line);
 131                         }
 132                 break;
 133 
 134                 case NUMERIC_FUNCTION_PARAM:
 135                         asprintf(pointer,
 136                                 "%s#%lu", param->str, param->num);
 137                 break;
 138 
 139                 case NUMERIC_METHOD_PARAM:
 140                         asprintf(pointer,
 141                                 "%s::%s#%lu",
 142                                 param->method.class,
 143                                 param->method.name,
 144                                 param->num);
 145                 break;
 146 
 147                 default:
 148                         asprintf(pointer,
 149                                 "%s", "unknown");
 150         }
 151 
 152         return *pointer;
 153 } /* }}} */
 154 
 155 PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t* src, phpdbg_param_t* dest TSRMLS_DC) /* {{{ */
 156 {
 157         switch ((dest->type = src->type)) {
 158                 case STACK_PARAM:
 159                         /* nope */
 160                 break;
 161                 
 162                 case STR_PARAM:
 163                         dest->str = estrndup(src->str, src->len);
 164                         dest->len = src->len;
 165                 break;
 166                 
 167                 case OP_PARAM:
 168                         dest->str = estrndup(src->str, src->len);
 169                         dest->len = src->len;
 170                 break;
 171 
 172                 case ADDR_PARAM:
 173                         dest->addr = src->addr;
 174                 break;
 175 
 176                 case NUMERIC_PARAM:
 177                         dest->num = src->num;
 178                 break;
 179 
 180                 case METHOD_PARAM:
 181                         dest->method.class = estrdup(src->method.class);
 182                         dest->method.name = estrdup(src->method.name);
 183                 break;
 184 
 185                 case NUMERIC_FILE_PARAM:
 186                 case FILE_PARAM:
 187                         dest->file.name = estrdup(src->file.name);
 188                         dest->file.line = src->file.line;
 189                         if (src->num)
 190                                 dest->num   = src->num;
 191                 break;
 192 
 193                 case NUMERIC_FUNCTION_PARAM:
 194                         dest->str = estrndup(src->str, src->len);
 195                         dest->num = src->num;
 196                         dest->len = src->len;
 197                 break;
 198 
 199                 case NUMERIC_METHOD_PARAM:
 200                         dest->method.class = estrdup(src->method.class);
 201                         dest->method.name = estrdup(src->method.name);
 202                         dest->num = src->num;
 203                 break;
 204 
 205                 case EMPTY_PARAM: { /* do nothing */ } break;
 206                 
 207                 default: {
 208                         /* not yet */
 209                 }
 210         }
 211 } /* }}} */
 212 
 213 PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *param TSRMLS_DC) /* {{{ */
 214 {
 215         zend_ulong hash = param->type;
 216 
 217         switch (param->type) {
 218                 case STACK_PARAM:
 219                         /* nope */
 220                 break;
 221                 
 222                 case STR_PARAM:
 223                         hash += zend_inline_hash_func(param->str, param->len);
 224                 break;
 225 
 226                 case METHOD_PARAM:
 227                         hash += zend_inline_hash_func(param->method.class, strlen(param->method.class));
 228                         hash += zend_inline_hash_func(param->method.name, strlen(param->method.name));
 229                 break;
 230 
 231                 case FILE_PARAM:
 232                         hash += zend_inline_hash_func(param->file.name, strlen(param->file.name));
 233                         hash += param->file.line;
 234                         if (param->num)
 235                                 hash += param->num;
 236                 break;
 237 
 238                 case ADDR_PARAM:
 239                         hash += param->addr;
 240                 break;
 241 
 242                 case NUMERIC_PARAM:
 243                         hash += param->num;
 244                 break;
 245 
 246                 case NUMERIC_FUNCTION_PARAM:
 247                         hash += zend_inline_hash_func(param->str, param->len);
 248                         hash += param->num;
 249                 break;
 250 
 251                 case NUMERIC_METHOD_PARAM:
 252                         hash += zend_inline_hash_func(param->method.class, strlen(param->method.class));
 253                         hash += zend_inline_hash_func(param->method.name, strlen(param->method.name));
 254                         if (param->num)
 255                                 hash+= param->num;
 256                 break;
 257 
 258                 case EMPTY_PARAM: { /* do nothing */ } break;
 259                 
 260                 default: {
 261                         /* not yet */
 262                 }
 263         }
 264 
 265         return hash;
 266 } /* }}} */
 267 
 268 PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *l, const phpdbg_param_t *r TSRMLS_DC) /* {{{ */
 269 {
 270         if (l && r) {
 271                 if (l->type == r->type) {
 272                         switch (l->type) {
 273                                 case STACK_PARAM:
 274                                         /* nope, or yep */
 275                                         return 1;
 276                                 break;
 277                                 
 278                                 case NUMERIC_FUNCTION_PARAM:
 279                                         if (l->num != r->num) {
 280                                                 break;
 281                                         }
 282                                 /* break intentionally omitted */
 283 
 284                                 case STR_PARAM:
 285                                         return (l->len == r->len) &&
 286                                                         (memcmp(l->str, r->str, l->len) == SUCCESS);
 287 
 288                                 case NUMERIC_PARAM:
 289                                         return (l->num == r->num);
 290 
 291                                 case ADDR_PARAM:
 292                                         return (l->addr == r->addr);
 293 
 294                                 case FILE_PARAM: {
 295                                         if (l->file.line == r->file.line) {
 296                                                 size_t lengths[2] = {
 297                                                         strlen(l->file.name), strlen(r->file.name)};
 298 
 299                                                 if (lengths[0] == lengths[1]) {
 300                                                         if ((!l->num && !r->num) || (l->num == r->num)) {
 301                                                                 return (memcmp(
 302                                                                         l->file.name, r->file.name, lengths[0]) == SUCCESS);
 303                                                         }
 304                                                 }
 305                                         }
 306                                 } break;
 307 
 308                                 case NUMERIC_METHOD_PARAM:
 309                                         if (l->num != r->num) {
 310                                                 break;
 311                                         }
 312                                 /* break intentionally omitted */
 313 
 314                                 case METHOD_PARAM: {
 315                                         size_t lengths[2] = {
 316                                                 strlen(l->method.class), strlen(r->method.class)};
 317                                         if (lengths[0] == lengths[1]) {
 318                                                 if (memcmp(l->method.class, r->method.class, lengths[0]) == SUCCESS) {
 319                                                         lengths[0] = strlen(l->method.name);
 320                                                         lengths[1] = strlen(r->method.name);
 321 
 322                                                         if (lengths[0] == lengths[1]) {
 323                                                                 return (memcmp(
 324                                                                         l->method.name, r->method.name, lengths[0]) == SUCCESS);
 325                                                         }
 326                                                 }
 327                                         }
 328                                 } break;
 329 
 330                                 case EMPTY_PARAM:
 331                                         return 1;
 332                                         
 333                                 default: {
 334                                         /* not yet */
 335                                 }
 336                         }
 337                 }
 338         }
 339         return 0;
 340 } /* }}} */
 341 
 342 /* {{{ */
 343 PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg) {
 344         if (param && param->type) {
 345                 switch (param->type) {
 346                         case STR_PARAM:
 347                                 fprintf(stderr, "%s STR_PARAM(%s=%lu)\n", msg, param->str, param->len);
 348                         break;
 349                         
 350                         case ADDR_PARAM:
 351                                 fprintf(stderr, "%s ADDR_PARAM(%lu)\n", msg, param->addr);
 352                         break;
 353                         
 354                         case NUMERIC_FILE_PARAM:
 355                                 fprintf(stderr, "%s NUMERIC_FILE_PARAM(%s:#%lu)\n", msg, param->file.name, param->file.line);
 356                         break;
 357                         
 358                         case FILE_PARAM:
 359                                 fprintf(stderr, "%s FILE_PARAM(%s:%lu)\n", msg, param->file.name, param->file.line);
 360                         break;
 361                         
 362                         case METHOD_PARAM:
 363                                 fprintf(stderr, "%s METHOD_PARAM(%s::%s)\n", msg, param->method.class, param->method.name);
 364                         break;
 365                         
 366                         case NUMERIC_METHOD_PARAM:
 367                                 fprintf(stderr, "%s NUMERIC_METHOD_PARAM(%s::%s)\n", msg, param->method.class, param->method.name);
 368                         break;
 369                         
 370                         case NUMERIC_FUNCTION_PARAM:
 371                                 fprintf(stderr, "%s NUMERIC_FUNCTION_PARAM(%s::%ld)\n", msg, param->str, param->num);
 372                         break;
 373                         
 374                         case NUMERIC_PARAM:
 375                                 fprintf(stderr, "%s NUMERIC_PARAM(%ld)\n", msg, param->num);
 376                         break;
 377                         
 378                         case COND_PARAM:
 379                                 fprintf(stderr, "%s COND_PARAM(%s=%lu)\n", msg, param->str, param->len);
 380                         break;
 381                         
 382                         case OP_PARAM:
 383                                 fprintf(stderr, "%s OP_PARAM(%s=%lu)\n", msg, param->str, param->len);
 384                         break;
 385                         
 386                         default: {
 387                                 /* not yet */
 388                         }
 389                 }
 390         }
 391 } /* }}} */
 392 
 393 /* {{{ */
 394 PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack) {
 395         if (stack && stack->next) {
 396                 phpdbg_param_t *remove = stack->next;
 397                 
 398                 while (remove) {
 399                         phpdbg_param_t *next = NULL;
 400                         
 401                         if (remove->next)
 402                                 next = remove->next;
 403                         
 404                         switch (remove->type) {
 405                                 case NUMERIC_METHOD_PARAM:
 406                                 case METHOD_PARAM:
 407                                         if (remove->method.class)
 408                                                 free(remove->method.class);
 409                                         if (remove->method.name)
 410                                                 free(remove->method.name);
 411                                 break;
 412 
 413                                 case NUMERIC_FUNCTION_PARAM:
 414                                 case STR_PARAM:
 415                                 case OP_PARAM:
 416                                         if (remove->str)
 417                                                 free(remove->str);      
 418                                 break;
 419                                 
 420                                 case NUMERIC_FILE_PARAM:
 421                                 case FILE_PARAM:
 422                                         if (remove->file.name)
 423                                                 free(remove->file.name);
 424                                 break;
 425                                 
 426                                 default: {
 427                                         /* nothing */
 428                                 }
 429                         }
 430                         
 431                         free(remove);
 432                         remove = NULL;
 433                         
 434                         if (next)
 435                                 remove = next; 
 436                         else break;
 437                 }
 438         }
 439         
 440         stack->next = NULL;
 441 } /* }}} */
 442 
 443 /* {{{ */
 444 PHPDBG_API void phpdbg_stack_push(phpdbg_param_t *stack, phpdbg_param_t *param) {
 445         phpdbg_param_t *next = calloc(1, sizeof(phpdbg_param_t));
 446 
 447         if (!next)
 448                 return;
 449 
 450         *(next) = *(param);
 451 
 452         next->next = NULL;
 453 
 454         if (stack->top == NULL) {
 455                 stack->top = next;
 456                 next->top = NULL;
 457                 stack->next = next;
 458         } else {
 459                 stack->top->next = next;
 460                 next->top = stack->top;
 461                 stack->top = next;
 462         }
 463 
 464         stack->len++;
 465 } /* }}} */
 466 
 467 PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param_t **stack, char **why TSRMLS_DC) {
 468         if (command) {
 469                 char buffer[128] = {0,};
 470                 const phpdbg_param_t *top = (stack != NULL) ? *stack : NULL;
 471                 const char *arg = command->args;
 472                 size_t least = 0L,
 473                            received = 0L,
 474                            current = 0L;
 475                 zend_bool optional = 0;
 476                 
 477                 /* check for arg spec */
 478                 if (!(arg) || !(*arg)) {
 479                         if (!top) {
 480                                 return SUCCESS;
 481                         }
 482                         
 483                         asprintf(why,
 484                                 "The command \"%s\" expected no arguments", 
 485                                 phpdbg_command_name(command, buffer));
 486                         return FAILURE;
 487                 }
 488                 
 489                 least = 0L;
 490                 
 491                 /* count least amount of arguments */
 492                 while (arg && *arg) {
 493                         if (arg[0] == '|') {
 494                                 break;
 495                         }
 496                         least++;
 497                         arg++;
 498                 }
 499                 
 500                 arg = command->args;
 501 
 502 #define verify_arg(e, a, t) if (!(a)) { \
 503         if (!optional) { \
 504                 asprintf(why, \
 505                         "The command \"%s\" expected %s and got nothing at parameter %lu", \
 506                         phpdbg_command_name(command, buffer), \
 507                         (e), \
 508                         current); \
 509                 return FAILURE;\
 510         } \
 511 } else if ((a)->type != (t)) { \
 512         asprintf(why, \
 513                 "The command \"%s\" expected %s and got %s at parameter %lu", \
 514                 phpdbg_command_name(command, buffer), \
 515                 (e),\
 516                 phpdbg_get_param_type((a) TSRMLS_CC), \
 517                 current); \
 518         return FAILURE; \
 519 }
 520 
 521                 while (arg && *arg) {
 522                         current++;
 523                         
 524                         switch (*arg) {
 525                                 case '|': {
 526                                         current--;
 527                                         optional = 1;
 528                                         arg++;
 529                                 } continue;
 530                                 
 531                                 case 'i': verify_arg("raw input", top, STR_PARAM); break;
 532                                 case 's': verify_arg("string", top, STR_PARAM); break;
 533                                 case 'n': verify_arg("number", top, NUMERIC_PARAM); break;
 534                                 case 'm': verify_arg("method", top, METHOD_PARAM); break;
 535                                 case 'a': verify_arg("address", top, ADDR_PARAM); break;
 536                                 case 'f': verify_arg("file:line", top, FILE_PARAM); break;
 537                                 case 'c': verify_arg("condition", top, COND_PARAM); break;
 538                                 case 'o': verify_arg("opcode", top, OP_PARAM); break;
 539                                 case 'b': verify_arg("boolean", top, NUMERIC_PARAM); break;
 540                                 
 541                                 case '*': { /* do nothing */ } break;
 542                         }
 543                         
 544                         if (top ) {
 545                                 top = top->next;
 546                         } else break;
 547                         
 548                         received++;
 549                         arg++;
 550                 }
 551 
 552 #undef verify_arg
 553 
 554                 if ((received < least)) {
 555                         asprintf(why,
 556                                 "The command \"%s\" expected at least %lu arguments (%s) and received %lu",
 557                                 phpdbg_command_name(command, buffer),
 558                                 least,
 559                                 command->args, 
 560                                 received);
 561                         return FAILURE;
 562                 }
 563         }
 564         
 565         return SUCCESS;
 566 }
 567 
 568 /* {{{ */
 569 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) {
 570         const phpdbg_command_t *command = commands;
 571         phpdbg_param_t *name = *top;
 572         const phpdbg_command_t *matched[3] = {NULL, NULL, NULL};
 573         ulong matches = 0L;
 574         
 575         while (command && command->name && command->handler) {
 576                 if ((name->len == 1) || (command->name_len >= name->len)) {
 577                         /* match single letter alias */
 578                         if (command->alias && (name->len == 1)) {
 579                                 if (command->alias == (*name->str)) {
 580                                         matched[matches] = command;
 581                                         matches++;
 582                                 }
 583                         } else {
 584 
 585                                 /* match full, case insensitive, command name */
 586                                 if (strncasecmp(command->name, name->str, name->len) == SUCCESS) {
 587                                         if (matches < 3) {
 588                                                 
 589                                                 /* only allow abbreviating commands that can be aliased */
 590                                                 if (((name->len != command->name_len) && command->alias) ||
 591                                                         (name->len == command->name_len)) {
 592                                                         matched[matches] = command;
 593                                                         matches++;
 594                                                 }
 595                                                 
 596                                                 
 597                                                 /* exact match */
 598                                                 if (name->len == command->name_len)
 599                                                         break;
 600                                         } else break;
 601                                 }
 602                         }
 603                 }
 604                 
 605                 command++;
 606         }
 607         
 608         switch (matches) {
 609                 case 0: {
 610                         if (parent) {
 611                                 asprintf(
 612                                 why,
 613                                 "The command \"%s %s\" could not be found", 
 614                                 parent->name, name->str);
 615                         } else asprintf(
 616                                 why,
 617                                 "The command \"%s\" could not be found", 
 618                                 name->str);
 619                 } return parent;
 620                 
 621                 case 1: {
 622                         (*top) = (*top)->next;
 623 
 624                         command = matched[0];
 625                 } break;
 626                 
 627                 default: {
 628                         char *list = NULL;
 629                         zend_uint it = 0;
 630                         size_t pos = 0;
 631                         
 632                         while (it < matches) {
 633                                 if (!list) {
 634                                         list = malloc(
 635                                                 matched[it]->name_len + 1 + 
 636                                                 ((it+1) < matches ? sizeof(", ")-1 : 0));
 637                                 } else {
 638                                         list = realloc(list, 
 639                                                 (pos + matched[it]->name_len) + 1  + 
 640                                                 ((it+1) < matches ? sizeof(", ")-1 : 0));
 641                                 }
 642                                 memcpy(&list[pos], matched[it]->name, matched[it]->name_len);
 643                                 pos += matched[it]->name_len;
 644                                 if ((it+1) < matches) {
 645                                         memcpy(&list[pos], ", ", sizeof(", ")-1);
 646                                         pos += (sizeof(", ") - 1);
 647                                 }
 648                                 
 649                                 list[pos] = 0;
 650                                 it++;
 651                         }
 652                         
 653                         asprintf(
 654                                 why,
 655                                 "The command \"%s\" is ambigious, matching %lu commands (%s)", 
 656                                 name->str, matches, list);
 657                         free(list);
 658                 } return NULL;
 659         }
 660 
 661         if (command->subs && (*top) && ((*top)->type == STR_PARAM)) {
 662                 return phpdbg_stack_resolve(command->subs, command, top, why);
 663         } else {
 664                 return command;
 665         }
 666 
 667         return NULL;
 668 } /* }}} */
 669 
 670 /* {{{ */
 671 PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, char **why TSRMLS_DC) {
 672         phpdbg_param_t *top = NULL;
 673         const phpdbg_command_t *handler = NULL;
 674         
 675         if (stack->type != STACK_PARAM) {
 676                 asprintf(
 677                         why, "The passed argument was not a stack !!");
 678                 return FAILURE;
 679         }
 680         
 681         if (!stack->len) {
 682                 asprintf(
 683                         why, "The stack contains nothing !!");
 684                 return FAILURE;
 685         }
 686         
 687         top = (phpdbg_param_t*) stack->next;
 688         
 689         switch (top->type) {
 690                 case EVAL_PARAM:
 691                         return PHPDBG_COMMAND_HANDLER(ev)(top TSRMLS_CC);
 692 
 693                 case RUN_PARAM:
 694                         return PHPDBG_COMMAND_HANDLER(run)(top TSRMLS_CC);
 695                 
 696                 case SHELL_PARAM:
 697                         return PHPDBG_COMMAND_HANDLER(sh)(top TSRMLS_CC);
 698                 
 699                 case STR_PARAM: {
 700                         handler = phpdbg_stack_resolve(
 701                                 phpdbg_prompt_commands, NULL, &top, why);
 702                         
 703                         if (handler) {
 704                                 if (phpdbg_stack_verify(handler, &top, why TSRMLS_CC) == SUCCESS) {
 705                                         return handler->handler(top TSRMLS_CC);
 706                                 }
 707                         }
 708                 } return FAILURE;
 709                 
 710                 default:
 711                         asprintf(
 712                                 why, "The first parameter makes no sense !!");
 713                         return FAILURE;
 714         }
 715         
 716         return SUCCESS;
 717 } /* }}} */
 718 
 719 PHPDBG_API char* phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */
 720 {
 721         char *cmd = NULL;
 722 #if !defined(HAVE_LIBREADLINE) && !defined(HAVE_LIBEDIT)
 723         char buf[PHPDBG_MAX_CMD];
 724 #endif
 725         char *buffer = NULL;
 726 
 727         if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
 728                 if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) &&
 729                         (buffered == NULL)) {
 730                         fflush(PHPDBG_G(io)[PHPDBG_STDOUT]);
 731                 }
 732 
 733                 if (buffered == NULL) {
 734 disconnect:
 735                         if (0) {
 736                                 PHPDBG_G(flags) |= (PHPDBG_IS_QUITTING|PHPDBG_IS_DISCONNECTED);
 737                                 zend_bailout();
 738                                 return NULL;
 739                         }
 740 
 741 #if !defined(HAVE_LIBREADLINE) && !defined(HAVE_LIBEDIT)
 742                         if (!(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
 743                                 if (!phpdbg_write("%s", phpdbg_get_prompt(TSRMLS_C))) {
 744                                         goto disconnect;
 745                                 }
 746                         }
 747                         
 748                         /* note: EOF is ignored */
 749 readline:       
 750                         if (!fgets(buf, PHPDBG_MAX_CMD, PHPDBG_G(io)[PHPDBG_STDIN])) {
 751                                 /* the user has gone away */
 752                                 if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
 753                                         goto disconnect;
 754                                 } else goto readline;
 755                         }
 756 
 757                         cmd = buf;
 758 #else
 759                         /* note: EOF makes readline write prompt again in local console mode */
 760 readline:
 761                         if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
 762                                 char buf[PHPDBG_MAX_CMD];
 763                                 if (fgets(buf, PHPDBG_MAX_CMD, PHPDBG_G(io)[PHPDBG_STDIN])) {
 764                                         cmd = buf;
 765                                 } else goto disconnect;
 766                         } else cmd = readline(phpdbg_get_prompt(TSRMLS_C));
 767 
 768                         if (!cmd) {
 769                                 goto readline;
 770                         }
 771 
 772                         if (!(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
 773                                 add_history(cmd);
 774                         }
 775 #endif
 776                 } else cmd = buffered;
 777                 
 778                 buffer = estrdup(cmd);
 779 
 780 #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT)
 781                 if (!buffered && cmd &&
 782                         !(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
 783                         free(cmd);
 784                 }
 785 #endif
 786         }
 787 
 788         if (buffer && isspace(*buffer)) {
 789                 char *trimmed = buffer;
 790                 while (isspace(*trimmed))
 791                         trimmed++;
 792 
 793                 trimmed = estrdup(trimmed);
 794                 efree(buffer);
 795                 buffer = trimmed;
 796         }
 797 
 798         if (buffer && strlen(buffer)) {
 799                 if (PHPDBG_G(buffer)) {
 800                         efree(PHPDBG_G(buffer));
 801                 }
 802                 PHPDBG_G(buffer) = estrdup(buffer);
 803         } else {
 804                 if (PHPDBG_G(buffer)) {
 805                         buffer = estrdup(PHPDBG_G(buffer));
 806                 }
 807         }
 808         
 809         return buffer;
 810 } /* }}} */
 811 
 812 PHPDBG_API void phpdbg_destroy_input(char **input TSRMLS_DC) /*{{{ */
 813 {
 814         efree(*input);
 815 } /* }}} */
 816 

/* [<][>][^][v][top][bottom][index][help] */