bb_get_[chomped]line_from_file wasn't descriptive enough.
[oweals/busybox.git] / shell / cmdedit.c
index 31f4c7b200e2b41126c106a4281d240eddb408ee..3f44ea0135cd7d3db8e842e9b6e9d55b1d7e83fe 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 
+#include "busybox.h"
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
@@ -41,9 +42,7 @@
 #include <signal.h>
 #include <limits.h>
 
-#include "busybox.h"
-
-#include "../shell/cmdedit.h"
+#include "cmdedit.h"
 
 
 #ifdef CONFIG_LOCALE_SUPPORT
 #define CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
 #endif
 
-#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
-#include "pwd_.h"
-#endif  /* advanced FEATURES */
-
-
 /* Maximum length of the linked list for the command line history */
 #ifndef CONFIG_FEATURE_COMMAND_HISTORY
 #define MAX_HISTORY   15
@@ -217,7 +211,7 @@ static void cmdedit_set_out_char(int next_char)
                printf("\033[7m%c\033[0m", c);
        } else
 #endif
-               putchar(c);
+               if (initial_settings.c_lflag & ECHO) putchar(c);
        if (++cmdedit_x >= cmdedit_termw) {
                /* terminal is scrolled down */
                cmdedit_y++;
@@ -248,13 +242,13 @@ static void goto_new_line(void)
 }
 
 
-static inline void out1str(const char *s)
+static void out1str(const char *s)
 {
        if ( s )
                fputs(s, stdout);
 }
 
-static inline void beep(void)
+static void beep(void)
 {
        putchar('\007');
 }
@@ -272,7 +266,6 @@ static void input_backward(int num)
                if (num < 4)
                        while (num-- > 0)
                                putchar('\b');
-
                else
                        printf("\033[%dD", num);
        } else {
@@ -312,7 +305,7 @@ static void parse_prompt(const char *prmt_ptr)
        int prmt_len = 0;
        size_t cur_prmt_len = 0;
        char  flg_not_length = '[';
-       char *prmt_mem_ptr = xcalloc(1, 1);
+       char *prmt_mem_ptr = xzalloc(1);
        char *pwd_buf = xgetcwd(0);
        char  buf2[PATH_MAX + 1];
        char  buf[2];
@@ -345,7 +338,7 @@ static void parse_prompt(const char *prmt_ptr)
                          case 'h':
                                pbuf = hostname_buf;
                                if (pbuf == 0) {
-                                       pbuf = xcalloc(256, 1);
+                                       pbuf = xzalloc(256);
                                        if (gethostname(pbuf, 255) < 0) {
                                                strcpy(pbuf, "?");
                                        } else {
@@ -371,7 +364,7 @@ static void parse_prompt(const char *prmt_ptr)
                                        pbuf = buf2;
                                        *pbuf = '~';
                                        strcpy(pbuf+1, pwd_buf+l);
-                                       }
+                               }
                                break;
 #endif
                          case 'W':
@@ -442,9 +435,10 @@ static void redraw(int y, int back_cursor)
 }
 
 #ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
-static char delbuf[BUFSIZ];  /* a place to store deleted characters */
-static char *delp = delbuf;
-static int newdelflag;      /* whether delbuf should be reused yet */
+#define DELBUFSIZ 128
+static char *delbuf;  /* a (malloced) place to store deleted characters */
+static char *delp;
+static char newdelflag;      /* whether delbuf should be reused yet */
 #endif
 
 /* Delete the char in front of the cursor, optionally saving it
@@ -459,10 +453,13 @@ static void input_delete(int save)
 #ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
        if (save) {
                if (newdelflag) {
+                       if (!delbuf)
+                               delbuf = malloc(DELBUFSIZ);
+                       /* safe if malloc fails */
                        delp = delbuf;
                        newdelflag = 0;
                }
-               if (delp - delbuf < BUFSIZ)
+               if (delbuf && (delp - delbuf < DELBUFSIZ))
                        *delp++ = command_ps[j];
        }
 #endif
@@ -543,8 +540,8 @@ static void cmdedit_init(void)
                my_euid = geteuid();
                entry = getpwuid(my_euid);
                if (entry) {
-                       user_buf = bb_xstrdup(entry->pw_name);
-                       home_pwd_buf = bb_xstrdup(entry->pw_dir);
+                       user_buf = xstrdup(entry->pw_name);
+                       home_pwd_buf = xstrdup(entry->pw_dir);
                }
 #endif
 
