Changeset 4303
- Timestamp:
- Nov 30, 2012 8:57:18 AM (12 years ago)
- Location:
- pjproject/branches/projects/cli
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/cli/pjlib-util/include/pjlib-util/cli_console.h
r4299 r4303 98 98 * @return PJ_SUCCESS if an input was read 99 99 */ 100 PJ_DECL(pj_status_t) pj_cli_console_process(pj_cli_sess *sess); 100 PJ_DECL(pj_status_t) pj_cli_console_process(pj_cli_sess *sess, 101 char *buf, 102 unsigned maxlen); 101 103 102 104 /** -
pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli.c
r4302 r4303 165 165 } pj_cli_arg_type; 166 166 167 st atic const struct167 struct arg_type 168 168 { 169 169 const pj_str_t msg; 170 } arg_type[ ] =171 { 172 { "Text", 4},173 { "Int", 3},174 { "Choice", 6}170 } arg_type[3] = 171 { 172 {{"Text", 4}}, 173 {{"Int", 3}}, 174 {{"Choice", 6}} 175 175 }; 176 176 … … 736 736 737 737 for (i = 0; i < cmd->arg_cnt; i++) { 738 unsigned j;739 740 738 pj_strdup(cli->pool, &cmd->arg[i].name, &args[i].name); 741 739 pj_strdup(cli->pool, &cmd->arg[i].desc, &args[i].desc); … … 835 833 /* Set the parse mode based on the latest char. */ 836 834 len = pj_ansi_strlen(cmdline); 837 if (len > 0 && cmdline[len - 1] == '\r') {835 if (len > 0 && ((cmdline[len - 1] == '\r')||(cmdline[len - 1] == '\n'))) { 838 836 cmdline[--len] = 0; 839 837 parse_mode = PARSE_EXEC; … … 921 919 } 922 920 923 } else if (parse_mode == PARSE_COMPLETION) { 924 if (info->hint[0].name.slen > str.slen) { 925 pj_str_t *hint_info = &info->hint[0].name; 926 pj_memmove(&hint_info->ptr[0], &hint_info->ptr[str.slen], 927 info->hint[0].name.slen-str.slen); 928 hint_info->slen = info->hint[0].name.slen-str.slen; 929 } else { 930 info->hint[0].name.slen = 0; 931 } 932 } 921 } 922 933 923 val->sess = sess; 934 924 return status; … … 1090 1080 if (arg->get_dyn_choice) { 1091 1081 pj_cli_dyn_choice_param dyn_choice_param; 1092 static constpj_str_t choice_str = {"choice", 6};1082 static pj_str_t choice_str = {"choice", 6}; 1093 1083 1094 1084 /* Get the dynamic choice values */ -
pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_console.c
r4302 r4303 28 28 #include <pjlib-util/errno.h> 29 29 30 #if defined(PJ_LINUX) && PJ_LINUX != 0 || \31 defined(PJ_DARWINOS) && PJ_DARWINOS != 032 #include <termios.h>33 34 static struct termios old, new;35 36 /* Initialize new terminal i/o settings */37 void initTermios(int echo)38 {39 tcgetattr(0, &old);40 new = old;41 new.c_lflag &= ~ICANON;42 new.c_lflag &= echo ? ECHO : ~ECHO;43 tcsetattr(0, TCSANOW, &new);44 }45 46 /* Restore old terminal i/o settings */47 void resetTermios(void)48 {49 tcsetattr(0, TCSANOW, &old);50 }51 52 /* Read 1 character - echo defines echo mode */53 char getch_(int echo)54 {55 char ch;56 initTermios(echo);57 ch = getchar();58 resetTermios();59 return ch;60 }61 62 /* Read 1 character without echo */63 char getch(void)64 {65 return getch_(0);66 }67 68 #endif69 70 /**71 * This specify the state of input character parsing.72 */73 typedef enum cmd_parse_state74 {75 ST_NORMAL,76 ST_SCANMODE,77 ST_ESC,78 ST_ARROWMODE79 } cmd_parse_state;80 81 30 /** 82 31 * This specify the state of output character parsing. … … 89 38 OP_CHOICE 90 39 } out_parse_state; 91 92 /**93 * This structure contains the command line shown to the user.94 */95 typedef struct console_recv_buf {96 /**97 * Buffer containing the characters, NULL terminated.98 */99 unsigned char rbuf[PJ_CLI_MAX_CMDBUF];100 101 /**102 * Current length of the command line.103 */104 unsigned len;105 106 /**107 * Current cursor position.108 */109 unsigned cur_pos;110 } console_recv_buf;111 112 typedef struct cmd_history113 {114 PJ_DECL_LIST_MEMBER(struct cmd_history);115 pj_str_t command;116 } cmd_history;117 40 118 41 struct cli_console_fe … … 124 47 pj_bool_t thread_quit; 125 48 pj_sem_t *thread_sem; 126 pj_cli_console_cfg cfg; 49 pj_cli_console_cfg cfg; 127 50 128 51 struct async_input_t 129 52 { 130 console_recv_buf recv_buf; 131 pj_sem_t *sem; 53 char *buf; 54 unsigned maxlen; 55 pj_sem_t *sem; 132 56 } input; 133 134 cmd_history *history;135 cmd_history *active_history;136 57 }; 137 138 static unsigned recv_buf_right_len(console_recv_buf *recv_buf)139 {140 return (recv_buf->len - recv_buf->cur_pos);141 }142 143 static pj_bool_t recv_buf_insert(console_recv_buf *recv_buf,144 unsigned char *data)145 {146 if (recv_buf->len+1 >= PJ_CLI_MAX_CMDBUF) {147 return PJ_FALSE;148 } else {149 if (*data == '\t' || *data == '?' || *data == '\r') {150 /* Always insert to the end of line */151 recv_buf->rbuf[recv_buf->len] = *data;152 } else {153 /* Insert based on the current cursor pos */154 unsigned cur_pos = recv_buf->cur_pos;155 unsigned rlen = recv_buf_right_len(recv_buf);156 if (rlen > 0) {157 /* Shift right characters */158 pj_memmove(&recv_buf->rbuf[cur_pos+1],159 &recv_buf->rbuf[cur_pos],160 rlen+1);161 }162 recv_buf->rbuf[cur_pos] = *data;163 }164 ++recv_buf->cur_pos;165 ++recv_buf->len;166 recv_buf->rbuf[recv_buf->len] = 0;167 }168 return PJ_TRUE;169 }170 171 static pj_bool_t recv_buf_backspace(console_recv_buf *recv_buf)172 {173 if ((recv_buf->cur_pos == 0) || (recv_buf->len == 0)) {174 return PJ_FALSE;175 } else {176 unsigned rlen = recv_buf_right_len(recv_buf);177 if (rlen) {178 unsigned cur_pos = recv_buf->cur_pos;179 pj_memmove(&recv_buf->rbuf[cur_pos-1], &recv_buf->rbuf[cur_pos],180 rlen);181 }182 --recv_buf->cur_pos;183 --recv_buf->len;184 recv_buf->rbuf[recv_buf->len] = 0;185 }186 return PJ_TRUE;187 }188 58 189 59 static void cli_console_write_log(pj_cli_front_end *fe, int level, … … 195 65 printf("%.*s", len, data); 196 66 } 197 198 67 199 68 static void cli_console_quit(pj_cli_front_end *fe, pj_cli_sess *req) … … 229 98 pj_assert(param); 230 99 231 param->log_level = PJ_CLI_CONSOLE_LOG_LEVEL; 100 param->log_level = PJ_CLI_CONSOLE_LOG_LEVEL; 101 param->prompt_str.slen = 0; 232 102 } 233 103 … … 251 121 sess = PJ_POOL_ZALLOC_T(pool, pj_cli_sess); 252 122 fe = PJ_POOL_ZALLOC_T(pool, struct cli_console_fe); 253 fe->history = PJ_POOL_ZALLOC_T(pool, struct cmd_history);254 pj_list_init(fe->history);255 fe->active_history = fe->history;256 123 257 124 if (!param) { … … 260 127 } 261 128 sess->fe = &fe->base; 262 sess->log_level = param->log_level; 129 sess->log_level = param->log_level; 263 130 sess->op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_sess_op); 264 131 fe->base.op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_front_end_op); … … 274 141 pj_cli_register_front_end(cli, &fe->base); 275 142 276 if ( fe->cfg.prompt_str.slen == 0) {143 if (param->prompt_str.slen == 0) { 277 144 pj_str_t prompt_sign = pj_str(">>> "); 278 char *prompt_data = pj_pool_alloc(fe->pool, 5); 279 fe->cfg.prompt_str.ptr = prompt_data; 280 281 pj_strcpy(&fe->cfg.prompt_str, &prompt_sign); 282 prompt_data[4] = 0; 283 } 145 fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool, prompt_sign.slen+1); 146 pj_strcpy(&fe->cfg.prompt_str, &prompt_sign); 147 } else { 148 fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool, 149 param->prompt_str.slen+1); 150 pj_strcpy(&fe->cfg.prompt_str, ¶m->prompt_str); 151 } 152 fe->cfg.prompt_str.ptr[fe->cfg.prompt_str.slen] = 0; 284 153 285 154 *p_sess = sess; … … 308 177 const pj_cli_exec_info *info, 309 178 const pj_str_t *msg, 310 pj_bool_t with_return, 311 pj_bool_t with_last_cmd) 179 pj_bool_t with_return) 312 180 { 313 181 pj_str_t send_data; … … 316 184 unsigned i; 317 185 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 318 console_recv_buf *recv_buf = &fe->input.recv_buf;319 186 320 187 send_data.ptr = &data_str[0]; … … 333 200 pj_strcat(&send_data, msg); 334 201 pj_strcat(&send_data, &fe->cfg.prompt_str); 335 if (with_last_cmd)336 pj_strcat2(&send_data, (char *)&recv_buf->rbuf[0]);337 202 338 203 send_data.ptr[send_data.slen] = 0; 339 printf("%s", send_data.ptr); 340 } 341 342 static void send_return_key(pj_cli_sess *sess) 343 { 344 PJ_UNUSED_ARG(sess); 345 printf("\r\n"); 204 printf("%s", send_data.ptr); 346 205 } 347 206 348 207 static void send_inv_arg(pj_cli_sess *sess, 349 208 const pj_cli_exec_info *info, 350 pj_bool_t with_return, 351 pj_bool_t with_last_cmd) 209 pj_bool_t with_return) 352 210 { 353 211 static const pj_str_t ERR_MSG = {"%Error : Invalid Arguments\r\n", 28}; 354 send_err_arg(sess, info, &ERR_MSG, with_return , with_last_cmd);212 send_err_arg(sess, info, &ERR_MSG, with_return); 355 213 } 356 214 357 215 static void send_too_many_arg(pj_cli_sess *sess, 358 216 const pj_cli_exec_info *info, 359 pj_bool_t with_return, 360 pj_bool_t with_last_cmd) 217 pj_bool_t with_return) 361 218 { 362 219 static const pj_str_t ERR_MSG = {"%Error : Too Many Arguments\r\n", 29}; 363 send_err_arg(sess, info, &ERR_MSG, with_return , with_last_cmd);220 send_err_arg(sess, info, &ERR_MSG, with_return); 364 221 } 365 222 366 223 static void send_ambi_arg(pj_cli_sess *sess, 367 224 const pj_cli_exec_info *info, 368 pj_bool_t with_return, 369 pj_bool_t with_last_cmd) 225 pj_bool_t with_return) 370 226 { 371 227 unsigned i; … … 375 231 char data[1028]; 376 232 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 377 console_recv_buf *recv_buf = &fe->input.recv_buf;378 233 const pj_cli_hint_info *hint = info->hint; 379 234 out_parse_state parse_state = OP_NORMAL; … … 444 299 pj_strcat2(&send_data, "\r\n"); 445 300 pj_strcat(&send_data, &fe->cfg.prompt_str); 446 if (with_last_cmd)447 pj_strcat2(&send_data, (char *)&recv_buf->rbuf[0]);448 301 449 302 send_data.ptr[send_data.slen] = 0; 450 printf("%s", send_data.ptr); 451 } 452 453 static void send_comp_arg(pj_cli_exec_info *info) 454 { 455 pj_str_t send_data; 456 char data[128]; 457 458 pj_strcat2(&info->hint[0].name, " "); 459 460 send_data.ptr = &data[0]; 461 send_data.slen = 0; 462 463 pj_strcat(&send_data, &info->hint[0].name); 464 465 send_data.ptr[send_data.slen] = 0; 466 printf("%s", send_data.ptr); 467 } 468 469 static int compare_str(void *value, const pj_list_type *nd) 470 { 471 cmd_history *node = (cmd_history*)nd; 472 return (pj_strcmp((pj_str_t *)value, &node->command)); 473 } 474 475 static pj_status_t insert_history(pj_cli_sess *sess, 476 char *cmd_val) 477 { 478 cmd_history *in_history; 479 pj_str_t cmd; 480 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 481 cmd.ptr = cmd_val; 482 cmd.slen = pj_ansi_strlen(cmd_val)-1; 483 484 if (cmd.slen == 0) 485 return PJ_SUCCESS; 486 487 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 488 489 /* Find matching history */ 490 in_history = pj_list_search(fe->history, (void*)&cmd, compare_str); 491 if (!in_history) { 492 if (pj_list_size(fe->history) < PJ_CLI_MAX_CMD_HISTORY) { 493 char *data_history; 494 in_history = PJ_POOL_ZALLOC_T(fe->pool, cmd_history); 495 pj_list_init(in_history); 496 data_history = (char *)pj_pool_calloc(fe->pool, 497 sizeof(char), PJ_CLI_MAX_CMDBUF); 498 in_history->command.ptr = data_history; 499 in_history->command.slen = 0; 500 } else { 501 /* Get the oldest history */ 502 in_history = fe->history->prev; 503 } 504 } else { 505 pj_list_insert_nodes_after(in_history->prev, in_history->next); 506 } 507 pj_strcpy(&in_history->command, pj_strtrim(&cmd)); 508 pj_list_push_front(fe->history, in_history); 509 fe->active_history = fe->history; 510 511 return PJ_SUCCESS; 512 } 513 514 static pj_str_t* get_prev_history(pj_cli_sess *sess, pj_bool_t is_forward) 515 { 516 pj_str_t *retval; 517 pj_size_t history_size; 518 cmd_history *node; 519 cmd_history *root; 520 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 521 522 PJ_ASSERT_RETURN(sess && fe, NULL); 523 524 node = fe->active_history; 525 root = fe->history; 526 history_size = pj_list_size(fe->history); 527 528 if (history_size == 0) { 529 return NULL; 530 } else { 531 if (is_forward) { 532 node = (node->next==root)?node->next->next:node->next; 533 } else { 534 node = (node->prev==root)?node->prev->prev:node->prev; 535 } 536 retval = &node->command; 537 fe->active_history = node; 538 } 539 return retval; 540 } 541 542 static pj_bool_t handle_alfa_num(console_recv_buf *recv_buf, 543 unsigned char *cdata) 544 { 545 if (recv_buf_right_len(recv_buf) > 0) { 546 char out_str[255]; 547 pj_memset(&out_str[0], 0, 255); 548 out_str[0] = *cdata; 549 pj_memcpy(&out_str[1], &recv_buf->rbuf[recv_buf->cur_pos], 550 recv_buf_right_len(recv_buf)); 551 pj_memset(&out_str[recv_buf_right_len(recv_buf)+1], '\b', 552 recv_buf_right_len(recv_buf)); 553 printf("%s", out_str); 554 } else { 555 printf("%c", *cdata); 556 } 557 return PJ_TRUE; 558 } 559 560 static pj_bool_t handle_backspace(console_recv_buf *recv_buf) 561 { 562 if (recv_buf_backspace(recv_buf)) { 563 if(recv_buf_right_len(recv_buf) > 0) { 564 char out_str[255]; 565 pj_memset(&out_str[0], 0, 255); 566 out_str[0] = '\b'; 567 pj_memcpy(&out_str[1], &recv_buf->rbuf[recv_buf->cur_pos], 568 recv_buf_right_len(recv_buf)); 569 out_str[recv_buf_right_len(recv_buf)+1] = ' '; 570 pj_memset(&out_str[recv_buf_right_len(recv_buf)+2], '\b', 571 recv_buf_right_len(recv_buf)+1); 572 printf("%s", out_str); 573 } else { 574 char out_str[4]; 575 out_str[0] = '\b'; 576 out_str[1] = ' '; 577 out_str[2] = '\b'; 578 out_str[3] = 0; 579 printf("%s", out_str); 580 } 581 return PJ_TRUE; 582 } 583 return PJ_FALSE; 584 } 585 586 static pj_bool_t handle_tab(pj_cli_sess *sess) 303 printf("%s", send_data.ptr); 304 } 305 306 static pj_bool_t handle_hint(pj_cli_sess *sess) 587 307 { 588 308 pj_status_t status; 589 309 pj_bool_t retval = PJ_TRUE; 590 unsigned len;591 310 592 311 pj_pool_t *pool; … … 594 313 pj_cli_exec_info info; 595 314 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 596 c onsole_recv_buf *recv_buf = &fe->input.recv_buf;315 char *recv_buf = fe->input.buf; 597 316 pj_cli_t *cli = sess->fe->cli; 598 317 599 pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_ tab",318 pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_hint", 600 319 PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC, 601 320 NULL); … … 603 322 cmd_val = PJ_POOL_ZALLOC_T(pool, pj_cli_cmd_val); 604 323 605 status = pj_cli_sess_parse(sess, (char *)recv_buf->rbuf, cmd_val, 606 pool, &info); 607 608 len = pj_ansi_strlen((char *)recv_buf->rbuf); 324 status = pj_cli_sess_parse(sess, recv_buf, cmd_val, 325 pool, &info); 609 326 610 327 switch (status) { 611 328 case PJ_CLI_EINVARG: 612 send_inv_arg(sess, &info, PJ_TRUE , PJ_TRUE);329 send_inv_arg(sess, &info, PJ_TRUE); 613 330 break; 614 331 case PJ_CLI_ETOOMANYARGS: 615 send_too_many_arg(sess, &info, PJ_TRUE , PJ_TRUE);332 send_too_many_arg(sess, &info, PJ_TRUE); 616 333 break; 617 334 case PJ_CLI_EMISSINGARG: 618 335 case PJ_CLI_EAMBIGUOUS: 619 send_ambi_arg(sess, &info, PJ_TRUE, PJ_TRUE); 620 break; 621 case PJ_SUCCESS: 622 if (len > recv_buf->cur_pos) 623 { 624 /* Send the cursor to EOL */ 625 unsigned char *data_sent = &recv_buf->rbuf[recv_buf->cur_pos-1]; 626 printf("%s", data_sent); 627 } 336 send_ambi_arg(sess, &info, PJ_TRUE); 337 break; 338 case PJ_SUCCESS: 628 339 if (info.hint_cnt > 0) { 629 /* Compelete command */ 630 send_comp_arg(&info); 631 632 pj_memcpy(&recv_buf->rbuf[len], 633 &info.hint[0].name.ptr[0], info.hint[0].name.slen); 634 635 len += info.hint[0].name.slen; 636 recv_buf->rbuf[len] = 0; 340 /* Compelete command */ 341 send_ambi_arg(sess, &info, PJ_TRUE); 637 342 } else { 638 343 retval = PJ_FALSE; 639 } 640 break; 641 } 642 recv_buf->len = len; 643 recv_buf->cur_pos = len; 344 } 345 break; 346 } 644 347 645 348 pj_pool_release(pool); … … 647 350 } 648 351 649 static pj_bool_t handle_ return(pj_cli_sess *sess)352 static pj_bool_t handle_exec(pj_cli_sess *sess) 650 353 { 651 354 pj_status_t status; … … 656 359 pj_cli_t *cli = sess->fe->cli; 657 360 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 658 console_recv_buf *recv_buf = &fe->input.recv_buf; 659 660 send_return_key(sess); 661 insert_history(sess, (char *)&recv_buf->rbuf[0]); 662 663 pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_return", 361 char *recv_buf = fe->input.buf; 362 363 printf("\r\n"); 364 365 pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_exec", 664 366 PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC, 665 367 NULL); 666 368 667 status = pj_cli_sess_exec(sess, (char *)&recv_buf->rbuf[0],369 status = pj_cli_sess_exec(sess, recv_buf, 668 370 pool, &info); 669 371 670 372 switch (status) { 671 373 case PJ_CLI_EINVARG: 672 send_inv_arg(sess, &info, PJ_FALSE , PJ_FALSE);374 send_inv_arg(sess, &info, PJ_FALSE); 673 375 break; 674 376 case PJ_CLI_ETOOMANYARGS: 675 send_too_many_arg(sess, &info, PJ_FALSE , PJ_FALSE);377 send_too_many_arg(sess, &info, PJ_FALSE); 676 378 break; 677 379 case PJ_CLI_EAMBIGUOUS: 678 380 case PJ_CLI_EMISSINGARG: 679 send_ambi_arg(sess, &info, PJ_FALSE , PJ_FALSE);381 send_ambi_arg(sess, &info, PJ_FALSE); 680 382 break; 681 383 case PJ_CLI_EEXIT: … … 683 385 break; 684 386 case PJ_SUCCESS: 685 send_prompt_str(sess); 387 send_prompt_str(sess); 686 388 break; 687 389 } 688 if (retval) {689 recv_buf->rbuf[0] = 0;690 recv_buf->len = 0;691 recv_buf->cur_pos = 0;692 }693 390 694 391 pj_pool_release(pool); … … 696 393 } 697 394 698 static pj_bool_t handle_up_down(pj_cli_sess *sess, pj_bool_t is_up) 699 { 700 pj_str_t *history; 701 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 702 console_recv_buf *recv_buf = &fe->input.recv_buf; 703 704 PJ_ASSERT_RETURN(sess && fe, PJ_FALSE); 705 706 history = get_prev_history(sess, is_up); 707 if (history) { 708 pj_str_t send_data; 709 char str[PJ_CLI_MAX_CMDBUF]; 710 send_data.ptr = &str[0]; 711 send_data.slen = 0; 712 713 if (recv_buf->cur_pos > 0) { 714 pj_memset(send_data.ptr, 0x08, recv_buf->cur_pos); 715 send_data.slen = recv_buf->cur_pos; 716 } 717 718 if (recv_buf->len > (unsigned)history->slen) { 719 unsigned buf_len = recv_buf->len; 720 pj_memset(&send_data.ptr[send_data.slen], 0x20, buf_len); 721 send_data.slen += buf_len; 722 pj_memset(&send_data.ptr[send_data.slen], 0x08, buf_len); 723 send_data.slen += buf_len; 724 } 725 /* Send data */ 726 pj_strcat(&send_data, history); 727 send_data.ptr[send_data.slen] = 0; 728 printf("%s", send_data.ptr); 729 pj_ansi_strncpy((char*)&recv_buf->rbuf, history->ptr, history->slen); 730 recv_buf->rbuf[history->slen] = 0; 731 recv_buf->len = history->slen; 732 recv_buf->cur_pos = recv_buf->len; 733 return PJ_TRUE; 734 } 735 return PJ_FALSE; 736 } 737 738 static pj_bool_t handle_left_key(console_recv_buf *recv_buf) 739 { 740 const static unsigned char BACK_SPACE = 0x08; 741 if (recv_buf->cur_pos) { 742 printf("%c", BACK_SPACE); 743 --recv_buf->cur_pos; 744 return PJ_TRUE; 745 } 746 return PJ_FALSE; 747 } 748 749 static pj_bool_t handle_right_key(console_recv_buf *recv_buf) 750 { 751 if (recv_buf_right_len(recv_buf)) { 752 unsigned char *data = &recv_buf->rbuf[recv_buf->cur_pos++]; 753 printf("%c", *data); 754 return PJ_TRUE; 755 } 756 return PJ_FALSE; 757 } 758 759 static int readchar_thread(void * p) 395 static int readline_thread(void * p) 760 396 { 761 397 struct cli_console_fe * fe = (struct cli_console_fe *)p; 762 cmd_parse_state parse_state = ST_NORMAL;763 398 764 399 printf("%s", fe->cfg.prompt_str.ptr); 765 400 766 401 while (!fe->thread_quit) { 767 unsigned char cdata;768 c onsole_recv_buf *recv_buf = &fe->input.recv_buf;402 unsigned input_len = 0; 403 char *recv_buf = fe->input.buf; 769 404 pj_bool_t is_valid = PJ_TRUE; 770 405 771 cdata = (unsigned char)getch(); 772 773 switch (parse_state) { 774 case ST_NORMAL: 775 if (cdata == '\b') { 776 is_valid = handle_backspace(recv_buf); 777 } else if (cdata == 224) { 778 parse_state = ST_SCANMODE; 779 } else if (cdata == 27) { 780 parse_state = ST_ESC; 781 } else { 782 if (cdata == '\n') 783 cdata = '\r'; 784 if (recv_buf_insert(recv_buf, &cdata)) { 785 if (cdata == '\r') { 786 is_valid = handle_return(fe->sess); 787 } else if ((cdata == '\t') || (cdata == '?')) { 788 is_valid = handle_tab(fe->sess); 789 } else if (cdata > 31 && cdata < 127) { 790 is_valid = handle_alfa_num(recv_buf, &cdata); 791 } 792 } else { 793 is_valid = PJ_FALSE; 794 } 795 } 796 break; 797 case ST_SCANMODE: 798 switch (cdata) { 799 case 72: 800 //UP 801 case 80: 802 //DOwN 803 is_valid = handle_up_down(fe->sess, (cdata==72)); 804 break; 805 case 75: 806 is_valid = handle_left_key(recv_buf); 807 //LEFT 808 break; 809 case 77: 810 is_valid = handle_right_key(recv_buf); 811 //RIGHT 812 break; 813 }; 814 parse_state = ST_NORMAL; 815 break; 816 case ST_ESC: 817 parse_state = (cdata == 91)?ST_ARROWMODE:ST_NORMAL; 818 break; 819 case ST_ARROWMODE: 820 switch (cdata) { 821 case 65: 822 //UP 823 case 66: 824 //DOwN 825 is_valid = handle_up_down(fe->sess, (cdata==65)); 826 break; 827 case 68: 828 is_valid = handle_left_key(recv_buf); 829 //LEFT 830 break; 831 case 67: 832 is_valid = handle_right_key(recv_buf); 833 //RIGHT 834 break; 835 }; 836 parse_state = ST_NORMAL; 837 break; 838 }; 406 fgets(recv_buf, fe->input.maxlen, stdin); 407 input_len = pj_ansi_strlen(fe->input.buf); 408 if ((input_len > 1) && (fe->input.buf[input_len-2] == '?')) { 409 fe->input.buf[input_len-1] = 0; 410 is_valid = handle_hint(fe->sess); 411 } else { 412 is_valid = handle_exec(fe->sess); 413 } 839 414 840 415 pj_sem_post(fe->input.sem); … … 846 421 } 847 422 848 PJ_DEF(pj_status_t) pj_cli_console_process(pj_cli_sess *sess) 423 PJ_DEF(pj_status_t) pj_cli_console_process(pj_cli_sess *sess, 424 char *buf, 425 unsigned maxlen) 849 426 { 850 427 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 851 428 852 429 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 430 431 fe->input.buf = buf; 432 fe->input.maxlen = maxlen; 853 433 854 434 if (!fe->input_thread) { 855 435 pj_status_t status; 856 436 857 status = pj_thread_create(fe->pool, NULL, &read char_thread, fe,437 status = pj_thread_create(fe->pool, NULL, &readline_thread, fe, 858 438 0, 0, &fe->input_thread); 859 439 if (status != PJ_SUCCESS) -
pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_telnet.c
r4302 r4303 27 27 #include <pj/pool.h> 28 28 #include <pj/string.h> 29 #include <pj/except.h> 29 30 #include <pjlib-util/errno.h> 31 #include <pjlib-util/scanner.h> 30 32 31 33 #define CLI_TELNET_BUF_SIZE 256 … … 889 891 } 890 892 893 /* Syntax error handler for parser. */ 894 static void on_syntax_error(pj_scanner *scanner) 895 { 896 PJ_UNUSED_ARG(scanner); 897 PJ_THROW(PJ_EINVAL); 898 } 899 900 static pj_status_t get_last_token(pj_str_t *cmd, pj_str_t *str) 901 { 902 pj_scanner scanner; 903 PJ_USE_EXCEPTION; 904 pj_scan_init(&scanner, cmd->ptr, cmd->slen, PJ_SCAN_AUTOSKIP_WS, 905 &on_syntax_error); 906 PJ_TRY { 907 while (!pj_scan_is_eof(&scanner)) { 908 pj_scan_get_until_chr(&scanner, " \t\r\n", str); 909 } 910 } 911 PJ_CATCH_ANY { 912 pj_scan_fini(&scanner); 913 return PJ_GET_EXCEPTION(); 914 } 915 PJ_END; 916 return PJ_SUCCESS; 917 } 918 891 919 static pj_bool_t handle_tab(cli_telnet_sess *sess) 892 920 { … … 930 958 if (info.hint_cnt > 0) { 931 959 /* Complete command */ 932 send_comp_arg(sess, &info); 933 934 pj_memcpy(&sess->rcmd->rbuf[len], 935 &info.hint[0].name.ptr[0], info.hint[0].name.slen); 936 937 len += info.hint[0].name.slen; 938 sess->rcmd->rbuf[len] = 0; 960 pj_str_t cmd = pj_str((char *)&sess->rcmd->rbuf[0]); 961 pj_str_t last_token; 962 963 if (get_last_token(&cmd, &last_token) == PJ_SUCCESS) { 964 pj_str_t *hint_info = &info.hint[0].name; 965 pj_strtrim(&last_token); 966 if (hint_info->slen > last_token.slen) { 967 hint_info->slen -= last_token.slen; 968 pj_memmove(&hint_info->ptr[0], &hint_info->ptr[last_token.slen], 969 hint_info->slen); 970 } 971 send_comp_arg(sess, &info); 972 973 pj_memcpy(&sess->rcmd->rbuf[len], &info.hint[0].name.ptr[0], 974 info.hint[0].name.slen); 975 976 len += info.hint[0].name.slen; 977 sess->rcmd->rbuf[len] = 0; 978 } 939 979 } else { 940 980 retval = PJ_FALSE; -
pjproject/branches/projects/cli/pjsip-apps/src/samples/clidemo.c
r4302 r4303 190 190 tcfg.port = 0; 191 191 #endif 192 tcfg.port = 2233; 193 tcfg.prompt_str = pj_str("CoolWater% "); 192 194 status = pj_cli_telnet_create(cli, &tcfg, NULL); 193 195 if (status != PJ_SUCCESS) … … 221 223 pj_status_t status; 222 224 pj_cli_sess *sess; 223 225 pj_cli_console_cfg console_cfg; 226 227 pj_cli_console_cfg_default(&console_cfg); 228 console_cfg.prompt_str = pj_str("HotWater> "); 229 224 230 /* 225 231 * Create the console front end 226 232 */ 227 status = pj_cli_console_create(cli, NULL, &sess, NULL);233 status = pj_cli_console_create(cli, &console_cfg, &sess, NULL); 228 234 if (status != PJ_SUCCESS) 229 235 return status; … … 235 241 */ 236 242 for (;;) { 243 char cmdline[PJ_CLI_MAX_CMDBUF]; 237 244 pj_status_t status; 238 245 239 status = pj_cli_console_process(sess );246 status = pj_cli_console_process(sess, &cmdline[0], sizeof(cmdline)); 240 247 if (status != PJ_SUCCESS) 241 248 break; -
pjproject/branches/projects/cli/third_party
- Property svn:externals
-
old new 1 portaudio -r1433 https://subversion.assembla.com/svn/portaudio/portaudio/trunk1 portaudio -r1433 https://subversion.assembla.com/svn/portaudio/portaudio/trunk
-
- Property svn:externals
Note: See TracChangeset
for help on using the changeset viewer.