| @@ -89,22 +89,17 @@ |
| #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 <termios.h> |
| #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,19 +201,6 @@ static void cmdedit_reset_term(void) |
| handlers_sets &= ~SET_WCHG_HANDLERS; |
| } |
| fflush(stdout); |
| - | #if 0 |
| - | //#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 |
| } |
| |
| |
| @@ -368,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, "?"); |
| @@ -1122,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, |
| @@ -1165,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 */ |
| @@ -1271,31 +1262,26 @@ prepare_to_die: |
| printf("\033[J"); |
| break; |
| case 12: |
| - | { |
| /* Control-l -- clear screen */ |
| - | int old_cursor = cursor; |
| printf("\033[H"); |
| - | redraw(0, len-old_cursor); |
| - | } |
| + | 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) { |
| @@ -1319,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(); |
| @@ -1330,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(); |
| @@ -1428,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; |