Convert cmdedit into more generic line input facility
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 22 Jan 2007 07:21:38 +0000 (07:21 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 22 Jan 2007 07:21:38 +0000 (07:21 -0000)
(make history and completion optional at runtime).
Use it for fdisk, as an example.
Some unrelated fixes in fdisk are also here.

include/libbb.h
shell/Kbuild
shell/ash.c
shell/cmdedit.c
shell/cmdedit.h
shell/hush.c
shell/lash.c
shell/msh.c
util-linux/fdisk.c
util-linux/fdisk_osf.c

index 0b066d1bdb2d173fa57d69600184fab89abbea49..f990b0ebda5c65fbf116b01535fd7553043f72ad 100644 (file)
@@ -583,6 +583,42 @@ extern unsigned long long bb_makedev(unsigned int major, unsigned int minor);
 #endif
 
 
+#if ENABLE_FEATURE_COMMAND_EDITING
+/* It's NOT just ENABLEd or disabled. It's a number: */
+#ifdef CONFIG_FEATURE_COMMAND_HISTORY
+#define MAX_HISTORY (CONFIG_FEATURE_COMMAND_HISTORY + 0)
+#else
+#define MAX_HISTORY 0
+#endif
+struct line_input_t {
+       int flags;
+       const char *path_lookup;
+#if MAX_HISTORY
+       int cnt_history;
+       int cur_history;
+       USE_FEATURE_COMMAND_SAVEHISTORY(const char *hist_file;)
+       char *history[MAX_HISTORY + 1];
+#endif
+};
+enum {
+       DO_HISTORY = 1 * (MAX_HISTORY > 0),
+       SAVE_HISTORY = 2 * (MAX_HISTORY > 0) * ENABLE_FEATURE_COMMAND_SAVEHISTORY,
+       TAB_COMPLETION = 4 * ENABLE_FEATURE_COMMAND_TAB_COMPLETION,
+       USERNAME_COMPLETION = 8 * ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION,
+       VI_MODE = 0x10 * ENABLE_FEATURE_COMMAND_EDITING_VI,
+       WITH_PATH_LOOKUP = 0x20,
+       FOR_SHELL = DO_HISTORY | SAVE_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION,
+};
+typedef struct line_input_t line_input_t;
+line_input_t *new_line_input_t(int flags);
+int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state);
+#else
+int read_line_input(const char* prompt, char* command, int maxsize);
+#define read_line_input(prompt, command, maxsize, state) \
+       read_line_input(prompt, command, maxsize)
+#endif
+
+
 #ifndef COMM_LEN
 #ifdef TASK_COMM_LEN
 enum { COMM_LEN = TASK_COMM_LEN };
index eb0199ee2bcefe08448162f5237caa7f00c2de6c..9c60698f794c7a60ca2e95534c94601c64b8d34b 100644 (file)
@@ -5,8 +5,8 @@
 # Licensed under the GPL v2, see the file LICENSE in this tarball.
 
 lib-y:=
-lib-$(CONFIG_ASH)                      += ash.o
-lib-$(CONFIG_HUSH)                     += hush.o
-lib-$(CONFIG_LASH)                     += lash.o
-lib-$(CONFIG_MSH)                      += msh.o
-lib-$(CONFIG_FEATURE_COMMAND_EDITING)  += cmdedit.o
+lib-y              += cmdedit.o
+lib-$(CONFIG_ASH)  += ash.o
+lib-$(CONFIG_HUSH) += hush.o
+lib-$(CONFIG_LASH) += lash.o
+lib-$(CONFIG_MSH)  += msh.o
index 2db3302c7078b6c73834f33dc19dfa7d2013b2e1..8afdf3d2127050308a13dbf700c8a0ed637612ae 100644 (file)
@@ -92,7 +92,6 @@
 #include <termios.h>
 #endif
 
-#include "cmdedit.h"
 
 #ifdef __GLIBC__
 /* glibc sucks */
@@ -1238,7 +1237,7 @@ static int fgcmd(int, char **);
 static int getoptscmd(int, char **);
 #endif
 static int hashcmd(int, char **);
-#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+#if !ENABLE_FEATURE_SH_EXTRA_QUIET
 static int helpcmd(int argc, char **argv);
 #endif
 #if JOBS
