X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=shell%2Fcmdedit.c;h=4f124d6475989e4e0bc804e35c8669000455ae6f;hb=ab6526c8b3d0d38bec62b181276380c0533a151d;hp=09791892583a01e862e081e73fd9fcef5db0437b;hpb=28a78ab62c011820d91ab9edc5ae45196d813a13;p=oweals%2Fbusybox.git diff --git a/shell/cmdedit.c b/shell/cmdedit.c index 097918925..4f124d647 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c @@ -27,86 +27,68 @@ Small bugs (simple effect): - not true viewing if terminal size (x*y symbols) less size (prompt + editor`s line + 2 symbols) + - not true viewing if length prompt less terminal width */ -//#define TEST +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "busybox.h" -#ifndef TEST +#ifdef BB_LOCALE_SUPPORT +#define Isprint(c) isprint((c)) +#else +#define Isprint(c) ( (c) >= ' ' && (c) != ((unsigned char)'\233') ) +#endif -#include "busybox.h" +#ifndef TEST #define D(x) #else -//#define BB_FEATURE_NONPRINTABLE_INVERSE_PUT -//#define BB_FEATURE_BASH_STYLE_PROMT +#define BB_FEATURE_COMMAND_EDITING +#define BB_FEATURE_COMMAND_TAB_COMPLETION +#define BB_FEATURE_COMMAND_USERNAME_COMPLETION +#define BB_FEATURE_NONPRINTABLE_INVERSE_PUT +#define BB_FEATURE_CLEAN_UP -#define TRUE 1 -#define FALSE 0 #define D(x) x #endif /* TEST */ -#ifdef BB_FEATURE_SH_COMMAND_EDITING - -#ifndef BB_FEATURE_SH_TAB_COMPLETION -#undef BB_FEATURE_SH_USERNAME_COMPLETION +#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION +#include +#include #endif -#if defined(BB_FEATURE_SH_USERNAME_COMPLETION) || defined(BB_FEATURE_BASH_STYLE_PROMT) -#define BB_FEATURE_GETUSERNAME_AND_HOMEDIR -#endif +#ifdef BB_FEATURE_COMMAND_EDITING -#include -#include -#include -#include -#include -#include -#include -#include -#include +#ifndef BB_FEATURE_COMMAND_TAB_COMPLETION +#undef BB_FEATURE_COMMAND_USERNAME_COMPLETION +#endif -#ifdef BB_FEATURE_SH_TAB_COMPLETION -#include -#include +#if defined(BB_FEATURE_COMMAND_USERNAME_COMPLETION) || defined(BB_FEATURE_SH_FANCY_PROMPT) +#define BB_FEATURE_GETUSERNAME_AND_HOMEDIR #endif #ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR -#ifndef TEST -#include "pwd_grp/pwd.h" -#else -#include -#endif /* TEST */ +# ifndef TEST +# include "pwd_grp/pwd.h" +# else +# include +# endif /* TEST */ #endif /* advanced FEATURES */ -#ifdef TEST -void *xrealloc(void *old, size_t size) -{ - return realloc(old, size); -} - -void *xmalloc(size_t size) -{ - return malloc(size); -} -char *xstrdup(const char *s) -{ - return strdup(s); -} - -void *xcalloc(size_t size, size_t se) -{ - return calloc(size, se); -} - -#define error_msg(s, d) fprintf(stderr, s, d) -#endif - struct history { char *s; @@ -124,28 +106,14 @@ static struct history *his_front = NULL; static struct history *his_end = NULL; -/* ED: sparc termios is broken: revert back to old termio handling. */ - -#if #cpu(sparc) -# include -# define termios termio -# define setTermSettings(fd,argp) ioctl(fd,TCSETAF,argp) -# define getTermSettings(fd,argp) ioctl(fd,TCGETA,argp) -#else -# include -# define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp) -# define getTermSettings(fd,argp) tcgetattr(fd, argp); -#endif +#include +#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp) +#define getTermSettings(fd,argp) tcgetattr(fd, argp); /* Current termio and the previous termio before starting sh */ static struct termios initial_settings, new_settings; -#ifndef _POSIX_VDISABLE -#define _POSIX_VDISABLE '\0' -#endif - - static volatile int cmdedit_termw = 80; /* actual terminal width */ static int history_counter = 0; /* Number of commands in history list */ @@ -153,26 +121,26 @@ static volatile int handlers_sets = 0; /* Set next bites: */ enum { - SET_ATEXIT = 1, /* when atexit() has been called and - get euid,uid,gid to fast compare */ - SET_TERM_HANDLERS = 2, /* set many terminates signal handlers */ - SET_WCHG_HANDLERS = 4, /* winchg signal handler */ - SET_RESET_TERM = 8, /* if the terminal needs to be reset upon exit */ + SET_ATEXIT = 1, /* when atexit() has been called + and get euid,uid,gid to fast compare */ + SET_TERM_HANDLERS = 2, /* set many terminates signal handlers */ + SET_WCHG_HANDLERS = 4, /* winchg signal handler */ + SET_RESET_TERM = 8, /* if the terminal needs to be reset upon exit */ }; -static int cmdedit_x; /* real x terminal position */ -static int cmdedit_y; /* pseudoreal y terminal position */ +static int cmdedit_x; /* real x terminal position */ +static int cmdedit_y; /* pseudoreal y terminal position */ static int cmdedit_prmt_len; /* lenght prompt without colores string */ -static int cursor; /* required global for signal handler */ -static int len; /* --- "" - - "" - -"- --""-- --""--- */ -static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */ +static int cursor; /* required global for signal handler */ +static int len; /* --- "" - - "" - -"- --""-- --""--- */ +static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */ static -#ifndef BB_FEATURE_BASH_STYLE_PROMT +#ifndef BB_FEATURE_SH_FANCY_PROMPT const #endif -char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ +char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ /* Link into lash to reset context to 0 on ^C and such */ extern unsigned int shell_context; @@ -184,13 +152,13 @@ static char *home_pwd_buf = ""; static int my_euid; #endif -#ifdef BB_FEATURE_BASH_STYLE_PROMT +#ifdef BB_FEATURE_SH_FANCY_PROMPT static char *hostname_buf = ""; static int num_ok_lines = 1; #endif -#ifdef BB_FEATURE_SH_TAB_COMPLETION +#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION #ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR static int my_euid; @@ -199,7 +167,7 @@ static int my_euid; static int my_uid; static int my_gid; -#endif /* BB_FEATURE_SH_TAB_COMPLETION */ +#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ static void cmdedit_setwidth(int w, int redraw_flg); @@ -230,7 +198,7 @@ static void win_changed(int nsig) static void cmdedit_reset_term(void) { if ((handlers_sets & SET_RESET_TERM) != 0) { - /* sparc and other have broken termios support: use old termio handling. */ +/* sparc and other have broken termios support: use old termio handling. */ setTermSettings(fileno(stdin), (void *) &initial_settings); handlers_sets &= ~SET_RESET_TERM; } @@ -244,7 +212,6 @@ static void cmdedit_reset_term(void) if (his_front) { struct history *n; - //while(his_front!=his_end) { while (his_front != his_end) { n = his_front->n; free(his_front->s); @@ -260,15 +227,15 @@ static void cmdedit_reset_term(void) static void cmdedit_set_out_char(int next_char) { - int c = command_ps[cursor]; + int c = (int)((unsigned char) command_ps[cursor]); if (c == 0) - c = ' '; /* destroy end char? */ + c = ' '; /* destroy end char? */ #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT - if (!isprint(c)) { /* Inverse put non-printable characters */ - if (((unsigned char) c) >= 128) + if (!Isprint(c)) { /* Inverse put non-printable characters */ + if (c >= 128) c -= 128; - if (((unsigned char) c) < ' ') + if (c < ' ') c += '@'; if (c == 127) c = '?'; @@ -321,7 +288,7 @@ static void input_backward(int num) { if (num > cursor) num = cursor; - cursor -= num; /* new cursor (in command, not terminal) */ + cursor -= num; /* new cursor (in command, not terminal) */ if (cmdedit_x >= num) { /* no to up line */ cmdedit_x -= num; @@ -354,150 +321,140 @@ static void put_prompt(void) cursor = 0; } -#ifdef BB_FEATURE_BASH_STYLE_PROMT -static void -add_to_prompt(char **prmt_mem_ptr, int *alm, int *prmt_len, - const char *addb) +#ifndef BB_FEATURE_SH_FANCY_PROMPT +static void parse_prompt(const char *prmt_ptr) { - int l = strlen(addb); - - *prmt_len += l; - if (*alm < (*prmt_len) + 1) { - *alm = (*prmt_len) + 1; - *prmt_mem_ptr = xrealloc(*prmt_mem_ptr, *alm); - } - strcat(*prmt_mem_ptr, addb); + cmdedit_prompt = prmt_ptr; + cmdedit_prmt_len = strlen(prmt_ptr); + put_prompt(); } -#endif - +#else static void parse_prompt(const char *prmt_ptr) { -#ifdef BB_FEATURE_BASH_STYLE_PROMT - int alm = strlen(prmt_ptr) + 1; /* supposedly require memory */ int prmt_len = 0; int sub_len = 0; - int flg_not_length = '['; - char *prmt_mem_ptr = xstrdup(prmt_ptr); - char pwd_buf[PATH_MAX + 1]; - char buf[16]; - int c; - - pwd_buf[0] = 0; - *prmt_mem_ptr = 0; + char flg_not_length = '['; + char *prmt_mem_ptr = xcalloc(1, 1); + char *pwd_buf = xgetcwd(0); + char buf2[PATH_MAX + 1]; + char buf[2]; + char c; + char *pbuf; + + if (!pwd_buf) { + pwd_buf=(char *)unknown; + } while (*prmt_ptr) { + pbuf = buf; + pbuf[1] = 0; c = *prmt_ptr++; if (c == '\\') { - c = *prmt_ptr; - if (c == 0) + const char *cp = prmt_ptr; + int l; + + c = process_escape_sequence(&prmt_ptr); + if(prmt_ptr==cp) { + if (*cp == 0) break; - prmt_ptr++; - switch (c) { - case 'u': - add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, user_buf); - continue; - case 'h': - if (hostname_buf[0] == 0) { - hostname_buf = xcalloc(256, 1); - if (gethostname(hostname_buf, 255) < 0) { - strcpy(hostname_buf, "?"); + c = *prmt_ptr++; + switch (c) { +#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR + case 'u': + pbuf = user_buf; + break; +#endif + case 'h': + pbuf = hostname_buf; + if (*pbuf == 0) { + pbuf = xcalloc(256, 1); + if (gethostname(pbuf, 255) < 0) { + strcpy(pbuf, "?"); } else { - char *s = strchr(hostname_buf, '.'); + char *s = strchr(pbuf, '.'); if (s) *s = 0; } + hostname_buf = pbuf; } - add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, - hostname_buf); - continue; - case '$': + break; + case '$': c = my_euid == 0 ? '#' : '$'; break; - case 'w': - if (pwd_buf[0] == 0) { - int l; - - getcwd(pwd_buf, PATH_MAX); - l = strlen(home_pwd_buf); - if (home_pwd_buf[0] != 0 && - strncmp(home_pwd_buf, pwd_buf, l) == 0) { - strcpy(pwd_buf + 1, pwd_buf + l); - pwd_buf[0] = '~'; +#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR + case 'w': + pbuf = pwd_buf; + l = strlen(home_pwd_buf); + if (home_pwd_buf[0] != 0 && + strncmp(home_pwd_buf, pbuf, l) == 0 && + (pbuf[l]=='/' || pbuf[l]=='\0') && + strlen(pwd_buf+l) UCHAR_MAX || (eho - buf) < l) { + int h; + buf2[l++] = *prmt_ptr; + buf2[l] = 0; + h = strtol(buf2, &pbuf, 16); + if (h > UCHAR_MAX || (pbuf - buf2) < l) { l--; break; } prmt_ptr++; } - buf[l] = 0; - ho = strtol(buf, 0, c == 'x' ? 16 : 8); - c = ho == 0 ? '?' : (char) ho; + buf2[l] = 0; + c = (char)strtol(buf2, 0, 16); + if(c==0) + c = '?'; + pbuf = buf; break; - } - case '[': - case ']': + case '[': case ']': if (c == flg_not_length) { flg_not_length = flg_not_length == '[' ? ']' : '['; continue; } break; - } + } + } } - buf[0] = c; - buf[1] = 0; - add_to_prompt(&prmt_mem_ptr, &alm, &prmt_len, buf); + if(pbuf == buf) + *pbuf = c; + prmt_len += strlen(pbuf); + prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); if (flg_not_length == ']') sub_len++; } - cmdedit_prmt_len = prmt_len - sub_len; + if(pwd_buf!=(char *)unknown) + free(pwd_buf); cmdedit_prompt = prmt_mem_ptr; -#else - cmdedit_prompt = prmt_ptr; - cmdedit_prmt_len = strlen(prmt_ptr); -#endif + cmdedit_prmt_len = prmt_len - sub_len; put_prompt(); } +#endif /* draw promt, editor line, and clear tail */ static void redraw(int y, int back_cursor) { - if (y > 0) /* up to start y */ + if (y > 0) /* up to start y */ printf("\033[%dA", y); cmdedit_y = 0; /* new quasireal y */ putchar('\r'); @@ -517,7 +474,7 @@ static void input_delete(void) strcpy(command_ps + j, command_ps + j + 1); len--; - input_end(); /* rewtite new line */ + input_end(); /* rewtite new line */ cmdedit_set_out_char(0); /* destroy end char */ input_backward(cursor - j); /* back to old pos cursor */ } @@ -544,7 +501,7 @@ static void clean_up_and_die(int sig) { goto_new_line(); if (sig != SIGINT) - exit(EXIT_SUCCESS); /* cmdedit_reset_term() called in atexit */ + exit(EXIT_SUCCESS); /* cmdedit_reset_term() called in atexit */ cmdedit_reset_term(); } @@ -555,7 +512,6 @@ static void cmdedit_setwidth(int w, int redraw_flg) cmdedit_termw = cmdedit_termw % w; } if (w > cmdedit_termw) { - cmdedit_termw = w; if (redraw_flg) { @@ -571,6 +527,7 @@ static void cmdedit_setwidth(int w, int redraw_flg) extern void cmdedit_init(void) { + cmdedit_prmt_len = 0; if ((handlers_sets & SET_WCHG_HANDLERS) == 0) { /* emulate usage handler to set handler and call yours work */ win_changed(-SIGWINCH); @@ -589,14 +546,14 @@ extern void cmdedit_init(void) } #endif -#ifdef BB_FEATURE_SH_TAB_COMPLETION +#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION #ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR my_euid = geteuid(); #endif my_uid = getuid(); my_gid = getgid(); -#endif /* BB_FEATURE_SH_TAB_COMPLETION */ +#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ handlers_sets |= SET_ATEXIT; atexit(cmdedit_reset_term); /* be sure to do this only once */ } @@ -608,10 +565,9 @@ extern void cmdedit_init(void) signal(SIGTERM, clean_up_and_die); handlers_sets |= SET_TERM_HANDLERS; } - } -#ifdef BB_FEATURE_SH_TAB_COMPLETION +#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION static int is_execute(const struct stat *st) { @@ -622,7 +578,7 @@ static int is_execute(const struct stat *st) return FALSE; } -#ifdef BB_FEATURE_SH_USERNAME_COMPLETION +#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION static char **username_tab_completion(char *ud, int *num_matches) { @@ -631,19 +587,19 @@ static char **username_tab_completion(char *ud, int *num_matches) char *temp; - ud++; /* ~user/... to user/... */ + ud++; /* ~user/... to user/... */ userlen = strlen(ud); if (num_matches == 0) { /* "~/..." or "~user/..." */ char *sav_ud = ud - 1; char *home = 0; - if (*ud == '/') { /* "~/..." */ + if (*ud == '/') { /* "~/..." */ home = home_pwd_buf; } else { /* "~user/..." */ temp = strchr(ud, '/'); - *temp = 0; /* ~user\0 */ + *temp = 0; /* ~user\0 */ entry = getpwnam(ud); *temp = '/'; /* restore ~user/... */ ud = temp; @@ -659,7 +615,7 @@ static char **username_tab_completion(char *ud, int *num_matches) strcpy(sav_ud, temp2); } } - return 0; /* void, result save to argument :-) */ + return 0; /* void, result save to argument :-) */ } else { /* "~[^/]*" */ char **matches = (char **) NULL; @@ -684,7 +640,7 @@ static char **username_tab_completion(char *ud, int *num_matches) return (matches); } } -#endif /* BB_FEATURE_SH_USERNAME_COMPLETION */ +#endif /* BB_FEATURE_COMMAND_USERNAME_COMPLETION */ enum { FIND_EXE_ONLY = 0, @@ -709,11 +665,11 @@ static int path_parse(char ***p, int flags) npth = 0; for (;;) { - npth++; /* count words is + 1 count ':' */ + npth++; /* count words is + 1 count ':' */ tmp = strchr(tmp, ':'); if (tmp) { if (*++tmp == 0) - break; /* : */ + break; /* : */ } else break; } @@ -722,7 +678,7 @@ static int path_parse(char ***p, int flags) tmp = pth; (*p)[0] = xstrdup(tmp); - npth = 1; /* count words is + 1 count ':' */ + npth = 1; /* count words is + 1 count ':' */ for (;;) { tmp = strchr(tmp, ':'); @@ -753,7 +709,7 @@ static char *add_quote_for_spec_chars(char *found) } static char **exe_n_cwd_tab_completion(char *command, int *num_matches, - int type) + int type) { char **matches = 0; @@ -766,7 +722,7 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, char **paths = path1; int npaths; int i; - char found[BUFSIZ + 4 + PATH_MAX]; + char *found; char *pfind = strrchr(command, '/'); path1[0] = "."; @@ -781,7 +737,7 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, strcpy(dirbuf, command); /* set dir only */ dirbuf[(pfind - command) + 1] = 0; -#ifdef BB_FEATURE_SH_USERNAME_COMPLETION +#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION if (dirbuf[0] == '~') /* ~/... or ~user/... */ username_tab_completion(dirbuf, 0); #endif @@ -795,11 +751,10 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, for (i = 0; i < npaths; i++) { dir = opendir(paths[i]); - if (!dir) /* Don't print an error */ + if (!dir) /* Don't print an error */ continue; while ((next = readdir(dir)) != NULL) { - const char *str_merge = "%s/%s"; char *str_found = next->d_name; /* matched ? */ @@ -812,25 +767,23 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, else continue; } - if (paths[i][strlen(paths[i]) - 1] == '/') - str_merge = "%s%s"; - sprintf(found, str_merge, paths[i], str_found); + found = concat_path_file(paths[i], str_found); /* hmm, remover in progress? */ - if (stat(found, &st) < 0) - continue; + if (stat(found, &st) < 0) + goto cont; /* find with dirs ? */ if (paths[i] != dirbuf) strcpy(found, next->d_name); /* only name */ if (S_ISDIR(st.st_mode)) { /* name is directory */ - /* algorithmic only "/" ? */ - if (*str_found) - strcat(found, "/"); + str_found = found; + found = concat_path_file(found, ""); + free(str_found); str_found = add_quote_for_spec_chars(found); } else { /* not put found file if search only dirs for cd */ - if (type == FIND_DIR_ONLY) - continue; + if (type == FIND_DIR_ONLY) + goto cont; str_found = add_quote_for_spec_chars(found); if (type == FIND_FILE_ONLY || (type == FIND_EXE_ONLY && is_execute(&st) == TRUE)) @@ -840,6 +793,8 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, matches = xrealloc(matches, (nm + 1) * sizeof(char *)); matches[nm++] = str_found; +cont: + free(found); } closedir(dir); } @@ -986,7 +941,8 @@ static int find_match(char *matchBuf, int *len_with_quotes) for (i = 0; int_buf[i]; i++) if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') { if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY - && strncmp(&matchBuf[pos_buf[0]], "cd", 2) == 0) + && matchBuf[pos_buf[0]]=='c' + && matchBuf[pos_buf[1]]=='d' ) command_mode = FIND_DIR_ONLY; else { command_mode = FIND_FILE_ONLY; @@ -1006,20 +962,19 @@ static int find_match(char *matchBuf, int *len_with_quotes) /* skip first not quoted '\'' or '"' */ for (i = 0; int_buf[i] == '\'' || int_buf[i] == '"'; i++); /* collapse quote or unquote // or /~ */ - while ((int_buf[i] & ~QUOT) == '/' && ( - (int_buf[i + 1] & ~QUOT) == '/' - || (int_buf[i + 1] & ~QUOT) == - '~')) i++; - if (i) - collapse_pos(0, i); + while ((int_buf[i] & ~QUOT) == '/' && + ((int_buf[i + 1] & ~QUOT) == '/' + || (int_buf[i + 1] & ~QUOT) == '~')) { + i++; + } /* set only match and destroy quotes */ j = 0; - for (i = 0; pos_buf[i] >= 0; i++) { - matchBuf[i] = matchBuf[pos_buf[i]]; + for (c = 0; pos_buf[i] >= 0; i++) { + matchBuf[c++] = matchBuf[pos_buf[i]]; j = pos_buf[i] + 1; } - matchBuf[i] = 0; + matchBuf[c] = 0; /* old lenght matchBuf with quotes symbols */ *len_with_quotes = j ? j - pos_buf[0] : 0; @@ -1062,7 +1017,7 @@ static void input_tab(int *lastWasTab) /* Free up any memory already allocated */ input_tab(0); -#ifdef BB_FEATURE_SH_USERNAME_COMPLETION +#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION /* If the word starts with `~' and there is no slash in the word, * then try completing this word as a username. */ @@ -1073,16 +1028,37 @@ static void input_tab(int *lastWasTab) * in the current working directory that matches. */ if (!matches) matches = - exe_n_cwd_tab_completion(matchBuf, &num_matches, - find_type); - + exe_n_cwd_tab_completion(matchBuf, + &num_matches, find_type); + /* Remove duplicate found */ + if(matches) { + int i, j; + /* bubble */ + for(i=0; i<(num_matches-1); i++) + for(j=i+1; j 1) { char *tmp1; beep(); if (!matches) - return; /* not found */ + return; /* not found */ /* sort */ qsort(matches, num_matches, sizeof(char *), match_compare); @@ -1098,7 +1074,7 @@ static void input_tab(int *lastWasTab) free(tmp); return; } - } else { /* one match */ + } else { /* one match */ tmp = matches[0]; /* for next completion current found */ *lastWasTab = FALSE; @@ -1123,8 +1099,7 @@ static void input_tab(int *lastWasTab) /* new len */ len = strlen(command_ps); /* write out the matched command */ - input_end(); - input_backward(cursor - recalc_pos); + redraw(cmdedit_y, len - recalc_pos); } if (tmp != matches[0]) free(tmp); @@ -1161,7 +1136,7 @@ static void input_tab(int *lastWasTab) } } } -#endif /* BB_FEATURE_SH_TAB_COMPLETION */ +#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ static void get_previous_history(struct history **hp, struct history *p) { @@ -1198,49 +1173,56 @@ enum { * Furthermore, the "vi" command editing keys are not implemented. * */ + extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) { - int inputFd = fileno(stdin); - int break_out = 0; int lastWasTab = FALSE; - char c = 0; + 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 */ + cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ len = 0; command_ps = command; - if (new_settings.c_cc[VMIN] == 0) { /* first call */ + if (new_settings.c_cc[VERASE] == 0) { /* first call */ - getTermSettings(inputFd, (void *) &initial_settings); + getTermSettings(0, (void *) &initial_settings); memcpy(&new_settings, &initial_settings, sizeof(struct termios)); - + new_settings.c_lflag &= ~ICANON; /* unbuffered input */ + /* Turn off echoing and CTRL-C, so we can trap it */ + new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG); +#ifndef linux + /* Hmm, in linux c_cc[] not parsed if set ~ICANON */ new_settings.c_cc[VMIN] = 1; new_settings.c_cc[VTIME] = 0; - new_settings.c_cc[VINTR] = _POSIX_VDISABLE; /* Turn off CTRL-C, so we can trap it */ - new_settings.c_lflag &= ~ICANON; /* unbuffered input */ - new_settings.c_lflag &= ~(ECHO | ECHOCTL | ECHONL); /* Turn off echoing */ + /* Turn off CTRL-C, so we can trap it */ +# ifndef _POSIX_VDISABLE +# define _POSIX_VDISABLE '\0' +# endif + new_settings.c_cc[VINTR] = _POSIX_VDISABLE; +#endif } command[0] = 0; - setTermSettings(inputFd, (void *) &new_settings); + setTermSettings(0, (void *) &new_settings); handlers_sets |= SET_RESET_TERM; - /* Print out the command prompt */ - parse_prompt(prompt); /* Now initialize things */ cmdedit_init(); + /* Print out the command prompt */ + parse_prompt(prompt); while (1) { fflush(stdout); /* buffered out to fast */ - if (read(inputFd, &c, 1) < 1) - return; + if (read(0, &c, 1) < 1) + /* if we can't read input then exit */ + goto prepare_to_die; switch (c) { case '\n': @@ -1272,6 +1254,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) /* Control-d -- Delete one character, or exit * if the len=0 and no chars to delete */ if (len == 0) { +prepare_to_die: printf("exit"); clean_up_and_die(0); } else { @@ -1292,7 +1275,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) input_backspace(); break; case '\t': -#ifdef BB_FEATURE_SH_TAB_COMPLETION +#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION input_tab(&lastWasTab); #endif break; @@ -1324,15 +1307,15 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) case ESC:{ /* escape sequence follows */ - if (read(inputFd, &c, 1) < 1) + if (read(0, &c, 1) < 1) return; /* different vt100 emulations */ if (c == '[' || c == 'O') { - if (read(inputFd, &c, 1) < 1) + if (read(0, &c, 1) < 1) return; } switch (c) { -#ifdef BB_FEATURE_SH_TAB_COMPLETION +#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION case '\t': /* Alt-Tab */ input_tab(&lastWasTab); @@ -1393,17 +1376,17 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) } if (c >= '1' && c <= '9') do - if (read(inputFd, &c, 1) < 1) + if (read(0, &c, 1) < 1) return; while (c != '~'); break; } - default: /* If it's regular input, do the normal thing */ + default: /* If it's regular input, do the normal thing */ #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT /* Control-V -- Add non-printable symbol */ if (c == 22) { - if (read(inputFd, &c, 1) < 1) + if (read(0, &c, 1) < 1) return; if (c == 0) { beep(); @@ -1411,7 +1394,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) } } else #endif - if (!isprint(c)) /* Skip non-printable characters */ + if (!Isprint(c)) /* Skip non-printable characters */ break; if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ @@ -1444,7 +1427,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) lastWasTab = FALSE; } - setTermSettings(inputFd, (void *) &initial_settings); + setTermSettings(0, (void *) &initial_settings); handlers_sets &= ~SET_RESET_TERM; /* Handle command history log */ @@ -1490,16 +1473,16 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) history_counter++; } } -#if defined(BB_FEATURE_BASH_STYLE_PROMT) +#if defined(BB_FEATURE_SH_FANCY_PROMPT) num_ok_lines++; #endif } command[len++] = '\n'; /* set '\n' */ command[len] = 0; -#if defined(BB_FEATURE_CLEAN_UP) && defined(BB_FEATURE_SH_TAB_COMPLETION) +#if defined(BB_FEATURE_CLEAN_UP) && defined(BB_FEATURE_COMMAND_TAB_COMPLETION) input_tab(0); /* strong free */ #endif -#if defined(BB_FEATURE_BASH_STYLE_PROMT) +#if defined(BB_FEATURE_SH_FANCY_PROMPT) free(cmdedit_prompt); #endif return; @@ -1520,32 +1503,46 @@ extern void cmdedit_terminate(void) } } -#endif /* BB_FEATURE_SH_COMMAND_EDITING */ +#endif /* BB_FEATURE_COMMAND_EDITING */ #ifdef TEST +const char *applet_name = "debug stuff usage"; +const char *memory_exhausted = "Memory exhausted"; + +#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT +#include +#endif + unsigned int shell_context; int main(int argc, char **argv) { char buff[BUFSIZ]; char *prompt = -#if defined(BB_FEATURE_BASH_STYLE_PROMT) - "\\[\\033[32;1m\\]\\u@\\[\\033[33;1m\\]\\h:\ +#if defined(BB_FEATURE_SH_FANCY_PROMPT) + "\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:\ \\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] \ -\\!\\[\\033[36;1m\\]\\$ \\[\\033[0m\\]"; +\\!\\[\\e[36;1m\\]\\$ \\[\\E[0m\\]"; #else "% "; #endif +#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT + setlocale(LC_ALL, ""); +#endif shell_context = 1; do { + int l; cmdedit_read_input(prompt, buff); + l = strlen(buff); + if(l > 0 && buff[l-1] == '\n') + buff[l-1] = 0; printf("*** cmdedit_read_input() returned line =%s=\n", buff); } while (shell_context); printf("*** cmdedit_read_input() detect ^C\n"); return 0; } -#endif /* TEST */ +#endif /* TEST */