From 8e1c71529c2bf38a04d4a117e625e59044a0785a Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 22 Jan 2007 07:21:38 +0000 Subject: [PATCH] Convert cmdedit into more generic line input facility (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 | 36 +++++ shell/Kbuild | 10 +- shell/ash.c | 106 +++++++------- shell/cmdedit.c | 316 ++++++++++++++++++++--------------------- shell/cmdedit.h | 21 +-- shell/hush.c | 13 +- shell/lash.c | 14 +- shell/msh.c | 26 ++-- util-linux/fdisk.c | 309 +++++++++++++++++++--------------------- util-linux/fdisk_osf.c | 46 +++--- 10 files changed, 459 insertions(+), 438 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 0b066d1bd..f990b0ebd 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -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 }; diff --git a/shell/Kbuild b/shell/Kbuild index eb0199ee2..9c60698f7 100644 --- a/shell/Kbuild +++ b/shell/Kbuild @@ -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 diff --git a/shell/ash.c b/shell/ash.c index 2db3302c7..8afdf3d21 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -92,7 +92,6 @@ #include #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; diff --git a/shell/cmdedit.c b/shell/cmdedit.c index a1432af15..554a4ebec 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c @@ -30,7 +30,6 @@ #include #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 @@ -61,29 +59,21 @@ #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= or PATH=: */ 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; /* : */ + 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; /* : */ - (*p)[npth++] = &(*p)[0][(tmp - pth)]; /* p[next]=p[0][&'\0'+1] */ + *tmp++ = '\0'; /* ':' -> '\0' */ + if (*tmp == '\0') + break; /* : */ + 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; } diff --git a/shell/cmdedit.h b/shell/cmdedit.h index 4a32cf63e..7af2f75fb 100644 --- a/shell/cmdedit.h +++ b/shell/cmdedit.h @@ -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 */ diff --git a/shell/hush.c b/shell/hush.c index 8f2dc80f2..2c88238ae 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -98,7 +98,6 @@ /* #include */ /* #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; diff --git a/shell/lash.c b/shell/lash.c index b2ccaf0a1..a09a9a9b1 100644 --- a/shell/lash.c +++ b/shell/lash.c @@ -23,8 +23,6 @@ #include "busybox.h" #include -#include "cmdedit.h" - #include #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; diff --git a/shell/msh.c b/shell/msh.c index c88308f8f..8746e42bc 100644 --- a/shell/msh.c +++ b/shell/msh.c @@ -17,7 +17,6 @@ #include #include -#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); diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index cc6dfa57a..f15b9af91 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -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') { diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c index 16a046ea3..3f56bd27d 100644 --- a/util-linux/fdisk_osf.c +++ b/util-linux/fdisk_osf.c @@ -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); -- 2.25.1