@@ -1347,7 +1346,7 @@ static const struct builtincmd builtincmd[] = {
        { BUILTIN_REGULAR       "getopts", getoptscmd },
 #endif
        { BUILTIN_NOSPEC        "hash", hashcmd },
-#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+#if !ENABLE_FEATURE_SH_EXTRA_QUIET
        { BUILTIN_NOSPEC        "help", helpcmd },
 #endif
 #if JOBS
@@ -1529,7 +1528,7 @@ static struct var varinit[] = {
        {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
        {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
 #endif
-#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
+#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
        {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
 #endif
 };
@@ -1934,10 +1933,6 @@ struct shparam {
 #define debug optlist[15]
 #endif
 
-#ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
-#define setvimode(on) viflag = 0   /* forcibly keep the option off */
-#endif
-
 /*      options.c */
 
 
@@ -3718,7 +3713,7 @@ shellexec(char **argv, const char *path, int idx)
        clearredir(1);
        envp = environment();
        if (strchr(argv[0], '/') || is_safe_applet(argv[0])
-#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+#if ENABLE_FEATURE_SH_STANDALONE_SHELL
         || find_applet_by_name(argv[0])
 #endif
        ) {
@@ -3775,7 +3770,7 @@ tryexec(char *cmd, char **argv, char **envp)
                applet_name = cmd;
                exit(a->main(argc, argv));
        }
-#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+#if ENABLE_FEATURE_SH_STANDALONE_SHELL
        if (find_applet_by_name(cmd) != NULL) {
                /* re-exec ourselves with the new arguments */
                execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
@@ -3949,7 +3944,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
                return;
        }
 
-#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+#if ENABLE_FEATURE_SH_STANDALONE_SHELL
        if (find_applet_by_name(name)) {
                entry->cmdtype = CMDNORMAL;
                entry->u.index = -1;
@@ -6045,21 +6040,18 @@ static char * pfgets(char *line, int len)
 }
 
 
-
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
-#ifdef CONFIG_ASH_EXPAND_PRMT
-static char *cmdedit_prompt;
-#else
+#if ENABLE_FEATURE_COMMAND_EDITING
+static line_input_t *line_input_state;
+//static SKIP_ASH_EXPAND_PRMT(const) char *cmdedit_prompt;
 static const char *cmdedit_prompt;
-#endif
 static void putprompt(const char *s)
 {
-#ifdef CONFIG_ASH_EXPAND_PRMT
-       free(cmdedit_prompt);
-       cmdedit_prompt = xstrdup(s);
-#else
+       if (ENABLE_ASH_EXPAND_PRMT) {
+               free((char*)cmdedit_prompt);
+               cmdedit_prompt = xstrdup(s);
+               return;
+       }
        cmdedit_prompt = s;
-#endif
 }
 #else
 static void putprompt(const char *s)
@@ -6068,6 +6060,16 @@ static void putprompt(const char *s)
 }
 #endif
 
+#if ENABLE_FEATURE_COMMAND_EDITING_VI
+#define setvimode(on) do { \
+       if (on) line_input_state->flags |= VI_MODE; \
+       else line_input_state->flags &= ~VI_MODE; \
+} while (0)
+#else
+#define setvimode(on) viflag = 0   /* forcibly keep the option off */
+#endif
+
+
 static int preadfd(void)
 {
        int nr;
@@ -6075,25 +6077,25 @@ static int preadfd(void)
        parsenextc = buf;
 
 retry:
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
        if (!iflag || parsefile->fd)
                nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
        else {
-#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
-               cmdedit_path_lookup = pathval();
+#if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
+               line_input_state->path_lookup = pathval();
 #endif
-               nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
-               if(nr == 0) {
-                       /* Ctrl+C presend */
-                       if(trap[SIGINT]) {
+               nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
+               if (nr == 0) {
+                       /* Ctrl+C pressed */
+                       if (trap[SIGINT]) {
                                buf[0] = '\n';
-                               buf[1] = 0;
+                               buf[1] = '\0';
                                raise(SIGINT);
                                return 1;
                        }
                        goto retry;
                }
-               if(nr < 0 && errno == 0) {
+               if (nr < 0 && errno == 0) {
                        /* Ctrl+D presend */
                        nr = 0;
                }
@@ -7913,6 +7915,10 @@ ash_main(int argc, char **argv)
 #if PROFILE
        monitor(4, etext, profile_buf, sizeof profile_buf, 50);
 #endif
+
+#if ENABLE_FEATURE_COMMAND_EDITING
+       line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
+#endif
        state = 0;
        if (setjmp(jmploc.loc)) {
                int e;
@@ -7954,11 +7960,11 @@ ash_main(int argc, char **argv)
        init();
        setstackmark(&smark);
        procargs(argc, argv);
-#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
-       if ( iflag ) {
+#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
+       if (iflag) {
                const char *hp = lookupvar("HISTFILE");
 
-               if(hp == NULL ) {
+               if (hp == NULL) {
                        hp = lookupvar("HOME");
                        if(hp != NULL) {
                                char *defhp = concat_path_file(hp, ".ash_history");
@@ -7995,15 +8001,15 @@ state3:
                evalstring(minusc, 0);
 
        if (sflag || minusc == NULL) {
-#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
-           if ( iflag ) {
-               const char *hp = lookupvar("HISTFILE");
+#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
+               if ( iflag ) {
+                       const char *hp = lookupvar("HISTFILE");
 
-               if(hp != NULL )
-                       load_history ( hp );
-           }
+                       if (hp != NULL)
+                               line_input_state->hist_file = hp;
+               }
 #endif
-state4: /* XXX ??? - why isn't this before the "if" statement */
+ state4: /* XXX ??? - why isn't this before the "if" statement */
                cmdloop(1);
        }
 #if PROFILE
@@ -11880,7 +11886,7 @@ setinteractive(int on)
        setsignal(SIGINT);
        setsignal(SIGQUIT);
        setsignal(SIGTERM);
-#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+#if !ENABLE_FEATURE_SH_EXTRA_QUIET
                if(is_interactive > 1) {
                        /* Looks like they want an interactive shell */
                        static int do_banner;
@@ -11897,7 +11903,7 @@ setinteractive(int on)
 }
 
 
-#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+#if !ENABLE_FEATURE_SH_EXTRA_QUIET
 /*** List the available builtins ***/
 
 static int helpcmd(int argc, char **argv)
@@ -11913,7 +11919,7 @@ static int helpcmd(int argc, char **argv)
                        col = 0;
                }
        }
-#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+#if ENABLE_FEATURE_SH_STANDALONE_SHELL
        for (i = 0; i < NUM_APPLETS; i++) {
                col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
                if (col > 60) {
@@ -11945,7 +11951,7 @@ exitshell(void)
 /* dash bug: it just does _exit(exitstatus) here
  * but we have to do setjobctl(0) first!
  * (bug is still not fixed in dash-0.5.3 - if you run dash
- * under Midnight Commander, on exit MC is backgrounded) */
+ * under Midnight Commander, on exit from dash MC is backgrounded) */
                        status = exitstatus;
                goto out;
        }
@@ -11955,14 +11961,6 @@ exitshell(void)
                evalstring(p, 0);
        }
        flushall();
-#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
-       if (iflag && rootshell) {
-               const char *hp = lookupvar("HISTFILE");
-
-               if (hp != NULL)
-                       save_history(hp);
-       }
-#endif
 out:
        setjobctl(0);
        _exit(status);
@@ -13491,7 +13489,7 @@ static const char op_tokens[] = {
 #define endexpression &op_tokens[sizeof(op_tokens)-7]
 
 
-static arith_t arith (const char *expr, int *perrcode)
+static arith_t arith(const char *expr, int *perrcode)
 {
     char arithval; /* Current character under analysis */
     operator lasttok, op;
index a1432af157a272155d42e4075bb6b9eca78e9284..554a4ebecef6539ada5c818ded1e1f50f44f32a3 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <sys/ioctl.h>
 #include "busybox.h"
-#include "cmdedit.h"
 
 
 /* FIXME: obsolete CONFIG item? */
@@ -51,7 +50,6 @@
 /* Entire file (except TESTing part) sits inside this #if */
 #if ENABLE_FEATURE_COMMAND_EDITING
 
-
 #if ENABLE_LOCALE_SUPPORT
 #define Isprint(c) isprint(c)
 #else
 #define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \
 (ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION || ENABLE_FEATURE_SH_FANCY_PROMPT)
 
-/* Maximum length of command line history */
-#if !ENABLE_FEATURE_COMMAND_HISTORY
-#define MAX_HISTORY   15
-#else
-#define MAX_HISTORY   (CONFIG_FEATURE_COMMAND_HISTORY + 0)
-#endif
 
+static line_input_t *state;
 
-/* Current termios and the previous termios before starting sh */
 static struct termios initial_settings, new_settings;
 
-static
-volatile unsigned cmdedit_termw = 80;        /* actual terminal width */
-
+static volatile unsigned cmdedit_termw = 80;        /* actual terminal width */
 
 static int cmdedit_x;           /* real x terminal position */
 static int cmdedit_y;           /* pseudoreal y terminal position */
 static int cmdedit_prmt_len;    /* length of prompt (without colors etc) */
 
-static int cursor;
-static int len;
+static unsigned cursor;
+static unsigned command_len;
 static char *command_ps;
-static SKIP_FEATURE_SH_FANCY_PROMPT(const) char *cmdedit_prompt;
+static const char *cmdedit_prompt;
 
 #if ENABLE_FEATURE_SH_FANCY_PROMPT
 static char *hostname_buf;
@@ -142,7 +132,7 @@ static void cmdedit_set_out_char(int next_char)
 /* Move to end of line (by printing all chars till the end) */
 static void input_end(void)
 {
-       while (cursor < len)
+       while (cursor < command_len)
                cmdedit_set_out_char(' ');
 }
 
@@ -200,7 +190,7 @@ static void input_backward(unsigned num)
 static void put_prompt(void)
 {
        out1str(cmdedit_prompt);
-       cmdedit_x = cmdedit_prmt_len;   /* count real x terminal position */
+       cmdedit_x = cmdedit_prmt_len;
        cursor = 0;
 // Huh? what if cmdedit_prmt_len >= width?
        cmdedit_y = 0;                  /* new quasireal y */
@@ -231,7 +221,7 @@ static void input_delete(int save)
 {
        int j = cursor;
 
-       if (j == len)
+       if (j == command_len)
                return;
 
 #if ENABLE_FEATURE_COMMAND_EDITING_VI
@@ -249,7 +239,7 @@ static void input_delete(int save)
 #endif
 
        strcpy(command_ps + j, command_ps + j + 1);
-       len--;
+       command_len--;
        input_end();                    /* rewrite new line */
        cmdedit_set_out_char(' ');      /* erase char */
        input_backward(cursor - j);     /* back to old pos cursor */
@@ -285,7 +275,7 @@ static void input_backspace(void)
 /* Move forward one character */
 static void input_forward(void)
 {
-       if (cursor < len)
+       if (cursor < command_len)
                cmdedit_set_out_char(command_ps[cursor + 1]);
 }
 
@@ -372,54 +362,50 @@ enum {
        FIND_FILE_ONLY = 2,
 };
 
-#if ENABLE_ASH
-const char *cmdedit_path_lookup;
-#endif
 static int path_parse(char ***p, int flags)
 {
        int npth;
        const char *tmp;
-#if ENABLE_ASH
-       const char *pth = cmdedit_path_lookup;
-#else
-       const char *pth = getenv("PATH")
-#endif
+       const char *pth;
+       char **res;
 
        /* if not setenv PATH variable, to search cur dir "." */
        if (flags != FIND_EXE_ONLY)
                return 1;
+
+       if (state->flags & WITH_PATH_LOOKUP)
+               pth = state->path_lookup;
+       else
+               pth = getenv("PATH");
        /* PATH=<empty> or PATH=:<empty> */
        if (!pth || !pth[0] || LONE_CHAR(pth, ':'))
                return 1;
 
        tmp = pth;
-       npth = 0;
-
+       npth = 1; /* path component count */
        while (1) {
-               npth++;                 /* count words is + 1 count ':' */
                tmp = strchr(tmp, ':');
                if (!tmp)
                        break;
                if (*++tmp == '\0')
                        break;  /* :<empty> */
+               npth++;
        }
 
-       *p = xmalloc(npth * sizeof(char *));
-
+       res = xmalloc(npth * sizeof(char*));
+       res[0] = xstrdup(pth);
        tmp = pth;
-       (*p)[0] = xstrdup(tmp);
-       npth = 1;                       /* count words is + 1 count ':' */
-
+       npth = 1;
        while (1) {
                tmp = strchr(tmp, ':');
                if (!tmp)
                        break;
-               (*p)[0][(tmp - pth)] = 0;       /* ':' -> '\0' */
-               if (*++tmp == 0)
-                       break;                  /* :<empty> */
-               (*p)[npth++] = &(*p)[0][(tmp - pth)];   /* p[next]=p[0][&'\0'+1] */
+               *tmp++ = '\0'; /* ':' -> '\0' */
+               if (*tmp == '\0')
+                       break; /* :<empty> */
+               res[npth++] = tmp;
        }
-
+       *p = res;
        return npth;
 }
 
@@ -742,6 +728,9 @@ static int match_compare(const void *a, const void *b)
 /* Do TAB completion */
 static void input_tab(int *lastWasTab)
 {
+       if (!(state->flags & TAB_COMPLETION))
+               return;
+
        if (!*lastWasTab) {
                char *tmp, *tmp1;
                int len_found;
@@ -764,13 +753,13 @@ static void input_tab(int *lastWasTab)
 #if ENABLE_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. */
-
-               if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0)
-                       username_tab_completion(matchBuf, NULL);
-               if (!matches)
+               if (state->flags & USERNAME_COMPLETION)
+                       if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0)
+                               username_tab_completion(matchBuf, NULL);
 #endif
                /* Try to match any executable in our path and everything
                 * in the current working directory */
+               if (!matches)
                        exe_n_cwd_tab_completion(matchBuf, find_type);
                /* Sort, then remove any duplicates found */
                if (matches) {
@@ -855,51 +844,48 @@ static void input_tab(int *lastWasTab)
        }
 }
 
+#else
+#define input_tab(a) ((void)0)
 #endif  /* FEATURE_COMMAND_TAB_COMPLETION */
 
 
 #if MAX_HISTORY > 0
 
-static char *history[MAX_HISTORY+1]; /* history + current */
-/* saved history lines */
-static int n_history;
-/* current pointer to history line */
-static int cur_history;
-
+/* state->flags is already checked to be nonzero */
 static void get_previous_history(void)
 {
-       if (command_ps[0] != '\0' || history[cur_history] == NULL) {
-               free(history[cur_history]);
-               history[cur_history] = xstrdup(command_ps);
+       if (command_ps[0] != '\0' || state->history[state->cur_history] == NULL) {
+               free(state->history[state->cur_history]);
+               state->history[state->cur_history] = xstrdup(command_ps);
        }
-       cur_history--;
+       state->cur_history--;
 }
 
 static int get_next_history(void)
 {
-       int ch = cur_history;
-
-       if (ch < n_history) {
-               get_previous_history(); /* save the current history line */
-               cur_history = ch + 1;
-               return cur_history;
-       } else {
-               beep();
-               return 0;
+       if (state->flags & DO_HISTORY) {
+               int ch = state->cur_history;
+               if (ch < state->cnt_history) {
+                       get_previous_history(); /* save the current history line */
+                       state->cur_history = ch + 1;
+                       return state->cur_history;
+               }
        }
+       beep();
+       return 0;
 }
 
 #if ENABLE_FEATURE_COMMAND_SAVEHISTORY
+/* state->flags is already checked to be nonzero */
 void load_history(const char *fromfile)
 {
        FILE *fp;
        int hi;
 
        /* cleanup old */
-
-       for (hi = n_history; hi > 0;) {
+       for (hi = state->cnt_history; hi > 0;) {
                hi--;
-               free(history[hi]);
+               free(state->history[hi]);
        }
 
        fp = fopen(fromfile, "r");
@@ -917,29 +903,62 @@ void load_history(const char *fromfile)
                                free(hl);
                                continue;
                        }
-                       history[hi++] = hl;
+                       state->history[hi++] = hl;
                }
                fclose(fp);
        }
-       cur_history = n_history = hi;
+       state->cur_history = state->cnt_history = hi;
 }
 
+/* state->flags is already checked to be nonzero */
 void save_history(const char *tofile)
 {
-       FILE *fp = fopen(tofile, "w");
+       FILE *fp;
 
+       fp = fopen(tofile, "w");
        if (fp) {
                int i;
 
-               for (i = 0; i < n_history; i++) {
-                       fprintf(fp, "%s\n", history[i]);
+               for (i = 0; i < state->cnt_history; i++) {
+                       fprintf(fp, "%s\n", state->history[i]);
                }
                fclose(fp);
        }
 }
+#else
+#define load_history(a) ((void)0)
+#define save_history(a) ((void)0)
 #endif /* FEATURE_COMMAND_SAVEHISTORY */
 
-#endif /* MAX_HISTORY > 0 */
+static void remember_in_history(const char *str)
+{
+       int i;
+
+       if (!(state->flags & DO_HISTORY))
+               return;
+
+       i = state->cnt_history;
+       free(state->history[MAX_HISTORY]);
+       state->history[MAX_HISTORY] = NULL;
+       /* After max history, remove the oldest command */
+       if (i >= MAX_HISTORY) {
+               free(state->history[0]);
+               for (i = 0; i < MAX_HISTORY-1; i++)
+                       state->history[i] = state->history[i+1];
+       }
+// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..."
+// (i.e. do not save dups?)
+       state->history[i++] = xstrdup(str);
+       state->cur_history = i;
+       state->cnt_history = i;
+       if (state->flags & SAVE_HISTORY)
+               save_history(state->hist_file);
+       USE_FEATURE_SH_FANCY_PROMPT(num_ok_lines++;)
+}
+
+#else /* MAX_HISTORY == 0 */
+#define remember_in_history(a) ((void)0)
+#endif /* MAX_HISTORY */
 
 
 /*
@@ -960,13 +979,6 @@ void save_history(const char *tofile)
  */
 
 #if ENABLE_FEATURE_COMMAND_EDITING_VI
-static int vi_mode;
-
-void setvimode(int viflag)
-{
-       vi_mode = viflag;
-}
-
 static void
 vi_Word_motion(char *command, int eat)
 {
@@ -1058,13 +1070,11 @@ vi_back_motion(char *command)
                        input_backward(1);
        }
 }
-#else
-enum { vi_mode = 0 };
 #endif
 
 
 /*
- * cmdedit_read_input and its helpers
+ * read_line_input and its helpers
  */
 
 #if !ENABLE_FEATURE_SH_FANCY_PROMPT
@@ -1190,7 +1200,7 @@ static void parse_prompt(const char *prmt_ptr)
                        cmdedit_prmt_len += cur_prmt_len;
                prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);
        }
-       if (pwd_buf!=(char *)bb_msg_unknown)
+       if (pwd_buf != (char *)bb_msg_unknown)
                free(pwd_buf);
        cmdedit_prompt = prmt_mem_ptr;
        put_prompt();
@@ -1217,7 +1227,7 @@ static void cmdedit_setwidth(unsigned w, int 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);
+               redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), command_len - cursor);
                fflush(stdout);
        }
 }
@@ -1275,9 +1285,10 @@ static void cmdedit_init(void)
 #undef CTRL
 #define CTRL(a) ((a) & ~0x40)
 
-
-int cmdedit_read_input(char *prompt, char command[BUFSIZ])
+int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *st)
 {
+       static const int null_flags;
+
        int lastWasTab = FALSE;
        unsigned int ic;
        unsigned char c;
@@ -1286,18 +1297,28 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
        smallint vi_cmdmode = 0;
        smalluint prevc;
 #endif
+
+// FIXME: audit & improve this
+       if (maxsize > BUFSIZ)
+               maxsize = BUFSIZ;
+
+       /* With null flags, no other fields are ever used */
+       state = st ? st : (line_input_t*) &null_flags;
+       if (state->flags & SAVE_HISTORY)
+               load_history(state->hist_file);
+
        /* prepare before init handlers */
        cmdedit_y = 0;  /* quasireal y, not true if line > xt*yt */
-       len = 0;
+       command_len = 0;
        command_ps = command;
        command[0] = '\0';
 
        getTermSettings(0, (void *) &initial_settings);
-       memcpy(&new_settings, &initial_settings, sizeof(struct termios));
+       memcpy(&new_settings, &initial_settings, sizeof(new_settings));
        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);
-       /* Hmm, in linux c_cc[] not parsed if set ~ICANON */
+       /* Hmm, in linux c_cc[] is not parsed if ICANON is off */
        new_settings.c_cc[VMIN] = 1;
        new_settings.c_cc[VTIME] = 0;
        /* Turn off CTRL-C, so we can trap it */
@@ -1354,34 +1375,18 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                vi_case(CTRL('C')|vbit:)
                        /* Control-c -- stop gathering input */
                        goto_new_line();
-#if !ENABLE_ASH
-                       command[0] = '\0';
-                       len = 0;
-                       lastWasTab = FALSE;
-                       put_prompt();
-#else
-                       len = 0;
-                       break_out = -1; /* to control traps */
-#endif
+                       command_len = 0;
+                       break_out = -1; /* "do not append '\n'" */
                        break;
                case CTRL('D'):
                        /* Control-d -- Delete one character, or exit
                         * if the len=0 and no chars to delete */
-                       if (len == 0) {
+                       if (command_len == 0) {
                                errno = 0;
  prepare_to_die:
-// So, our API depends on whether we have ash compiled in or not? Crap...
-#if !ENABLE_ASH
-                               printf("exit");
-                               goto_new_line();
-                               /* cmdedit_reset_term() called in atexit */
-// FIXME. this is definitely not good
-                               exit(EXIT_SUCCESS);
-#else
                                /* to control stopped jobs */
-                               break_out = len = -1;
+                               break_out = command_len = -1;
                                break;
-#endif
                        }
                        input_delete(0);
                        break;
@@ -1407,23 +1412,21 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                        break;
 
                case '\t':
-#if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
                        input_tab(&lastWasTab);
-#endif
                        break;
 
 #if ENABLE_FEATURE_EDITING_FANCY_KEYS
                case CTRL('K'):
                        /* Control-k -- clear to end of line */
                        command[cursor] = 0;
-                       len = cursor;
+                       command_len = cursor;
                        printf("\033[J");
                        break;
                case CTRL('L'):
                vi_case(CTRL('L')|vbit:)
                        /* Control-l -- clear screen */
                        printf("\033[H");
-                       redraw(0, len - cursor);
+                       redraw(0, command_len - cursor);
                        break;
 #endif
 
@@ -1439,12 +1442,11 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                vi_case(CTRL('P')|vbit:)
                vi_case('k'|vbit:)
                        /* Control-p -- Get previous command from history */
-                       if (cur_history > 0) {
+                       if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
                                get_previous_history();
                                goto rewrite_line;
-                       } else {
-                               beep();
                        }
+                       beep();
                        break;
 #endif
 
@@ -1454,7 +1456,8 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                        /* Control-U -- Clear line before cursor */
                        if (cursor) {
                                strcpy(command, command + cursor);
-                               redraw(cmdedit_y, len -= cursor);
+                               command_len -= cursor;
+                               redraw(cmdedit_y, command_len);
                        }
                        break;
 #endif
@@ -1571,7 +1574,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                                break;
                        case '$':  /* "d$", "c$" */
                        clear_to_eol:
-                               while (cursor < len)
+                               while (cursor < command_len)
                                        input_delete(1);
                                break;
                        }
@@ -1599,7 +1602,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                case '\x1b': /* ESC */
 
 #if ENABLE_FEATURE_COMMAND_EDITING_VI
-                       if (vi_mode) {
+                       if (state->flags & VI_MODE) {
                                /* ESC: insert mode --> command mode */
                                vi_cmdmode = 1;
                                input_backward(1);
@@ -1634,7 +1637,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
 #if MAX_HISTORY > 0
                        case 'A':
                                /* Up Arrow -- Get previous command from history */
-                               if (cur_history > 0) {
+                               if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
                                        get_previous_history();
                                        goto rewrite_line;
                                }
@@ -1647,9 +1650,9 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
  rewrite_line:
                                /* Rewrite the line with the selected history item */
                                /* change command */
-                               len = strlen(strcpy(command, history[cur_history]));
+                               command_len = strlen(strcpy(command, state->history[state->cur_history]));
                                /* redraw and go to eol (bol, in vi */
-                               redraw(cmdedit_y, vi_mode ? 9999 : 0);
+                               redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
                                break;
 #endif
                        case 'C':
@@ -1700,18 +1703,18 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                        if (!Isprint(c)) /* Skip non-printable characters */
                                break;
 
-                       if (len >= (BUFSIZ - 2))        /* Need to leave space for enter */
+                       if (command_len >= (maxsize - 2))        /* Need to leave space for enter */
                                break;
 
-                       len++;
-                       if (cursor == (len - 1)) {      /* Append if at the end of the line */
+                       command_len++;
+                       if (cursor == (command_len - 1)) {      /* Append if at the end of the line */
                                command[cursor] = c;
                                command[cursor+1] = '\0';
                                cmdedit_set_out_char(' ');
                        } else {                        /* Insert otherwise */
                                int sc = cursor;
 
-                               memmove(command + sc + 1, command + sc, len - sc);
+                               memmove(command + sc + 1, command + sc, command_len - sc);
                                command[sc] = c;
                                sc++;
                                /* rewrite from cursor */
@@ -1728,35 +1731,12 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
                        lastWasTab = FALSE;
        }
 
-#if MAX_HISTORY > 0
-       /* Handle command history log */
-       /* cleanup may be saved current command line */
-       if (len > 0) {
-               int i = n_history;
-
-               free(history[MAX_HISTORY]);
-               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;
-               USE_FEATURE_SH_FANCY_PROMPT(num_ok_lines++;)
-       }
-#else /* MAX_HISTORY == 0 */
-       /* dont put empty line */
-       USE_FEATURE_SH_FANCY_PROMPT(if (len > 0) num_ok_lines++;)
-#endif /* MAX_HISTORY */
+       if (command_len > 0)
+               remember_in_history(command);
 
        if (break_out > 0) {
-               command[len++] = '\n';
-               command[len] = '\0';
+               command[command_len++] = '\n';
+               command[command_len] = '\0';
        }
 
 #if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_COMMAND_TAB_COMPLETION
@@ -1764,11 +1744,29 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
 #endif
 
 #if ENABLE_FEATURE_SH_FANCY_PROMPT
-       free(cmdedit_prompt);
+       free((char*)cmdedit_prompt);
 #endif
        /* restore initial_settings and SIGWINCH handler */
        cmdedit_reset_term();
-       return len;
+       return command_len;
+}
+
+line_input_t *new_line_input_t(int flags)
+{
+       line_input_t *n = xzalloc(sizeof(*n));
+       n->flags = flags;
+       return n;
+}
+
+#else
+
+#undef read_line_input
+int read_line_input(const char* prompt, char* command, int maxsize)
+{
+       fputs(prompt, stdout);
+       fflush(stdout);
+       fgets(command, maxsize, stdin);
+       return strlen(command);
 }
 
 #endif  /* FEATURE_COMMAND_EDITING */
@@ -1801,13 +1799,13 @@ int main(int argc, char **argv)
 #endif
        while (1) {
                int l;
-               l = cmdedit_read_input(prompt, buff);
+               l = read_line_input(prompt, buff);
                if (l <= 0 || buff[l-1] != '\n')
                        break;
                buff[l-1] = 0;
-               printf("*** cmdedit_read_input() returned line =%s=\n", buff);
+               printf("*** read_line_input() returned line =%s=\n", buff);
        }
-       printf("*** cmdedit_read_input() detect ^D\n");
+       printf("*** read_line_input() detect ^D\n");
        return 0;
 }
 
index 4a32cf63ead1f1bd56f375052a569774b380dcc7..7af2f75fbc073b5b6bf686d819f22b39f606769f 100644 (file)
@@ -1,20 +1 @@
-/* vi: set sw=4 ts=4: */
-#ifndef CMDEDIT_H
-#define CMDEDIT_H
-
-int cmdedit_read_input(char* promptStr, char* command);
-
-#if ENABLE_ASH
-extern const char *cmdedit_path_lookup;
-#endif
-
-#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
-void load_history(const char *fromfile);
-void save_history(const char *tofile);
-#endif
-
-#if ENABLE_FEATURE_COMMAND_EDITING_VI
-void setvimode(int viflag);
-#endif
-
-#endif /* CMDEDIT_H */
+/* TO DELETE */
index 8f2dc80f2e1ed56d74247f293d2c8a23047eacb2..2c88238ae269cb9477c0db79e0c53b7305c91d31 100644 (file)
@@ -98,7 +98,6 @@
 /* #include <dmalloc.h> */
 /* #define DEBUG_SHELL */
 
-#include "cmdedit.h"
 
 #define SPECIAL_VAR_SYMBOL 03
 #define FLAG_EXIT_FROM_LOOP 1
@@ -883,20 +882,24 @@ static void setup_prompt_string(int promptmode, char **prompt_str)
        debug_printf("result %s\n",*prompt_str);
 }
 
+#if ENABLE_FEATURE_COMMAND_EDITING
+static line_input_t *line_input_state;
+#endif
+
 static void get_user_input(struct in_str *i)
 {
        char *prompt_str;
        static char the_command[BUFSIZ];
 
        setup_prompt_string(i->promptmode, &prompt_str);
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
        /*
         ** enable command line editing only while a command line
         ** is actually being read; otherwise, we'll end up bequeathing
         ** atexit() handlers and other unwanted stuff to our
         ** child processes (rob@sysgo.de)
         */
-       cmdedit_read_input(prompt_str, the_command);
+       read_line_input(prompt_str, the_command, BUFSIZ, line_input_state);
 #else
        fputs(prompt_str, stdout);
        fflush(stdout);
@@ -2647,6 +2650,10 @@ int hush_main(int argc, char **argv)
        FILE *input;
        char **e = environ;
 
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+       line_input_state = new_line_input_t(FOR_SHELL);
+#endif
+
        /* XXX what should these be while sourcing /etc/profile? */
        global_argc = argc;
        global_argv = argv;
index b2ccaf0a11a88078ff8e48d100b6157e99954c06..a09a9a9b1c889b9d9b60809b410b6d1265e434d0 100644 (file)
@@ -23,8 +23,6 @@
 
 #include "busybox.h"
 #include <getopt.h>
-#include "cmdedit.h"
-
 #include <glob.h>
 #define expand_t       glob_t
 
@@ -641,6 +639,10 @@ static inline void setup_prompt_string(char **prompt_str)
 #endif
 }
 
+#if ENABLE_FEATURE_COMMAND_EDITING
+static line_input_t *line_input_state;
+#endif
+
 static int get_command(FILE * source, char *command)
 {
        char *prompt_str;
@@ -659,14 +661,14 @@ static int get_command(FILE * source, char *command)
        if (source == stdin) {
                setup_prompt_string(&prompt_str);
 
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
                /*
                ** enable command line editing only while a command line
                ** is actually being read; otherwise, we'll end up bequeathing
                ** atexit() handlers and other unwanted stuff to our
                ** child processes (rob@sysgo.de)
                */
-               cmdedit_read_input(prompt_str, command);
+               read_line_input(prompt_str, command, BUFSIZ, line_input_state);
                return 0;
 #else
                fputs(prompt_str, stdout);
@@ -1505,6 +1507,10 @@ int lash_main(int argc_l, char **argv_l)
        argc = argc_l;
        argv = argv_l;
 
+#if ENABLE_FEATURE_COMMAND_EDITING
+       line_input_state = new_line_input_t(FOR_SHELL);
+#endif
+
        /* These variables need re-initializing when recursing */
        last_jobid = 0;
        close_me_list = NULL;
index c88308f8f87bb9038f922f1a23579cb0766399d3..8746e42bcea8023049efe49c444d98d48d8c6054 100644 (file)
@@ -17,7 +17,6 @@
 #include <setjmp.h>
 #include <sys/times.h>
 
-#include "cmdedit.h"
 
 /*#define MSHDEBUG 1*/
 
@@ -777,7 +776,7 @@ void print_tree(struct op *head)
 #endif                                                 /* MSHDEBUG */
 
 
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
 static char *current_prompt;
 #endif
 
@@ -787,6 +786,10 @@ static char *current_prompt;
  */
 
 
+#if ENABLE_FEATURE_COMMAND_EDITING
+static line_input_t *line_input_state;
+#endif
+
 int msh_main(int argc, char **argv)
 {
        int f;
@@ -795,6 +798,10 @@ int msh_main(int argc, char **argv)
        char *name, **ap;
        int (*iof) (struct ioarg *);
 
+#if ENABLE_FEATURE_COMMAND_EDITING
+       line_input_state = new_line_input_t(FOR_SHELL);
+#endif
+
        DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
 
        initarea();
@@ -964,7 +971,7 @@ int msh_main(int argc, char **argv)
 
        for (;;) {
                if (interactive && e.iop <= iostack) {
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
                        current_prompt = prompt->value;
 #else
                        prs(prompt->value);
@@ -2371,7 +2378,7 @@ static int yylex(int cf)
                startl = 1;
                if (multiline || cf & CONTIN) {
                        if (interactive && e.iop <= iostack) {
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
                                current_prompt = cprompt->value;
 #else
                                prs(cprompt->value);
@@ -2432,7 +2439,7 @@ static int collect(int c, int c1)
                        return YYERRCODE;
                }
                if (interactive && c == '\n' && e.iop <= iostack) {
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
                        current_prompt = cprompt->value;
 #else
                        prs(cprompt->value);
@@ -4666,7 +4673,7 @@ static int readc(void)
                                        return e.iop->prev = 0;
                                }
                                if (interactive && e.iop == iostack + 1) {
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
                                        current_prompt = prompt->value;
 #else
                                        prs(prompt->value);
@@ -4898,13 +4905,13 @@ static int filechar(struct ioarg *ap)
                ap->afpos++;
                return *bp->bufp++ & 0177;
        }
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
        if (interactive && isatty(ap->afile)) {
                static char mycommand[BUFSIZ];
                static int position = 0, size = 0;
 
                while (size == 0 || position >= size) {
-                       cmdedit_read_input(current_prompt, mycommand);
+                       read_line_input(current_prompt, mycommand, BUFSIZ, line_input_state);
                        size = strlen(mycommand);
                        position = 0;
                }
@@ -4913,7 +4920,6 @@ static int filechar(struct ioarg *ap)
                return c;
        } else
 #endif
-
        {
                i = safe_read(ap->afile, &c, sizeof(c));
                return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
@@ -5150,7 +5156,7 @@ static void readhere(char **name, char *s, int ec)
                e.iobase = e.iop;
                for (;;) {
                        if (interactive && e.iop <= iostack) {
-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#if ENABLE_FEATURE_COMMAND_EDITING
                                current_prompt = cprompt->value;
 #else
                                prs(cprompt->value);
index cc6dfa57a034cf7ccd0c6598b0685a6a884b1f5f..f15b9af919daf92120b4838405cb3672fd26ab4e 100644 (file)
@@ -202,7 +202,7 @@ static int get_boot(enum action what);
                        })
 
 
-#define LINE_LENGTH     800
+#define LINE_LENGTH     80
 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
                                (n) * sizeof(struct partition)))
 #define sector(s)       ((s) & 0x3f)
@@ -291,16 +291,20 @@ write_part_table_flag(char *b)
 static char line_buffer[LINE_LENGTH];
 static char *line_ptr;
 
-/* read line; return 0 or first char */
+/* read line; return 0 or first printable char */
 static int
-read_line(void)
+read_line(const char *prompt)
 {
-       fflush(stdout);         /* requested by niles@scyld.com */
+       int sz;
+
+       sz = read_line_input(prompt, line_buffer, LINE_LENGTH, NULL);
+       if (sz <= 0)
+               exit(0); /* Ctrl-D or Ctrl-C */
+
+       if (line_buffer[sz-1] == '\n')
+               line_buffer[--sz] = '\0';
+
        line_ptr = line_buffer;
-       if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
-               /* error or eof */
-               bb_error_msg_and_die("\ngot EOF, exiting");
-       }
        while (*line_ptr && !isgraph(*line_ptr))
                line_ptr++;
        return *line_ptr;
@@ -309,22 +313,19 @@ read_line(void)
 static char
 read_nonempty(const char *mesg)
 {
-       do {
-               fputs(mesg, stdout);
-       } while (!read_line());
+       while (!read_line(mesg)) /* repeat */;
        return *line_ptr;
 }
 
 static char
 read_maybe_empty(const char *mesg)
 {
-       fputs(mesg, stdout);
-       if (!read_line()) {
+       if (!read_line(mesg)) {
                line_ptr = line_buffer;
-               *line_ptr = '\n';
-               line_ptr[1] = 0;
+               line_ptr[0] = '\n';
+               line_ptr[1] = '\0';
        }
-       return *line_ptr;
+       return line_ptr[0];
 }
 
 static int
@@ -469,9 +470,9 @@ static const struct systypes i386_sys_types[] = {
        { "\x16" "Hidden FAT16" },
        { "\x17" "Hidden HPFS/NTFS" },
        { "\x1b" "Hidden Win95 FAT32" },
-       { "\x1c" "Hidden Win95 FAT32 (LBA)" },
-       { "\x1e" "Hidden Win95 FAT16 (LBA)" },
-       { "\x3c" "PartitionMagic recovery" },
+       { "\x1c" "Hidden W95 FAT32 (LBA)" },
+       { "\x1e" "Hidden W95 FAT16 (LBA)" },
+       { "\x3c" "Part.Magic recovery" },
        { "\x41" "PPC PReP Boot" },
        { "\x42" "SFS" },
        { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
@@ -485,7 +486,7 @@ static const struct systypes i386_sys_types[] = {
        { "\x87" "NTFS volume set" },
        { "\x8e" "Linux LVM" },
        { "\x9f" "BSD/OS" },           /* BSDI */
-       { "\xa0" "IBM Thinkpad hibernation" },
+       { "\xa0" "Thinkpad hibernation" },
        { "\xa5" "FreeBSD" },          /* various BSD flavours */
        { "\xa6" "OpenBSD" },
        { "\xa8" "Darwin UFS" },
@@ -718,71 +719,61 @@ is_dos_partition(int t)
 static void
 menu(void)
 {
+       puts(_("Command Action"));
        if (LABEL_IS_SUN) {
-               puts(_("Command action"));
-               puts(_("\ta\ttoggle a read only flag"));           /* sun */
-               puts(_("\tb\tedit bsd disklabel"));
-               puts(_("\tc\ttoggle the mountable flag"));         /* sun */
-               puts(_("\td\tdelete a partition"));
-               puts(_("\tl\tlist known partition types"));
-               puts(_("\tm\tprint this menu"));
-               puts(_("\tn\tadd a new partition"));
-               puts(_("\to\tcreate a new empty DOS partition table"));
-               puts(_("\tp\tprint the partition table"));
-               puts(_("\tq\tquit without saving changes"));
-               puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
-               puts(_("\tt\tchange a partition's system id"));
-               puts(_("\tu\tchange display/entry units"));
-               puts(_("\tv\tverify the partition table"));
-               puts(_("\tw\twrite table to disk and exit"));
+               puts(_("a\ttoggle a read only flag"));           /* sun */
+               puts(_("b\tedit bsd disklabel"));
+               puts(_("c\ttoggle the mountable flag"));         /* sun */
+               puts(_("d\tdelete a partition"));
+               puts(_("l\tlist known partition types"));
+               puts(_("n\tadd a new partition"));
+               puts(_("o\tcreate a new empty DOS partition table"));
+               puts(_("p\tprint the partition table"));
+               puts(_("q\tquit without saving changes"));
+               puts(_("s\tcreate a new empty Sun disklabel"));  /* sun */
+               puts(_("t\tchange a partition's system id"));
+               puts(_("u\tchange display/entry units"));
+               puts(_("v\tverify the partition table"));
+               puts(_("w\twrite table to disk and exit"));
 #if ENABLE_FEATURE_FDISK_ADVANCED
-               puts(_("\tx\textra functionality (experts only)"));
+               puts(_("x\textra functionality (experts only)"));
 #endif
-       } else
-       if (LABEL_IS_SGI) {
-               puts(_("Command action"));
-               puts(_("\ta\tselect bootable partition"));    /* sgi flavour */
-               puts(_("\tb\tedit bootfile entry"));          /* sgi */
-               puts(_("\tc\tselect sgi swap partition"));    /* sgi flavour */
-               puts(_("\td\tdelete a partition"));
-               puts(_("\tl\tlist known partition types"));
-               puts(_("\tm\tprint this menu"));
-               puts(_("\tn\tadd a new partition"));
-               puts(_("\to\tcreate a new empty DOS partition table"));
-               puts(_("\tp\tprint the partition table"));
-               puts(_("\tq\tquit without saving changes"));
-               puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
-               puts(_("\tt\tchange a partition's system id"));
-               puts(_("\tu\tchange display/entry units"));
-               puts(_("\tv\tverify the partition table"));
-               puts(_("\tw\twrite table to disk and exit"));
-       } else
-       if (LABEL_IS_AIX) {
-               puts(_("Command action"));
-               puts(_("\tm\tprint this menu"));
-               puts(_("\to\tcreate a new empty DOS partition table"));
-               puts(_("\tq\tquit without saving changes"));
-               puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
-       } else
-       {
-               puts(_("Command action"));
-               puts(_("\ta\ttoggle a bootable flag"));
-               puts(_("\tb\tedit bsd disklabel"));
-               puts(_("\tc\ttoggle the dos compatibility flag"));
-               puts(_("\td\tdelete a partition"));
-               puts(_("\tl\tlist known partition types"));
-               puts(_("\tm\tprint this menu"));
-               puts(_("\tn\tadd a new partition"));
-               puts(_("\to\tcreate a new empty DOS partition table"));
-               puts(_("\tp\tprint the partition table"));
-               puts(_("\tq\tquit without saving changes"));
-               puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
-               puts(_("\tt\tchange a partition's system id"));
-               puts(_("\tu\tchange display/entry units"));
-               puts(_("\tv\tverify the partition table"));
-               puts(_("\tw\twrite table to disk and exit"));
+       } else if (LABEL_IS_SGI) {
+               puts(_("a\tselect bootable partition"));    /* sgi flavour */
+               puts(_("b\tedit bootfile entry"));          /* sgi */
+               puts(_("c\tselect sgi swap partition"));    /* sgi flavour */
+               puts(_("d\tdelete a partition"));
+               puts(_("l\tlist known partition types"));
+               puts(_("n\tadd a new partition"));
+               puts(_("o\tcreate a new empty DOS partition table"));
+               puts(_("p\tprint the partition table"));
+               puts(_("q\tquit without saving changes"));
+               puts(_("s\tcreate a new empty Sun disklabel"));  /* sun */
+               puts(_("t\tchange a partition's system id"));
+               puts(_("u\tchange display/entry units"));
+               puts(_("v\tverify the partition table"));
+               puts(_("w\twrite table to disk and exit"));
+       } else if (LABEL_IS_AIX) {
+               puts(_("o\tcreate a new empty DOS partition table"));
+               puts(_("q\tquit without saving changes"));
+               puts(_("s\tcreate a new empty Sun disklabel"));  /* sun */
+       } else {
+               puts(_("a\ttoggle a bootable flag"));
+               puts(_("b\tedit bsd disklabel"));
+               puts(_("c\ttoggle the dos compatibility flag"));
+               puts(_("d\tdelete a partition"));
+               puts(_("l\tlist known partition types"));
+               puts(_("n\tadd a new partition"));
+               puts(_("o\tcreate a new empty DOS partition table"));
+               puts(_("p\tprint the partition table"));
+               puts(_("q\tquit without saving changes"));
+               puts(_("s\tcreate a new empty Sun disklabel"));  /* sun */
+               puts(_("t\tchange a partition's system id"));
+               puts(_("u\tchange display/entry units"));
+               puts(_("v\tverify the partition table"));
+               puts(_("w\twrite table to disk and exit"));
 #if ENABLE_FEATURE_FDISK_ADVANCED
-               puts(_("\tx\textra functionality (experts only)"));
+               puts(_("x\textra functionality (experts only)"));
 #endif
        }
 }
@@ -793,73 +784,64 @@ menu(void)
 static void
 xmenu(void)
 {
+       puts(_("Command Action"));
        if (LABEL_IS_SUN) {
-               puts(_("Command action"));
-               puts(_("\ta\tchange number of alternate cylinders"));      /*sun*/
-               puts(_("\tc\tchange number of cylinders"));
-               puts(_("\td\tprint the raw data in the partition table"));
-               puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
-               puts(_("\th\tchange number of heads"));
-               puts(_("\ti\tchange interleave factor"));                  /*sun*/
-               puts(_("\to\tchange rotation speed (rpm)"));               /*sun*/
-               puts(_("\tm\tprint this menu"));
-               puts(_("\tp\tprint the partition table"));
-               puts(_("\tq\tquit without saving changes"));
-               puts(_("\tr\treturn to main menu"));
-               puts(_("\ts\tchange number of sectors/track"));
-               puts(_("\tv\tverify the partition table"));
-               puts(_("\tw\twrite table to disk and exit"));
-               puts(_("\ty\tchange number of physical cylinders"));       /*sun*/
-       }  else
-       if (LABEL_IS_SGI) {
-               puts(_("Command action"));
-               puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
-               puts(_("\tc\tchange number of cylinders"));
-               puts(_("\td\tprint the raw data in the partition table"));
-               puts(_("\te\tlist extended partitions"));          /* !sun */
-               puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
-               puts(_("\th\tchange number of heads"));
-               puts(_("\tm\tprint this menu"));
-               puts(_("\tp\tprint the partition table"));
-               puts(_("\tq\tquit without saving changes"));
-               puts(_("\tr\treturn to main menu"));
-               puts(_("\ts\tchange number of sectors/track"));
-               puts(_("\tv\tverify the partition table"));
-               puts(_("\tw\twrite table to disk and exit"));
-       } else
-       if (LABEL_IS_AIX) {
-               puts(_("Command action"));
-               puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
-               puts(_("\tc\tchange number of cylinders"));
-               puts(_("\td\tprint the raw data in the partition table"));
-               puts(_("\te\tlist extended partitions"));          /* !sun */
-               puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
-               puts(_("\th\tchange number of heads"));
-               puts(_("\tm\tprint this menu"));
-               puts(_("\tp\tprint the partition table"));
-               puts(_("\tq\tquit without saving changes"));
-               puts(_("\tr\treturn to main menu"));
-               puts(_("\ts\tchange number of sectors/track"));
-               puts(_("\tv\tverify the partition table"));
-               puts(_("\tw\twrite table to disk and exit"));
-       }  else {
-               puts(_("Command action"));
-               puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
-               puts(_("\tc\tchange number of cylinders"));
-               puts(_("\td\tprint the raw data in the partition table"));
-               puts(_("\te\tlist extended partitions"));          /* !sun */
-               puts(_("\tf\tfix partition order"));               /* !sun, !aix, !sgi */
+               puts(_("a\tchange number of alternate cylinders"));      /*sun*/
+               puts(_("c\tchange number of cylinders"));
+               puts(_("d\tprint the raw data in the partition table"));
+               puts(_("e\tchange number of extra sectors per cylinder"));/*sun*/
+               puts(_("h\tchange number of heads"));
+               puts(_("i\tchange interleave factor"));                  /*sun*/
+               puts(_("o\tchange rotation speed (rpm)"));               /*sun*/
+               puts(_("p\tprint the partition table"));
+               puts(_("q\tquit without saving changes"));
+               puts(_("r\treturn to main menu"));
+               puts(_("s\tchange number of sectors/track"));
+               puts(_("v\tverify the partition table"));
+               puts(_("w\twrite table to disk and exit"));
+               puts(_("y\tchange number of physical cylinders"));       /*sun*/
+       } else if (LABEL_IS_SGI) {
+               puts(_("b\tmove beginning of data in a partition")); /* !sun */
+               puts(_("c\tchange number of cylinders"));
+               puts(_("d\tprint the raw data in the partition table"));
+               puts(_("e\tlist extended partitions"));          /* !sun */
+               puts(_("g\tcreate an IRIX (SGI) partition table"));/* sgi */
+               puts(_("h\tchange number of heads"));
+               puts(_("p\tprint the partition table"));
+               puts(_("q\tquit without saving changes"));
+               puts(_("r\treturn to main menu"));
+               puts(_("s\tchange number of sectors/track"));
+               puts(_("v\tverify the partition table"));
+               puts(_("w\twrite table to disk and exit"));
+       } else if (LABEL_IS_AIX) {
+               puts(_("b\tmove beginning of data in a partition")); /* !sun */
+               puts(_("c\tchange number of cylinders"));
+               puts(_("d\tprint the raw data in the partition table"));
+               puts(_("e\tlist extended partitions"));          /* !sun */
+               puts(_("g\tcreate an IRIX (SGI) partition table"));/* sgi */
+               puts(_("h\tchange number of heads"));
+               puts(_("p\tprint the partition table"));
+               puts(_("q\tquit without saving changes"));
+               puts(_("r\treturn to main menu"));
+               puts(_("s\tchange number of sectors/track"));
+               puts(_("v\tverify the partition table"));
+               puts(_("w\twrite table to disk and exit"));
+       } else {
+               puts(_("b\tmove beginning of data in a partition")); /* !sun */
+               puts(_("c\tchange number of cylinders"));
+               puts(_("d\tprint the raw data in the partition table"));
+               puts(_("e\tlist extended partitions"));          /* !sun */
+               puts(_("f\tfix partition order"));               /* !sun, !aix, !sgi */
 #if ENABLE_FEATURE_SGI_LABEL
-               puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
+               puts(_("g\tcreate an IRIX (SGI) partition table"));/* sgi */
 #endif
-               puts(_("\th\tchange number of heads"));
-               puts(_("\tm\tprint this menu"));
-               puts(_("\tp\tprint the partition table"));
-               puts(_("\tq\tquit without saving changes"));
-               puts(_("\tr\treturn to main menu"));
-               puts(_("\ts\tchange number of sectors/track"));
-               puts(_("\tv\tverify the partition table"));
-               puts(_("\tw\twrite table to disk and exit"));
+               puts(_("h\tchange number of heads"));
+               puts(_("p\tprint the partition table"));
+               puts(_("q\tquit without saving changes"));
+               puts(_("r\treturn to main menu"));
+               puts(_("s\tchange number of sectors/track"));
+               puts(_("v\tverify the partition table"));
+               puts(_("w\twrite table to disk and exit"));
        }
 }
 #endif /* ADVANCED mode */
@@ -883,7 +865,7 @@ static const char *partition_type(unsigned char type)
        const struct systypes *types = get_sys_types();
 
        for (i = 0; types[i].name; i++)
-               if ((unsigned char )types[i].name[0] == type)
+               if ((unsigned char)types[i].name[0] == type)
                        return types[i].name + 1;
 
        return _("Unknown");
@@ -899,24 +881,29 @@ get_sysid(int i)
                                ptes[i].part_table->sys_ind);
 }
 
-void list_types(const struct systypes *sys)
+static void list_types(const struct systypes *sys)
 {
-       unsigned last[4], done = 0, next = 0, size;
+       enum { COLS = 3 };
+
+       unsigned last[COLS];
+       unsigned done, next, size;
        int i;
 
-       for (i = 0; sys[i].name; i++);
-       size = i;
+       for (size = 0; sys[size].name; size++) /* */;
 
-       for (i = 3; i >= 0; i--)
-               last[3 - i] = done += (size + i - done) / (i + 1);
-       i = done = 0;
+       done = 0;
+       for (i = COLS-1; i >= 0; i--) {
+               done += (size + i - done) / (i + 1);
+               last[COLS-1 - i] = done;
+       }
 
+       i = done = next = 0;
        do {
-               printf("%c%2x  %-15.15s", i ? ' ' : '\n',
+               printf("%c%2x %-22.22s", i ? ' ' : '\n',
                        (unsigned char)sys[next].name[0],
-                       partition_type((unsigned char)sys[next].name[0]));
+                       sys[next].name + 1);
                next = last[i++] + done;
-               if (i > 3 || next >= last[i]) {
+               if (i >= COLS || next >= last[i]) {
                        i = 0;
                        next = ++done;
                }
@@ -2415,10 +2402,12 @@ new_partition(void)
                                 "an extended partition first\n"));
        } else {
                char c, line[LINE_LENGTH];
-               snprintf(line, sizeof(line), "%s\n   %s\n   p   primary "
-                                               "partition (1-4)\n",
-                        "Command action", (extended_offset ?
-                        "l   logical (5 or over)" : "e   extended"));
+               snprintf(line, sizeof(line),
+                       "Command action\n"
+                       "   %s\n"
+                       "   p   primary partition (1-4)\n",
+                       (extended_offset ?
+                       "l   logical (5 or over)" : "e   extended"));
                while (1) {
                        c = read_nonempty(line);
                        if (c == 'p' || c == 'P') {
index 16a046ea36bc3cd3c7a32212d6cb3072226963f0..3f56bd27d62ec9f7a89e5146d22e6b22d13b9b97 100644 (file)
@@ -308,22 +308,21 @@ bsd_trydev(const char * dev)
 static void
 bsd_menu(void)
 {
-       puts(_("Command action"));
-       puts(_("\td\tdelete a BSD partition"));
-       puts(_("\te\tedit drive data"));
-       puts(_("\ti\tinstall bootstrap"));
-       puts(_("\tl\tlist known filesystem types"));
-       puts(_("\tm\tprint this menu"));
-       puts(_("\tn\tadd a new BSD partition"));
-       puts(_("\tp\tprint BSD partition table"));
-       puts(_("\tq\tquit without saving changes"));
-       puts(_("\tr\treturn to main menu"));
-       puts(_("\ts\tshow complete disklabel"));
-       puts(_("\tt\tchange a partition's filesystem id"));
-       puts(_("\tu\tchange units (cylinders/sectors)"));
-       puts(_("\tw\twrite disklabel to disk"));
+       puts(_("Command Action"));
+       puts(_("d\tdelete a BSD partition"));
+       puts(_("e\tedit drive data"));
+       puts(_("i\tinstall bootstrap"));
+       puts(_("l\tlist known filesystem types"));
+       puts(_("n\tadd a new BSD partition"));
+       puts(_("p\tprint BSD partition table"));
+       puts(_("q\tquit without saving changes"));
+       puts(_("r\treturn to main menu"));
+       puts(_("s\tshow complete disklabel"));
+       puts(_("t\tchange a partition's filesystem id"));
+       puts(_("u\tchange units (cylinders/sectors)"));
+       puts(_("w\twrite disklabel to disk"));
 #if !defined(__alpha__)
-       puts(_("\tx\tlink BSD partition to non-BSD partition"));
+       puts(_("x\tlink BSD partition to non-BSD partition"));
 #endif
 }
 
@@ -633,13 +632,15 @@ xbsd_create_disklabel(void)
 static int
 edit_int(int def, char *mesg)
 {
+       mesg = xasprintf("%s (%d): ", mesg, def);
        do {
-               fputs(mesg, stdout);
-               printf(" (%d): ", def);
-               if (!read_line())
-                       return def;
+               if (!read_line(mesg))
+                       goto ret;
        } while (!isdigit(*line_ptr));
-       return atoi(line_ptr);
+       def = atoi(line_ptr);
+ ret:
+       free(mesg);
+       return def;
 }
 
 static void
@@ -718,10 +719,9 @@ xbsd_write_bootstrap(void)
        else
                dkbasename = "wd";
 
-       printf(_("Bootstrap: %sboot -> boot%s (%s): "),
+       snprintf(path, sizeof(path), "Bootstrap: %sboot -> boot%s (%s): ",
                dkbasename, dkbasename, dkbasename);
-       if (read_line()) {
-               line_ptr[strlen(line_ptr)-1] = '\0';
+       if (read_line(path)) {
                dkbasename = line_ptr;
        }
        snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);