cmdedit: more optimizations
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 21 Jan 2007 19:19:46 +0000 (19:19 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 21 Jan 2007 19:19:46 +0000 (19:19 -0000)
shell/cmdedit.c

index 1143ded77e59ce28bd186b65a1f63edd7ca878df..39cab19a02a60f91e520d226f91daeda5f26d5f0 100644 (file)
@@ -119,14 +119,6 @@ static struct termios initial_settings, new_settings;
 
 static
 volatile unsigned cmdedit_termw = 80;        /* actual terminal width */
-static
-volatile int handlers_sets = 0; /* Set next bits: */
-enum {
-       SET_ATEXIT = 1,         /* when atexit() has been called
-                                  and get euid,uid,gid to fast compare */
-       SET_WCHG_HANDLERS = 2,  /* winchg signal handler */
-       SET_RESET_TERM = 4,     /* if the terminal needs to be reset upon exit */
-};
 
 
 static int cmdedit_x;           /* real x terminal position */
@@ -148,10 +140,6 @@ static char *user_buf = "";
 static char *home_pwd_buf = "";
 #endif
 
-#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR || ENABLE_FEATURE_COMMAND_TAB_COMPLETION
-static int my_euid;
-#endif
-
 #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
 static int my_uid;
 static int my_gid;
@@ -339,7 +327,6 @@ static void input_backspace(void)
        }
 }
 
-
 /* Move forward one character */
 static void input_forward(void)
 {
@@ -347,10 +334,21 @@ static void input_forward(void)
                cmdedit_set_out_char(command_ps[cursor + 1]);
 }
 
+
 #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
 
 static char **matches;
-static int num_matches;
+static unsigned num_matches;
+
+static void free_tab_completion_data(void)
+{
+       if (matches) {
+               while (num_matches)
+                       free(matches[--num_matches]);
+               free(matches);
+               matches = NULL;
+       }
+}
 
 static void add_match(char *matched)
 {
@@ -363,7 +361,6 @@ static void add_match(char *matched)
 }
 
 #if ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION
-
 static void username_tab_completion(char *ud, char *with_shash_flg)
 {
        struct passwd *entry;
@@ -504,7 +501,6 @@ static void exe_n_cwd_tab_completion(char *command, int type)
        }
 
        for (i = 0; i < npaths; i++) {
-
                dir = opendir(paths[i]);
                if (!dir)                       /* Don't print an error */
                        continue;
@@ -559,7 +555,6 @@ static void exe_n_cwd_tab_completion(char *command, int type)
        }
 }
 
-
 #define QUOT (UCHAR_MAX+1)
 
 #define collapse_pos(is, in) { \
@@ -580,8 +575,8 @@ static int find_match(char *matchBuf, int *len_with_quotes)
                if (int_buf[i] == 0) {
                        pos_buf[i] = -1;        /* indicator end line */
                        break;
-               } else
-                       pos_buf[i] = i;
+               }
+               pos_buf[i] = i;
        }
 
        /* mask \+symbol and convert '\t' to ' ' */
@@ -731,9 +726,9 @@ static int find_match(char *matchBuf, int *len_with_quotes)
 }
 
 /*
  display by column original ideas from ls applet,
  very optimize by my :)
-*/
* display by column (original idea from ls applet,
* very optimized by me :)
+ */
 static void showfiles(void)
 {
        int ncols, row;
@@ -770,11 +765,6 @@ static void showfiles(void)
        }
 }
 
-static int match_compare(const void *a, const void *b)
-{
-       return strcmp(*(char**)a, *(char**)b);
-}
-
 static char *add_quote_for_spec_chars(char *found)
 {
        int l = 0;
@@ -789,18 +779,14 @@ static char *add_quote_for_spec_chars(char *found)
        return s;
 }
 
