X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=shell%2Fcmdedit.c;h=16ec2f823323491ff3cdedad97c073bb5f976d51;hb=95b520110dc1ee6ee670817fdd6312a8565cf34c;hp=ce5450032eff30ccdf69d367134d65e013031fb0;hpb=ed424dbf1d3d4f0448b9bfdc6b6128d4c90514ee;p=oweals%2Fbusybox.git diff --git a/shell/cmdedit.c b/shell/cmdedit.c index ce5450032..16ec2f823 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c @@ -3,7 +3,7 @@ * Termios command line History and Editting. * * Copyright (c) 1986-2001 may safely be consumed by a BSD or GPL license. - * Written by: Vladimir Oleynik + * Written by: Vladimir Oleynik * * Used ideas: * Adam Rogoyski @@ -76,16 +76,16 @@ #undef BB_FEATURE_COMMAND_USERNAME_COMPLETION #endif -#if defined(BB_FEATURE_COMMAND_USERNAME_COMPLETION) || !defined(BB_FEATURE_SH_SIMPLE_PROMPT) +#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 */ @@ -106,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 */ @@ -137,9 +123,8 @@ 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_WCHG_HANDLERS = 2, /* winchg signal handler */ + SET_RESET_TERM = 4, /* if the terminal needs to be reset upon exit */ }; @@ -151,22 +136,18 @@ static int cursor; /* required global for signal handler */ static int len; /* --- "" - - "" - -"- --""-- --""--- */ static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */ static -#ifdef BB_FEATURE_SH_SIMPLE_PROMPT +#ifndef BB_FEATURE_SH_FANCY_PROMPT const #endif char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ -/* Link into lash to reset context to 0 on ^C and such */ -extern unsigned int shell_context; - - #ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR static char *user_buf = ""; static char *home_pwd_buf = ""; static int my_euid; #endif -#ifndef BB_FEATURE_SH_SIMPLE_PROMPT +#ifdef BB_FEATURE_SH_FANCY_PROMPT static char *hostname_buf = ""; static int num_ok_lines = 1; #endif @@ -183,13 +164,17 @@ static int my_gid; #endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ +/* It seems that libc5 doesn't know what a sighandler_t is... */ +#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1) +typedef void (*sighandler_t) (int); +#endif static void cmdedit_setwidth(int w, int redraw_flg); static void win_changed(int nsig) { struct winsize win = { 0, 0, 0, 0 }; - static __sighandler_t previous_SIGWINCH_handler; /* for reset */ + static sighandler_t previous_SIGWINCH_handler; /* for reset */ /* emulate || signal call */ if (nsig == -SIGWINCH || nsig == SIGWINCH) { @@ -333,9 +318,10 @@ static void put_prompt(void) out1str(cmdedit_prompt); cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ cursor = 0; + cmdedit_y = 0; /* new quasireal y */ } -#ifdef BB_FEATURE_SH_SIMPLE_PROMPT +#ifndef BB_FEATURE_SH_FANCY_PROMPT static void parse_prompt(const char *prmt_ptr) { cmdedit_prompt = prmt_ptr; @@ -355,6 +341,10 @@ static void parse_prompt(const char *prmt_ptr) char c; char *pbuf; + if (!pwd_buf) { + pwd_buf=(char *)unknown; + } + while (*prmt_ptr) { pbuf = buf; pbuf[1] = 0; @@ -452,7 +442,8 @@ static void parse_prompt(const char *prmt_ptr) if (flg_not_length == ']') sub_len++; } - free(pwd_buf); + if(pwd_buf!=(char *)unknown) + free(pwd_buf); cmdedit_prompt = prmt_mem_ptr; cmdedit_prmt_len = prmt_len - sub_len; put_prompt(); @@ -465,7 +456,6 @@ static void redraw(int y, int back_cursor) { if (y > 0) /* up to start y */ printf("\033[%dA", y); - cmdedit_y = 0; /* new quasireal y */ putchar('\r'); put_prompt(); input_end(); /* rewrite */ @@ -506,14 +496,6 @@ static void input_forward(void) } -static void clean_up_and_die(int sig) -{ - goto_new_line(); - if (sig != SIGINT) - exit(EXIT_SUCCESS); /* cmdedit_reset_term() called in atexit */ - cmdedit_reset_term(); -} - static void cmdedit_setwidth(int w, int redraw_flg) { cmdedit_termw = cmdedit_prmt_len + 2; @@ -534,7 +516,7 @@ static void cmdedit_setwidth(int w, int redraw_flg) } } -extern void cmdedit_init(void) +static void cmdedit_init(void) { cmdedit_prmt_len = 0; if ((handlers_sets & SET_WCHG_HANDLERS) == 0) { @@ -566,15 +548,6 @@ extern void cmdedit_init(void) handlers_sets |= SET_ATEXIT; atexit(cmdedit_reset_term); /* be sure to do this only once */ } - - if ((handlers_sets & SET_TERM_HANDLERS) == 0) { - signal(SIGKILL, clean_up_and_die); - signal(SIGINT, clean_up_and_die); - signal(SIGQUIT, clean_up_and_die); - signal(SIGTERM, clean_up_and_die); - handlers_sets |= SET_TERM_HANDLERS; - } - } #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION @@ -977,17 +950,14 @@ static int find_match(char *matchBuf, int *len_with_quotes) || (int_buf[i + 1] & ~QUOT) == '~')) { i++; } - if (i) { - collapse_pos(0, 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; @@ -1041,9 +1011,30 @@ 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; @@ -1091,8 +1082,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); @@ -1167,10 +1157,9 @@ enum { * */ -extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) -{ - int inputFd = fileno(stdin); +int cmdedit_read_input(char *prompt, char command[BUFSIZ]) +{ int break_out = 0; int lastWasTab = FALSE; @@ -1182,23 +1171,24 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) len = 0; command_ps = command; - if (new_settings.c_cc[VMIN] == 0) { /* first call */ - - getTermSettings(inputFd, (void *) &initial_settings); - memcpy(&new_settings, &initial_settings, sizeof(struct termios)); - - new_settings.c_cc[VMIN] = 1; - new_settings.c_cc[VTIME] = 0; - /* Turn off CTRL-C, so we can trap it */ - new_settings.c_cc[VINTR] = _POSIX_VDISABLE; - new_settings.c_lflag &= ~ICANON; /* unbuffered input */ - /* Turn off echoing */ - new_settings.c_lflag &= ~(ECHO | ECHOCTL | ECHONL); - } - + 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; + /* 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; /* Now initialize things */ @@ -1210,7 +1200,7 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) fflush(stdout); /* buffered out to fast */ - if (read(inputFd, &c, 1) < 1) + if (safe_read(0, &c, 1) < 1) /* if we can't read input then exit */ goto prepare_to_die; @@ -1231,22 +1221,26 @@ extern void cmdedit_read_input(char *prompt, char command[BUFSIZ]) break; case 3: /* Control-c -- stop gathering input */ - - /* Link into lash to reset context to 0 on ^C and such */ - shell_context = 0; - - /* Go to the next line */ goto_new_line(); command[0] = 0; - - return; + len = 0; + lastWasTab = FALSE; + put_prompt(); + break; case 4: /* Control-d -- Delete one character, or exit * if the len=0 and no chars to delete */ if (len == 0) { prepare_to_die: +#if !defined(BB_ASH) printf("exit"); - clean_up_and_die(0); + goto_new_line(); + /* cmdedit_reset_term() called in atexit */ + exit(EXIT_SUCCESS); +#else + break_out = -1; /* for control stoped jobs */ + break; +#endif } else { input_delete(); } @@ -1297,12 +1291,12 @@ prepare_to_die: case ESC:{ /* escape sequence follows */ - if (read(inputFd, &c, 1) < 1) - return; + if (safe_read(0, &c, 1) < 1) + goto prepare_to_die; /* different vt100 emulations */ if (c == '[' || c == 'O') { - if (read(inputFd, &c, 1) < 1) - return; + if (safe_read(0, &c, 1) < 1) + goto prepare_to_die; } switch (c) { #ifdef BB_FEATURE_COMMAND_TAB_COMPLETION @@ -1366,8 +1360,8 @@ prepare_to_die: } if (c >= '1' && c <= '9') do - if (read(inputFd, &c, 1) < 1) - return; + if (safe_read(0, &c, 1) < 1) + goto prepare_to_die; while (c != '~'); break; } @@ -1376,8 +1370,8 @@ prepare_to_die: #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT /* Control-V -- Add non-printable symbol */ if (c == 22) { - if (read(inputFd, &c, 1) < 1) - return; + if (safe_read(0, &c, 1) < 1) + goto prepare_to_die; if (c == 0) { beep(); break; @@ -1417,7 +1411,7 @@ prepare_to_die: lastWasTab = FALSE; } - setTermSettings(inputFd, (void *) &initial_settings); + setTermSettings(0, (void *) &initial_settings); handlers_sets &= ~SET_RESET_TERM; /* Handle command history log */ @@ -1463,35 +1457,25 @@ prepare_to_die: history_counter++; } } -#if !defined(BB_FEATURE_SH_SIMPLE_PROMPT) +#if defined(BB_FEATURE_SH_FANCY_PROMPT) num_ok_lines++; #endif } + if(break_out>0) { command[len++] = '\n'; /* set '\n' */ command[len] = 0; + } #if defined(BB_FEATURE_CLEAN_UP) && defined(BB_FEATURE_COMMAND_TAB_COMPLETION) input_tab(0); /* strong free */ #endif -#if !defined(BB_FEATURE_SH_SIMPLE_PROMPT) +#if defined(BB_FEATURE_SH_FANCY_PROMPT) free(cmdedit_prompt); #endif - return; + cmdedit_reset_term(); + return len; } -/* Undo the effects of cmdedit_init(). */ -extern void cmdedit_terminate(void) -{ - cmdedit_reset_term(); - if ((handlers_sets & SET_TERM_HANDLERS) != 0) { - signal(SIGKILL, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGWINCH, SIG_DFL); - handlers_sets &= ~SET_TERM_HANDLERS; - } -} #endif /* BB_FEATURE_COMMAND_EDITING */ @@ -1505,13 +1489,11 @@ const char *memory_exhausted = "Memory exhausted"; #include #endif -unsigned int shell_context; - int main(int argc, char **argv) { char buff[BUFSIZ]; char *prompt = -#if !defined(BB_FEATURE_SH_SIMPLE_PROMPT) +#if defined(BB_FEATURE_SH_FANCY_PROMPT) "\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:\ \\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] \ \\!\\[\\e[36;1m\\]\\$ \\[\\E[0m\\]"; @@ -1522,15 +1504,16 @@ int main(int argc, char **argv) #ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT setlocale(LC_ALL, ""); #endif - shell_context = 1; - do { + while(1) { int l; cmdedit_read_input(prompt, buff); l = strlen(buff); + if(l==0) + break; 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; }