@@ -631,7 +628,7 @@ static void username_tab_completion(char *ud, char *with_shash_flg)
                while ((entry = getpwent()) != NULL) {
                        /* Null usernames should result in all users as possible completions. */
                        if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) {
-                               add_match(bb_xasprintf("~%s", entry->pw_name), '/');
+                               add_match(xasprintf("~%s", entry->pw_name), '/');
                        }
                }
 
@@ -681,7 +678,7 @@ static int path_parse(char ***p, int flags)
        *p = xmalloc(npth * sizeof(char *));
 
        tmp = pth;
-       (*p)[0] = bb_xstrdup(tmp);
+       (*p)[0] = xstrdup(tmp);
        npth = 1;                       /* count words is + 1 count ':' */
 
        for (;;) {
@@ -709,7 +706,7 @@ static char *add_quote_for_spec_chars(char *found, int add)
                s[l++] = *found++;
        }
        if(add)
-           s[l++] = (char)add;
+               s[l++] = (char)add;
        s[l] = 0;
        return s;
 }
@@ -992,7 +989,7 @@ static void showfiles(void)
        for (row = 0; row < nrows; row++) {
                l = strlen(matches[row]);
                if(add_char_to_match[row])
-                   l++;
+                       l++;
                if (column_width < l)
                        column_width = l;
        }
@@ -1018,8 +1015,8 @@ static void showfiles(void)
                        printf("%s%s", matches[n], str_add_chr);
                        l = strlen(matches[n]);
                        while(l < acol) {
-                           putchar(' ');
-                           l++;
+                               putchar(' ');
+                               l++;
                        }
                }
                str_add_chr[0] = add_char_to_match[n];
@@ -1078,30 +1075,32 @@ static void input_tab(int *lastWasTab)
                        int i, j, n, srt;
                        /* bubble */
                        n = num_matches;
-                       for(i=0; i<(n-1); i++)
-                           for(j=i+1; j<n; j++)
-                               if(matches[i]!=NULL && matches[j]!=NULL) {
-                                   srt = strcmp(matches[i], matches[j]);
-                                   if(srt == 0) {
-                                       free(matches[j]);
-                                       matches[j]=0;
-                                   } else if(srt > 0) {
-                                       tmp1 = matches[i];
-                                       matches[i] = matches[j];
-                                       matches[j] = tmp1;
-                                       srt = add_char_to_match[i];
-                                       add_char_to_match[i] = add_char_to_match[j];
-                                       add_char_to_match[j] = srt;
-                                   }
+                       for(i=0; i<(n-1); i++) {
+                               for(j=i+1; j<n; j++) {
+                                       if(matches[i]!=NULL && matches[j]!=NULL) {
+                                               srt = strcmp(matches[i], matches[j]);
+                                               if(srt == 0) {
+                                                       free(matches[j]);
+                                                       matches[j]=0;
+                                               } else if(srt > 0) {
+                                                       tmp1 = matches[i];
+                                                       matches[i] = matches[j];
+                                                       matches[j] = tmp1;
+                                                       srt = add_char_to_match[i];
+                                                       add_char_to_match[i] = add_char_to_match[j];
+                                                       add_char_to_match[j] = srt;
+                                               }
+                                       }
                                }
+                       }
                        j = n;
                        n = 0;
                        for(i=0; i<j; i++)
-                           if(matches[i]) {
-                               matches[n]=matches[i];
-                               add_char_to_match[n]=add_char_to_match[i];
-                               n++;
-                           }
+                               if(matches[i]) {
+                                       matches[n]=matches[i];
+                                       add_char_to_match[n]=add_char_to_match[i];
+                                       n++;
+                               }
                        num_matches = n;
                }
                /* Did we find exactly one match? */
@@ -1111,7 +1110,7 @@ static void input_tab(int *lastWasTab)
                        if (!matches)
                                return;         /* not found */
                        /* find minimal match */