+static int match_compare(const void *a, const void *b)
+{
+       return strcmp(*(char**)a, *(char**)b);
+}
+
+/* Do TAB completion */
 static void input_tab(int *lastWasTab)
 {
-       /* Do TAB completion */
-       if (lastWasTab == 0) {          /* free all memory */
-               if (matches) {
-                       while (num_matches > 0)
-                               free(matches[--num_matches]);
-                       free(matches);
-                       matches = (char **) NULL;
-               }
-               return;
-       }
        if (!*lastWasTab) {
                char *tmp, *tmp1;
                int len_found;
@@ -813,12 +799,12 @@ static void input_tab(int *lastWasTab)
                /* Make a local copy of the string -- up
                 * to the position of the cursor */
                tmp = strncpy(matchBuf, command_ps, cursor);
-               tmp[cursor] = 0;
+               tmp[cursor] = '\0';
 
                find_type = find_match(matchBuf, &recalc_pos);
 
                /* Free up any memory already allocated */
-               input_tab(0);
+               free_tab_completion_data();
 
 #if ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION
                /* If the word starts with `~' and there is no slash in the word,
@@ -829,24 +815,24 @@ static void input_tab(int *lastWasTab)
                if (!matches)
 #endif
                /* Try to match any executable in our path and everything
-                * in the current working directory that matches.  */
+                * in the current working directory */
                        exe_n_cwd_tab_completion(matchBuf, find_type);
                /* Sort, then remove any duplicates found */
                if (matches) {
                        int i, n = 0;
                        qsort(matches, num_matches, sizeof(char*), match_compare);
                        for (i = 0; i < num_matches - 1; ++i) {
-                               if (matches[i] && matches[i+1]) {
+                               if (matches[i] && matches[i+1]) { /* paranoia */
                                        if (strcmp(matches[i], matches[i+1]) == 0) {
                                                free(matches[i]);
-                                               matches[i] = 0;
+                                               matches[i] = NULL; /* paranoia */
                                        } else {
                                                matches[n++] = matches[i];
                                        }
                                }
                        }
-                       matches[n++] = matches[num_matches-1];
-                       num_matches = n;
+                       matches[n] = matches[i];
+                       num_matches = n + 1;
                }
                /* Did we find exactly one match? */
                if (!matches || num_matches > 1) {
@@ -858,10 +844,10 @@ static void input_tab(int *lastWasTab)
                        for (tmp = tmp1; *tmp; tmp++)
                                for (len_found = 1; len_found < num_matches; len_found++)
                                        if (matches[len_found][(tmp - tmp1)] != *tmp) {
-                                               *tmp = 0;
+                                               *tmp = '\0';
                                                break;
                                        }
-                       if (*tmp1 == 0) {        /* have unique */
+                       if (*tmp1 == '\0') {        /* have unique */
                                free(tmp1);
                                return;
                        }
@@ -881,7 +867,6 @@ static void input_tab(int *lastWasTab)
                len_found = strlen(tmp);
                /* have space to placed match? */
                if ((len_found - strlen(matchBuf) + len) < BUFSIZ) {
-
                        /* before word for match   */
                        command_ps[cursor - recalc_pos] = 0;
                        /* save   tail line        */
@@ -914,6 +899,7 @@ static void input_tab(int *lastWasTab)
                }
        }
 }
+
 #endif  /* FEATURE_COMMAND_TAB_COMPLETION */
 
 
@@ -927,7 +913,7 @@ static int cur_history;
 
 static void get_previous_history(void)
 {
-       if (command_ps[0] != 0 || history[cur_history] == 0) {
+       if (command_ps[0] != '\0' || history[cur_history] == NULL) {
                free(history[cur_history]);
                history[cur_history] = xstrdup(command_ps);
        }
@@ -1126,81 +1112,6 @@ enum { vi_mode = 0 };
  * cmdedit_read_input and its helpers
  */
 
-#define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp)
-#define getTermSettings(fd, argp) tcgetattr(fd, argp);
-
-static sighandler_t previous_SIGWINCH_handler;
-
-static void cmdedit_reset_term(void)
-{
-       if (handlers_sets & SET_RESET_TERM) {
-               setTermSettings(STDIN_FILENO, (void *) &initial_settings);
-               handlers_sets &= ~SET_RESET_TERM;
-       }
-       if (handlers_sets & SET_WCHG_HANDLERS) {
-               /* restore SIGWINCH handler */
-               signal(SIGWINCH, previous_SIGWINCH_handler);
-               handlers_sets &= ~SET_WCHG_HANDLERS;
-       }
-       fflush(stdout);
-}
-
-static void cmdedit_setwidth(unsigned w, int redraw_flg)
-{
-       cmdedit_termw = w;
-       if (redraw_flg) {
-               /* new y for current cursor */
-               int new_y = (cursor + cmdedit_prmt_len) / w;
-               /* redraw */
-               redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor);
-               fflush(stdout);
-       }
-}
-
-static void win_changed(int nsig)
-{
-       int width;
-       get_terminal_width_height(0, &width, NULL);
-       cmdedit_setwidth(width, nsig /* - just a yes/no flag */);
-       if (nsig == SIGWINCH)
-               signal(SIGWINCH, win_changed); /* rearm ourself */
-}
-
-static void cmdedit_init(void)
-{
-       cmdedit_prmt_len = 0;
-       if (!(handlers_sets & SET_WCHG_HANDLERS)) {
-               previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
-               win_changed(0); /* do initial resizing */
-               handlers_sets |= SET_WCHG_HANDLERS;
-       }
-
-       if (!(handlers_sets & SET_ATEXIT)) {
-#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
-               struct passwd *entry;
-
-               my_euid = geteuid();
-               entry = getpwuid(my_euid);
-               if (entry) {
-                       user_buf = xstrdup(entry->pw_name);
-                       home_pwd_buf = xstrdup(entry->pw_dir);
-               }
-#endif
-
-#if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
-
-#if !ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
-               my_euid = geteuid();
-#endif
-               my_uid = getuid();
-               my_gid = getgid();
-#endif  /* FEATURE_COMMAND_TAB_COMPLETION */
-               handlers_sets |= SET_ATEXIT;
-// Crap. We should be able to do it without atexit.
-               atexit(cmdedit_reset_term);     /* be sure to do this only once */
-       }
-}
-
 #if !ENABLE_FEATURE_SH_FANCY_PROMPT
 static void parse_prompt(const char *prmt_ptr)
 {
@@ -1259,7 +1170,7 @@ static void parse_prompt(const char *prmt_ptr)
                                        }
                                        break;
                                case '$':
-                                       c = (my_euid == 0 ? '#' : '$');
+                                       c = (geteuid() == 0 ? '#' : '$');
                                        break;
 #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
                                case 'w':
@@ -1283,7 +1194,8 @@ static void parse_prompt(const char *prmt_ptr)
                                                pbuf += (cp-pbuf) + 1;
                                        break;
                                case '!':
-                                       snprintf(pbuf = buf2, sizeof(buf2), "%d", num_ok_lines);
+                                       pbuf = buf2;
+                                       snprintf(buf2, sizeof(buf2), "%d", num_ok_lines);
                                        break;
                                case 'e': case 'E':     /* \e \E = \033 */
                                        c = '\033';
@@ -1330,11 +1242,71 @@ static void parse_prompt(const char *prmt_ptr)
 }
 #endif
 
+#define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp)
+#define getTermSettings(fd, argp) tcgetattr(fd, argp);
+
+static sighandler_t previous_SIGWINCH_handler;
+
+static void cmdedit_reset_term(void)
+{
+       setTermSettings(STDIN_FILENO, (void *) &initial_settings);
+       /* restore SIGWINCH handler */
+       signal(SIGWINCH, previous_SIGWINCH_handler);
+       fflush(stdout);
+}
+
+static void cmdedit_setwidth(unsigned w, int redraw_flg)
+{
+       cmdedit_termw = w;
+       if (redraw_flg) {
+               /* new y for current cursor */
+               int new_y = (cursor + cmdedit_prmt_len) / w;
+               /* redraw */
+               redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor);
+               fflush(stdout);
+       }
+}
+
+static void win_changed(int nsig)
+{
+       int width;
+       get_terminal_width_height(0, &width, NULL);
+       cmdedit_setwidth(width, nsig /* - just a yes/no flag */);
+       if (nsig == SIGWINCH)
+               signal(SIGWINCH, win_changed); /* rearm ourself */
+}
+
+static void cmdedit_init(void)
+{
+       cmdedit_prmt_len = 0;
+       previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
+       win_changed(0); /* do initial resizing */
+
+#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
+       {
+               struct passwd *entry;
+
+               entry = getpwuid(geteuid());
+               if (entry) {
+                       user_buf = xstrdup(entry->pw_name);
+                       home_pwd_buf = xstrdup(entry->pw_dir);
+               }
+       }
+#endif
+
+#if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
+       my_uid = getuid();
+       my_gid = getgid();
+#endif
+// Crap. We should be able to do it without atexit.
+       atexit(cmdedit_reset_term);     /* be sure to do this only once */
+}
+
 /*
- * the emacs and vi modes share much of the code in the big
- * command loop.  commands entered when in vi's command mode (aka
+ * The emacs and vi modes share much of the code in the big
+ * command loop.  Commands entered when in vi's command mode (aka
  * "escape mode") get an extra bit added to distinguish them --
- * this keeps them from being self-inserted.  this clutters the
+ * this keeps them from being self-inserted.  This clutters the
  * big switch a bit, but keeps all the code in one place.
  */
 
@@ -1379,7 +1351,6 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
 #endif
        new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
        setTermSettings(0, (void *) &new_settings);
-       handlers_sets |= SET_RESET_TERM;
 
        /* Now initialize things */
        cmdedit_init();
@@ -1387,11 +1358,12 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
        parse_prompt(prompt);
 
        while (1) {
-               fflush(stdout);                 /* buffered out to fast */
+               fflush(stdout);
 
-               if (safe_read(0, &c, 1) < 1)
+               if (safe_read(0, &c, 1) < 1) {
                        /* if we can't read input then exit */
                        goto prepare_to_die;
+               }
 
                ic = c;
 
@@ -1789,23 +1761,22 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                        lastWasTab = FALSE;
        }
 
-       setTermSettings(0, (void *) &initial_settings);
-       handlers_sets &= ~SET_RESET_TERM;
-
 #if MAX_HISTORY > 0
        /* Handle command history log */
        /* cleanup may be saved current command line */
-       if (len > 0) {                                      /* no put empty line */
+       if (len > 0) {
                int i = n_history;
 
                free(history[MAX_HISTORY]);
-               history[MAX_HISTORY] = 0;
+               history[MAX_HISTORY] = NULL;
                /* After max history, remove the oldest command */
                if (i >= MAX_HISTORY) {
                        free(history[0]);
                        for (i = 0; i < MAX_HISTORY-1; i++)
                                history[i] = history[i+1];
                }
+// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..."
+// (i.e. do not save dups?)
                history[i++] = xstrdup(command);
                cur_history = i;
                n_history = i;
@@ -1822,12 +1793,13 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
        }
 
 #if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_COMMAND_TAB_COMPLETION
-       input_tab(0);
+       free_tab_completion_data();
 #endif
 
 #if ENABLE_FEATURE_SH_FANCY_PROMPT
        free(cmdedit_prompt);
 #endif
+       /* restore initial_settings and SIGWINCH handler */
        cmdedit_reset_term();
        return len;
 }