diff options
| author | Eric Andersen <andersen@codepoet.org> | 2001-03-13 22:57:56 +0000 |
|---|---|---|
| committer | Eric Andersen <andersen@codepoet.org> | 2001-03-13 22:57:56 +0000 |
| commit | b3d6e2df95a21034e41d46a18c71dd1c4e07e987 (patch) | |
| tree | 2d549a0d8748a9673be658e193a8104149cf2c15 /shell | |
| parent | 798ab301c772cc18ab64f94386da3c7ec10daf42 (diff) | |
| download | busybox-w32-b3d6e2df95a21034e41d46a18c71dd1c4e07e987.tar.gz busybox-w32-b3d6e2df95a21034e41d46a18c71dd1c4e07e987.tar.bz2 busybox-w32-b3d6e2df95a21034e41d46a18c71dd1c4e07e987.zip | |
Update the lash shell (hopefully the last time...) so things like
echo "foo bar" and echo -n "foo\t\\\\\tbar" work as expected.
Merge prompt printing work from Vladimir.
-Erik
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/cmdedit.c | 173 | ||||
| -rw-r--r-- | shell/cmdedit.h | 5 | ||||
| -rw-r--r-- | shell/lash.c | 180 |
3 files changed, 216 insertions, 142 deletions
diff --git a/shell/cmdedit.c b/shell/cmdedit.c index 272d22fc0..1b5cbbfab 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | Small bugs (simple effect): | 27 | Small bugs (simple effect): |
| 28 | - not true viewing if terminal size (x*y symbols) less | 28 | - not true viewing if terminal size (x*y symbols) less |
| 29 | size (prompt + editor`s line + 2 symbols) | 29 | size (prompt + editor`s line + 2 symbols) |
| 30 | - not true viewing if length prompt less terminal width | ||
| 30 | */ | 31 | */ |
| 31 | 32 | ||
| 32 | 33 | ||
| @@ -50,29 +51,36 @@ | |||
| 50 | 51 | ||
| 51 | #else | 52 | #else |
| 52 | 53 | ||
| 53 | #define BB_FEATURE_SH_COMMAND_EDITING | 54 | #define BB_FEATURE_COMMAND_EDITING |
| 54 | #define BB_FEATURE_SH_TAB_COMPLETION | 55 | #define BB_FEATURE_COMMAND_TAB_COMPLETION |
| 55 | #define BB_FEATURE_SH_USERNAME_COMPLETION | 56 | #define BB_FEATURE_COMMAND_USERNAME_COMPLETION |
| 56 | #define BB_FEATURE_NONPRINTABLE_INVERSE_PUT | 57 | #define BB_FEATURE_NONPRINTABLE_INVERSE_PUT |
| 57 | #define BB_FEATURE_BASH_STYLE_PROMT | 58 | #undef BB_FEATURE_SIMPLE_PROMPT |
| 58 | #define BB_FEATURE_CLEAN_UP | 59 | #define BB_FEATURE_CLEAN_UP |
| 59 | 60 | ||
| 60 | #define D(x) x | 61 | #define D(x) x |
| 61 | 62 | ||
| 63 | #ifndef TRUE | ||
| 64 | #define TRUE 1 | ||
| 65 | #endif | ||
| 66 | #ifndef FALSE | ||
| 67 | #define FALSE 0 | ||
| 68 | #endif | ||
| 69 | |||
| 62 | #endif /* TEST */ | 70 | #endif /* TEST */ |
| 63 | 71 | ||
| 64 | #ifdef BB_FEATURE_SH_TAB_COMPLETION | 72 | #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION |
| 65 | #include <dirent.h> | 73 | #include <dirent.h> |
| 66 | #include <sys/stat.h> | 74 | #include <sys/stat.h> |
| 67 | #endif | 75 | #endif |
| 68 | 76 | ||
| 69 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 77 | #ifdef BB_FEATURE_COMMAND_EDITING |
| 70 | 78 | ||
| 71 | #ifndef BB_FEATURE_SH_TAB_COMPLETION | 79 | #ifndef BB_FEATURE_COMMAND_TAB_COMPLETION |
| 72 | #undef BB_FEATURE_SH_USERNAME_COMPLETION | 80 | #undef BB_FEATURE_COMMAND_USERNAME_COMPLETION |
| 73 | #endif | 81 | #endif |
| 74 | 82 | ||
| 75 | #if defined(BB_FEATURE_SH_USERNAME_COMPLETION) || defined(BB_FEATURE_BASH_STYLE_PROMT) | 83 | #if defined(BB_FEATURE_COMMAND_USERNAME_COMPLETION) || !defined(BB_FEATURE_SIMPLE_PROMPT) |
| 76 | #define BB_FEATURE_GETUSERNAME_AND_HOMEDIR | 84 | #define BB_FEATURE_GETUSERNAME_AND_HOMEDIR |
| 77 | #endif | 85 | #endif |
| 78 | 86 | ||
| @@ -154,26 +162,26 @@ static | |||
| 154 | volatile int handlers_sets = 0; /* Set next bites: */ | 162 | volatile int handlers_sets = 0; /* Set next bites: */ |
| 155 | 163 | ||
| 156 | enum { | 164 | enum { |
| 157 | SET_ATEXIT = 1, /* when atexit() has been called and | 165 | SET_ATEXIT = 1, /* when atexit() has been called |
| 158 | get euid,uid,gid to fast compare */ | 166 | and get euid,uid,gid to fast compare */ |
| 159 | SET_TERM_HANDLERS = 2, /* set many terminates signal handlers */ | 167 | SET_TERM_HANDLERS = 2, /* set many terminates signal handlers */ |
| 160 | SET_WCHG_HANDLERS = 4, /* winchg signal handler */ | 168 | SET_WCHG_HANDLERS = 4, /* winchg signal handler */ |
| 161 | SET_RESET_TERM = 8, /* if the terminal needs to be reset upon exit */ | 169 | SET_RESET_TERM = 8, /* if the terminal needs to be reset upon exit */ |
| 162 | }; | 170 | }; |
| 163 | 171 | ||
| 164 | 172 | ||
| 165 | static int cmdedit_x; /* real x terminal position */ | 173 | static int cmdedit_x; /* real x terminal position */ |
| 166 | static int cmdedit_y; /* pseudoreal y terminal position */ | 174 | static int cmdedit_y; /* pseudoreal y terminal position */ |
| 167 | static int cmdedit_prmt_len; /* lenght prompt without colores string */ | 175 | static int cmdedit_prmt_len; /* lenght prompt without colores string */ |
| 168 | 176 | ||
| 169 | static int cursor; /* required global for signal handler */ | 177 | static int cursor; /* required global for signal handler */ |
| 170 | static int len; /* --- "" - - "" - -"- --""-- --""--- */ | 178 | static int len; /* --- "" - - "" - -"- --""-- --""--- */ |
| 171 | static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */ | 179 | static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */ |
| 172 | static | 180 | static |
| 173 | #ifndef BB_FEATURE_BASH_STYLE_PROMT | 181 | #ifdef BB_FEATURE_SIMPLE_PROMPT |
| 174 | const | 182 | const |
| 175 | #endif | 183 | #endif |
| 176 | char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ | 184 | char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ |
| 177 | 185 | ||
| 178 | /* Link into lash to reset context to 0 on ^C and such */ | 186 | /* Link into lash to reset context to 0 on ^C and such */ |
| 179 | extern unsigned int shell_context; | 187 | extern unsigned int shell_context; |
| @@ -185,13 +193,13 @@ static char *home_pwd_buf = ""; | |||
| 185 | static int my_euid; | 193 | static int my_euid; |
| 186 | #endif | 194 | #endif |
| 187 | 195 | ||
| 188 | #ifdef BB_FEATURE_BASH_STYLE_PROMT | 196 | #ifndef BB_FEATURE_SIMPLE_PROMPT |
| 189 | static char *hostname_buf = ""; | 197 | static char *hostname_buf = ""; |
| 190 | static int num_ok_lines = 1; | 198 | static int num_ok_lines = 1; |
| 191 | #endif | 199 | #endif |
| 192 | 200 | ||
| 193 | 201 | ||
| 194 | #ifdef BB_FEATURE_SH_TAB_COMPLETION | 202 | #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION |
| 195 | 203 | ||
| 196 | #ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR | 204 | #ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR |
| 197 | static int my_euid; | 205 | static int my_euid; |
| @@ -200,7 +208,7 @@ static int my_euid; | |||
| 200 | static int my_uid; | 208 | static int my_uid; |
| 201 | static int my_gid; | 209 | static int my_gid; |
| 202 | 210 | ||
| 203 | #endif /* BB_FEATURE_SH_TAB_COMPLETION */ | 211 | #endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ |
| 204 | 212 | ||
| 205 | 213 | ||
| 206 | static void cmdedit_setwidth(int w, int redraw_flg); | 214 | static void cmdedit_setwidth(int w, int redraw_flg); |
| @@ -245,7 +253,6 @@ static void cmdedit_reset_term(void) | |||
| 245 | if (his_front) { | 253 | if (his_front) { |
| 246 | struct history *n; | 254 | struct history *n; |
| 247 | 255 | ||
| 248 | //while(his_front!=his_end) { | ||
| 249 | while (his_front != his_end) { | 256 | while (his_front != his_end) { |
| 250 | n = his_front->n; | 257 | n = his_front->n; |
| 251 | free(his_front->s); | 258 | free(his_front->s); |
| @@ -355,25 +362,27 @@ static void put_prompt(void) | |||
| 355 | cursor = 0; | 362 | cursor = 0; |
| 356 | } | 363 | } |
| 357 | 364 | ||
| 358 | #ifdef BB_FEATURE_BASH_STYLE_PROMT | 365 | #ifdef BB_FEATURE_SIMPLE_PROMPT |
| 359 | static void | 366 | static void parse_prompt(const char *prmt_ptr) |
| 360 | add_to_prompt(char **prmt_mem_ptr, int *alm, int *prmt_len, | ||
| 361 | const char *addb) | ||
| 362 | { | 367 | { |
| 363 | int l = strlen(addb); | 368 | cmdedit_prompt = prmt_ptr; |
| 364 | 369 | cmdedit_prmt_len = strlen(prmt_ptr); | |
| 365 | *prmt_len += l; | 370 | put_prompt(); |
| 371 | } | ||
| 372 | #else | ||
| 373 | static void add_to_prompt(char **prmt_mem_ptr, int *alm, | ||
| 374 | int *prmt_len, const char *addb) | ||
| 375 | { | ||
| 376 | *prmt_len += strlen(addb); | ||
| 366 | if (*alm < (*prmt_len) + 1) { | 377 | if (*alm < (*prmt_len) + 1) { |
| 367 | *alm = (*prmt_len) + 1; | 378 | *alm = (*prmt_len) + 1; |
| 368 | *prmt_mem_ptr = xrealloc(*prmt_mem_ptr, *alm); | 379 | *prmt_mem_ptr = xrealloc(*prmt_mem_ptr, *alm); |
| 369 | } | 380 | } |
| 370 | strcat(*prmt_mem_ptr, addb); | 381 | strcat(*prmt_mem_ptr, addb); |
| 371 | } | 382 | } |
| 372 | #endif | ||
| 373 | 383 | ||
| 374 | static void parse_prompt(const char *prmt_ptr) | 384 | static void parse_prompt(const char *prmt_ptr) |
| 375 | { | 385 | { |
| 376 | #ifdef BB_FEATURE_BASH_STYLE_PROMT | ||
| 377 | int alm = strlen(prmt_ptr) + 1; /* supposedly require memory */ | 386 | int alm = strlen(prmt_ptr) + 1; /* supposedly require memory */ |
| 378 | int prmt_len = 0; | 387 | int prmt_len = 0; |
| 379 | int sub_len = 0; | 388 | int sub_len = 0; |
| @@ -394,9 +403,11 @@ static void parse_prompt(const char *prmt_ptr) | |||
| 394 | break; | 403 | break; |
| 395 | prmt_ptr++; | 404 | prmt_ptr++; |
| 396 | switch (c) { | 405 | switch (c) { |
| 406 | #ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR | ||
| 397 | case 'u': | 407 | case 'u': |
| 398 | add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, user_buf); | 408 | add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, user_buf); |
| 399 | continue; | 409 | continue; |
| 410 | #endif | ||
| 400 | case 'h': | 411 | case 'h': |
| 401 | if (hostname_buf[0] == 0) { | 412 | if (hostname_buf[0] == 0) { |
| 402 | hostname_buf = xcalloc(256, 1); | 413 | hostname_buf = xcalloc(256, 1); |
| @@ -415,6 +426,7 @@ static void parse_prompt(const char *prmt_ptr) | |||
| 415 | case '$': | 426 | case '$': |
| 416 | c = my_euid == 0 ? '#' : '$'; | 427 | c = my_euid == 0 ? '#' : '$'; |
| 417 | break; | 428 | break; |
| 429 | #ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR | ||
| 418 | case 'w': | 430 | case 'w': |
| 419 | if (pwd_buf[0] == 0) { | 431 | if (pwd_buf[0] == 0) { |
| 420 | int l; | 432 | int l; |
| @@ -429,6 +441,7 @@ static void parse_prompt(const char *prmt_ptr) | |||
| 429 | } | 441 | } |
| 430 | add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, pwd_buf); | 442 | add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, pwd_buf); |
| 431 | continue; | 443 | continue; |
| 444 | #endif | ||
| 432 | case '!': | 445 | case '!': |
| 433 | snprintf(buf, sizeof(buf), "%d", num_ok_lines); | 446 | snprintf(buf, sizeof(buf), "%d", num_ok_lines); |
| 434 | add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, buf); | 447 | add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, buf); |
| @@ -485,20 +498,21 @@ static void parse_prompt(const char *prmt_ptr) | |||
| 485 | if (flg_not_length == ']') | 498 | if (flg_not_length == ']') |
| 486 | sub_len++; | 499 | sub_len++; |
| 487 | } | 500 | } |
| 501 | #if 0 | ||
| 488 | cmdedit_prmt_len = prmt_len - sub_len; | 502 | cmdedit_prmt_len = prmt_len - sub_len; |
| 489 | cmdedit_prompt = prmt_mem_ptr; | ||
| 490 | #else | ||
| 491 | cmdedit_prompt = prmt_ptr; | 503 | cmdedit_prompt = prmt_ptr; |
| 492 | cmdedit_prmt_len = strlen(prmt_ptr); | 504 | #endif |
| 493 | #endif | 505 | cmdedit_prompt = prmt_mem_ptr; |
| 506 | cmdedit_prmt_len = strlen(cmdedit_prompt); | ||
| 494 | put_prompt(); | 507 | put_prompt(); |
| 495 | } | 508 | } |
| 509 | #endif | ||
| 496 | 510 | ||
| 497 | 511 | ||
| 498 | /* draw promt, editor line, and clear tail */ | 512 | /* draw promt, editor line, and clear tail */ |
| 499 | static void redraw(int y, int back_cursor) | 513 | static void redraw(int y, int back_cursor) |
| 500 | { | 514 | { |
| 501 | if (y > 0) /* up to start y */ | 515 | if (y > 0) /* up to start y */ |
| 502 | printf("\033[%dA", y); | 516 | printf("\033[%dA", y); |
| 503 | cmdedit_y = 0; /* new quasireal y */ | 517 | cmdedit_y = 0; /* new quasireal y */ |
| 504 | putchar('\r'); | 518 | putchar('\r'); |
| @@ -518,7 +532,7 @@ static void input_delete(void) | |||
| 518 | 532 | ||
| 519 | strcpy(command_ps + j, command_ps + j + 1); | 533 | strcpy(command_ps + j, command_ps + j + 1); |
| 520 | len--; | 534 | len--; |
| 521 | input_end(); /* rewtite new line */ | 535 | input_end(); /* rewtite new line */ |
| 522 | cmdedit_set_out_char(0); /* destroy end char */ | 536 | cmdedit_set_out_char(0); /* destroy end char */ |
| 523 | input_backward(cursor - j); /* back to old pos cursor */ | 537 | input_backward(cursor - j); /* back to old pos cursor */ |
| 524 | } | 538 | } |
| @@ -545,7 +559,7 @@ static void clean_up_and_die(int sig) | |||
| 545 | { | 559 | { |
| 546 | goto_new_line(); | 560 | goto_new_line(); |
| 547 | if (sig != SIGINT) | 561 | if (sig != SIGINT) |
| 548 | exit(EXIT_SUCCESS); /* cmdedit_reset_term() called in atexit */ | 562 | exit(EXIT_SUCCESS); /* cmdedit_reset_term() called in atexit */ |
| 549 | cmdedit_reset_term(); | 563 | cmdedit_reset_term(); |
| 550 | } | 564 | } |
| 551 | 565 | ||
| @@ -556,7 +570,6 @@ static void cmdedit_setwidth(int w, int redraw_flg) | |||
| 556 | cmdedit_termw = cmdedit_termw % w; | 570 | cmdedit_termw = cmdedit_termw % w; |
| 557 | } | 571 | } |
| 558 | if (w > cmdedit_termw) { | 572 | if (w > cmdedit_termw) { |
| 559 | |||
| 560 | cmdedit_termw = w; | 573 | cmdedit_termw = w; |
| 561 | 574 | ||
| 562 | if (redraw_flg) { | 575 | if (redraw_flg) { |
| @@ -590,14 +603,14 @@ extern void cmdedit_init(void) | |||
| 590 | } | 603 | } |
| 591 | #endif | 604 | #endif |
| 592 | 605 | ||
| 593 | #ifdef BB_FEATURE_SH_TAB_COMPLETION | 606 | #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION |
| 594 | 607 | ||
| 595 | #ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR | 608 | #ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR |
| 596 | my_euid = geteuid(); | 609 | my_euid = geteuid(); |
| 597 | #endif | 610 | #endif |
| 598 | my_uid = getuid(); | 611 | my_uid = getuid(); |
| 599 | my_gid = getgid(); | 612 | my_gid = getgid(); |
| 600 | #endif /* BB_FEATURE_SH_TAB_COMPLETION */ | 613 | #endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ |
| 601 | handlers_sets |= SET_ATEXIT; | 614 | handlers_sets |= SET_ATEXIT; |
| 602 | atexit(cmdedit_reset_term); /* be sure to do this only once */ | 615 | atexit(cmdedit_reset_term); /* be sure to do this only once */ |
| 603 | } | 616 | } |
| @@ -612,7 +625,7 @@ extern void cmdedit_init(void) | |||
| 612 | 625 | ||
| 613 | } | 626 | } |
| 614 | 627 | ||
| 615 | #ifdef BB_FEATURE_SH_TAB_COMPLETION | 628 | #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION |
| 616 | 629 | ||
| 617 | static int is_execute(const struct stat *st) | 630 | static int is_execute(const struct stat *st) |
| 618 | { | 631 | { |
| @@ -623,7 +636,7 @@ static int is_execute(const struct stat *st) | |||
| 623 | return FALSE; | 636 | return FALSE; |
| 624 | } | 637 | } |
| 625 | 638 | ||
| 626 | #ifdef BB_FEATURE_SH_USERNAME_COMPLETION | 639 | #ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION |
| 627 | 640 | ||
| 628 | static char **username_tab_completion(char *ud, int *num_matches) | 641 | static char **username_tab_completion(char *ud, int *num_matches) |
| 629 | { | 642 | { |
| @@ -632,19 +645,19 @@ static char **username_tab_completion(char *ud, int *num_matches) | |||
| 632 | char *temp; | 645 | char *temp; |
| 633 | 646 | ||
| 634 | 647 | ||
| 635 | ud++; /* ~user/... to user/... */ | 648 | ud++; /* ~user/... to user/... */ |
| 636 | userlen = strlen(ud); | 649 | userlen = strlen(ud); |
| 637 | 650 | ||
| 638 | if (num_matches == 0) { /* "~/..." or "~user/..." */ | 651 | if (num_matches == 0) { /* "~/..." or "~user/..." */ |
| 639 | char *sav_ud = ud - 1; | 652 | char *sav_ud = ud - 1; |
| 640 | char *home = 0; | 653 | char *home = 0; |
| 641 | 654 | ||
| 642 | if (*ud == '/') { /* "~/..." */ | 655 | if (*ud == '/') { /* "~/..." */ |
| 643 | home = home_pwd_buf; | 656 | home = home_pwd_buf; |
| 644 | } else { | 657 | } else { |
| 645 | /* "~user/..." */ | 658 | /* "~user/..." */ |
| 646 | temp = strchr(ud, '/'); | 659 | temp = strchr(ud, '/'); |
| 647 | *temp = 0; /* ~user\0 */ | 660 | *temp = 0; /* ~user\0 */ |
| 648 | entry = getpwnam(ud); | 661 | entry = getpwnam(ud); |
| 649 | *temp = '/'; /* restore ~user/... */ | 662 | *temp = '/'; /* restore ~user/... */ |
| 650 | ud = temp; | 663 | ud = temp; |
| @@ -660,7 +673,7 @@ static char **username_tab_completion(char *ud, int *num_matches) | |||
| 660 | strcpy(sav_ud, temp2); | 673 | strcpy(sav_ud, temp2); |
| 661 | } | 674 | } |
| 662 | } | 675 | } |
| 663 | return 0; /* void, result save to argument :-) */ | 676 | return 0; /* void, result save to argument :-) */ |
| 664 | } else { | 677 | } else { |
| 665 | /* "~[^/]*" */ | 678 | /* "~[^/]*" */ |
| 666 | char **matches = (char **) NULL; | 679 | char **matches = (char **) NULL; |
| @@ -685,7 +698,7 @@ static char **username_tab_completion(char *ud, int *num_matches) | |||
| 685 | return (matches); | 698 | return (matches); |
| 686 | } | 699 | } |
| 687 | } | 700 | } |
| 688 | #endif /* BB_FEATURE_SH_USERNAME_COMPLETION */ | 701 | #endif /* BB_FEATURE_COMMAND_USERNAME_COMPLETION */ |
| 689 | 702 | ||
| 690 | enum { | 703 | enum { |
| 691 | FIND_EXE_ONLY = 0, | 704 | FIND_EXE_ONLY = 0, |
| @@ -710,11 +723,11 @@ static int path_parse(char ***p, int flags) | |||
| 710 | npth = 0; | 723 | npth = 0; |
| 711 | 724 | ||
| 712 | for (;;) { | 725 | for (;;) { |
| 713 | npth++; /* count words is + 1 count ':' */ | 726 | npth++; /* count words is + 1 count ':' */ |
| 714 | tmp = strchr(tmp, ':'); | 727 | tmp = strchr(tmp, ':'); |
| 715 | if (tmp) { | 728 | if (tmp) { |
| 716 | if (*++tmp == 0) | 729 | if (*++tmp == 0) |
| 717 | break; /* :<empty> */ | 730 | break; /* :<empty> */ |
| 718 | } else | 731 | } else |
| 719 | break; | 732 | break; |
| 720 | } | 733 | } |
| @@ -723,7 +736,7 @@ static int path_parse(char ***p, int flags) | |||
| 723 | 736 | ||
| 724 | tmp = pth; | 737 | tmp = pth; |
| 725 | (*p)[0] = xstrdup(tmp); | 738 | (*p)[0] = xstrdup(tmp); |
| 726 | npth = 1; /* count words is + 1 count ':' */ | 739 | npth = 1; /* count words is + 1 count ':' */ |
| 727 | 740 | ||
| 728 | for (;;) { | 741 | for (;;) { |
| 729 | tmp = strchr(tmp, ':'); | 742 | tmp = strchr(tmp, ':'); |
| @@ -754,7 +767,7 @@ static char *add_quote_for_spec_chars(char *found) | |||
| 754 | } | 767 | } |
| 755 | 768 | ||
| 756 | static char **exe_n_cwd_tab_completion(char *command, int *num_matches, | 769 | static char **exe_n_cwd_tab_completion(char *command, int *num_matches, |
| 757 | int type) | 770 | int type) |
| 758 | { | 771 | { |
| 759 | 772 | ||
| 760 | char **matches = 0; | 773 | char **matches = 0; |
| @@ -782,7 +795,7 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, | |||
| 782 | strcpy(dirbuf, command); | 795 | strcpy(dirbuf, command); |
| 783 | /* set dir only */ | 796 | /* set dir only */ |
| 784 | dirbuf[(pfind - command) + 1] = 0; | 797 | dirbuf[(pfind - command) + 1] = 0; |
| 785 | #ifdef BB_FEATURE_SH_USERNAME_COMPLETION | 798 | #ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION |
| 786 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ | 799 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ |
| 787 | username_tab_completion(dirbuf, 0); | 800 | username_tab_completion(dirbuf, 0); |
| 788 | #endif | 801 | #endif |
| @@ -796,7 +809,7 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, | |||
| 796 | for (i = 0; i < npaths; i++) { | 809 | for (i = 0; i < npaths; i++) { |
| 797 | 810 | ||
| 798 | dir = opendir(paths[i]); | 811 | dir = opendir(paths[i]); |
| 799 | if (!dir) /* Don't print an error */ | 812 | if (!dir) /* Don't print an error */ |
| 800 | continue; | 813 | continue; |
| 801 | 814 | ||
| 802 | while ((next = readdir(dir)) != NULL) { | 815 | while ((next = readdir(dir)) != NULL) { |
| @@ -987,7 +1000,8 @@ static int find_match(char *matchBuf, int *len_with_quotes) | |||
| 987 | for (i = 0; int_buf[i]; i++) | 1000 | for (i = 0; int_buf[i]; i++) |
| 988 | if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') { | 1001 | if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') { |
| 989 | if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY | 1002 | if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY |
| 990 | && strncmp(&matchBuf[pos_buf[0]], "cd", 2) == 0) | 1003 | && matchBuf[pos_buf[0]]=='c' |
| 1004 | && matchBuf[pos_buf[1]]=='d' ) | ||
| 991 | command_mode = FIND_DIR_ONLY; | 1005 | command_mode = FIND_DIR_ONLY; |
| 992 | else { | 1006 | else { |
| 993 | command_mode = FIND_FILE_ONLY; | 1007 | command_mode = FIND_FILE_ONLY; |
| @@ -1065,7 +1079,7 @@ static void input_tab(int *lastWasTab) | |||
| 1065 | /* Free up any memory already allocated */ | 1079 | /* Free up any memory already allocated */ |
| 1066 | input_tab(0); | 1080 | input_tab(0); |
| 1067 | 1081 | ||
| 1068 | #ifdef BB_FEATURE_SH_USERNAME_COMPLETION | 1082 | #ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION |
| 1069 | /* If the word starts with `~' and there is no slash in the word, | 1083 | /* If the word starts with `~' and there is no slash in the word, |
| 1070 | * then try completing this word as a username. */ | 1084 | * then try completing this word as a username. */ |
| 1071 | 1085 | ||
| @@ -1085,7 +1099,7 @@ static void input_tab(int *lastWasTab) | |||
| 1085 | 1099 | ||
| 1086 | beep(); | 1100 | beep(); |
| 1087 | if (!matches) | 1101 | if (!matches) |
| 1088 | return; /* not found */ | 1102 | return; /* not found */ |
| 1089 | /* sort */ | 1103 | /* sort */ |
| 1090 | qsort(matches, num_matches, sizeof(char *), match_compare); | 1104 | qsort(matches, num_matches, sizeof(char *), match_compare); |
| 1091 | 1105 | ||
| @@ -1101,7 +1115,7 @@ static void input_tab(int *lastWasTab) | |||
| 1101 | free(tmp); | 1115 | free(tmp); |
| 1102 | return; | 1116 | return; |
| 1103 | } | 1117 | } |
| 1104 | } else { /* one match */ | 1118 | } else { /* one match */ |
| 1105 | tmp = matches[0]; | 1119 | tmp = matches[0]; |
| 1106 | /* for next completion current found */ | 1120 | /* for next completion current found */ |
| 1107 | *lastWasTab = FALSE; | 1121 | *lastWasTab = FALSE; |
| @@ -1164,7 +1178,7 @@ static void input_tab(int *lastWasTab) | |||
| 1164 | } | 1178 | } |
| 1165 | } | 1179 | } |
| 1166 | } | 1180 | } |
| 1167 | #endif /* BB_FEATURE_SH_TAB_COMPLETION */ | 1181 | #endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ |
| 1168 | 1182 | ||
| 1169 | static void get_previous_history(struct history **hp, struct history *p) | 1183 | static void get_previous_history(struct history **hp, struct history *p) |
| 1170 | { | 1184 | { |
| @@ -1201,6 +1215,7 @@ enum { | |||
| 1201 | * Furthermore, the "vi" command editing keys are not implemented. | 1215 | * Furthermore, the "vi" command editing keys are not implemented. |
| 1202 | * | 1216 | * |
| 1203 | */ | 1217 | */ |
| 1218 | |||
| 1204 | extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) | 1219 | extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) |
| 1205 | { | 1220 | { |
| 1206 | 1221 | ||
| @@ -1212,7 +1227,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1212 | struct history *hp = his_end; | 1227 | struct history *hp = his_end; |
| 1213 | 1228 | ||
| 1214 | /* prepare before init handlers */ | 1229 | /* prepare before init handlers */ |
| 1215 | cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ | 1230 | cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ |
| 1216 | len = 0; | 1231 | len = 0; |
| 1217 | command_ps = command; | 1232 | command_ps = command; |
| 1218 | 1233 | ||
| @@ -1223,9 +1238,11 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1223 | 1238 | ||
| 1224 | new_settings.c_cc[VMIN] = 1; | 1239 | new_settings.c_cc[VMIN] = 1; |
| 1225 | new_settings.c_cc[VTIME] = 0; | 1240 | new_settings.c_cc[VTIME] = 0; |
| 1226 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; /* Turn off CTRL-C, so we can trap it */ | 1241 | /* Turn off CTRL-C, so we can trap it */ |
| 1242 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; | ||
| 1227 | new_settings.c_lflag &= ~ICANON; /* unbuffered input */ | 1243 | new_settings.c_lflag &= ~ICANON; /* unbuffered input */ |
| 1228 | new_settings.c_lflag &= ~(ECHO | ECHOCTL | ECHONL); /* Turn off echoing */ | 1244 | /* Turn off echoing */ |
| 1245 | new_settings.c_lflag &= ~(ECHO | ECHOCTL | ECHONL); | ||
| 1229 | } | 1246 | } |
| 1230 | 1247 | ||
| 1231 | command[0] = 0; | 1248 | command[0] = 0; |
| @@ -1295,7 +1312,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1295 | input_backspace(); | 1312 | input_backspace(); |
| 1296 | break; | 1313 | break; |
| 1297 | case '\t': | 1314 | case '\t': |
| 1298 | #ifdef BB_FEATURE_SH_TAB_COMPLETION | 1315 | #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION |
| 1299 | input_tab(&lastWasTab); | 1316 | input_tab(&lastWasTab); |
| 1300 | #endif | 1317 | #endif |
| 1301 | break; | 1318 | break; |
| @@ -1335,7 +1352,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1335 | return; | 1352 | return; |
| 1336 | } | 1353 | } |
| 1337 | switch (c) { | 1354 | switch (c) { |
| 1338 | #ifdef BB_FEATURE_SH_TAB_COMPLETION | 1355 | #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION |
| 1339 | case '\t': /* Alt-Tab */ | 1356 | case '\t': /* Alt-Tab */ |
| 1340 | 1357 | ||
| 1341 | input_tab(&lastWasTab); | 1358 | input_tab(&lastWasTab); |
| @@ -1402,7 +1419,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1402 | break; | 1419 | break; |
| 1403 | } | 1420 | } |
| 1404 | 1421 | ||
| 1405 | default: /* If it's regular input, do the normal thing */ | 1422 | default: /* If it's regular input, do the normal thing */ |
| 1406 | #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT | 1423 | #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT |
| 1407 | /* Control-V -- Add non-printable symbol */ | 1424 | /* Control-V -- Add non-printable symbol */ |
| 1408 | if (c == 22) { | 1425 | if (c == 22) { |
| @@ -1493,16 +1510,16 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1493 | history_counter++; | 1510 | history_counter++; |
| 1494 | } | 1511 | } |
| 1495 | } | 1512 | } |
| 1496 | #if defined(BB_FEATURE_BASH_STYLE_PROMT) | 1513 | #if !defined(BB_FEATURE_SIMPLE_PROMPT) |
| 1497 | num_ok_lines++; | 1514 | num_ok_lines++; |
| 1498 | #endif | 1515 | #endif |
| 1499 | } | 1516 | } |
| 1500 | command[len++] = '\n'; /* set '\n' */ | 1517 | command[len++] = '\n'; /* set '\n' */ |
| 1501 | command[len] = 0; | 1518 | command[len] = 0; |
| 1502 | #if defined(BB_FEATURE_CLEAN_UP) && defined(BB_FEATURE_SH_TAB_COMPLETION) | 1519 | #if defined(BB_FEATURE_CLEAN_UP) && defined(BB_FEATURE_COMMAND_TAB_COMPLETION) |
| 1503 | input_tab(0); /* strong free */ | 1520 | input_tab(0); /* strong free */ |
| 1504 | #endif | 1521 | #endif |
| 1505 | #if defined(BB_FEATURE_BASH_STYLE_PROMT) | 1522 | #if !defined(BB_FEATURE_SIMPLE_PROMPT) |
| 1506 | free(cmdedit_prompt); | 1523 | free(cmdedit_prompt); |
| 1507 | #endif | 1524 | #endif |
| 1508 | return; | 1525 | return; |
| @@ -1523,7 +1540,7 @@ extern void cmdedit_terminate(void) | |||
| 1523 | } | 1540 | } |
| 1524 | } | 1541 | } |
| 1525 | 1542 | ||
| 1526 | #endif /* BB_FEATURE_SH_COMMAND_EDITING */ | 1543 | #endif /* BB_FEATURE_COMMAND_EDITING */ |
| 1527 | 1544 | ||
| 1528 | 1545 | ||
| 1529 | #ifdef TEST | 1546 | #ifdef TEST |
| @@ -1534,21 +1551,25 @@ int main(int argc, char **argv) | |||
| 1534 | { | 1551 | { |
| 1535 | char buff[BUFSIZ]; | 1552 | char buff[BUFSIZ]; |
| 1536 | char *prompt = | 1553 | char *prompt = |
| 1537 | #if defined(BB_FEATURE_BASH_STYLE_PROMT) | 1554 | #if !defined(BB_FEATURE_SIMPLE_PROMPT) |
| 1538 | "\\[\\033[32;1m\\]\\u@\\[\\033[33;1m\\]\\h:\ | 1555 | "\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:\ |
| 1539 | \\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] \ | 1556 | \\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] \ |
| 1540 | \\!\\[\\033[36;1m\\]\\$ \\[\\033[0m\\]"; | 1557 | \\!\\[\\e[36;1m\\]\\$ \\[\\E[0m\\]"; |
| 1541 | #else | 1558 | #else |
| 1542 | "% "; | 1559 | "% "; |
| 1543 | #endif | 1560 | #endif |
| 1544 | 1561 | ||
| 1545 | shell_context = 1; | 1562 | shell_context = 1; |
| 1546 | do { | 1563 | do { |
| 1564 | int l; | ||
| 1547 | cmdedit_read_input(prompt, buff); | 1565 | cmdedit_read_input(prompt, buff); |
| 1566 | l = strlen(buff); | ||
| 1567 | if(l > 0 && buff[l-1] == '\n') | ||
| 1568 | buff[l-1] = 0; | ||
| 1548 | printf("*** cmdedit_read_input() returned line =%s=\n", buff); | 1569 | printf("*** cmdedit_read_input() returned line =%s=\n", buff); |
| 1549 | } while (shell_context); | 1570 | } while (shell_context); |
| 1550 | printf("*** cmdedit_read_input() detect ^C\n"); | 1571 | printf("*** cmdedit_read_input() detect ^C\n"); |
| 1551 | return 0; | 1572 | return 0; |
| 1552 | } | 1573 | } |
| 1553 | 1574 | ||
| 1554 | #endif /* TEST */ | 1575 | #endif /* TEST */ |
diff --git a/shell/cmdedit.h b/shell/cmdedit.h index b96ffd373..0ab94c6ce 100644 --- a/shell/cmdedit.h +++ b/shell/cmdedit.h | |||
| @@ -1,13 +1,14 @@ | |||
| 1 | #ifndef CMDEDIT_H | 1 | #ifndef CMDEDIT_H |
| 2 | #define CMDEDIT_H | 2 | #define CMDEDIT_H |
| 3 | 3 | ||
| 4 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 4 | #ifdef BB_FEATURE_COMMAND_EDITING |
| 5 | #include <stddef.h> | 5 | #include <stddef.h> |
| 6 | #include "busybox.h" | ||
| 6 | 7 | ||
| 7 | void cmdedit_init(void); | 8 | void cmdedit_init(void); |
| 8 | void cmdedit_terminate(void); | 9 | void cmdedit_terminate(void); |
| 9 | void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */ | 10 | void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */ |
| 10 | 11 | ||
| 11 | #endif /* BB_FEATURE_SH_COMMAND_EDITING */ | 12 | #endif /* BB_FEATURE_COMMAND_EDITING */ |
| 12 | 13 | ||
| 13 | #endif /* CMDEDIT_H */ | 14 | #endif /* CMDEDIT_H */ |
diff --git a/shell/lash.c b/shell/lash.c index 67d6e4f51..49fb6b536 100644 --- a/shell/lash.c +++ b/shell/lash.c | |||
| @@ -39,11 +39,15 @@ | |||
| 39 | //#define BB_FEATURE_SH_BACKTICKS | 39 | //#define BB_FEATURE_SH_BACKTICKS |
| 40 | // | 40 | // |
| 41 | //If, then, else, etc. support.. This should now behave basically | 41 | //If, then, else, etc. support.. This should now behave basically |
| 42 | //like any other Bourne shell... | 42 | //like any other Bourne shell -- sortof... |
| 43 | #define BB_FEATURE_SH_IF_EXPRESSIONS | 43 | #define BB_FEATURE_SH_IF_EXPRESSIONS |
| 44 | // | 44 | // |
| 45 | /* This is currently a little broken... */ | 45 | /* This is currently sortof broken, only for the brave... */ |
| 46 | //#define HANDLE_CONTINUATION_CHARS | 46 | #undef HANDLE_CONTINUATION_CHARS |
| 47 | // | ||
| 48 | /* This would be great -- if wordexp wouldn't strip all quoting | ||
| 49 | * out from the target strings... As is, a parser needs */ | ||
| 50 | #undef BB_FEATURE_SH_WORDEXP | ||
| 47 | // | 51 | // |
| 48 | //For debugging/development on the shell only... | 52 | //For debugging/development on the shell only... |
| 49 | //#define DEBUG_SHELL | 53 | //#define DEBUG_SHELL |
| @@ -61,10 +65,9 @@ | |||
| 61 | #include <unistd.h> | 65 | #include <unistd.h> |
| 62 | #include <getopt.h> | 66 | #include <getopt.h> |
| 63 | 67 | ||
| 64 | //#undef __GLIBC__ | 68 | #undef BB_FEATURE_SH_WORDEXP |
| 65 | //#undef __UCLIBC__ | ||
| 66 | 69 | ||
| 67 | #if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) | 70 | #if BB_FEATURE_SH_WORDEXP |
| 68 | #include <wordexp.h> | 71 | #include <wordexp.h> |
| 69 | #define expand_t wordexp_t | 72 | #define expand_t wordexp_t |
| 70 | #undef BB_FEATURE_SH_BACKTICKS | 73 | #undef BB_FEATURE_SH_BACKTICKS |
| @@ -227,6 +230,10 @@ static int show_x_trace; | |||
| 227 | static char syntax_err[]="syntax error near unexpected token"; | 230 | static char syntax_err[]="syntax error near unexpected token"; |
| 228 | #endif | 231 | #endif |
| 229 | 232 | ||
| 233 | static char *PS1; | ||
| 234 | static char *PS2; | ||
| 235 | |||
| 236 | |||
| 230 | #ifdef DEBUG_SHELL | 237 | #ifdef DEBUG_SHELL |
| 231 | static inline void debug_printf(const char *format, ...) | 238 | static inline void debug_printf(const char *format, ...) |
| 232 | { | 239 | { |
| @@ -286,7 +293,7 @@ static int builtin_cd(struct child_prog *child) | |||
| 286 | else | 293 | else |
| 287 | newdir = child->argv[1]; | 294 | newdir = child->argv[1]; |
| 288 | if (chdir(newdir)) { | 295 | if (chdir(newdir)) { |
| 289 | printf("cd: %s: %s\n", newdir, strerror(errno)); | 296 | printf("cd: %s: %m\n", newdir); |
| 290 | return EXIT_FAILURE; | 297 | return EXIT_FAILURE; |
| 291 | } | 298 | } |
| 292 | getcwd(cwd, sizeof(char)*MAX_LINE); | 299 | getcwd(cwd, sizeof(char)*MAX_LINE); |
| @@ -425,13 +432,20 @@ static int builtin_pwd(struct child_prog *dummy) | |||
| 425 | static int builtin_export(struct child_prog *child) | 432 | static int builtin_export(struct child_prog *child) |
| 426 | { | 433 | { |
| 427 | int res; | 434 | int res; |
| 435 | char *v = child->argv[1]; | ||
| 428 | 436 | ||
| 429 | if (child->argv[1] == NULL) { | 437 | if (v == NULL) { |
| 430 | return (builtin_env(child)); | 438 | return (builtin_env(child)); |
| 431 | } | 439 | } |
| 432 | res = putenv(child->argv[1]); | 440 | res = putenv(v); |
| 433 | if (res) | 441 | if (res) |
| 434 | fprintf(stderr, "export: %s\n", strerror(errno)); | 442 | fprintf(stderr, "export: %m\n"); |
| 443 | #ifndef BB_FEATURE_SIMPLE_PROMPT | ||
| 444 | if (strncmp(v, "PS1=", 4)==0) | ||
| 445 | PS1 = getenv("PS1"); | ||
| 446 | else if (strncmp(v, "PS2=", 4)==0) | ||
| 447 | PS2 = getenv("PS2"); | ||
| 448 | #endif | ||
| 435 | return (res); | 449 | return (res); |
| 436 | } | 450 | } |
| 437 | 451 | ||
| @@ -461,7 +475,7 @@ static int builtin_read(struct child_prog *child) | |||
| 461 | if((s = strdup(string))) | 475 | if((s = strdup(string))) |
| 462 | res = putenv(s); | 476 | res = putenv(s); |
| 463 | if (res) | 477 | if (res) |
| 464 | fprintf(stderr, "read: %s\n", strerror(errno)); | 478 | fprintf(stderr, "read: %m\n"); |
| 465 | } | 479 | } |
| 466 | else | 480 | else |
| 467 | fgets(string, sizeof(string), stdin); | 481 | fgets(string, sizeof(string), stdin); |
| @@ -759,8 +773,7 @@ static int setup_redirects(struct child_prog *prog, int squirrel[]) | |||
| 759 | if (openfd < 0) { | 773 | if (openfd < 0) { |
| 760 | /* this could get lost if stderr has been redirected, but | 774 | /* this could get lost if stderr has been redirected, but |
| 761 | bash and ash both lose it as well (though zsh doesn't!) */ | 775 | bash and ash both lose it as well (though zsh doesn't!) */ |
| 762 | error_msg("error opening %s: %s", redir->filename, | 776 | perror_msg("error opening %s", redir->filename); |
| 763 | strerror(errno)); | ||
| 764 | return 1; | 777 | return 1; |
| 765 | } | 778 | } |
| 766 | 779 | ||
| @@ -790,57 +803,40 @@ static void restore_redirects(int squirrel[]) | |||
| 790 | } | 803 | } |
| 791 | } | 804 | } |
| 792 | 805 | ||
| 793 | #if defined(BB_FEATURE_SH_SIMPLE_PROMPT) | 806 | static inline void cmdedit_set_initial_prompt(void) |
| 794 | static char* setup_prompt_string(int state) | ||
| 795 | { | 807 | { |
| 796 | char prompt_str[BUFSIZ]; | 808 | #ifdef BB_FEATURE_SIMPLE_PROMPT |
| 797 | 809 | PS1 = NULL; | |
| 798 | /* Set up the prompt */ | 810 | PS2 = "> "; |
| 799 | if (state == 0) { | ||
| 800 | /* simple prompt */ | ||
| 801 | sprintf(prompt_str, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# "); | ||
| 802 | } else { | ||
| 803 | strcpy(prompt_str,"> "); | ||
| 804 | } | ||
| 805 | |||
| 806 | return(strdup(prompt_str)); /* Must free this memory */ | ||
| 807 | } | ||
| 808 | |||
| 809 | #else | 811 | #else |
| 812 | PS1 = getenv("PS1"); | ||
| 813 | if(PS1==0) { | ||
| 814 | PS1 = "\\w \\$ "; | ||
| 815 | } | ||
| 816 | PS2 = getenv("PS2"); | ||
| 817 | if(PS2==0) | ||
| 818 | PS2 = "> "; | ||
| 819 | #endif | ||
| 820 | } | ||
| 810 | 821 | ||
| 811 | static char* setup_prompt_string(int state) | 822 | static inline void setup_prompt_string(char **prompt_str) |
| 812 | { | 823 | { |
| 813 | char user[9],buf[255],*s; | 824 | #ifdef BB_FEATURE_SIMPLE_PROMPT |
| 814 | char prompt[3]; | ||
| 815 | char prompt_str[BUFSIZ]; | ||
| 816 | |||
| 817 | /* Set up the prompt */ | 825 | /* Set up the prompt */ |
| 818 | if (state == 0) { | 826 | if (shell_context == 0) { |
| 819 | /* get User Name and setup prompt */ | 827 | if (PS1) |
| 820 | strcpy(prompt,( geteuid() != 0 ) ? "$ ":"# "); | 828 | free(PS1); |
| 821 | my_getpwuid(user, geteuid()); | 829 | PS1=xmalloc(strlen(cwd)+4); |
| 822 | 830 | sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# "); | |
| 823 | /* get HostName */ | 831 | *prompt_str = PS1; |
| 824 | gethostname(buf, 255); | ||
| 825 | s = strchr(buf, '.'); | ||
| 826 | if (s) { | ||
| 827 | *s = 0; | ||
| 828 | } | ||
| 829 | } else { | 832 | } else { |
| 830 | strcpy(prompt,"> "); | 833 | *prompt_str = PS2; |
| 831 | } | 834 | } |
| 832 | 835 | #else | |
| 833 | if (state == 0) { | 836 | *prompt_str = (shell_context==0)? PS1 : PS2; |
| 834 | snprintf(prompt_str, BUFSIZ-1, "[%s@%s %s]%s", user, buf, | 837 | #endif |
| 835 | get_last_path_component(cwd), prompt); | ||
| 836 | } else { | ||
| 837 | sprintf(prompt_str, "%s", prompt); | ||
| 838 | } | ||
| 839 | return(strdup(prompt_str)); /* Must free this memory */ | ||
| 840 | } | 838 | } |
| 841 | 839 | ||
| 842 | #endif | ||
| 843 | |||
| 844 | static int get_command(FILE * source, char *command) | 840 | static int get_command(FILE * source, char *command) |
| 845 | { | 841 | { |
| 846 | char *prompt_str; | 842 | char *prompt_str; |
| @@ -857,9 +853,9 @@ static int get_command(FILE * source, char *command) | |||
| 857 | } | 853 | } |
| 858 | 854 | ||
| 859 | if (source == stdin) { | 855 | if (source == stdin) { |
| 860 | prompt_str = setup_prompt_string(shell_context); | 856 | setup_prompt_string(&prompt_str); |
| 861 | 857 | ||
| 862 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 858 | #ifdef BB_FEATURE_COMMAND_EDITING |
| 863 | /* | 859 | /* |
| 864 | ** enable command line editing only while a command line | 860 | ** enable command line editing only while a command line |
| 865 | ** is actually being read; otherwise, we'll end up bequeathing | 861 | ** is actually being read; otherwise, we'll end up bequeathing |
| @@ -868,11 +864,9 @@ static int get_command(FILE * source, char *command) | |||
| 868 | */ | 864 | */ |
| 869 | cmdedit_read_input(prompt_str, command); | 865 | cmdedit_read_input(prompt_str, command); |
| 870 | cmdedit_terminate(); | 866 | cmdedit_terminate(); |
| 871 | free(prompt_str); | ||
| 872 | return 0; | 867 | return 0; |
| 873 | #else | 868 | #else |
| 874 | fputs(prompt_str, stdout); | 869 | fputs(prompt_str, stdout); |
| 875 | free(prompt_str); | ||
| 876 | #endif | 870 | #endif |
| 877 | } | 871 | } |
| 878 | 872 | ||
| @@ -910,25 +904,72 @@ static char* itoa(register int i) | |||
| 910 | } | 904 | } |
| 911 | #endif | 905 | #endif |
| 912 | 906 | ||
| 907 | #if defined BB_FEATURE_SH_ENVIRONMENT && ! defined BB_FEATURE_SH_WORDEXP | ||
| 908 | char * strsep_space( char *string, int * index) | ||
| 909 | { | ||
| 910 | char *token, *begin; | ||
| 911 | |||
| 912 | begin = string; | ||
| 913 | |||
| 914 | /* Short circuit the trivial case */ | ||
| 915 | if ( !string || ! string[*index]) | ||
| 916 | return NULL; | ||
| 917 | |||
| 918 | /* Find the end of the token. */ | ||
| 919 | while( string && string[*index] && !isspace(string[*index]) ) { | ||
| 920 | (*index)++; | ||
| 921 | } | ||
| 922 | |||
| 923 | /* Find the end of any whitespace trailing behind | ||
| 924 | * the token and let that be part of the token */ | ||
| 925 | while( string && string[*index] && isspace(string[*index]) ) { | ||
| 926 | (*index)++; | ||
| 927 | } | ||
| 928 | |||
| 929 | if (! string && *index==0) { | ||
| 930 | /* Nothing useful was found */ | ||
| 931 | return NULL; | ||
| 932 | } | ||
| 933 | |||
| 934 | token = xmalloc(*index); | ||
| 935 | token[*index] = '\0'; | ||
| 936 | strncpy(token, string, *index); | ||
| 937 | |||
| 938 | return token; | ||
| 939 | } | ||
| 940 | #endif | ||
| 941 | |||
| 942 | |||
| 913 | static int expand_arguments(char *command) | 943 | static int expand_arguments(char *command) |
| 914 | { | 944 | { |
| 915 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 945 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
| 916 | expand_t expand_result; | 946 | expand_t expand_result; |
| 917 | char *src, *dst, *var; | 947 | char *src, *dst, *var; |
| 948 | int index = 0; | ||
| 918 | int i=0, length, total_length=0, retval; | 949 | int i=0, length, total_length=0, retval; |
| 919 | const char *out_of_space = "out of space during expansion"; | 950 | const char *out_of_space = "out of space during expansion"; |
| 920 | #endif | 951 | #endif |
| 921 | 952 | ||
| 922 | /* get rid of the terminating \n */ | 953 | /* get rid of the terminating \n */ |
| 923 | chomp(command); | 954 | chomp(command); |
| 955 | |||
| 956 | /* Fix up escape sequences to be the Real Thing(tm) */ | ||
| 957 | while( command && command[index]) { | ||
| 958 | if (command[index] == '\\') { | ||
| 959 | char *tmp = command+index+1; | ||
| 960 | command[index+1] = process_escape_sequence( &tmp ); | ||
| 961 | memmove(command+index, command+index+1, strlen(command+index)); | ||
| 962 | } | ||
| 963 | index++; | ||
| 964 | } | ||
| 924 | 965 | ||
| 925 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 966 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
| 926 | 967 | ||
| 927 | 968 | ||
| 928 | #if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) | 969 | #if BB_FEATURE_SH_WORDEXP |
| 929 | /* This first part uses wordexp() which is a wonderful C lib | 970 | /* This first part uses wordexp() which is a wonderful C lib |
| 930 | * function which expands nearly everything. */ | 971 | * function which expands nearly everything. */ |
| 931 | retval = wordexp (command, &expand_result, 0); | 972 | retval = wordexp (command, &expand_result, WRDE_SHOWERR); |
| 932 | if (retval == WRDE_NOSPACE) { | 973 | if (retval == WRDE_NOSPACE) { |
| 933 | /* Mem may have been allocated... */ | 974 | /* Mem may have been allocated... */ |
| 934 | wordfree (&expand_result); | 975 | wordfree (&expand_result); |
| @@ -970,15 +1011,17 @@ static int expand_arguments(char *command) | |||
| 970 | { | 1011 | { |
| 971 | 1012 | ||
| 972 | int flags = GLOB_NOCHECK|GLOB_BRACE|GLOB_TILDE; | 1013 | int flags = GLOB_NOCHECK|GLOB_BRACE|GLOB_TILDE; |
| 973 | char * tmpcmd, *cmd, *cmd_copy; | 1014 | char *tmpcmd, *cmd, *cmd_copy; |
| 974 | /* We need a clean copy, so strsep can mess up the copy while | 1015 | /* We need a clean copy, so strsep can mess up the copy while |
| 975 | * we write stuff into the original (in a minute) */ | 1016 | * we write stuff into the original (in a minute) */ |
| 976 | cmd = cmd_copy = strdup(command); | 1017 | cmd = cmd_copy = strdup(command); |
| 977 | *command = '\0'; | 1018 | *command = '\0'; |
| 978 | for (tmpcmd = cmd; (tmpcmd = strsep(&cmd, " \t")) != NULL;) { | 1019 | for (index = 0, tmpcmd = cmd; |
| 1020 | (tmpcmd = strsep_space(cmd, &index)) != NULL; cmd += index, index=0) { | ||
| 979 | if (*tmpcmd == '\0') | 1021 | if (*tmpcmd == '\0') |
| 980 | break; | 1022 | break; |
| 981 | retval = glob(tmpcmd, flags, NULL, &expand_result); | 1023 | retval = glob(tmpcmd, flags, NULL, &expand_result); |
| 1024 | free(tmpcmd); /* Free mem allocated by strsep_space */ | ||
| 982 | if (retval == GLOB_NOSPACE) { | 1025 | if (retval == GLOB_NOSPACE) { |
| 983 | /* Mem may have been allocated... */ | 1026 | /* Mem may have been allocated... */ |
| 984 | globfree (&expand_result); | 1027 | globfree (&expand_result); |
| @@ -1711,7 +1754,8 @@ static int busy_loop(FILE * input) | |||
| 1711 | if (!parse_command(&next_command, &newjob, &inbg) && | 1754 | if (!parse_command(&next_command, &newjob, &inbg) && |
| 1712 | newjob.num_progs) { | 1755 | newjob.num_progs) { |
| 1713 | int pipefds[2] = {-1,-1}; | 1756 | int pipefds[2] = {-1,-1}; |
| 1714 | debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob); | 1757 | debug_printf( "job=%p fed to run_command by busy_loop()'\n", |
| 1758 | &newjob); | ||
| 1715 | run_command(&newjob, inbg, pipefds); | 1759 | run_command(&newjob, inbg, pipefds); |
| 1716 | } | 1760 | } |
| 1717 | else { | 1761 | else { |
| @@ -1879,5 +1923,13 @@ int shell_main(int argc_l, char **argv_l) | |||
| 1879 | atexit(free_memory); | 1923 | atexit(free_memory); |
| 1880 | #endif | 1924 | #endif |
| 1881 | 1925 | ||
| 1926 | #ifdef BB_FEATURE_COMMAND_EDITING | ||
| 1927 | cmdedit_set_initial_prompt(); | ||
| 1928 | #else | ||
| 1929 | PS1 = NULL; | ||
| 1930 | PS2 = "> "; | ||
| 1931 | #endif | ||
| 1932 | |||
| 1882 | return (busy_loop(input)); | 1933 | return (busy_loop(input)); |
| 1883 | } | 1934 | } |
| 1935 | |||