-                       tmp1 = bb_xstrdup(matches[0]);
+                       tmp1 = xstrdup(matches[0]);
                        for (tmp = tmp1; *tmp; tmp++)
                                for (len_found = 1; len_found < num_matches; len_found++)
                                        if (matches[len_found][(tmp - tmp1)] != *tmp) {
@@ -1172,7 +1171,7 @@ static void get_previous_history(void)
 {
        if(command_ps[0] != 0 || history[cur_history] == 0) {
                free(history[cur_history]);
-               history[cur_history] = bb_xstrdup(command_ps);
+               history[cur_history] = xstrdup(command_ps);
        }
        cur_history--;
 }
@@ -1206,7 +1205,7 @@ void load_history ( const char *fromfile )
        if (( fp = fopen ( fromfile, "r" ))) {
 
                for ( hi = 0; hi < MAX_HISTORY; ) {
-                       char * hl = bb_get_chomped_line_from_file(fp);
+                       char * hl = xmalloc_getline(fp);
                        int l;
 
                        if(!hl)
@@ -1370,23 +1369,18 @@ vi_back_motion(char *command)
 #endif
 
 /*
- * the normal emacs mode and vi's insert mode are the same.
- * commands entered when in vi command mode ("escape mode") get
- * an extra bit added to distinguish them.  this lets them share
- * much of the code in the big switch and while loop.  i
- * experimented with an ugly macro to make the case labels for
- * these cases go away entirely when vi mode isn't configured, in
- * hopes of letting the jump tables get smaller:
- *  #define vcase(caselabel) caselabel
- * and then
- *      case CNTRL('A'):
- *      case vcase(VICMD('0'):)
- * but it didn't seem to make any difference in code size,
- * and the macro-ized code was too ugly.
+ * 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
+ * big switch a bit, but keeps all the code in one place.
  */
 
-#define VI_cmdbit 0x100
-#define VICMD(somecmd) ((somecmd)|VI_cmdbit)
+#define vbit 0x100
+
+/* leave out the "vi-mode"-only case labels if vi editing isn't
+ * configured. */
+#define vi_case(caselabel) USE_FEATURE_COMMAND_EDITING(caselabel)
 
 /* convert uppercase ascii to equivalent control char, for readability */
 #define CNTRL(uc_char) ((uc_char) - 0x40)
@@ -1398,8 +1392,9 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
        int break_out = 0;
        int lastWasTab = FALSE;
        unsigned char c;
+       unsigned int ic;
 #ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
-       unsigned int ic, prevc;
+       unsigned int prevc;
        int vi_cmdmode = 0;
 #endif
        /* prepare before init handlers */
@@ -1438,38 +1433,37 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                        /* if we can't read input then exit */
                        goto prepare_to_die;
 
+               ic = c;
+
 #ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
                newdelflag = 1;
-               ic = c;
                if (vi_cmdmode)
-                       ic |= VI_cmdbit;
-               switch (ic)
-#else
-               switch (c)
+                       ic |= vbit;
 #endif
+               switch (ic)
                {
                case '\n':
                case '\r':
-               case VICMD('\n'):
-               case VICMD('\r'):
+               vi_case( case '\n'|vbit: )
+               vi_case( case '\r'|vbit: )
                        /* Enter */
                        goto_new_line();
                        break_out = 1;
                        break;
                case CNTRL('A'):
-               case VICMD('0'):
+               vi_case( case '0'|vbit: )
                        /* Control-a -- Beginning of line */
                        input_backward(cursor);
                        break;
                case CNTRL('B'):
-               case VICMD('h'):
-               case VICMD('\b'):
-               case VICMD(DEL):
+               vi_case( case 'h'|vbit: )
+               vi_case( case '\b'|vbit: )
+               vi_case( case DEL|vbit: )
                        /* Control-b -- Move back one character */
                        input_backward(1);
                        break;
                case CNTRL('C'):
-               case VICMD(CNTRL('C')):
+               vi_case( case CNTRL('C')|vbit: )
                        /* Control-c -- stop gathering input */
                        goto_new_line();
 #ifndef CONFIG_ASH
@@ -1503,13 +1497,13 @@ prepare_to_die:
                        }
                        break;
                case CNTRL('E'):
-               case VICMD('$'):
+               vi_case( case '$'|vbit: )
                        /* Control-e -- End of line */
                        input_end();
                        break;
                case CNTRL('F'):
-               case VICMD('l'):
-               case VICMD(' '):
+               vi_case( case 'l'|vbit: )
+               vi_case( case ' '|vbit: )
                        /* Control-f -- Move forward one character */
                        input_forward();
                        break;
@@ -1530,22 +1524,22 @@ prepare_to_die:
                        printf("\033[J");
                        break;
                case CNTRL('L'):
-               case VICMD(CNTRL('L')):
+               vi_case( case CNTRL('L')|vbit: )
                        /* Control-l -- clear screen */
                        printf("\033[H");
                        redraw(0, len-cursor);
                        break;
 #if MAX_HISTORY >= 1
                case CNTRL('N'):
-               case VICMD(CNTRL('N')):
-               case VICMD('j'):
+               vi_case( case CNTRL('N')|vbit: )
+               vi_case( case 'j'|vbit: )
                        /* Control-n -- Get next command in history */
                        if (get_next_history())
                                goto rewrite_line;
                        break;
                case CNTRL('P'):
-               case VICMD(CNTRL('P')):
-               case VICMD('k'):
+               vi_case( case CNTRL('P')|vbit: )
+               vi_case( case 'k'|vbit: )
                        /* Control-p -- Get previous command from history */
                        if (cur_history > 0) {
                                get_previous_history();
@@ -1556,7 +1550,7 @@ prepare_to_die:
                        break;
 #endif
                case CNTRL('U'):
-               case VICMD(CNTRL('U')):
+               vi_case( case CNTRL('U')|vbit: )
                        /* Control-U -- Clear line before cursor */
                        if (cursor) {
                                strcpy(command, command + cursor);
@@ -1564,7 +1558,7 @@ prepare_to_die:
                        }
                        break;
                case CNTRL('W'):
-               case VICMD(CNTRL('W')):
+               vi_case( case CNTRL('W')|vbit: )
                        /* Control-W -- Remove the last word */
                        while (cursor > 0 && isspace(command[cursor-1]))
                                input_backspace();
@@ -1572,123 +1566,123 @@ prepare_to_die:
                                input_backspace();
                        break;
 #if CONFIG_FEATURE_COMMAND_EDITING_VI
-               case VICMD('i'):
+               case 'i'|vbit:
                        vi_cmdmode = 0;
                        break;
-               case VICMD('I'):
+               case 'I'|vbit:
                        input_backward(cursor);
                        vi_cmdmode = 0;
                        break;
-               case VICMD('a'):
+               case 'a'|vbit:
                        input_forward();
                        vi_cmdmode = 0;
                        break;
-               case VICMD('A'):
+               case 'A'|vbit:
                        input_end();
                        vi_cmdmode = 0;
                        break;
-               case VICMD('x'):
+               case 'x'|vbit:
                        input_delete(1);
                        break;
-               case VICMD('X'):
+               case 'X'|vbit:
                        if (cursor > 0) {
                                input_backward(1);
                                input_delete(1);
                        }
                        break;
-               case VICMD('W'):
+               case 'W'|vbit:
                        vi_Word_motion(command, 1);
                        break;
-               case VICMD('w'):
+               case 'w'|vbit:
                        vi_word_motion(command, 1);
                        break;
-               case VICMD('E'):
+               case 'E'|vbit:
                        vi_End_motion(command);
                        break;
-               case VICMD('e'):
+               case 'e'|vbit:
                        vi_end_motion(command);
                        break;
-               case VICMD('B'):
+               case 'B'|vbit:
                        vi_Back_motion(command);
                        break;
-               case VICMD('b'):
+               case 'b'|vbit:
                        vi_back_motion(command);
                        break;
-               case VICMD('C'):
+               case 'C'|vbit:
                        vi_cmdmode = 0;
                        /* fall through */
-               case VICMD('D'):
+               case 'D'|vbit:
                        goto clear_to_eol;
 
-               case VICMD('c'):
+               case 'c'|vbit:
                        vi_cmdmode = 0;
                        /* fall through */
-               case VICMD('d'):
+               case 'd'|vbit:
                        {
-                       int nc, sc;
-                       sc = cursor;
-                       prevc = ic;
-                       if (safe_read(0, &c, 1) < 1)
-                               goto prepare_to_die;
-                       if (c == (prevc & 0xff)) {
-                           /* "cc", "dd" */
-                           input_backward(cursor);
-                           goto clear_to_eol;
-                           break;
-                       }
-                       switch(c) {
-                       case 'w':
-                       case 'W':
-                       case 'e':
-                       case 'E':
-                           switch (c) {
-                           case 'w':   /* "dw", "cw" */
-                                   vi_word_motion(command, vi_cmdmode);
-                                   break;
-                           case 'W':   /* 'dW', 'cW' */
-                                   vi_Word_motion(command, vi_cmdmode);
-                                   break;
-                           case 'e':   /* 'de', 'ce' */
-                                   vi_end_motion(command);
-                                   input_forward();
-                                   break;
-                           case 'E':   /* 'dE', 'cE' */
-                                   vi_End_motion(command);
-                                   input_forward();
-                                   break;
-                           }
-                           nc = cursor;
-                           input_backward(cursor - sc);
-                           while (nc-- > cursor)
-                                   input_delete(1);
-                           break;
-                       case 'b':  /* "db", "cb" */
-                       case 'B':  /* implemented as B */
-                           if (c == 'b')
-                                   vi_back_motion(command);
-                           else
-                                   vi_Back_motion(command);
-                           while (sc-- > cursor)
-                                   input_delete(1);
-                           break;
-                       case ' ':  /* "d ", "c " */
-                           input_delete(1);
-                           break;
-                       case '$':  /* "d$", "c$" */
-                       clear_to_eol:
-                           while (cursor < len)
-                                   input_delete(1);
-                           break;
-                       }
+                               int nc, sc;
+                               sc = cursor;
+                               prevc = ic;
+                               if (safe_read(0, &c, 1) < 1)
+                                       goto prepare_to_die;
+                               if (c == (prevc & 0xff)) {
+                                       /* "cc", "dd" */
+                                       input_backward(cursor);
+                                       goto clear_to_eol;
+                                       break;
+                               }
+                               switch(c) {
+                               case 'w':
+                               case 'W':
+                               case 'e':
+                               case 'E':
+                                       switch (c) {
+                                       case 'w':   /* "dw", "cw" */
+                                               vi_word_motion(command, vi_cmdmode);
+                                               break;
+                                       case 'W':   /* 'dW', 'cW' */
+                                               vi_Word_motion(command, vi_cmdmode);
+                                               break;
+                                       case 'e':   /* 'de', 'ce' */
+                                               vi_end_motion(command);
+                                               input_forward();
+                                               break;
+                                       case 'E':   /* 'dE', 'cE' */
+                                               vi_End_motion(command);
+                                               input_forward();
+                                               break;
+                                       }
+                                       nc = cursor;
+                                       input_backward(cursor - sc);
+                                       while (nc-- > cursor)
+                                               input_delete(1);
+                                       break;
+                               case 'b':  /* "db", "cb" */
+                               case 'B':  /* implemented as B */
+                                       if (c == 'b')
+                                               vi_back_motion(command);
+                                       else
+                                               vi_Back_motion(command);
+                                       while (sc-- > cursor)
+                                               input_delete(1);
+                                       break;
+                               case ' ':  /* "d ", "c " */
+                                       input_delete(1);
+                                       break;
+                               case '$':  /* "d$", "c$" */
+                               clear_to_eol:
+                                       while (cursor < len)
+                                               input_delete(1);
+                                       break;
+                               }
                        }
                        break;
-               case VICMD('p'):
+               case 'p'|vbit:
                        input_forward();
                        /* fallthrough */
-               case VICMD('P'):
+               case 'P'|vbit:
                        put();
                        break;
-               case VICMD('r'):
+               case 'r'|vbit:
                        if (safe_read(0, &c, 1) < 1)
                                goto prepare_to_die;
                        if (c == 0)
@@ -1700,7 +1694,9 @@ prepare_to_die:
                        }
                        break;
 #endif /* CONFIG_FEATURE_COMMAND_EDITING_VI */
-               case ESC:{
+
+               case ESC:
+
 #if CONFIG_FEATURE_COMMAND_EDITING_VI
                        if (vi_mode) {
                                /* ESC: insert mode --> command mode */
@@ -1714,8 +1710,8 @@ prepare_to_die:
                                goto prepare_to_die;
                        /* different vt100 emulations */
                        if (c == '[' || c == 'O') {
-               case VICMD('['):
-               case VICMD('O'):
+               vi_case( case '['|vbit: )
+               vi_case( case 'O'|vbit: )
                                if (safe_read(0, &c, 1) < 1)
                                        goto prepare_to_die;
                        }
@@ -1787,7 +1783,6 @@ rewrite_line:
                                beep();
                        }
                        break;
-               }
 
                default:        /* If it's regular input, do the normal thing */
 #ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
@@ -1857,7 +1852,7 @@ rewrite_line:
                        for(i = 0; i < (MAX_HISTORY-1); i++)
                                history[i] = history[i+1];
                }
-               history[i++] = bb_xstrdup(command);
+               history[i++] = xstrdup(command);
                cur_history = i;
                n_history = i;
 #if defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
@@ -1892,7 +1887,7 @@ rewrite_line:
 
 #ifdef TEST
 
-const char *bb_applet_name = "debug stuff usage";
+const char *applet_name = "debug stuff usage";
 
 #ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
 #include <locale.h>