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.
This commit is contained in:
Denis Vlasenko 2007-01-22 07:21:38 +00:00
parent 00cdbd8fc2
commit 8e1c71529c
10 changed files with 459 additions and 438 deletions

View 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 };

View 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

View 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;

View 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
@ -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=<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;
}

View 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 */

View 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;

View 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;

View 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);

View 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') {

View 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);