X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=shell%2Fcmdedit.c;h=b6e743eb4118f33532758d84d687043c7c01f2e6;hb=062c74f71035091fcef0b20ff4e8cb77d18124cc;hp=3810c230a5bcf555b8cae2845f696fa9486d0ecd;hpb=889a301a0c992cef843322ba7d2af62fcf44ab2a;p=oweals%2Fbusybox.git diff --git a/shell/cmdedit.c b/shell/cmdedit.c index 3810c230a..b6e743eb4 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c @@ -82,29 +82,24 @@ #ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR # ifndef TEST -# include "pwd.h" +# include "pwd_.h" # else # include # endif /* TEST */ #endif /* advanced FEATURES */ - -struct history { - char *s; - struct history *p; - struct history *n; -}; - /* Maximum length of the linked list for the command line history */ -static const int MAX_HISTORY = 15; - -/* First element in command line list */ -static struct history *his_front = NULL; - -/* Last element in command line list */ -static struct history *his_end = NULL; - +#define MAX_HISTORY 15 +#if MAX_HISTORY < 1 +#warning cmdedit: You set MAX_HISTORY < 1. The history algorithm switched off. +#else +static char *history[MAX_HISTORY+1]; /* history + current */ +/* saved history lines */ +static int n_history; +/* current pointer to history line */ +static int cur_history; +#endif #include #define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp) @@ -116,7 +111,6 @@ static struct termios initial_settings, new_settings; static volatile int cmdedit_termw = 80; /* actual terminal width */ -static int history_counter = 0; /* Number of commands in history list */ static volatile int handlers_sets = 0; /* Set next bites: */ @@ -148,7 +142,7 @@ static int my_euid; #endif #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT -static char *hostname_buf = ""; +static char *hostname_buf; static int num_ok_lines = 1; #endif @@ -207,18 +201,6 @@ static void cmdedit_reset_term(void) handlers_sets &= ~SET_WCHG_HANDLERS; } fflush(stdout); -#ifdef CONFIG_FEATURE_CLEAN_UP - if (his_front) { - struct history *n; - - while (his_front != his_end) { - n = his_front->n; - free(his_front->s); - free(his_front); - his_front = n; - } - } -#endif } @@ -274,7 +256,8 @@ static void goto_new_line(void) static inline void out1str(const char *s) { - fputs(s, stdout); + if ( s ) + fputs(s, stdout); } static inline void beep(void) { @@ -366,7 +349,7 @@ static void parse_prompt(const char *prmt_ptr) #endif case 'h': pbuf = hostname_buf; - if (*pbuf == 0) { + if (pbuf == 0) { pbuf = xcalloc(256, 1); if (gethostname(pbuf, 255) < 0) { strcpy(pbuf, "?"); @@ -610,8 +593,7 @@ static char **username_tab_completion(char *ud, int *num_matches) /* Null usernames should result in all users as possible completions. */ if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) { - temp = xmalloc(3 + strlen(entry->pw_name)); - sprintf(temp, "~%s/", entry->pw_name); + bb_asprintf(&temp, "~%s/", entry->pw_name); matches = xrealloc(matches, (nm + 1) * sizeof(char *)); matches[nm++] = temp; @@ -1121,18 +1103,29 @@ static void input_tab(int *lastWasTab) } #endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */ -static void get_previous_history(struct history **hp, struct history *p) +#if MAX_HISTORY >= 1 +static void get_previous_history(void) { - if ((*hp)->s) - free((*hp)->s); - (*hp)->s = xstrdup(command_ps); - *hp = p; + if(command_ps[0] != 0 || history[cur_history] == 0) { + free(history[cur_history]); + history[cur_history] = xstrdup(command_ps); + } + cur_history--; } -static inline void get_next_history(struct history **hp) +static int get_next_history(void) { - get_previous_history(hp, (*hp)->n); + int ch = cur_history; + + if (ch < n_history) { + get_previous_history(); /* save the current history line */ + return (cur_history = ch+1); + } else { + beep(); + return 0; + } } +#endif enum { ESC = 27, @@ -1164,7 +1157,6 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) int break_out = 0; int lastWasTab = FALSE; unsigned char c = 0; - struct history *hp = his_end; /* prepare before init handlers */ cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ @@ -1263,34 +1255,33 @@ prepare_to_die: input_tab(&lastWasTab); #endif break; - case 12: - /* Control-l -- clear screen - * if the len=0 and no chars in edit line */ - if (len == 0) { - printf("\033[H\033[J"); - put_prompt(); - } else { - beep(); - } + case 11: + /* Control-k -- clear to end of line */ + *(command + cursor) = 0; + len = cursor; + printf("\033[J"); + break; + case 12: + /* Control-l -- clear screen */ + printf("\033[H"); + redraw(0, len-cursor); break; +#if MAX_HISTORY >= 1 case 14: /* Control-n -- Get next command in history */ - if (hp && hp->n && hp->n->s) { - get_next_history(&hp); + if (get_next_history()) goto rewrite_line; - } else { - beep(); - } break; case 16: /* Control-p -- Get previous command from history */ - if (hp && hp->p) { - get_previous_history(&hp, hp->p); + if (cur_history > 0) { + get_previous_history(); goto rewrite_line; } else { beep(); } break; +#endif case 21: /* Control-U -- Clear line before cursor */ if (cursor) { @@ -1314,10 +1305,11 @@ prepare_to_die: input_tab(&lastWasTab); break; #endif +#if MAX_HISTORY >= 1 case 'A': /* Up Arrow -- Get previous command from history */ - if (hp && hp->p) { - get_previous_history(&hp, hp->p); + if (cur_history > 0) { + get_previous_history(); goto rewrite_line; } else { beep(); @@ -1325,21 +1317,16 @@ prepare_to_die: break; case 'B': /* Down Arrow -- Get next command in history */ - if (hp && hp->n && hp->n->s) { - get_next_history(&hp); - goto rewrite_line; - } else { - beep(); - } + if (!get_next_history()) break; - /* Rewrite the line with the selected history item */ - rewrite_line: +rewrite_line: /* change command */ - len = strlen(strcpy(command, hp->s)); + len = strlen(strcpy(command, history[cur_history])); /* redraw and go to end line */ redraw(cmdedit_y, 0); break; +#endif case 'C': /* Right Arrow -- Move forward one character */ input_forward(); @@ -1423,53 +1410,33 @@ prepare_to_die: setTermSettings(0, (void *) &initial_settings); handlers_sets &= ~SET_RESET_TERM; +#if MAX_HISTORY >= 1 /* Handle command history log */ + /* cleanup may be saved current command line */ + free(history[MAX_HISTORY]); + history[MAX_HISTORY] = 0; if (len) { /* no put empty line */ - - struct history *h = his_end; - char *ss; - - ss = xstrdup(command); /* duplicate */ - - if (h == 0) { - /* No previous history -- this memory is never freed */ - h = his_front = xmalloc(sizeof(struct history)); - h->n = xmalloc(sizeof(struct history)); - - h->p = NULL; - h->s = ss; - h->n->p = h; - h->n->n = NULL; - h->n->s = NULL; - his_end = h->n; - history_counter++; - } else { - /* Add a new history command -- this memory is never freed */ - h->n = xmalloc(sizeof(struct history)); - - h->n->p = h; - h->n->n = NULL; - h->n->s = NULL; - h->s = ss; - his_end = h->n; - + int i = n_history; /* After max history, remove the oldest command */ - if (history_counter >= MAX_HISTORY) { - - struct history *p = his_front->n; - - p->p = NULL; - free(his_front->s); - free(his_front); - his_front = p; - } else { - history_counter++; - } + if (i >= MAX_HISTORY) { + free(history[0]); + for(i = 0; i < (MAX_HISTORY-1); i++) + history[i] = history[i+1]; } + history[i++] = xstrdup(command); + cur_history = i; + n_history = i; #if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) num_ok_lines++; #endif } +#else /* MAX_HISTORY < 1 */ +#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) + if (len) { /* no put empty line */ + num_ok_lines++; + } +#endif +#endif /* MAX_HISTORY >= 1 */ if(break_out>0) { command[len++] = '\n'; /* set '\n' */ command[len] = 0;