aboutsummaryrefslogtreecommitdiff
path: root/shell/cmdedit.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-07-28 09:56:35 +0000
committerEric Andersen <andersen@codepoet.org>2003-07-28 09:56:35 +0000
commitc470f4477ad7f548ee3ccd3662c83899a5648297 (patch)
treef561378ba4d38e7ed9c6d318c97166a993252582 /shell/cmdedit.c
parent9b4766116579e1b614b537d72730b7e7f5d7e66c (diff)
downloadbusybox-w32-c470f4477ad7f548ee3ccd3662c83899a5648297.tar.gz
busybox-w32-c470f4477ad7f548ee3ccd3662c83899a5648297.tar.bz2
busybox-w32-c470f4477ad7f548ee3ccd3662c83899a5648297.zip
This is synced from dash-0.4.17 and full ready for insert to new busybox
version: ftp://ftp.simtreas.ru/pub/my/bb/new News: - code is smalest! - support ${var...} expr - used new very strongly steal controlling terminal
Diffstat (limited to 'shell/cmdedit.c')
-rw-r--r--shell/cmdedit.c223
1 files changed, 118 insertions, 105 deletions
diff --git a/shell/cmdedit.c b/shell/cmdedit.c
index 843f73fef..717067267 100644
--- a/shell/cmdedit.c
+++ b/shell/cmdedit.c
@@ -9,7 +9,7 @@
9 * Adam Rogoyski <rogoyski@cs.utexas.edu> 9 * Adam Rogoyski <rogoyski@cs.utexas.edu>
10 * Dave Cinege <dcinege@psychosis.com> 10 * Dave Cinege <dcinege@psychosis.com>
11 * Jakub Jelinek (c) 1995 11 * Jakub Jelinek (c) 1995
12 * Erik Andersen <andersen@codepoet.org> (Majorly adjusted for busybox) 12 * Erik Andersen <andersee@debian.org> (Majorly adjusted for busybox)
13 * 13 *
14 * This code is 'as is' with no warranty. 14 * This code is 'as is' with no warranty.
15 * 15 *
@@ -63,7 +63,7 @@
63 63
64#define D(x) x 64#define D(x) x
65 65
66#endif /* TEST */ 66#endif /* TEST */
67 67
68#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION 68#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
69#include <dirent.h> 69#include <dirent.h>
@@ -86,7 +86,7 @@
86# else 86# else
87# include <pwd.h> 87# include <pwd.h>
88# endif /* TEST */ 88# endif /* TEST */
89#endif /* advanced FEATURES */ 89#endif /* advanced FEATURES */
90 90
91 91
92/* Maximum length of the linked list for the command line history */ 92/* Maximum length of the linked list for the command line history */
@@ -115,30 +115,30 @@ static struct termios initial_settings, new_settings;
115 115
116 116
117static 117static
118volatile int cmdedit_termw = 80; /* actual terminal width */ 118volatile int cmdedit_termw = 80; /* actual terminal width */
119static 119static
120volatile int handlers_sets = 0; /* Set next bites: */ 120volatile int handlers_sets = 0; /* Set next bites: */
121 121
122enum { 122enum {
123 SET_ATEXIT = 1, /* when atexit() has been called 123 SET_ATEXIT = 1, /* when atexit() has been called
124 and get euid,uid,gid to fast compare */ 124 and get euid,uid,gid to fast compare */
125 SET_WCHG_HANDLERS = 2, /* winchg signal handler */ 125 SET_WCHG_HANDLERS = 2, /* winchg signal handler */
126 SET_RESET_TERM = 4, /* if the terminal needs to be reset upon exit */ 126 SET_RESET_TERM = 4, /* if the terminal needs to be reset upon exit */
127}; 127};
128 128
129 129
130static int cmdedit_x; /* real x terminal position */ 130static int cmdedit_x; /* real x terminal position */
131static int cmdedit_y; /* pseudoreal y terminal position */ 131static int cmdedit_y; /* pseudoreal y terminal position */
132static int cmdedit_prmt_len; /* lenght prompt without colores string */ 132static int cmdedit_prmt_len; /* lenght prompt without colores string */
133 133
134static int cursor; /* required global for signal handler */ 134static int cursor; /* required global for signal handler */
135static int len; /* --- "" - - "" - -"- --""-- --""--- */ 135static int len; /* --- "" - - "" - -"- --""-- --""--- */
136static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */ 136static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */
137static 137static
138#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT 138#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
139 const 139 const
140#endif 140#endif
141char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ 141char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */
142 142
143#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR 143#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
144static char *user_buf = ""; 144static char *user_buf = "";
@@ -161,31 +161,36 @@ static int my_euid;
161static int my_uid; 161static int my_uid;
162static int my_gid; 162static int my_gid;
163 163
164#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */ 164#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
165
166/* It seems that libc5 doesn't know what a sighandler_t is... */
167#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1)
168typedef void (*sighandler_t) (int);
169#endif
165 170
166static void cmdedit_setwidth(int w, int redraw_flg); 171static void cmdedit_setwidth(int w, int redraw_flg);
167 172
168static void win_changed(int nsig) 173static void win_changed(int nsig)
169{ 174{
170 struct winsize win = { 0, 0, 0, 0 }; 175 struct winsize win = { 0, 0, 0, 0 };
171 static sighandler_t previous_SIGWINCH_handler; /* for reset */ 176 static sighandler_t previous_SIGWINCH_handler; /* for reset */
172 177
173 /* emulate || signal call */ 178 /* emulate || signal call */
174 if (nsig == -SIGWINCH || nsig == SIGWINCH) { 179 if (nsig == -SIGWINCH || nsig == SIGWINCH) {
175 ioctl(0, TIOCGWINSZ, &win); 180 ioctl(0, TIOCGWINSZ, &win);
176 if (win.ws_col > 0) { 181 if (win.ws_col > 0) {
177 cmdedit_setwidth(win.ws_col, nsig == SIGWINCH); 182 cmdedit_setwidth(win.ws_col, nsig == SIGWINCH);
178 } 183 }
179 } 184 }
180 /* Unix not all standart in recall signal */ 185 /* Unix not all standart in recall signal */
181 186
182 if (nsig == -SIGWINCH) /* save previous handler */ 187 if (nsig == -SIGWINCH) /* save previous handler */
183 previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); 188 previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
184 else if (nsig == SIGWINCH) /* signaled called handler */ 189 else if (nsig == SIGWINCH) /* signaled called handler */
185 signal(SIGWINCH, win_changed); /* set for next call */ 190 signal(SIGWINCH, win_changed); /* set for next call */
186 else /* nsig == 0 */ 191 else /* nsig == 0 */
187 /* set previous handler */ 192 /* set previous handler */
188 signal(SIGWINCH, previous_SIGWINCH_handler); /* reset */ 193 signal(SIGWINCH, previous_SIGWINCH_handler); /* reset */
189} 194}
190 195
191static void cmdedit_reset_term(void) 196static void cmdedit_reset_term(void)
@@ -211,9 +216,9 @@ static void cmdedit_set_out_char(int next_char)
211 int c = (int)((unsigned char) command_ps[cursor]); 216 int c = (int)((unsigned char) command_ps[cursor]);
212 217
213 if (c == 0) 218 if (c == 0)
214 c = ' '; /* destroy end char? */ 219 c = ' '; /* destroy end char? */
215#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT 220#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
216 if (!Isprint(c)) { /* Inverse put non-printable characters */ 221 if (!Isprint(c)) { /* Inverse put non-printable characters */
217 if (c >= 128) 222 if (c >= 128)
218 c -= 128; 223 c -= 128;
219 if (c < ' ') 224 if (c < ' ')
@@ -270,9 +275,9 @@ static void input_backward(int num)
270{ 275{
271 if (num > cursor) 276 if (num > cursor)
272 num = cursor; 277 num = cursor;
273 cursor -= num; /* new cursor (in command, not terminal) */ 278 cursor -= num; /* new cursor (in command, not terminal) */
274 279
275 if (cmdedit_x >= num) { /* no to up line */ 280 if (cmdedit_x >= num) { /* no to up line */
276 cmdedit_x -= num; 281 cmdedit_x -= num;
277 if (num < 4) 282 if (num < 4)
278 while (num-- > 0) 283 while (num-- > 0)
@@ -284,22 +289,22 @@ static void input_backward(int num)
284 int count_y; 289 int count_y;
285 290
286 if (cmdedit_x) { 291 if (cmdedit_x) {
287 putchar('\r'); /* back to first terminal pos. */ 292 putchar('\r'); /* back to first terminal pos. */
288 num -= cmdedit_x; /* set previous backward */ 293 num -= cmdedit_x; /* set previous backward */
289 } 294 }
290 count_y = 1 + num / cmdedit_termw; 295 count_y = 1 + num / cmdedit_termw;
291 printf("\033[%dA", count_y); 296 printf("\033[%dA", count_y);
292 cmdedit_y -= count_y; 297 cmdedit_y -= count_y;
293 /* require forward after uping */ 298 /* require forward after uping */
294 cmdedit_x = cmdedit_termw * count_y - num; 299 cmdedit_x = cmdedit_termw * count_y - num;
295 printf("\033[%dC", cmdedit_x); /* set term cursor */ 300 printf("\033[%dC", cmdedit_x); /* set term cursor */
296 } 301 }
297} 302}
298 303
299static void put_prompt(void) 304static void put_prompt(void)
300{ 305{
301 out1str(cmdedit_prompt); 306 out1str(cmdedit_prompt);
302 cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ 307 cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */
303 cursor = 0; 308 cursor = 0;
304 cmdedit_y = 0; /* new quasireal y */ 309 cmdedit_y = 0; /* new quasireal y */
305} 310}
@@ -335,7 +340,7 @@ static void parse_prompt(const char *prmt_ptr)
335 if (c == '\\') { 340 if (c == '\\') {
336 const char *cp = prmt_ptr; 341 const char *cp = prmt_ptr;
337 int l; 342 int l;
338 343
339 c = bb_process_escape_sequence(&prmt_ptr); 344 c = bb_process_escape_sequence(&prmt_ptr);
340 if(prmt_ptr==cp) { 345 if(prmt_ptr==cp) {
341 if (*cp == 0) 346 if (*cp == 0)
@@ -346,7 +351,7 @@ static void parse_prompt(const char *prmt_ptr)
346 case 'u': 351 case 'u':
347 pbuf = user_buf; 352 pbuf = user_buf;
348 break; 353 break;
349#endif 354#endif
350 case 'h': 355 case 'h':
351 pbuf = hostname_buf; 356 pbuf = hostname_buf;
352 if (pbuf == 0) { 357 if (pbuf == 0) {
@@ -378,7 +383,7 @@ static void parse_prompt(const char *prmt_ptr)
378 strcpy(pbuf+1, pwd_buf+l); 383 strcpy(pbuf+1, pwd_buf+l);
379 } 384 }
380 break; 385 break;
381#endif 386#endif
382 case 'W': 387 case 'W':
383 pbuf = pwd_buf; 388 pbuf = pwd_buf;
384 cp = strrchr(pbuf,'/'); 389 cp = strrchr(pbuf,'/');
@@ -391,7 +396,7 @@ static void parse_prompt(const char *prmt_ptr)
391 case 'e': case 'E': /* \e \E = \033 */ 396 case 'e': case 'E': /* \e \E = \033 */
392 c = '\033'; 397 c = '\033';
393 break; 398 break;
394 case 'x': case 'X': 399 case 'x': case 'X':
395 for (l = 0; l < 3;) { 400 for (l = 0; l < 3;) {
396 int h; 401 int h;
397 buf2[l++] = *prmt_ptr; 402 buf2[l++] = *prmt_ptr;
@@ -416,7 +421,7 @@ static void parse_prompt(const char *prmt_ptr)
416 } 421 }
417 break; 422 break;
418 } 423 }
419 } 424 }
420 } 425 }
421 if(pbuf == buf) 426 if(pbuf == buf)
422 *pbuf = c; 427 *pbuf = c;
@@ -437,12 +442,12 @@ static void parse_prompt(const char *prmt_ptr)
437/* draw promt, editor line, and clear tail */ 442/* draw promt, editor line, and clear tail */
438static void redraw(int y, int back_cursor) 443static void redraw(int y, int back_cursor)
439{ 444{
440 if (y > 0) /* up to start y */ 445 if (y > 0) /* up to start y */
441 printf("\033[%dA", y); 446 printf("\033[%dA", y);
442 putchar('\r'); 447 putchar('\r');
443 put_prompt(); 448 put_prompt();
444 input_end(); /* rewrite */ 449 input_end(); /* rewrite */
445 printf("\033[J"); /* destroy tail after cursor */ 450 printf("\033[J"); /* destroy tail after cursor */
446 input_backward(back_cursor); 451 input_backward(back_cursor);
447} 452}
448 453
@@ -456,9 +461,9 @@ static void input_delete(void)
456 461
457 strcpy(command_ps + j, command_ps + j + 1); 462 strcpy(command_ps + j, command_ps + j + 1);
458 len--; 463 len--;
459 input_end(); /* rewtite new line */ 464 input_end(); /* rewtite new line */
460 cmdedit_set_out_char(0); /* destroy end char */ 465 cmdedit_set_out_char(0); /* destroy end char */
461 input_backward(cursor - j); /* back to old pos cursor */ 466 input_backward(cursor - j); /* back to old pos cursor */
462} 467}
463 468
464/* Delete the char in back of the cursor */ 469/* Delete the char in back of the cursor */
@@ -496,7 +501,7 @@ static void cmdedit_setwidth(int w, int redraw_flg)
496 redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor); 501 redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor);
497 fflush(stdout); 502 fflush(stdout);
498 } 503 }
499 } 504 }
500} 505}
501 506
502static void cmdedit_init(void) 507static void cmdedit_init(void)
@@ -527,9 +532,9 @@ static void cmdedit_init(void)
527#endif 532#endif
528 my_uid = getuid(); 533 my_uid = getuid();
529 my_gid = getgid(); 534 my_gid = getgid();
530#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */ 535#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
531 handlers_sets |= SET_ATEXIT; 536 handlers_sets |= SET_ATEXIT;
532 atexit(cmdedit_reset_term); /* be sure to do this only once */ 537 atexit(cmdedit_reset_term); /* be sure to do this only once */
533 } 538 }
534} 539}
535 540
@@ -553,35 +558,35 @@ static char **username_tab_completion(char *ud, int *num_matches)
553 char *temp; 558 char *temp;
554 559
555 560
556 ud++; /* ~user/... to user/... */ 561 ud++; /* ~user/... to user/... */
557 userlen = strlen(ud); 562 userlen = strlen(ud);
558 563
559 if (num_matches == 0) { /* "~/..." or "~user/..." */ 564 if (num_matches == 0) { /* "~/..." or "~user/..." */
560 char *sav_ud = ud - 1; 565 char *sav_ud = ud - 1;
561 char *home = 0; 566 char *home = 0;
562 567
563 if (*ud == '/') { /* "~/..." */ 568 if (*ud == '/') { /* "~/..." */
564 home = home_pwd_buf; 569 home = home_pwd_buf;
565 } else { 570 } else {
566 /* "~user/..." */ 571 /* "~user/..." */
567 temp = strchr(ud, '/'); 572 temp = strchr(ud, '/');
568 *temp = 0; /* ~user\0 */ 573 *temp = 0; /* ~user\0 */
569 entry = getpwnam(ud); 574 entry = getpwnam(ud);
570 *temp = '/'; /* restore ~user/... */ 575 *temp = '/'; /* restore ~user/... */
571 ud = temp; 576 ud = temp;
572 if (entry) 577 if (entry)
573 home = entry->pw_dir; 578 home = entry->pw_dir;
574 } 579 }
575 if (home) { 580 if (home) {
576 if ((userlen + strlen(home) + 1) < BUFSIZ) { 581 if ((userlen + strlen(home) + 1) < BUFSIZ) {
577 char temp2[BUFSIZ]; /* argument size */ 582 char temp2[BUFSIZ]; /* argument size */
578 583
579 /* /home/user/... */ 584 /* /home/user/... */
580 sprintf(temp2, "%s%s", home, ud); 585 sprintf(temp2, "%s%s", home, ud);
581 strcpy(sav_ud, temp2); 586 strcpy(sav_ud, temp2);
582 } 587 }
583 } 588 }
584 return 0; /* void, result save to argument :-) */ 589 return 0; /* void, result save to argument :-) */
585 } else { 590 } else {
586 /* "~[^/]*" */ 591 /* "~[^/]*" */
587 char **matches = (char **) NULL; 592 char **matches = (char **) NULL;
@@ -593,7 +598,7 @@ static char **username_tab_completion(char *ud, int *num_matches)
593 /* Null usernames should result in all users as possible completions. */ 598 /* Null usernames should result in all users as possible completions. */
594 if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) { 599 if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) {
595 600
596 bb_xasprintf(&temp, "~%s/", entry->pw_name); 601 bb_xasprintf(&temp, "~%s/", entry->pw_name);
597 matches = xrealloc(matches, (nm + 1) * sizeof(char *)); 602 matches = xrealloc(matches, (nm + 1) * sizeof(char *));
598 603
599 matches[nm++] = temp; 604 matches[nm++] = temp;
@@ -605,7 +610,7 @@ static char **username_tab_completion(char *ud, int *num_matches)
605 return (matches); 610 return (matches);
606 } 611 }
607} 612}
608#endif /* CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION */ 613#endif /* CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION */
609 614
610enum { 615enum {
611 FIND_EXE_ONLY = 0, 616 FIND_EXE_ONLY = 0,
@@ -630,11 +635,11 @@ static int path_parse(char ***p, int flags)
630 npth = 0; 635 npth = 0;
631 636
632 for (;;) { 637 for (;;) {
633 npth++; /* count words is + 1 count ':' */ 638 npth++; /* count words is + 1 count ':' */
634 tmp = strchr(tmp, ':'); 639 tmp = strchr(tmp, ':');
635 if (tmp) { 640 if (tmp) {
636 if (*++tmp == 0) 641 if (*++tmp == 0)
637 break; /* :<empty> */ 642 break; /* :<empty> */
638 } else 643 } else
639 break; 644 break;
640 } 645 }
@@ -643,17 +648,17 @@ static int path_parse(char ***p, int flags)
643 648
644 tmp = pth; 649 tmp = pth;
645 (*p)[0] = bb_xstrdup(tmp); 650 (*p)[0] = bb_xstrdup(tmp);
646 npth = 1; /* count words is + 1 count ':' */ 651 npth = 1; /* count words is + 1 count ':' */
647 652
648 for (;;) { 653 for (;;) {
649 tmp = strchr(tmp, ':'); 654 tmp = strchr(tmp, ':');
650 if (tmp) { 655 if (tmp) {
651 (*p)[0][(tmp - pth)] = 0; /* ':' -> '\0' */ 656 (*p)[0][(tmp - pth)] = 0; /* ':' -> '\0' */
652 if (*++tmp == 0) 657 if (*++tmp == 0)
653 break; /* :<empty> */ 658 break; /* :<empty> */
654 } else 659 } else
655 break; 660 break;
656 (*p)[npth++] = &(*p)[0][(tmp - pth)]; /* p[next]=p[0][&'\0'+1] */ 661 (*p)[npth++] = &(*p)[0][(tmp - pth)]; /* p[next]=p[0][&'\0'+1] */
657 } 662 }
658 663
659 return npth; 664 return npth;
@@ -703,20 +708,20 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches,
703 /* set dir only */ 708 /* set dir only */
704 dirbuf[(pfind - command) + 1] = 0; 709 dirbuf[(pfind - command) + 1] = 0;
705#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION 710#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
706 if (dirbuf[0] == '~') /* ~/... or ~user/... */ 711 if (dirbuf[0] == '~') /* ~/... or ~user/... */
707 username_tab_completion(dirbuf, 0); 712 username_tab_completion(dirbuf, 0);
708#endif 713#endif
709 /* "strip" dirname in command */ 714 /* "strip" dirname in command */
710 pfind++; 715 pfind++;
711 716
712 paths[0] = dirbuf; 717 paths[0] = dirbuf;
713 npaths = 1; /* only 1 dir */ 718 npaths = 1; /* only 1 dir */
714 } 719 }
715 720
716 for (i = 0; i < npaths; i++) { 721 for (i = 0; i < npaths; i++) {
717 722
718 dir = opendir(paths[i]); 723 dir = opendir(paths[i]);
719 if (!dir) /* Don't print an error */ 724 if (!dir) /* Don't print an error */
720 continue; 725 continue;
721 726
722 while ((next = readdir(dir)) != NULL) { 727 while ((next = readdir(dir)) != NULL) {
@@ -728,17 +733,17 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches,
728 /* not see .name without .match */ 733 /* not see .name without .match */
729 if (*str_found == '.' && *pfind == 0) { 734 if (*str_found == '.' && *pfind == 0) {
730 if (*paths[i] == '/' && paths[i][1] == 0 735 if (*paths[i] == '/' && paths[i][1] == 0
731 && str_found[1] == 0) str_found = ""; /* only "/" */ 736 && str_found[1] == 0) str_found = ""; /* only "/" */
732 else 737 else
733 continue; 738 continue;
734 } 739 }
735 found = concat_path_file(paths[i], str_found); 740 found = concat_path_file(paths[i], str_found);
736 /* hmm, remover in progress? */ 741 /* hmm, remover in progress? */
737 if (stat(found, &st) < 0) 742 if (stat(found, &st) < 0)
738 goto cont; 743 goto cont;
739 /* find with dirs ? */ 744 /* find with dirs ? */
740 if (paths[i] != dirbuf) 745 if (paths[i] != dirbuf)
741 strcpy(found, next->d_name); /* only name */ 746 strcpy(found, next->d_name); /* only name */
742 if (S_ISDIR(st.st_mode)) { 747 if (S_ISDIR(st.st_mode)) {
743 /* name is directory */ 748 /* name is directory */
744 str_found = found; 749 str_found = found;
@@ -747,7 +752,7 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches,
747 str_found = add_quote_for_spec_chars(found); 752 str_found = add_quote_for_spec_chars(found);
748 } else { 753 } else {
749 /* not put found file if search only dirs for cd */ 754 /* not put found file if search only dirs for cd */
750 if (type == FIND_DIR_ONLY) 755 if (type == FIND_DIR_ONLY)
751 goto cont; 756 goto cont;
752 str_found = add_quote_for_spec_chars(found); 757 str_found = add_quote_for_spec_chars(found);
753 if (type == FIND_FILE_ONLY || 758 if (type == FIND_FILE_ONLY ||
@@ -764,7 +769,7 @@ cont:
764 closedir(dir); 769 closedir(dir);
765 } 770 }
766 if (paths != path1) { 771 if (paths != path1) {
767 free(paths[0]); /* allocated memory only in first member */ 772 free(paths[0]); /* allocated memory only in first member */
768 free(paths); 773 free(paths);
769 } 774 }
770 *num_matches = nm; 775 *num_matches = nm;
@@ -796,7 +801,7 @@ static int find_match(char *matchBuf, int *len_with_quotes)
796 for (i = 0;; i++) { 801 for (i = 0;; i++) {
797 int_buf[i] = (int) ((unsigned char) matchBuf[i]); 802 int_buf[i] = (int) ((unsigned char) matchBuf[i]);
798 if (int_buf[i] == 0) { 803 if (int_buf[i] == 0) {
799 pos_buf[i] = -1; /* indicator end line */ 804 pos_buf[i] = -1; /* indicator end line */
800 break; 805 break;
801 } else 806 } else
802 pos_buf[i] = i; 807 pos_buf[i] = i;
@@ -809,7 +814,7 @@ static int find_match(char *matchBuf, int *len_with_quotes)
809 int_buf[j] |= QUOT; 814 int_buf[j] |= QUOT;
810 i++; 815 i++;
811#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT 816#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
812 if (matchBuf[i] == '\t') /* algorithm equivalent */ 817 if (matchBuf[i] == '\t') /* algorithm equivalent */
813 int_buf[j] = ' ' | QUOT; 818 int_buf[j] = ' ' | QUOT;
814#endif 819#endif
815 } 820 }
@@ -852,7 +857,7 @@ static int find_match(char *matchBuf, int *len_with_quotes)
852 } 857 }
853 if (command_mode) { 858 if (command_mode) {
854 collapse_pos(0, i + command_mode); 859 collapse_pos(0, i + command_mode);
855 i = -1; /* hack incremet */ 860 i = -1; /* hack incremet */
856 } 861 }
857 } 862 }
858 /* collapse `command...` */ 863 /* collapse `command...` */
@@ -869,11 +874,11 @@ static int find_match(char *matchBuf, int *len_with_quotes)
869 collapse_pos(0, i + 1); 874 collapse_pos(0, i + 1);
870 break; 875 break;
871 } else 876 } else
872 i--; /* hack incremet */ 877 i--; /* hack incremet */
873 } 878 }
874 879
875 /* collapse (command...(command...)...) or {command...{command...}...} */ 880 /* collapse (command...(command...)...) or {command...{command...}...} */
876 c = 0; /* "recursive" level */ 881 c = 0; /* "recursive" level */
877 c2 = 0; 882 c2 = 0;
878 for (i = 0; int_buf[i]; i++) 883 for (i = 0; int_buf[i]; i++)
879 if (int_buf[i] == '(' || int_buf[i] == '{') { 884 if (int_buf[i] == '(' || int_buf[i] == '{') {
@@ -882,7 +887,7 @@ static int find_match(char *matchBuf, int *len_with_quotes)
882 else 887 else
883 c2++; 888 c2++;
884 collapse_pos(0, i + 1); 889 collapse_pos(0, i + 1);
885 i = -1; /* hack incremet */ 890 i = -1; /* hack incremet */
886 } 891 }
887 for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++) 892 for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++)
888 if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) { 893 if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) {
@@ -891,7 +896,7 @@ static int find_match(char *matchBuf, int *len_with_quotes)
891 else 896 else
892 c2--; 897 c2--;
893 collapse_pos(0, i + 1); 898 collapse_pos(0, i + 1);
894 i = -1; /* hack incremet */ 899 i = -1; /* hack incremet */
895 } 900 }
896 901
897 /* skip first not quote space */ 902 /* skip first not quote space */
@@ -927,7 +932,7 @@ static int find_match(char *matchBuf, int *len_with_quotes)
927 /* skip first not quoted '\'' or '"' */ 932 /* skip first not quoted '\'' or '"' */
928 for (i = 0; int_buf[i] == '\'' || int_buf[i] == '"'; i++); 933 for (i = 0; int_buf[i] == '\'' || int_buf[i] == '"'; i++);
929 /* collapse quote or unquote // or /~ */ 934 /* collapse quote or unquote // or /~ */
930 while ((int_buf[i] & ~QUOT) == '/' && 935 while ((int_buf[i] & ~QUOT) == '/' &&
931 ((int_buf[i + 1] & ~QUOT) == '/' 936 ((int_buf[i + 1] & ~QUOT) == '/'
932 || (int_buf[i + 1] & ~QUOT) == '~')) { 937 || (int_buf[i + 1] & ~QUOT) == '~')) {
933 i++; 938 i++;
@@ -991,7 +996,7 @@ static void input_tab(int *lastWasTab)
991 static int num_matches; 996 static int num_matches;
992 static char **matches; 997 static char **matches;
993 998
994 if (lastWasTab == 0) { /* free all memory */ 999 if (lastWasTab == 0) { /* free all memory */
995 if (matches) { 1000 if (matches) {
996 while (num_matches > 0) 1001 while (num_matches > 0)
997 free(matches[--num_matches]); 1002 free(matches[--num_matches]);
@@ -1008,7 +1013,7 @@ static void input_tab(int *lastWasTab)
1008 int find_type; 1013 int find_type;
1009 int recalc_pos; 1014 int recalc_pos;
1010 1015
1011 *lastWasTab = TRUE; /* flop trigger */ 1016 *lastWasTab = TRUE; /* flop trigger */
1012 1017
1013 /* Make a local copy of the string -- up 1018 /* Make a local copy of the string -- up
1014 * to the position of the cursor */ 1019 * to the position of the cursor */
@@ -1061,7 +1066,7 @@ static void input_tab(int *lastWasTab)
1061 1066
1062 beep(); 1067 beep();
1063 if (!matches) 1068 if (!matches)
1064 return; /* not found */ 1069 return; /* not found */
1065 /* sort */ 1070 /* sort */
1066 qsort(matches, num_matches, sizeof(char *), match_compare); 1071 qsort(matches, num_matches, sizeof(char *), match_compare);
1067 1072
@@ -1073,11 +1078,11 @@ static void input_tab(int *lastWasTab)
1073 *tmp1 = 0; 1078 *tmp1 = 0;
1074 break; 1079 break;
1075 } 1080 }
1076 if (*tmp == 0) { /* have unique */ 1081 if (*tmp == 0) { /* have unique */
1077 free(tmp); 1082 free(tmp);
1078 return; 1083 return;
1079 } 1084 }
1080 } else { /* one match */ 1085 } else { /* one match */
1081 tmp = matches[0]; 1086 tmp = matches[0];
1082 /* for next completion current found */ 1087 /* for next completion current found */
1083 *lastWasTab = FALSE; 1088 *lastWasTab = FALSE;
@@ -1111,7 +1116,7 @@ static void input_tab(int *lastWasTab)
1111 * just hit TAB again, print a list of all the 1116 * just hit TAB again, print a list of all the
1112 * available choices... */ 1117 * available choices... */
1113 if (matches && num_matches > 0) { 1118 if (matches && num_matches > 0) {
1114 int sav_cursor = cursor; /* change goto_new_line() */ 1119 int sav_cursor = cursor; /* change goto_new_line() */
1115 1120
1116 /* Go to the next line */ 1121 /* Go to the next line */
1117 goto_new_line(); 1122 goto_new_line();
@@ -1120,7 +1125,7 @@ static void input_tab(int *lastWasTab)
1120 } 1125 }
1121 } 1126 }
1122} 1127}
1123#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */ 1128#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
1124 1129
1125#if MAX_HISTORY >= 1 1130#if MAX_HISTORY >= 1
1126static void get_previous_history(void) 1131static void get_previous_history(void)
@@ -1159,7 +1164,7 @@ extern void load_history ( const char *fromfile )
1159 } 1164 }
1160 1165
1161 if (( fp = fopen ( fromfile, "r" ))) { 1166 if (( fp = fopen ( fromfile, "r" ))) {
1162 1167
1163 for ( hi = 0; hi < MAX_HISTORY; ) { 1168 for ( hi = 0; hi < MAX_HISTORY; ) {
1164 char * hl = bb_get_chomped_line_from_file(fp); 1169 char * hl = bb_get_chomped_line_from_file(fp);
1165 int l; 1170 int l;
@@ -1183,10 +1188,10 @@ extern void load_history ( const char *fromfile )
1183extern void save_history ( const char *tofile ) 1188extern void save_history ( const char *tofile )
1184{ 1189{
1185 FILE *fp = fopen ( tofile, "w" ); 1190 FILE *fp = fopen ( tofile, "w" );
1186 1191
1187 if ( fp ) { 1192 if ( fp ) {
1188 int i; 1193 int i;
1189 1194
1190 for ( i = 0; i < n_history; i++ ) { 1195 for ( i = 0; i < n_history; i++ ) {
1191 fputs ( history [i], fp ); 1196 fputs ( history [i], fp );
1192 fputc ( '\n', fp ); 1197 fputc ( '\n', fp );
@@ -1220,7 +1225,7 @@ enum {
1220 * Furthermore, the "vi" command editing keys are not implemented. 1225 * Furthermore, the "vi" command editing keys are not implemented.
1221 * 1226 *
1222 */ 1227 */
1223 1228
1224 1229
1225int cmdedit_read_input(char *prompt, char command[BUFSIZ]) 1230int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1226{ 1231{
@@ -1230,7 +1235,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1230 unsigned char c = 0; 1235 unsigned char c = 0;
1231 1236
1232 /* prepare before init handlers */ 1237 /* prepare before init handlers */
1233 cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ 1238 cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */
1234 len = 0; 1239 len = 0;
1235 command_ps = command; 1240 command_ps = command;
1236 1241
@@ -1247,7 +1252,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1247# ifndef _POSIX_VDISABLE 1252# ifndef _POSIX_VDISABLE
1248# define _POSIX_VDISABLE '\0' 1253# define _POSIX_VDISABLE '\0'
1249# endif 1254# endif
1250 new_settings.c_cc[VINTR] = _POSIX_VDISABLE; 1255 new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
1251#endif 1256#endif
1252 command[0] = 0; 1257 command[0] = 0;
1253 1258
@@ -1261,7 +1266,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1261 1266
1262 while (1) { 1267 while (1) {
1263 1268
1264 fflush(stdout); /* buffered out to fast */ 1269 fflush(stdout); /* buffered out to fast */
1265 1270
1266 if (safe_read(0, &c, 1) < 1) 1271 if (safe_read(0, &c, 1) < 1)
1267 /* if we can't read input then exit */ 1272 /* if we can't read input then exit */
@@ -1287,8 +1292,12 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1287 goto_new_line(); 1292 goto_new_line();
1288 command[0] = 0; 1293 command[0] = 0;
1289 len = 0; 1294 len = 0;
1295#if !defined(CONFIG_ASH)
1290 lastWasTab = FALSE; 1296 lastWasTab = FALSE;
1291 put_prompt(); 1297 put_prompt();
1298#else
1299 break_out = 2;
1300#endif
1292 break; 1301 break;
1293 case 4: 1302 case 4:
1294 /* Control-d -- Delete one character, or exit 1303 /* Control-d -- Delete one character, or exit
@@ -1327,14 +1336,14 @@ prepare_to_die:
1327#endif 1336#endif
1328 break; 1337 break;
1329 case 11: 1338 case 11:
1330 /* Control-k -- clear to end of line */ 1339 /* Control-k -- clear to end of line */
1331 *(command + cursor) = 0; 1340 *(command + cursor) = 0;
1332 len = cursor; 1341 len = cursor;
1333 printf("\033[J"); 1342 printf("\033[J");
1334 break; 1343 break;
1335 case 12: 1344 case 12:
1336 /* Control-l -- clear screen */ 1345 /* Control-l -- clear screen */
1337 printf("\033[H"); 1346 printf("\033[H");
1338 redraw(0, len-cursor); 1347 redraw(0, len-cursor);
1339 break; 1348 break;
1340#if MAX_HISTORY >= 1 1349#if MAX_HISTORY >= 1
@@ -1371,7 +1380,7 @@ prepare_to_die:
1371 } 1380 }
1372 switch (c) { 1381 switch (c) {
1373#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION 1382#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
1374 case '\t': /* Alt-Tab */ 1383 case '\t': /* Alt-Tab */
1375 1384
1376 input_tab(&lastWasTab); 1385 input_tab(&lastWasTab);
1377 break; 1386 break;
@@ -1433,7 +1442,7 @@ rewrite_line:
1433 break; 1442 break;
1434 } 1443 }
1435 1444
1436 default: /* If it's regular input, do the normal thing */ 1445 default: /* If it's regular input, do the normal thing */
1437#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT 1446#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
1438 /* Control-V -- Add non-printable symbol */ 1447 /* Control-V -- Add non-printable symbol */
1439 if (c == 22) { 1448 if (c == 22) {
@@ -1445,19 +1454,19 @@ rewrite_line:
1445 } 1454 }
1446 } else 1455 } else
1447#endif 1456#endif
1448 if (!Isprint(c)) /* Skip non-printable characters */ 1457 if (!Isprint(c)) /* Skip non-printable characters */
1449 break; 1458 break;
1450 1459
1451 if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ 1460 if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */
1452 break; 1461 break;
1453 1462
1454 len++; 1463 len++;
1455 1464
1456 if (cursor == (len - 1)) { /* Append if at the end of the line */ 1465 if (cursor == (len - 1)) { /* Append if at the end of the line */
1457 *(command + cursor) = c; 1466 *(command + cursor) = c;
1458 *(command + cursor + 1) = 0; 1467 *(command + cursor + 1) = 0;
1459 cmdedit_set_out_char(0); 1468 cmdedit_set_out_char(0);
1460 } else { /* Insert otherwise */ 1469 } else { /* Insert otherwise */
1461 int sc = cursor; 1470 int sc = cursor;
1462 1471
1463 memmove(command + sc + 1, command + sc, len - sc); 1472 memmove(command + sc + 1, command + sc, len - sc);
@@ -1471,7 +1480,7 @@ rewrite_line:
1471 1480
1472 break; 1481 break;
1473 } 1482 }
1474 if (break_out) /* Enter is the command terminator, no more input. */ 1483 if (break_out) /* Enter is the command terminator, no more input. */
1475 break; 1484 break;
1476 1485
1477 if (c != '\t') 1486 if (c != '\t')
@@ -1486,7 +1495,7 @@ rewrite_line:
1486 /* cleanup may be saved current command line */ 1495 /* cleanup may be saved current command line */
1487 free(history[MAX_HISTORY]); 1496 free(history[MAX_HISTORY]);
1488 history[MAX_HISTORY] = 0; 1497 history[MAX_HISTORY] = 0;
1489 if (len) { /* no put empty line */ 1498 if (len) { /* no put empty line */
1490 int i = n_history; 1499 int i = n_history;
1491 /* After max history, remove the oldest command */ 1500 /* After max history, remove the oldest command */
1492 if (i >= MAX_HISTORY) { 1501 if (i >= MAX_HISTORY) {
@@ -1508,23 +1517,27 @@ rewrite_line:
1508 } 1517 }
1509#endif 1518#endif
1510#endif /* MAX_HISTORY >= 1 */ 1519#endif /* MAX_HISTORY >= 1 */
1511 if(break_out>0) { 1520 if(break_out == 1) {
1512 command[len++] = '\n'; /* set '\n' */ 1521 command[len++] = '\n'; /* set '\n' */
1513 command[len] = 0; 1522 command[len] = 0;
1514 } 1523 }
1515#if defined(CONFIG_FEATURE_CLEAN_UP) && defined(CONFIG_FEATURE_COMMAND_TAB_COMPLETION) 1524#if defined(CONFIG_FEATURE_CLEAN_UP) && defined(CONFIG_FEATURE_COMMAND_TAB_COMPLETION)
1516 input_tab(0); /* strong free */ 1525 input_tab(0); /* strong free */
1517#endif 1526#endif
1518#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) 1527#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1519 free(cmdedit_prompt); 1528 free(cmdedit_prompt);
1520#endif 1529#endif
1521 cmdedit_reset_term(); 1530 cmdedit_reset_term();
1531#if !defined(CONFIG_ASH)
1522 return len; 1532 return len;
1533#else
1534 return break_out < 0 ? break_out : len;
1535#endif
1523} 1536}
1524 1537
1525 1538
1526 1539
1527#endif /* CONFIG_FEATURE_COMMAND_EDITING */ 1540#endif /* CONFIG_FEATURE_COMMAND_EDITING */
1528 1541
1529 1542
1530#ifdef TEST 1543#ifdef TEST
@@ -1565,4 +1578,4 @@ int main(int argc, char **argv)
1565 return 0; 1578 return 0;
1566} 1579}
1567 1580
1568#endif /* TEST */ 1581#endif /* TEST */