aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libbb.h36
-rw-r--r--shell/Kbuild10
-rw-r--r--shell/ash.c106
-rw-r--r--shell/cmdedit.c316
-rw-r--r--shell/cmdedit.h21
-rw-r--r--shell/hush.c13
-rw-r--r--shell/lash.c14
-rw-r--r--shell/msh.c26
-rw-r--r--util-linux/fdisk.c309
-rw-r--r--util-linux/fdisk_osf.c46
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);
583#endif 583#endif
584 584
585 585
586#if ENABLE_FEATURE_COMMAND_EDITING
587/* It's NOT just ENABLEd or disabled. It's a number: */
588#ifdef CONFIG_FEATURE_COMMAND_HISTORY
589#define MAX_HISTORY (CONFIG_FEATURE_COMMAND_HISTORY + 0)
590#else
591#define MAX_HISTORY 0
592#endif
593struct line_input_t {
594 int flags;
595 const char *path_lookup;
596#if MAX_HISTORY
597 int cnt_history;
598 int cur_history;
599 USE_FEATURE_COMMAND_SAVEHISTORY(const char *hist_file;)
600 char *history[MAX_HISTORY + 1];
601#endif
602};
603enum {
604 DO_HISTORY = 1 * (MAX_HISTORY > 0),
605 SAVE_HISTORY = 2 * (MAX_HISTORY > 0) * ENABLE_FEATURE_COMMAND_SAVEHISTORY,
606 TAB_COMPLETION = 4 * ENABLE_FEATURE_COMMAND_TAB_COMPLETION,
607 USERNAME_COMPLETION = 8 * ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION,
608 VI_MODE = 0x10 * ENABLE_FEATURE_COMMAND_EDITING_VI,
609 WITH_PATH_LOOKUP = 0x20,
610 FOR_SHELL = DO_HISTORY | SAVE_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION,
611};
612typedef struct line_input_t line_input_t;
613line_input_t *new_line_input_t(int flags);
614int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state);
615#else
616int read_line_input(const char* prompt, char* command, int maxsize);
617#define read_line_input(prompt, command, maxsize, state) \
618 read_line_input(prompt, command, maxsize)
619#endif
620
621
586#ifndef COMM_LEN 622#ifndef COMM_LEN
587#ifdef TASK_COMM_LEN 623#ifdef TASK_COMM_LEN
588enum { COMM_LEN = TASK_COMM_LEN }; 624enum { 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 @@
5# Licensed under the GPL v2, see the file LICENSE in this tarball. 5# Licensed under the GPL v2, see the file LICENSE in this tarball.
6 6
7lib-y:= 7lib-y:=
8lib-$(CONFIG_ASH) += ash.o 8lib-y += cmdedit.o
9lib-$(CONFIG_HUSH) += hush.o 9lib-$(CONFIG_ASH) += ash.o
10lib-$(CONFIG_LASH) += lash.o 10lib-$(CONFIG_HUSH) += hush.o
11lib-$(CONFIG_MSH) += msh.o 11lib-$(CONFIG_LASH) += lash.o
12lib-$(CONFIG_FEATURE_COMMAND_EDITING) += cmdedit.o 12lib-$(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 @@
92#include <termios.h> 92#include <termios.h>
93#endif 93#endif
94 94
95#include "cmdedit.h"
96 95
97#ifdef __GLIBC__ 96#ifdef __GLIBC__
98/* glibc sucks */ 97/* glibc sucks */
@@ -1238,7 +1237,7 @@ static int fgcmd(int, char **);
1238static int getoptscmd(int, char **); 1237static int getoptscmd(int, char **);
1239#endif 1238#endif
1240static int hashcmd(int, char **); 1239static int hashcmd(int, char **);
1241#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 1240#if !ENABLE_FEATURE_SH_EXTRA_QUIET
1242static int helpcmd(int argc, char **argv); 1241static int helpcmd(int argc, char **argv);
1243#endif 1242#endif
1244#if JOBS 1243#if JOBS
@@ -1347,7 +1346,7 @@ static const struct builtincmd builtincmd[] = {
1347 { BUILTIN_REGULAR "getopts", getoptscmd }, 1346 { BUILTIN_REGULAR "getopts", getoptscmd },
1348#endif 1347#endif
1349 { BUILTIN_NOSPEC "hash", hashcmd }, 1348 { BUILTIN_NOSPEC "hash", hashcmd },
1350#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 1349#if !ENABLE_FEATURE_SH_EXTRA_QUIET
1351 { BUILTIN_NOSPEC "help", helpcmd }, 1350 { BUILTIN_NOSPEC "help", helpcmd },
1352#endif 1351#endif
1353#if JOBS 1352#if JOBS
@@ -1529,7 +1528,7 @@ static struct var varinit[] = {
1529 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all }, 1528 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1530 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype }, 1529 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1531#endif 1530#endif
1532#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY 1531#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
1533 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL }, 1532 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1534#endif 1533#endif
1535}; 1534};
@@ -1934,10 +1933,6 @@ struct shparam {
1934#define debug optlist[15] 1933#define debug optlist[15]
1935#endif 1934#endif
1936 1935
1937#ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1938#define setvimode(on) viflag = 0 /* forcibly keep the option off */
1939#endif
1940
1941/* options.c */ 1936/* options.c */
1942 1937
1943 1938
@@ -3718,7 +3713,7 @@ shellexec(char **argv, const char *path, int idx)
3718 clearredir(1); 3713 clearredir(1);
3719 envp = environment(); 3714 envp = environment();
3720 if (strchr(argv[0], '/') || is_safe_applet(argv[0]) 3715 if (strchr(argv[0], '/') || is_safe_applet(argv[0])
3721#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL 3716#if ENABLE_FEATURE_SH_STANDALONE_SHELL
3722 || find_applet_by_name(argv[0]) 3717 || find_applet_by_name(argv[0])
3723#endif 3718#endif
3724 ) { 3719 ) {
@@ -3775,7 +3770,7 @@ tryexec(char *cmd, char **argv, char **envp)
3775 applet_name = cmd; 3770 applet_name = cmd;
3776 exit(a->main(argc, argv)); 3771 exit(a->main(argc, argv));
3777 } 3772 }
3778#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL 3773#if ENABLE_FEATURE_SH_STANDALONE_SHELL
3779 if (find_applet_by_name(cmd) != NULL) { 3774 if (find_applet_by_name(cmd) != NULL) {
3780 /* re-exec ourselves with the new arguments */ 3775 /* re-exec ourselves with the new arguments */
3781 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp); 3776 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
@@ -3949,7 +3944,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
3949 return; 3944 return;
3950 } 3945 }
3951 3946
3952#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL 3947#if ENABLE_FEATURE_SH_STANDALONE_SHELL
3953 if (find_applet_by_name(name)) { 3948 if (find_applet_by_name(name)) {
3954 entry->cmdtype = CMDNORMAL; 3949 entry->cmdtype = CMDNORMAL;
3955 entry->u.index = -1; 3950 entry->u.index = -1;
@@ -6045,21 +6040,18 @@ static char * pfgets(char *line, int len)
6045} 6040}
6046 6041
6047 6042
6048 6043#if ENABLE_FEATURE_COMMAND_EDITING
6049#ifdef CONFIG_FEATURE_COMMAND_EDITING 6044static line_input_t *line_input_state;
6050#ifdef CONFIG_ASH_EXPAND_PRMT 6045//static SKIP_ASH_EXPAND_PRMT(const) char *cmdedit_prompt;
6051static char *cmdedit_prompt;
6052#else
6053static const char *cmdedit_prompt; 6046static const char *cmdedit_prompt;
6054#endif
6055static void putprompt(const char *s) 6047static void putprompt(const char *s)
6056{ 6048{
6057#ifdef CONFIG_ASH_EXPAND_PRMT 6049 if (ENABLE_ASH_EXPAND_PRMT) {
6058 free(cmdedit_prompt); 6050 free((char*)cmdedit_prompt);
6059 cmdedit_prompt = xstrdup(s); 6051 cmdedit_prompt = xstrdup(s);
6060#else 6052 return;
6053 }
6061 cmdedit_prompt = s; 6054 cmdedit_prompt = s;
6062#endif
6063} 6055}
6064#else 6056#else
6065static void putprompt(const char *s) 6057static void putprompt(const char *s)
@@ -6068,6 +6060,16 @@ static void putprompt(const char *s)
6068} 6060}
6069#endif 6061#endif
6070 6062
6063#if ENABLE_FEATURE_COMMAND_EDITING_VI
6064#define setvimode(on) do { \
6065 if (on) line_input_state->flags |= VI_MODE; \
6066 else line_input_state->flags &= ~VI_MODE; \
6067} while (0)
6068#else
6069#define setvimode(on) viflag = 0 /* forcibly keep the option off */
6070#endif
6071
6072
6071static int preadfd(void) 6073static int preadfd(void)
6072{ 6074{
6073 int nr; 6075 int nr;
@@ -6075,25 +6077,25 @@ static int preadfd(void)
6075 parsenextc = buf; 6077 parsenextc = buf;
6076 6078
6077retry: 6079retry:
6078#ifdef CONFIG_FEATURE_COMMAND_EDITING 6080#if ENABLE_FEATURE_COMMAND_EDITING
6079 if (!iflag || parsefile->fd) 6081 if (!iflag || parsefile->fd)
6080 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1); 6082 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6081 else { 6083 else {
6082#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION 6084#if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
6083 cmdedit_path_lookup = pathval(); 6085 line_input_state->path_lookup = pathval();
6084#endif 6086#endif
6085 nr = cmdedit_read_input((char *) cmdedit_prompt, buf); 6087 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
6086 if(nr == 0) { 6088 if (nr == 0) {
6087 /* Ctrl+C presend */ 6089 /* Ctrl+C pressed */
6088 if(trap[SIGINT]) { 6090 if (trap[SIGINT]) {
6089 buf[0] = '\n'; 6091 buf[0] = '\n';
6090 buf[1] = 0; 6092 buf[1] = '\0';
6091 raise(SIGINT); 6093 raise(SIGINT);
6092 return 1; 6094 return 1;
6093 } 6095 }
6094 goto retry; 6096 goto retry;
6095 } 6097 }
6096 if(nr < 0 && errno == 0) { 6098 if (nr < 0 && errno == 0) {
6097 /* Ctrl+D presend */ 6099 /* Ctrl+D presend */
6098 nr = 0; 6100 nr = 0;
6099 } 6101 }
@@ -7913,6 +7915,10 @@ ash_main(int argc, char **argv)
7913#if PROFILE 7915#if PROFILE
7914 monitor(4, etext, profile_buf, sizeof profile_buf, 50); 7916 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7915#endif 7917#endif
7918
7919#if ENABLE_FEATURE_COMMAND_EDITING
7920 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
7921#endif
7916 state = 0; 7922 state = 0;
7917 if (setjmp(jmploc.loc)) { 7923 if (setjmp(jmploc.loc)) {
7918 int e; 7924 int e;
@@ -7954,11 +7960,11 @@ ash_main(int argc, char **argv)
7954 init(); 7960 init();
7955 setstackmark(&smark); 7961 setstackmark(&smark);
7956 procargs(argc, argv); 7962 procargs(argc, argv);
7957#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY 7963#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
7958 if ( iflag ) { 7964 if (iflag) {
7959 const char *hp = lookupvar("HISTFILE"); 7965 const char *hp = lookupvar("HISTFILE");
7960 7966
7961 if(hp == NULL ) { 7967 if (hp == NULL) {
7962 hp = lookupvar("HOME"); 7968 hp = lookupvar("HOME");
7963 if(hp != NULL) { 7969 if(hp != NULL) {
7964 char *defhp = concat_path_file(hp, ".ash_history"); 7970 char *defhp = concat_path_file(hp, ".ash_history");
@@ -7995,15 +8001,15 @@ state3:
7995 evalstring(minusc, 0); 8001 evalstring(minusc, 0);
7996 8002
7997 if (sflag || minusc == NULL) { 8003 if (sflag || minusc == NULL) {
7998#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY 8004#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
7999 if ( iflag ) { 8005 if ( iflag ) {
8000 const char *hp = lookupvar("HISTFILE"); 8006 const char *hp = lookupvar("HISTFILE");
8001 8007
8002 if(hp != NULL ) 8008 if (hp != NULL)
8003 load_history ( hp ); 8009 line_input_state->hist_file = hp;
8004 } 8010 }
8005#endif 8011#endif
8006state4: /* XXX ??? - why isn't this before the "if" statement */ 8012 state4: /* XXX ??? - why isn't this before the "if" statement */
8007 cmdloop(1); 8013 cmdloop(1);
8008 } 8014 }
8009#if PROFILE 8015#if PROFILE
@@ -11880,7 +11886,7 @@ setinteractive(int on)
11880 setsignal(SIGINT); 11886 setsignal(SIGINT);
11881 setsignal(SIGQUIT); 11887 setsignal(SIGQUIT);
11882 setsignal(SIGTERM); 11888 setsignal(SIGTERM);
11883#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 11889#if !ENABLE_FEATURE_SH_EXTRA_QUIET
11884 if(is_interactive > 1) { 11890 if(is_interactive > 1) {
11885 /* Looks like they want an interactive shell */ 11891 /* Looks like they want an interactive shell */
11886 static int do_banner; 11892 static int do_banner;
@@ -11897,7 +11903,7 @@ setinteractive(int on)
11897} 11903}
11898 11904
11899 11905
11900#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 11906#if !ENABLE_FEATURE_SH_EXTRA_QUIET
11901/*** List the available builtins ***/ 11907/*** List the available builtins ***/
11902 11908
11903static int helpcmd(int argc, char **argv) 11909static int helpcmd(int argc, char **argv)
@@ -11913,7 +11919,7 @@ static int helpcmd(int argc, char **argv)
11913 col = 0; 11919 col = 0;
11914 } 11920 }
11915 } 11921 }
11916#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL 11922#if ENABLE_FEATURE_SH_STANDALONE_SHELL
11917 for (i = 0; i < NUM_APPLETS; i++) { 11923 for (i = 0; i < NUM_APPLETS; i++) {
11918 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name); 11924 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11919 if (col > 60) { 11925 if (col > 60) {
@@ -11945,7 +11951,7 @@ exitshell(void)
11945/* dash bug: it just does _exit(exitstatus) here 11951/* dash bug: it just does _exit(exitstatus) here
11946 * but we have to do setjobctl(0) first! 11952 * but we have to do setjobctl(0) first!
11947 * (bug is still not fixed in dash-0.5.3 - if you run dash 11953 * (bug is still not fixed in dash-0.5.3 - if you run dash
11948 * under Midnight Commander, on exit MC is backgrounded) */ 11954 * under Midnight Commander, on exit from dash MC is backgrounded) */
11949 status = exitstatus; 11955 status = exitstatus;
11950 goto out; 11956 goto out;
11951 } 11957 }
@@ -11955,14 +11961,6 @@ exitshell(void)
11955 evalstring(p, 0); 11961 evalstring(p, 0);
11956 } 11962 }
11957 flushall(); 11963 flushall();
11958#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11959 if (iflag && rootshell) {
11960 const char *hp = lookupvar("HISTFILE");
11961
11962 if (hp != NULL)
11963 save_history(hp);
11964 }
11965#endif
11966out: 11964out:
11967 setjobctl(0); 11965 setjobctl(0);
11968 _exit(status); 11966 _exit(status);
@@ -13491,7 +13489,7 @@ static const char op_tokens[] = {
13491#define endexpression &op_tokens[sizeof(op_tokens)-7] 13489#define endexpression &op_tokens[sizeof(op_tokens)-7]
13492 13490
13493 13491
13494static arith_t arith (const char *expr, int *perrcode) 13492static arith_t arith(const char *expr, int *perrcode)
13495{ 13493{
13496 char arithval; /* Current character under analysis */ 13494 char arithval; /* Current character under analysis */
13497 operator lasttok, op; 13495 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 @@
30 30
31#include <sys/ioctl.h> 31#include <sys/ioctl.h>
32#include "busybox.h" 32#include "busybox.h"
33#include "cmdedit.h"
34 33
35 34
36/* FIXME: obsolete CONFIG item? */ 35/* FIXME: obsolete CONFIG item? */
@@ -51,7 +50,6 @@
51/* Entire file (except TESTing part) sits inside this #if */ 50/* Entire file (except TESTing part) sits inside this #if */
52#if ENABLE_FEATURE_COMMAND_EDITING 51#if ENABLE_FEATURE_COMMAND_EDITING
53 52
54
55#if ENABLE_LOCALE_SUPPORT 53#if ENABLE_LOCALE_SUPPORT
56#define Isprint(c) isprint(c) 54#define Isprint(c) isprint(c)
57#else 55#else
@@ -61,29 +59,21 @@
61#define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \ 59#define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \
62(ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION || ENABLE_FEATURE_SH_FANCY_PROMPT) 60(ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION || ENABLE_FEATURE_SH_FANCY_PROMPT)
63 61
64/* Maximum length of command line history */
65#if !ENABLE_FEATURE_COMMAND_HISTORY
66#define MAX_HISTORY 15
67#else
68#define MAX_HISTORY (CONFIG_FEATURE_COMMAND_HISTORY + 0)
69#endif
70 62
63static line_input_t *state;
71 64
72/* Current termios and the previous termios before starting sh */
73static struct termios initial_settings, new_settings; 65static struct termios initial_settings, new_settings;
74 66
75static 67static volatile unsigned cmdedit_termw = 80; /* actual terminal width */
76volatile unsigned cmdedit_termw = 80; /* actual terminal width */
77
78 68
79static int cmdedit_x; /* real x terminal position */ 69static int cmdedit_x; /* real x terminal position */
80static int cmdedit_y; /* pseudoreal y terminal position */ 70static int cmdedit_y; /* pseudoreal y terminal position */
81static int cmdedit_prmt_len; /* length of prompt (without colors etc) */ 71static int cmdedit_prmt_len; /* length of prompt (without colors etc) */
82 72
83static int cursor; 73static unsigned cursor;
84static int len; 74static unsigned command_len;
85static char *command_ps; 75static char *command_ps;
86static SKIP_FEATURE_SH_FANCY_PROMPT(const) char *cmdedit_prompt; 76static const char *cmdedit_prompt;
87 77
88#if ENABLE_FEATURE_SH_FANCY_PROMPT 78#if ENABLE_FEATURE_SH_FANCY_PROMPT
89static char *hostname_buf; 79static char *hostname_buf;
@@ -142,7 +132,7 @@ static void cmdedit_set_out_char(int next_char)
142/* Move to end of line (by printing all chars till the end) */ 132/* Move to end of line (by printing all chars till the end) */
143static void input_end(void) 133static void input_end(void)
144{ 134{
145 while (cursor < len) 135 while (cursor < command_len)
146 cmdedit_set_out_char(' '); 136 cmdedit_set_out_char(' ');
147} 137}
148 138
@@ -200,7 +190,7 @@ static void input_backward(unsigned num)
200static void put_prompt(void) 190static void put_prompt(void)
201{ 191{
202 out1str(cmdedit_prompt); 192 out1str(cmdedit_prompt);
203 cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ 193 cmdedit_x = cmdedit_prmt_len;
204 cursor = 0; 194 cursor = 0;
205// Huh? what if cmdedit_prmt_len >= width? 195// Huh? what if cmdedit_prmt_len >= width?
206 cmdedit_y = 0; /* new quasireal y */ 196 cmdedit_y = 0; /* new quasireal y */
@@ -231,7 +221,7 @@ static void input_delete(int save)
231{ 221{
232 int j = cursor; 222 int j = cursor;
233 223
234 if (j == len) 224 if (j == command_len)
235 return; 225 return;
236 226
237#if ENABLE_FEATURE_COMMAND_EDITING_VI 227#if ENABLE_FEATURE_COMMAND_EDITING_VI
@@ -249,7 +239,7 @@ static void input_delete(int save)
249#endif 239#endif
250 240
251 strcpy(command_ps + j, command_ps + j + 1); 241 strcpy(command_ps + j, command_ps + j + 1);
252 len--; 242 command_len--;
253 input_end(); /* rewrite new line */ 243 input_end(); /* rewrite new line */
254 cmdedit_set_out_char(' '); /* erase char */ 244 cmdedit_set_out_char(' '); /* erase char */
255 input_backward(cursor - j); /* back to old pos cursor */ 245 input_backward(cursor - j); /* back to old pos cursor */
@@ -285,7 +275,7 @@ static void input_backspace(void)
285/* Move forward one character */ 275/* Move forward one character */
286static void input_forward(void) 276static void input_forward(void)
287{ 277{
288 if (cursor < len) 278 if (cursor < command_len)
289 cmdedit_set_out_char(command_ps[cursor + 1]); 279 cmdedit_set_out_char(command_ps[cursor + 1]);
290} 280}
291 281
@@ -372,54 +362,50 @@ enum {
372 FIND_FILE_ONLY = 2, 362 FIND_FILE_ONLY = 2,
373}; 363};
374 364
375#if ENABLE_ASH
376const char *cmdedit_path_lookup;
377#endif
378static int path_parse(char ***p, int flags) 365static int path_parse(char ***p, int flags)
379{ 366{
380 int npth; 367 int npth;
381 const char *tmp; 368 const char *tmp;
382#if ENABLE_ASH 369 const char *pth;
383 const char *pth = cmdedit_path_lookup; 370 char **res;
384#else
385 const char *pth = getenv("PATH")
386#endif
387 371
388 /* if not setenv PATH variable, to search cur dir "." */ 372 /* if not setenv PATH variable, to search cur dir "." */
389 if (flags != FIND_EXE_ONLY) 373 if (flags != FIND_EXE_ONLY)
390 return 1; 374 return 1;
375
376 if (state->flags & WITH_PATH_LOOKUP)
377 pth = state->path_lookup;
378 else
379 pth = getenv("PATH");
391 /* PATH=<empty> or PATH=:<empty> */ 380 /* PATH=<empty> or PATH=:<empty> */
392 if (!pth || !pth[0] || LONE_CHAR(pth, ':')) 381 if (!pth || !pth[0] || LONE_CHAR(pth, ':'))
393 return 1; 382 return 1;
394 383
395 tmp = pth; 384 tmp = pth;
396 npth = 0; 385 npth = 1; /* path component count */
397
398 while (1) { 386 while (1) {
399 npth++; /* count words is + 1 count ':' */
400 tmp = strchr(tmp, ':'); 387 tmp = strchr(tmp, ':');
401 if (!tmp) 388 if (!tmp)
402 break; 389 break;
403 if (*++tmp == '\0') 390 if (*++tmp == '\0')
404 break; /* :<empty> */ 391 break; /* :<empty> */
392 npth++;
405 } 393 }
406 394
407 *p = xmalloc(npth * sizeof(char *)); 395 res = xmalloc(npth * sizeof(char*));
408 396 res[0] = xstrdup(pth);
409 tmp = pth; 397 tmp = pth;
410 (*p)[0] = xstrdup(tmp); 398 npth = 1;
411 npth = 1; /* count words is + 1 count ':' */
412
413 while (1) { 399 while (1) {
414 tmp = strchr(tmp, ':'); 400 tmp = strchr(tmp, ':');
415 if (!tmp) 401 if (!tmp)
416 break; 402 break;
417 (*p)[0][(tmp - pth)] = 0; /* ':' -> '\0' */ 403 *tmp++ = '\0'; /* ':' -> '\0' */
418 if (*++tmp == 0) 404 if (*tmp == '\0')
419 break; /* :<empty> */ 405 break; /* :<empty> */
420 (*p)[npth++] = &(*p)[0][(tmp - pth)]; /* p[next]=p[0][&'\0'+1] */ 406 res[npth++] = tmp;
421 } 407 }
422 408 *p = res;
423 return npth; 409 return npth;
424} 410}
425 411
@@ -742,6 +728,9 @@ static int match_compare(const void *a, const void *b)
742/* Do TAB completion */ 728/* Do TAB completion */
743static void input_tab(int *lastWasTab) 729static void input_tab(int *lastWasTab)
744{ 730{
731 if (!(state->flags & TAB_COMPLETION))
732 return;
733
745 if (!*lastWasTab) { 734 if (!*lastWasTab) {
746 char *tmp, *tmp1; 735 char *tmp, *tmp1;
747 int len_found; 736 int len_found;
@@ -764,13 +753,13 @@ static void input_tab(int *lastWasTab)
764#if ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION 753#if ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION
765 /* If the word starts with `~' and there is no slash in the word, 754 /* If the word starts with `~' and there is no slash in the word,
766 * then try completing this word as a username. */ 755 * then try completing this word as a username. */
767 756 if (state->flags & USERNAME_COMPLETION)
768 if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0) 757 if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0)
769 username_tab_completion(matchBuf, NULL); 758 username_tab_completion(matchBuf, NULL);
770 if (!matches)
771#endif 759#endif
772 /* Try to match any executable in our path and everything 760 /* Try to match any executable in our path and everything
773 * in the current working directory */ 761 * in the current working directory */
762 if (!matches)
774 exe_n_cwd_tab_completion(matchBuf, find_type); 763 exe_n_cwd_tab_completion(matchBuf, find_type);
775 /* Sort, then remove any duplicates found */ 764 /* Sort, then remove any duplicates found */
776 if (matches) { 765 if (matches) {
@@ -855,51 +844,48 @@ static void input_tab(int *lastWasTab)
855 } 844 }
856} 845}
857 846
847#else
848#define input_tab(a) ((void)0)
858#endif /* FEATURE_COMMAND_TAB_COMPLETION */ 849#endif /* FEATURE_COMMAND_TAB_COMPLETION */
859 850
860 851
861#if MAX_HISTORY > 0 852#if MAX_HISTORY > 0
862 853
863static char *history[MAX_HISTORY+1]; /* history + current */ 854/* state->flags is already checked to be nonzero */
864/* saved history lines */
865static int n_history;
866/* current pointer to history line */
867static int cur_history;
868
869static void get_previous_history(void) 855static void get_previous_history(void)
870{ 856{
871 if (command_ps[0] != '\0' || history[cur_history] == NULL) { 857 if (command_ps[0] != '\0' || state->history[state->cur_history] == NULL) {
872 free(history[cur_history]); 858 free(state->history[state->cur_history]);
873 history[cur_history] = xstrdup(command_ps); 859 state->history[state->cur_history] = xstrdup(command_ps);
874 } 860 }
875 cur_history--; 861 state->cur_history--;
876} 862}
877 863
878static int get_next_history(void) 864static int get_next_history(void)
879{ 865{
880 int ch = cur_history; 866 if (state->flags & DO_HISTORY) {
881 867 int ch = state->cur_history;
882 if (ch < n_history) { 868 if (ch < state->cnt_history) {
883 get_previous_history(); /* save the current history line */ 869 get_previous_history(); /* save the current history line */
884 cur_history = ch + 1; 870 state->cur_history = ch + 1;
885 return cur_history; 871 return state->cur_history;
886 } else { 872 }
887 beep();
888 return 0;
889 } 873 }
874 beep();
875 return 0;
890} 876}
891 877
892#if ENABLE_FEATURE_COMMAND_SAVEHISTORY 878#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
879/* state->flags is already checked to be nonzero */
893void load_history(const char *fromfile) 880void load_history(const char *fromfile)
894{ 881{
895 FILE *fp; 882 FILE *fp;
896 int hi; 883 int hi;
897 884
898 /* cleanup old */ 885 /* cleanup old */
899 886 for (hi = state->cnt_history; hi > 0;) {
900 for (hi = n_history; hi > 0;) {
901 hi--; 887 hi--;
902 free(history[hi]); 888 free(state->history[hi]);
903 } 889 }
904 890
905 fp = fopen(fromfile, "r"); 891 fp = fopen(fromfile, "r");
@@ -917,29 +903,62 @@ void load_history(const char *fromfile)
917 free(hl); 903 free(hl);
918 continue; 904 continue;
919 } 905 }
920 history[hi++] = hl; 906 state->history[hi++] = hl;
921 } 907 }
922 fclose(fp); 908 fclose(fp);
923 } 909 }
924 cur_history = n_history = hi; 910 state->cur_history = state->cnt_history = hi;
925} 911}
926 912
913/* state->flags is already checked to be nonzero */
927void save_history(const char *tofile) 914void save_history(const char *tofile)
928{ 915{
929 FILE *fp = fopen(tofile, "w"); 916 FILE *fp;
930 917
918 fp = fopen(tofile, "w");
931 if (fp) { 919 if (fp) {
932 int i; 920 int i;
933 921
934 for (i = 0; i < n_history; i++) { 922 for (i = 0; i < state->cnt_history; i++) {
935 fprintf(fp, "%s\n", history[i]); 923 fprintf(fp, "%s\n", state->history[i]);
936 } 924 }
937 fclose(fp); 925 fclose(fp);
938 } 926 }
939} 927}
928#else
929#define load_history(a) ((void)0)
930#define save_history(a) ((void)0)
940#endif /* FEATURE_COMMAND_SAVEHISTORY */ 931#endif /* FEATURE_COMMAND_SAVEHISTORY */
941 932
942#endif /* MAX_HISTORY > 0 */ 933static void remember_in_history(const char *str)
934{
935 int i;
936
937 if (!(state->flags & DO_HISTORY))
938 return;
939
940 i = state->cnt_history;
941 free(state->history[MAX_HISTORY]);
942 state->history[MAX_HISTORY] = NULL;
943 /* After max history, remove the oldest command */
944 if (i >= MAX_HISTORY) {
945 free(state->history[0]);
946 for (i = 0; i < MAX_HISTORY-1; i++)
947 state->history[i] = state->history[i+1];
948 }
949// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..."
950// (i.e. do not save dups?)
951 state->history[i++] = xstrdup(str);
952 state->cur_history = i;
953 state->cnt_history = i;
954 if (state->flags & SAVE_HISTORY)
955 save_history(state->hist_file);
956 USE_FEATURE_SH_FANCY_PROMPT(num_ok_lines++;)
957}
958
959#else /* MAX_HISTORY == 0 */
960#define remember_in_history(a) ((void)0)
961#endif /* MAX_HISTORY */
943 962
944 963
945/* 964/*
@@ -960,13 +979,6 @@ void save_history(const char *tofile)
960 */ 979 */
961 980
962#if ENABLE_FEATURE_COMMAND_EDITING_VI 981#if ENABLE_FEATURE_COMMAND_EDITING_VI
963static int vi_mode;
964
965void setvimode(int viflag)
966{
967 vi_mode = viflag;
968}
969
970static void 982static void
971vi_Word_motion(char *command, int eat) 983vi_Word_motion(char *command, int eat)
972{ 984{
@@ -1058,13 +1070,11 @@ vi_back_motion(char *command)
1058 input_backward(1); 1070 input_backward(1);
1059 } 1071 }
1060} 1072}
1061#else
1062enum { vi_mode = 0 };
1063#endif 1073#endif
1064 1074
1065 1075
1066/* 1076/*
1067 * cmdedit_read_input and its helpers 1077 * read_line_input and its helpers
1068 */ 1078 */
1069 1079
1070#if !ENABLE_FEATURE_SH_FANCY_PROMPT 1080#if !ENABLE_FEATURE_SH_FANCY_PROMPT
@@ -1190,7 +1200,7 @@ static void parse_prompt(const char *prmt_ptr)
1190 cmdedit_prmt_len += cur_prmt_len; 1200 cmdedit_prmt_len += cur_prmt_len;
1191 prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); 1201 prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);
1192 } 1202 }
1193 if (pwd_buf!=(char *)bb_msg_unknown) 1203 if (pwd_buf != (char *)bb_msg_unknown)
1194 free(pwd_buf); 1204 free(pwd_buf);
1195 cmdedit_prompt = prmt_mem_ptr; 1205 cmdedit_prompt = prmt_mem_ptr;
1196 put_prompt(); 1206 put_prompt();
@@ -1217,7 +1227,7 @@ static void cmdedit_setwidth(unsigned w, int redraw_flg)
1217 /* new y for current cursor */ 1227 /* new y for current cursor */
1218 int new_y = (cursor + cmdedit_prmt_len) / w; 1228 int new_y = (cursor + cmdedit_prmt_len) / w;
1219 /* redraw */ 1229 /* redraw */
1220 redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor); 1230 redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), command_len - cursor);
1221 fflush(stdout); 1231 fflush(stdout);
1222 } 1232 }
1223} 1233}
@@ -1275,9 +1285,10 @@ static void cmdedit_init(void)
1275#undef CTRL 1285#undef CTRL
1276#define CTRL(a) ((a) & ~0x40) 1286#define CTRL(a) ((a) & ~0x40)
1277 1287
1278 1288int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *st)
1279int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1280{ 1289{
1290 static const int null_flags;
1291
1281 int lastWasTab = FALSE; 1292 int lastWasTab = FALSE;
1282 unsigned int ic; 1293 unsigned int ic;
1283 unsigned char c; 1294 unsigned char c;
@@ -1286,18 +1297,28 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1286 smallint vi_cmdmode = 0; 1297 smallint vi_cmdmode = 0;
1287 smalluint prevc; 1298 smalluint prevc;
1288#endif 1299#endif
1300
1301// FIXME: audit & improve this
1302 if (maxsize > BUFSIZ)
1303 maxsize = BUFSIZ;
1304
1305 /* With null flags, no other fields are ever used */
1306 state = st ? st : (line_input_t*) &null_flags;
1307 if (state->flags & SAVE_HISTORY)
1308 load_history(state->hist_file);
1309
1289 /* prepare before init handlers */ 1310 /* prepare before init handlers */
1290 cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ 1311 cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */
1291 len = 0; 1312 command_len = 0;
1292 command_ps = command; 1313 command_ps = command;
1293 command[0] = '\0'; 1314 command[0] = '\0';
1294 1315
1295 getTermSettings(0, (void *) &initial_settings); 1316 getTermSettings(0, (void *) &initial_settings);
1296 memcpy(&new_settings, &initial_settings, sizeof(struct termios)); 1317 memcpy(&new_settings, &initial_settings, sizeof(new_settings));
1297 new_settings.c_lflag &= ~ICANON; /* unbuffered input */ 1318 new_settings.c_lflag &= ~ICANON; /* unbuffered input */
1298 /* Turn off echoing and CTRL-C, so we can trap it */ 1319 /* Turn off echoing and CTRL-C, so we can trap it */
1299 new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG); 1320 new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
1300 /* Hmm, in linux c_cc[] not parsed if set ~ICANON */ 1321 /* Hmm, in linux c_cc[] is not parsed if ICANON is off */
1301 new_settings.c_cc[VMIN] = 1; 1322 new_settings.c_cc[VMIN] = 1;
1302 new_settings.c_cc[VTIME] = 0; 1323 new_settings.c_cc[VTIME] = 0;
1303 /* Turn off CTRL-C, so we can trap it */ 1324 /* Turn off CTRL-C, so we can trap it */
@@ -1354,34 +1375,18 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1354 vi_case(CTRL('C')|vbit:) 1375 vi_case(CTRL('C')|vbit:)
1355 /* Control-c -- stop gathering input */ 1376 /* Control-c -- stop gathering input */
1356 goto_new_line(); 1377 goto_new_line();
1357#if !ENABLE_ASH 1378 command_len = 0;
1358 command[0] = '\0'; 1379 break_out = -1; /* "do not append '\n'" */
1359 len = 0;
1360 lastWasTab = FALSE;
1361 put_prompt();
1362#else
1363 len = 0;
1364 break_out = -1; /* to control traps */
1365#endif
1366 break; 1380 break;
1367 case CTRL('D'): 1381 case CTRL('D'):
1368 /* Control-d -- Delete one character, or exit 1382 /* Control-d -- Delete one character, or exit
1369 * if the len=0 and no chars to delete */ 1383 * if the len=0 and no chars to delete */
1370 if (len == 0) { 1384 if (command_len == 0) {
1371 errno = 0; 1385 errno = 0;
1372 prepare_to_die: 1386 prepare_to_die:
1373// So, our API depends on whether we have ash compiled in or not? Crap...
1374#if !ENABLE_ASH
1375 printf("exit");
1376 goto_new_line();
1377 /* cmdedit_reset_term() called in atexit */
1378// FIXME. this is definitely not good
1379 exit(EXIT_SUCCESS);
1380#else
1381 /* to control stopped jobs */ 1387 /* to control stopped jobs */
1382 break_out = len = -1; 1388 break_out = command_len = -1;
1383 break; 1389 break;
1384#endif
1385 } 1390 }
1386 input_delete(0); 1391 input_delete(0);
1387 break; 1392 break;
@@ -1407,23 +1412,21 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1407 break; 1412 break;
1408 1413
1409 case '\t': 1414 case '\t':
1410#if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
1411 input_tab(&lastWasTab); 1415 input_tab(&lastWasTab);
1412#endif
1413 break; 1416 break;
1414 1417
1415#if ENABLE_FEATURE_EDITING_FANCY_KEYS 1418#if ENABLE_FEATURE_EDITING_FANCY_KEYS
1416 case CTRL('K'): 1419 case CTRL('K'):
1417 /* Control-k -- clear to end of line */ 1420 /* Control-k -- clear to end of line */
1418 command[cursor] = 0; 1421 command[cursor] = 0;
1419 len = cursor; 1422 command_len = cursor;
1420 printf("\033[J"); 1423 printf("\033[J");
1421 break; 1424 break;
1422 case CTRL('L'): 1425 case CTRL('L'):
1423 vi_case(CTRL('L')|vbit:) 1426 vi_case(CTRL('L')|vbit:)
1424 /* Control-l -- clear screen */ 1427 /* Control-l -- clear screen */
1425 printf("\033[H"); 1428 printf("\033[H");
1426 redraw(0, len - cursor); 1429 redraw(0, command_len - cursor);
1427 break; 1430 break;
1428#endif 1431#endif
1429 1432
@@ -1439,12 +1442,11 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1439 vi_case(CTRL('P')|vbit:) 1442 vi_case(CTRL('P')|vbit:)
1440 vi_case('k'|vbit:) 1443 vi_case('k'|vbit:)
1441 /* Control-p -- Get previous command from history */ 1444 /* Control-p -- Get previous command from history */
1442 if (cur_history > 0) { 1445 if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
1443 get_previous_history(); 1446 get_previous_history();
1444 goto rewrite_line; 1447 goto rewrite_line;
1445 } else {
1446 beep();
1447 } 1448 }
1449 beep();
1448 break; 1450 break;
1449#endif 1451#endif
1450 1452
@@ -1454,7 +1456,8 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1454 /* Control-U -- Clear line before cursor */ 1456 /* Control-U -- Clear line before cursor */
1455 if (cursor) { 1457 if (cursor) {
1456 strcpy(command, command + cursor); 1458 strcpy(command, command + cursor);
1457 redraw(cmdedit_y, len -= cursor); 1459 command_len -= cursor;
1460 redraw(cmdedit_y, command_len);
1458 } 1461 }
1459 break; 1462 break;
1460#endif 1463#endif
@@ -1571,7 +1574,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1571 break; 1574 break;
1572 case '$': /* "d$", "c$" */ 1575 case '$': /* "d$", "c$" */
1573 clear_to_eol: 1576 clear_to_eol:
1574 while (cursor < len) 1577 while (cursor < command_len)
1575 input_delete(1); 1578 input_delete(1);
1576 break; 1579 break;
1577 } 1580 }
@@ -1599,7 +1602,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1599 case '\x1b': /* ESC */ 1602 case '\x1b': /* ESC */
1600 1603
1601#if ENABLE_FEATURE_COMMAND_EDITING_VI 1604#if ENABLE_FEATURE_COMMAND_EDITING_VI
1602 if (vi_mode) { 1605 if (state->flags & VI_MODE) {
1603 /* ESC: insert mode --> command mode */ 1606 /* ESC: insert mode --> command mode */
1604 vi_cmdmode = 1; 1607 vi_cmdmode = 1;
1605 input_backward(1); 1608 input_backward(1);
@@ -1634,7 +1637,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1634#if MAX_HISTORY > 0 1637#if MAX_HISTORY > 0
1635 case 'A': 1638 case 'A':
1636 /* Up Arrow -- Get previous command from history */ 1639 /* Up Arrow -- Get previous command from history */
1637 if (cur_history > 0) { 1640 if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
1638 get_previous_history(); 1641 get_previous_history();
1639 goto rewrite_line; 1642 goto rewrite_line;
1640 } 1643 }
@@ -1647,9 +1650,9 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1647 rewrite_line: 1650 rewrite_line:
1648 /* Rewrite the line with the selected history item */ 1651 /* Rewrite the line with the selected history item */
1649 /* change command */ 1652 /* change command */
1650 len = strlen(strcpy(command, history[cur_history])); 1653 command_len = strlen(strcpy(command, state->history[state->cur_history]));
1651 /* redraw and go to eol (bol, in vi */ 1654 /* redraw and go to eol (bol, in vi */
1652 redraw(cmdedit_y, vi_mode ? 9999 : 0); 1655 redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
1653 break; 1656 break;
1654#endif 1657#endif
1655 case 'C': 1658 case 'C':
@@ -1700,18 +1703,18 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1700 if (!Isprint(c)) /* Skip non-printable characters */ 1703 if (!Isprint(c)) /* Skip non-printable characters */
1701 break; 1704 break;
1702 1705
1703 if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ 1706 if (command_len >= (maxsize - 2)) /* Need to leave space for enter */
1704 break; 1707 break;
1705 1708
1706 len++; 1709 command_len++;
1707 if (cursor == (len - 1)) { /* Append if at the end of the line */ 1710 if (cursor == (command_len - 1)) { /* Append if at the end of the line */
1708 command[cursor] = c; 1711 command[cursor] = c;
1709 command[cursor+1] = '\0'; 1712 command[cursor+1] = '\0';
1710 cmdedit_set_out_char(' '); 1713 cmdedit_set_out_char(' ');
1711 } else { /* Insert otherwise */ 1714 } else { /* Insert otherwise */
1712 int sc = cursor; 1715 int sc = cursor;
1713 1716
1714 memmove(command + sc + 1, command + sc, len - sc); 1717 memmove(command + sc + 1, command + sc, command_len - sc);
1715 command[sc] = c; 1718 command[sc] = c;
1716 sc++; 1719 sc++;
1717 /* rewrite from cursor */ 1720 /* rewrite from cursor */
@@ -1728,35 +1731,12 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1728 lastWasTab = FALSE; 1731 lastWasTab = FALSE;
1729 } 1732 }
1730 1733
1731#if MAX_HISTORY > 0 1734 if (command_len > 0)
1732 /* Handle command history log */ 1735 remember_in_history(command);
1733 /* cleanup may be saved current command line */
1734 if (len > 0) {
1735 int i = n_history;
1736
1737 free(history[MAX_HISTORY]);
1738 history[MAX_HISTORY] = NULL;
1739 /* After max history, remove the oldest command */
1740 if (i >= MAX_HISTORY) {
1741 free(history[0]);
1742 for (i = 0; i < MAX_HISTORY-1; i++)
1743 history[i] = history[i+1];
1744 }
1745// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..."
1746// (i.e. do not save dups?)
1747 history[i++] = xstrdup(command);
1748 cur_history = i;
1749 n_history = i;
1750 USE_FEATURE_SH_FANCY_PROMPT(num_ok_lines++;)
1751 }
1752#else /* MAX_HISTORY == 0 */
1753 /* dont put empty line */
1754 USE_FEATURE_SH_FANCY_PROMPT(if (len > 0) num_ok_lines++;)
1755#endif /* MAX_HISTORY */
1756 1736
1757 if (break_out > 0) { 1737 if (break_out > 0) {
1758 command[len++] = '\n'; 1738 command[command_len++] = '\n';
1759 command[len] = '\0'; 1739 command[command_len] = '\0';
1760 } 1740 }
1761 1741
1762#if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_COMMAND_TAB_COMPLETION 1742#if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_COMMAND_TAB_COMPLETION
@@ -1764,11 +1744,29 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1764#endif 1744#endif
1765 1745
1766#if ENABLE_FEATURE_SH_FANCY_PROMPT 1746#if ENABLE_FEATURE_SH_FANCY_PROMPT
1767 free(cmdedit_prompt); 1747 free((char*)cmdedit_prompt);
1768#endif 1748#endif
1769 /* restore initial_settings and SIGWINCH handler */ 1749 /* restore initial_settings and SIGWINCH handler */
1770 cmdedit_reset_term(); 1750 cmdedit_reset_term();
1771 return len; 1751 return command_len;
1752}
1753
1754line_input_t *new_line_input_t(int flags)
1755{
1756 line_input_t *n = xzalloc(sizeof(*n));
1757 n->flags = flags;
1758 return n;
1759}
1760
1761#else
1762
1763#undef read_line_input
1764int read_line_input(const char* prompt, char* command, int maxsize)
1765{
1766 fputs(prompt, stdout);
1767 fflush(stdout);
1768 fgets(command, maxsize, stdin);
1769 return strlen(command);
1772} 1770}
1773 1771
1774#endif /* FEATURE_COMMAND_EDITING */ 1772#endif /* FEATURE_COMMAND_EDITING */
@@ -1801,13 +1799,13 @@ int main(int argc, char **argv)
1801#endif 1799#endif
1802 while (1) { 1800 while (1) {
1803 int l; 1801 int l;
1804 l = cmdedit_read_input(prompt, buff); 1802 l = read_line_input(prompt, buff);
1805 if (l <= 0 || buff[l-1] != '\n') 1803 if (l <= 0 || buff[l-1] != '\n')
1806 break; 1804 break;
1807 buff[l-1] = 0; 1805 buff[l-1] = 0;
1808 printf("*** cmdedit_read_input() returned line =%s=\n", buff); 1806 printf("*** read_line_input() returned line =%s=\n", buff);
1809 } 1807 }
1810 printf("*** cmdedit_read_input() detect ^D\n"); 1808 printf("*** read_line_input() detect ^D\n");
1811 return 0; 1809 return 0;
1812} 1810}
1813 1811
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 @@
1/* vi: set sw=4 ts=4: */ /* TO DELETE */
2#ifndef CMDEDIT_H
3#define CMDEDIT_H
4
5int cmdedit_read_input(char* promptStr, char* command);
6
7#if ENABLE_ASH
8extern const char *cmdedit_path_lookup;
9#endif
10
11#if ENABLE_FEATURE_COMMAND_SAVEHISTORY
12void load_history(const char *fromfile);
13void save_history(const char *tofile);
14#endif
15
16#if ENABLE_FEATURE_COMMAND_EDITING_VI
17void setvimode(int viflag);
18#endif
19
20#endif /* CMDEDIT_H */
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 @@
98/* #include <dmalloc.h> */ 98/* #include <dmalloc.h> */
99/* #define DEBUG_SHELL */ 99/* #define DEBUG_SHELL */
100 100
101#include "cmdedit.h"
102 101
103#define SPECIAL_VAR_SYMBOL 03 102#define SPECIAL_VAR_SYMBOL 03
104#define FLAG_EXIT_FROM_LOOP 1 103#define FLAG_EXIT_FROM_LOOP 1
@@ -883,20 +882,24 @@ static void setup_prompt_string(int promptmode, char **prompt_str)
883 debug_printf("result %s\n",*prompt_str); 882 debug_printf("result %s\n",*prompt_str);
884} 883}
885 884
885#if ENABLE_FEATURE_COMMAND_EDITING
886static line_input_t *line_input_state;
887#endif
888
886static void get_user_input(struct in_str *i) 889static void get_user_input(struct in_str *i)
887{ 890{
888 char *prompt_str; 891 char *prompt_str;
889 static char the_command[BUFSIZ]; 892 static char the_command[BUFSIZ];
890 893
891 setup_prompt_string(i->promptmode, &prompt_str); 894 setup_prompt_string(i->promptmode, &prompt_str);
892#ifdef CONFIG_FEATURE_COMMAND_EDITING 895#if ENABLE_FEATURE_COMMAND_EDITING
893 /* 896 /*
894 ** enable command line editing only while a command line 897 ** enable command line editing only while a command line
895 ** is actually being read; otherwise, we'll end up bequeathing 898 ** is actually being read; otherwise, we'll end up bequeathing
896 ** atexit() handlers and other unwanted stuff to our 899 ** atexit() handlers and other unwanted stuff to our
897 ** child processes (rob@sysgo.de) 900 ** child processes (rob@sysgo.de)
898 */ 901 */
899 cmdedit_read_input(prompt_str, the_command); 902 read_line_input(prompt_str, the_command, BUFSIZ, line_input_state);
900#else 903#else
901 fputs(prompt_str, stdout); 904 fputs(prompt_str, stdout);
902 fflush(stdout); 905 fflush(stdout);
@@ -2647,6 +2650,10 @@ int hush_main(int argc, char **argv)
2647 FILE *input; 2650 FILE *input;
2648 char **e = environ; 2651 char **e = environ;
2649 2652
2653#ifdef CONFIG_FEATURE_COMMAND_EDITING
2654 line_input_state = new_line_input_t(FOR_SHELL);
2655#endif
2656
2650 /* XXX what should these be while sourcing /etc/profile? */ 2657 /* XXX what should these be while sourcing /etc/profile? */
2651 global_argc = argc; 2658 global_argc = argc;
2652 global_argv = argv; 2659 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 @@
23 23
24#include "busybox.h" 24#include "busybox.h"
25#include <getopt.h> 25#include <getopt.h>
26#include "cmdedit.h"
27
28#include <glob.h> 26#include <glob.h>
29#define expand_t glob_t 27#define expand_t glob_t
30 28
@@ -641,6 +639,10 @@ static inline void setup_prompt_string(char **prompt_str)
641#endif 639#endif
642} 640}
643 641
642#if ENABLE_FEATURE_COMMAND_EDITING
643static line_input_t *line_input_state;
644#endif
645
644static int get_command(FILE * source, char *command) 646static int get_command(FILE * source, char *command)
645{ 647{
646 char *prompt_str; 648 char *prompt_str;
@@ -659,14 +661,14 @@ static int get_command(FILE * source, char *command)
659 if (source == stdin) { 661 if (source == stdin) {
660 setup_prompt_string(&prompt_str); 662 setup_prompt_string(&prompt_str);
661 663
662#ifdef CONFIG_FEATURE_COMMAND_EDITING 664#if ENABLE_FEATURE_COMMAND_EDITING
663 /* 665 /*
664 ** enable command line editing only while a command line 666 ** enable command line editing only while a command line
665 ** is actually being read; otherwise, we'll end up bequeathing 667 ** is actually being read; otherwise, we'll end up bequeathing
666 ** atexit() handlers and other unwanted stuff to our 668 ** atexit() handlers and other unwanted stuff to our
667 ** child processes (rob@sysgo.de) 669 ** child processes (rob@sysgo.de)
668 */ 670 */
669 cmdedit_read_input(prompt_str, command); 671 read_line_input(prompt_str, command, BUFSIZ, line_input_state);
670 return 0; 672 return 0;
671#else 673#else
672 fputs(prompt_str, stdout); 674 fputs(prompt_str, stdout);
@@ -1505,6 +1507,10 @@ int lash_main(int argc_l, char **argv_l)
1505 argc = argc_l; 1507 argc = argc_l;
1506 argv = argv_l; 1508 argv = argv_l;
1507 1509
1510#if ENABLE_FEATURE_COMMAND_EDITING
1511 line_input_state = new_line_input_t(FOR_SHELL);
1512#endif
1513
1508 /* These variables need re-initializing when recursing */ 1514 /* These variables need re-initializing when recursing */
1509 last_jobid = 0; 1515 last_jobid = 0;
1510 close_me_list = NULL; 1516 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 @@
17#include <setjmp.h> 17#include <setjmp.h>
18#include <sys/times.h> 18#include <sys/times.h>
19 19
20#include "cmdedit.h"
21 20
22/*#define MSHDEBUG 1*/ 21/*#define MSHDEBUG 1*/
23 22
@@ -777,7 +776,7 @@ void print_tree(struct op *head)
777#endif /* MSHDEBUG */ 776#endif /* MSHDEBUG */
778 777
779 778
780#ifdef CONFIG_FEATURE_COMMAND_EDITING 779#if ENABLE_FEATURE_COMMAND_EDITING
781static char *current_prompt; 780static char *current_prompt;
782#endif 781#endif
783 782
@@ -787,6 +786,10 @@ static char *current_prompt;
787 */ 786 */
788 787
789 788
789#if ENABLE_FEATURE_COMMAND_EDITING
790static line_input_t *line_input_state;
791#endif
792
790int msh_main(int argc, char **argv) 793int msh_main(int argc, char **argv)
791{ 794{
792 int f; 795 int f;
@@ -795,6 +798,10 @@ int msh_main(int argc, char **argv)
795 char *name, **ap; 798 char *name, **ap;
796 int (*iof) (struct ioarg *); 799 int (*iof) (struct ioarg *);
797 800
801#if ENABLE_FEATURE_COMMAND_EDITING
802 line_input_state = new_line_input_t(FOR_SHELL);
803#endif
804
798 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ)); 805 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
799 806
800 initarea(); 807 initarea();
@@ -964,7 +971,7 @@ int msh_main(int argc, char **argv)
964 971
965 for (;;) { 972 for (;;) {
966 if (interactive && e.iop <= iostack) { 973 if (interactive && e.iop <= iostack) {
967#ifdef CONFIG_FEATURE_COMMAND_EDITING 974#if ENABLE_FEATURE_COMMAND_EDITING
968 current_prompt = prompt->value; 975 current_prompt = prompt->value;
969#else 976#else
970 prs(prompt->value); 977 prs(prompt->value);
@@ -2371,7 +2378,7 @@ static int yylex(int cf)
2371 startl = 1; 2378 startl = 1;
2372 if (multiline || cf & CONTIN) { 2379 if (multiline || cf & CONTIN) {
2373 if (interactive && e.iop <= iostack) { 2380 if (interactive && e.iop <= iostack) {
2374#ifdef CONFIG_FEATURE_COMMAND_EDITING 2381#if ENABLE_FEATURE_COMMAND_EDITING
2375 current_prompt = cprompt->value; 2382 current_prompt = cprompt->value;
2376#else 2383#else
2377 prs(cprompt->value); 2384 prs(cprompt->value);
@@ -2432,7 +2439,7 @@ static int collect(int c, int c1)
2432 return YYERRCODE; 2439 return YYERRCODE;
2433 } 2440 }
2434 if (interactive && c == '\n' && e.iop <= iostack) { 2441 if (interactive && c == '\n' && e.iop <= iostack) {
2435#ifdef CONFIG_FEATURE_COMMAND_EDITING 2442#if ENABLE_FEATURE_COMMAND_EDITING
2436 current_prompt = cprompt->value; 2443 current_prompt = cprompt->value;
2437#else 2444#else
2438 prs(cprompt->value); 2445 prs(cprompt->value);
@@ -4666,7 +4673,7 @@ static int readc(void)
4666 return e.iop->prev = 0; 4673 return e.iop->prev = 0;
4667 } 4674 }
4668 if (interactive && e.iop == iostack + 1) { 4675 if (interactive && e.iop == iostack + 1) {
4669#ifdef CONFIG_FEATURE_COMMAND_EDITING 4676#if ENABLE_FEATURE_COMMAND_EDITING
4670 current_prompt = prompt->value; 4677 current_prompt = prompt->value;
4671#else 4678#else
4672 prs(prompt->value); 4679 prs(prompt->value);
@@ -4898,13 +4905,13 @@ static int filechar(struct ioarg *ap)
4898 ap->afpos++; 4905 ap->afpos++;
4899 return *bp->bufp++ & 0177; 4906 return *bp->bufp++ & 0177;
4900 } 4907 }
4901#ifdef CONFIG_FEATURE_COMMAND_EDITING 4908#if ENABLE_FEATURE_COMMAND_EDITING
4902 if (interactive && isatty(ap->afile)) { 4909 if (interactive && isatty(ap->afile)) {
4903 static char mycommand[BUFSIZ]; 4910 static char mycommand[BUFSIZ];
4904 static int position = 0, size = 0; 4911 static int position = 0, size = 0;
4905 4912
4906 while (size == 0 || position >= size) { 4913 while (size == 0 || position >= size) {
4907 cmdedit_read_input(current_prompt, mycommand); 4914 read_line_input(current_prompt, mycommand, BUFSIZ, line_input_state);
4908 size = strlen(mycommand); 4915 size = strlen(mycommand);
4909 position = 0; 4916 position = 0;
4910 } 4917 }
@@ -4913,7 +4920,6 @@ static int filechar(struct ioarg *ap)
4913 return c; 4920 return c;
4914 } else 4921 } else
4915#endif 4922#endif
4916
4917 { 4923 {
4918 i = safe_read(ap->afile, &c, sizeof(c)); 4924 i = safe_read(ap->afile, &c, sizeof(c));
4919 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0); 4925 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
@@ -5150,7 +5156,7 @@ static void readhere(char **name, char *s, int ec)
5150 e.iobase = e.iop; 5156 e.iobase = e.iop;
5151 for (;;) { 5157 for (;;) {
5152 if (interactive && e.iop <= iostack) { 5158 if (interactive && e.iop <= iostack) {
5153#ifdef CONFIG_FEATURE_COMMAND_EDITING 5159#if ENABLE_FEATURE_COMMAND_EDITING
5154 current_prompt = cprompt->value; 5160 current_prompt = cprompt->value;
5155#else 5161#else
5156 prs(cprompt->value); 5162 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);
202 }) 202 })
203 203
204 204
205#define LINE_LENGTH 800 205#define LINE_LENGTH 80
206#define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \ 206#define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
207 (n) * sizeof(struct partition))) 207 (n) * sizeof(struct partition)))
208#define sector(s) ((s) & 0x3f) 208#define sector(s) ((s) & 0x3f)
@@ -291,16 +291,20 @@ write_part_table_flag(char *b)
291static char line_buffer[LINE_LENGTH]; 291static char line_buffer[LINE_LENGTH];
292static char *line_ptr; 292static char *line_ptr;
293 293
294/* read line; return 0 or first char */ 294/* read line; return 0 or first printable char */
295static int 295static int
296read_line(void) 296read_line(const char *prompt)
297{ 297{
298 fflush(stdout); /* requested by niles@scyld.com */ 298 int sz;
299
300 sz = read_line_input(prompt, line_buffer, LINE_LENGTH, NULL);
301 if (sz <= 0)
302 exit(0); /* Ctrl-D or Ctrl-C */
303
304 if (line_buffer[sz-1] == '\n')
305 line_buffer[--sz] = '\0';
306
299 line_ptr = line_buffer; 307 line_ptr = line_buffer;
300 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
301 /* error or eof */
302 bb_error_msg_and_die("\ngot EOF, exiting");
303 }
304 while (*line_ptr && !isgraph(*line_ptr)) 308 while (*line_ptr && !isgraph(*line_ptr))
305 line_ptr++; 309 line_ptr++;
306 return *line_ptr; 310 return *line_ptr;
@@ -309,22 +313,19 @@ read_line(void)
309static char 313static char
310read_nonempty(const char *mesg) 314read_nonempty(const char *mesg)
311{ 315{
312 do { 316 while (!read_line(mesg)) /* repeat */;
313 fputs(mesg, stdout);
314 } while (!read_line());
315 return *line_ptr; 317 return *line_ptr;
316} 318}
317 319
318static char 320static char
319read_maybe_empty(const char *mesg) 321read_maybe_empty(const char *mesg)
320{ 322{
321 fputs(mesg, stdout); 323 if (!read_line(mesg)) {
322 if (!read_line()) {
323 line_ptr = line_buffer; 324 line_ptr = line_buffer;
324 *line_ptr = '\n'; 325 line_ptr[0] = '\n';
325 line_ptr[1] = 0; 326 line_ptr[1] = '\0';
326 } 327 }
327 return *line_ptr; 328 return line_ptr[0];
328} 329}
329 330
330static int 331static int
@@ -469,9 +470,9 @@ static const struct systypes i386_sys_types[] = {
469 { "\x16" "Hidden FAT16" }, 470 { "\x16" "Hidden FAT16" },
470 { "\x17" "Hidden HPFS/NTFS" }, 471 { "\x17" "Hidden HPFS/NTFS" },
471 { "\x1b" "Hidden Win95 FAT32" }, 472 { "\x1b" "Hidden Win95 FAT32" },
472 { "\x1c" "Hidden Win95 FAT32 (LBA)" }, 473 { "\x1c" "Hidden W95 FAT32 (LBA)" },
473 { "\x1e" "Hidden Win95 FAT16 (LBA)" }, 474 { "\x1e" "Hidden W95 FAT16 (LBA)" },
474 { "\x3c" "PartitionMagic recovery" }, 475 { "\x3c" "Part.Magic recovery" },
475 { "\x41" "PPC PReP Boot" }, 476 { "\x41" "PPC PReP Boot" },
476 { "\x42" "SFS" }, 477 { "\x42" "SFS" },
477 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ 478 { "\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[] = {
485 { "\x87" "NTFS volume set" }, 486 { "\x87" "NTFS volume set" },
486 { "\x8e" "Linux LVM" }, 487 { "\x8e" "Linux LVM" },
487 { "\x9f" "BSD/OS" }, /* BSDI */ 488 { "\x9f" "BSD/OS" }, /* BSDI */
488 { "\xa0" "IBM Thinkpad hibernation" }, 489 { "\xa0" "Thinkpad hibernation" },
489 { "\xa5" "FreeBSD" }, /* various BSD flavours */ 490 { "\xa5" "FreeBSD" }, /* various BSD flavours */
490 { "\xa6" "OpenBSD" }, 491 { "\xa6" "OpenBSD" },
491 { "\xa8" "Darwin UFS" }, 492 { "\xa8" "Darwin UFS" },
@@ -718,71 +719,61 @@ is_dos_partition(int t)
718static void 719static void
719menu(void) 720menu(void)
720{ 721{
722 puts(_("Command Action"));
721 if (LABEL_IS_SUN) { 723 if (LABEL_IS_SUN) {
722 puts(_("Command action")); 724 puts(_("a\ttoggle a read only flag")); /* sun */
723 puts(_("\ta\ttoggle a read only flag")); /* sun */ 725 puts(_("b\tedit bsd disklabel"));
724 puts(_("\tb\tedit bsd disklabel")); 726 puts(_("c\ttoggle the mountable flag")); /* sun */
725 puts(_("\tc\ttoggle the mountable flag")); /* sun */ 727 puts(_("d\tdelete a partition"));
726 puts(_("\td\tdelete a partition")); 728 puts(_("l\tlist known partition types"));
727 puts(_("\tl\tlist known partition types")); 729 puts(_("n\tadd a new partition"));
728 puts(_("\tm\tprint this menu")); 730 puts(_("o\tcreate a new empty DOS partition table"));
729 puts(_("\tn\tadd a new partition")); 731 puts(_("p\tprint the partition table"));
730 puts(_("\to\tcreate a new empty DOS partition table")); 732 puts(_("q\tquit without saving changes"));
731 puts(_("\tp\tprint the partition table")); 733 puts(_("s\tcreate a new empty Sun disklabel")); /* sun */
732 puts(_("\tq\tquit without saving changes")); 734 puts(_("t\tchange a partition's system id"));
733 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */ 735 puts(_("u\tchange display/entry units"));
734 puts(_("\tt\tchange a partition's system id")); 736 puts(_("v\tverify the partition table"));
735 puts(_("\tu\tchange display/entry units")); 737 puts(_("w\twrite table to disk and exit"));
736 puts(_("\tv\tverify the partition table"));
737 puts(_("\tw\twrite table to disk and exit"));
738#if ENABLE_FEATURE_FDISK_ADVANCED 738#if ENABLE_FEATURE_FDISK_ADVANCED
739 puts(_("\tx\textra functionality (experts only)")); 739 puts(_("x\textra functionality (experts only)"));
740#endif 740#endif
741 } else 741 } else if (LABEL_IS_SGI) {
742 if (LABEL_IS_SGI) { 742 puts(_("a\tselect bootable partition")); /* sgi flavour */
743 puts(_("Command action")); 743 puts(_("b\tedit bootfile entry")); /* sgi */
744 puts(_("\ta\tselect bootable partition")); /* sgi flavour */ 744 puts(_("c\tselect sgi swap partition")); /* sgi flavour */
745 puts(_("\tb\tedit bootfile entry")); /* sgi */ 745 puts(_("d\tdelete a partition"));
746 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */ 746 puts(_("l\tlist known partition types"));
747 puts(_("\td\tdelete a partition")); 747 puts(_("n\tadd a new partition"));
748 puts(_("\tl\tlist known partition types")); 748 puts(_("o\tcreate a new empty DOS partition table"));
749 puts(_("\tm\tprint this menu")); 749 puts(_("p\tprint the partition table"));
750 puts(_("\tn\tadd a new partition")); 750 puts(_("q\tquit without saving changes"));
751 puts(_("\to\tcreate a new empty DOS partition table")); 751 puts(_("s\tcreate a new empty Sun disklabel")); /* sun */
752 puts(_("\tp\tprint the partition table")); 752 puts(_("t\tchange a partition's system id"));
753 puts(_("\tq\tquit without saving changes")); 753 puts(_("u\tchange display/entry units"));
754 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */ 754 puts(_("v\tverify the partition table"));
755 puts(_("\tt\tchange a partition's system id")); 755 puts(_("w\twrite table to disk and exit"));
756 puts(_("\tu\tchange display/entry units")); 756 } else if (LABEL_IS_AIX) {
757 puts(_("\tv\tverify the partition table")); 757 puts(_("o\tcreate a new empty DOS partition table"));
758 puts(_("\tw\twrite table to disk and exit")); 758 puts(_("q\tquit without saving changes"));
759 } else 759 puts(_("s\tcreate a new empty Sun disklabel")); /* sun */
760 if (LABEL_IS_AIX) { 760 } else {
761 puts(_("Command action")); 761 puts(_("a\ttoggle a bootable flag"));
762 puts(_("\tm\tprint this menu")); 762 puts(_("b\tedit bsd disklabel"));
763 puts(_("\to\tcreate a new empty DOS partition table")); 763 puts(_("c\ttoggle the dos compatibility flag"));
764 puts(_("\tq\tquit without saving changes")); 764 puts(_("d\tdelete a partition"));
765 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */ 765 puts(_("l\tlist known partition types"));
766 } else 766 puts(_("n\tadd a new partition"));
767 { 767 puts(_("o\tcreate a new empty DOS partition table"));
768 puts(_("Command action")); 768 puts(_("p\tprint the partition table"));
769 puts(_("\ta\ttoggle a bootable flag")); 769 puts(_("q\tquit without saving changes"));
770 puts(_("\tb\tedit bsd disklabel")); 770 puts(_("s\tcreate a new empty Sun disklabel")); /* sun */
771 puts(_("\tc\ttoggle the dos compatibility flag")); 771 puts(_("t\tchange a partition's system id"));
772 puts(_("\td\tdelete a partition")); 772 puts(_("u\tchange display/entry units"));
773 puts(_("\tl\tlist known partition types")); 773 puts(_("v\tverify the partition table"));
774 puts(_("\tm\tprint this menu")); 774 puts(_("w\twrite table to disk and exit"));
775 puts(_("\tn\tadd a new partition"));
776 puts(_("\to\tcreate a new empty DOS partition table"));
777 puts(_("\tp\tprint the partition table"));
778 puts(_("\tq\tquit without saving changes"));
779 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
780 puts(_("\tt\tchange a partition's system id"));
781 puts(_("\tu\tchange display/entry units"));
782 puts(_("\tv\tverify the partition table"));
783 puts(_("\tw\twrite table to disk and exit"));
784#if ENABLE_FEATURE_FDISK_ADVANCED 775#if ENABLE_FEATURE_FDISK_ADVANCED
785 puts(_("\tx\textra functionality (experts only)")); 776 puts(_("x\textra functionality (experts only)"));
786#endif 777#endif
787 } 778 }
788} 779}
@@ -793,73 +784,64 @@ menu(void)
793static void 784static void
794xmenu(void) 785xmenu(void)
795{ 786{
787 puts(_("Command Action"));
796 if (LABEL_IS_SUN) { 788 if (LABEL_IS_SUN) {
797 puts(_("Command action")); 789 puts(_("a\tchange number of alternate cylinders")); /*sun*/
798 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/ 790 puts(_("c\tchange number of cylinders"));
799 puts(_("\tc\tchange number of cylinders")); 791 puts(_("d\tprint the raw data in the partition table"));
800 puts(_("\td\tprint the raw data in the partition table")); 792 puts(_("e\tchange number of extra sectors per cylinder"));/*sun*/
801 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/ 793 puts(_("h\tchange number of heads"));
802 puts(_("\th\tchange number of heads")); 794 puts(_("i\tchange interleave factor")); /*sun*/
803 puts(_("\ti\tchange interleave factor")); /*sun*/ 795 puts(_("o\tchange rotation speed (rpm)")); /*sun*/
804 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/ 796 puts(_("p\tprint the partition table"));
805 puts(_("\tm\tprint this menu")); 797 puts(_("q\tquit without saving changes"));
806 puts(_("\tp\tprint the partition table")); 798 puts(_("r\treturn to main menu"));
807 puts(_("\tq\tquit without saving changes")); 799 puts(_("s\tchange number of sectors/track"));
808 puts(_("\tr\treturn to main menu")); 800 puts(_("v\tverify the partition table"));
809 puts(_("\ts\tchange number of sectors/track")); 801 puts(_("w\twrite table to disk and exit"));
810 puts(_("\tv\tverify the partition table")); 802 puts(_("y\tchange number of physical cylinders")); /*sun*/
811 puts(_("\tw\twrite table to disk and exit")); 803 } else if (LABEL_IS_SGI) {
812 puts(_("\ty\tchange number of physical cylinders")); /*sun*/ 804 puts(_("b\tmove beginning of data in a partition")); /* !sun */
813 } else 805 puts(_("c\tchange number of cylinders"));
814 if (LABEL_IS_SGI) { 806 puts(_("d\tprint the raw data in the partition table"));
815 puts(_("Command action")); 807 puts(_("e\tlist extended partitions")); /* !sun */
816 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */ 808 puts(_("g\tcreate an IRIX (SGI) partition table"));/* sgi */
817 puts(_("\tc\tchange number of cylinders")); 809 puts(_("h\tchange number of heads"));
818 puts(_("\td\tprint the raw data in the partition table")); 810 puts(_("p\tprint the partition table"));
819 puts(_("\te\tlist extended partitions")); /* !sun */ 811 puts(_("q\tquit without saving changes"));
820 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */ 812 puts(_("r\treturn to main menu"));
821 puts(_("\th\tchange number of heads")); 813 puts(_("s\tchange number of sectors/track"));
822 puts(_("\tm\tprint this menu")); 814 puts(_("v\tverify the partition table"));
823 puts(_("\tp\tprint the partition table")); 815 puts(_("w\twrite table to disk and exit"));
824 puts(_("\tq\tquit without saving changes")); 816 } else if (LABEL_IS_AIX) {
825 puts(_("\tr\treturn to main menu")); 817 puts(_("b\tmove beginning of data in a partition")); /* !sun */
826 puts(_("\ts\tchange number of sectors/track")); 818 puts(_("c\tchange number of cylinders"));
827 puts(_("\tv\tverify the partition table")); 819 puts(_("d\tprint the raw data in the partition table"));
828 puts(_("\tw\twrite table to disk and exit")); 820 puts(_("e\tlist extended partitions")); /* !sun */
829 } else 821 puts(_("g\tcreate an IRIX (SGI) partition table"));/* sgi */
830 if (LABEL_IS_AIX) { 822 puts(_("h\tchange number of heads"));
831 puts(_("Command action")); 823 puts(_("p\tprint the partition table"));
832 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */ 824 puts(_("q\tquit without saving changes"));
833 puts(_("\tc\tchange number of cylinders")); 825 puts(_("r\treturn to main menu"));
834 puts(_("\td\tprint the raw data in the partition table")); 826 puts(_("s\tchange number of sectors/track"));
835 puts(_("\te\tlist extended partitions")); /* !sun */ 827 puts(_("v\tverify the partition table"));
836 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */ 828 puts(_("w\twrite table to disk and exit"));
837 puts(_("\th\tchange number of heads")); 829 } else {
838 puts(_("\tm\tprint this menu")); 830 puts(_("b\tmove beginning of data in a partition")); /* !sun */
839 puts(_("\tp\tprint the partition table")); 831 puts(_("c\tchange number of cylinders"));
840 puts(_("\tq\tquit without saving changes")); 832 puts(_("d\tprint the raw data in the partition table"));
841 puts(_("\tr\treturn to main menu")); 833 puts(_("e\tlist extended partitions")); /* !sun */
842 puts(_("\ts\tchange number of sectors/track")); 834 puts(_("f\tfix partition order")); /* !sun, !aix, !sgi */
843 puts(_("\tv\tverify the partition table"));
844 puts(_("\tw\twrite table to disk and exit"));
845 } else {
846 puts(_("Command action"));
847 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
848 puts(_("\tc\tchange number of cylinders"));
849 puts(_("\td\tprint the raw data in the partition table"));
850 puts(_("\te\tlist extended partitions")); /* !sun */
851 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
852#if ENABLE_FEATURE_SGI_LABEL 835#if ENABLE_FEATURE_SGI_LABEL
853 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */ 836 puts(_("g\tcreate an IRIX (SGI) partition table"));/* sgi */
854#endif 837#endif
855 puts(_("\th\tchange number of heads")); 838 puts(_("h\tchange number of heads"));
856 puts(_("\tm\tprint this menu")); 839 puts(_("p\tprint the partition table"));
857 puts(_("\tp\tprint the partition table")); 840 puts(_("q\tquit without saving changes"));
858 puts(_("\tq\tquit without saving changes")); 841 puts(_("r\treturn to main menu"));
859 puts(_("\tr\treturn to main menu")); 842 puts(_("s\tchange number of sectors/track"));
860 puts(_("\ts\tchange number of sectors/track")); 843 puts(_("v\tverify the partition table"));
861 puts(_("\tv\tverify the partition table")); 844 puts(_("w\twrite table to disk and exit"));
862 puts(_("\tw\twrite table to disk and exit"));
863 } 845 }
864} 846}
865#endif /* ADVANCED mode */ 847#endif /* ADVANCED mode */
@@ -883,7 +865,7 @@ static const char *partition_type(unsigned char type)
883 const struct systypes *types = get_sys_types(); 865 const struct systypes *types = get_sys_types();
884 866
885 for (i = 0; types[i].name; i++) 867 for (i = 0; types[i].name; i++)
886 if ((unsigned char )types[i].name[0] == type) 868 if ((unsigned char)types[i].name[0] == type)
887 return types[i].name + 1; 869 return types[i].name + 1;
888 870
889 return _("Unknown"); 871 return _("Unknown");
@@ -899,24 +881,29 @@ get_sysid(int i)
899 ptes[i].part_table->sys_ind); 881 ptes[i].part_table->sys_ind);
900} 882}
901 883
902void list_types(const struct systypes *sys) 884static void list_types(const struct systypes *sys)
903{ 885{
904 unsigned last[4], done = 0, next = 0, size; 886 enum { COLS = 3 };
887
888 unsigned last[COLS];
889 unsigned done, next, size;
905 int i; 890 int i;
906 891
907 for (i = 0; sys[i].name; i++); 892 for (size = 0; sys[size].name; size++) /* */;
908 size = i;
909 893
910 for (i = 3; i >= 0; i--) 894 done = 0;
911 last[3 - i] = done += (size + i - done) / (i + 1); 895 for (i = COLS-1; i >= 0; i--) {
912 i = done = 0; 896 done += (size + i - done) / (i + 1);
897 last[COLS-1 - i] = done;
898 }
913 899
900 i = done = next = 0;
914 do { 901 do {
915 printf("%c%2x %-15.15s", i ? ' ' : '\n', 902 printf("%c%2x %-22.22s", i ? ' ' : '\n',
916 (unsigned char)sys[next].name[0], 903 (unsigned char)sys[next].name[0],
917 partition_type((unsigned char)sys[next].name[0])); 904 sys[next].name + 1);
918 next = last[i++] + done; 905 next = last[i++] + done;
919 if (i > 3 || next >= last[i]) { 906 if (i >= COLS || next >= last[i]) {
920 i = 0; 907 i = 0;
921 next = ++done; 908 next = ++done;
922 } 909 }
@@ -2415,10 +2402,12 @@ new_partition(void)
2415 "an extended partition first\n")); 2402 "an extended partition first\n"));
2416 } else { 2403 } else {
2417 char c, line[LINE_LENGTH]; 2404 char c, line[LINE_LENGTH];
2418 snprintf(line, sizeof(line), "%s\n %s\n p primary " 2405 snprintf(line, sizeof(line),
2419 "partition (1-4)\n", 2406 "Command action\n"
2420 "Command action", (extended_offset ? 2407 " %s\n"
2421 "l logical (5 or over)" : "e extended")); 2408 " p primary partition (1-4)\n",
2409 (extended_offset ?
2410 "l logical (5 or over)" : "e extended"));
2422 while (1) { 2411 while (1) {
2423 c = read_nonempty(line); 2412 c = read_nonempty(line);
2424 if (c == 'p' || c == 'P') { 2413 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)
308static void 308static void
309bsd_menu(void) 309bsd_menu(void)
310{ 310{
311 puts(_("Command action")); 311 puts(_("Command Action"));
312 puts(_("\td\tdelete a BSD partition")); 312 puts(_("d\tdelete a BSD partition"));
313 puts(_("\te\tedit drive data")); 313 puts(_("e\tedit drive data"));
314 puts(_("\ti\tinstall bootstrap")); 314 puts(_("i\tinstall bootstrap"));
315 puts(_("\tl\tlist known filesystem types")); 315 puts(_("l\tlist known filesystem types"));
316 puts(_("\tm\tprint this menu")); 316 puts(_("n\tadd a new BSD partition"));
317 puts(_("\tn\tadd a new BSD partition")); 317 puts(_("p\tprint BSD partition table"));
318 puts(_("\tp\tprint BSD partition table")); 318 puts(_("q\tquit without saving changes"));
319 puts(_("\tq\tquit without saving changes")); 319 puts(_("r\treturn to main menu"));
320 puts(_("\tr\treturn to main menu")); 320 puts(_("s\tshow complete disklabel"));
321 puts(_("\ts\tshow complete disklabel")); 321 puts(_("t\tchange a partition's filesystem id"));
322 puts(_("\tt\tchange a partition's filesystem id")); 322 puts(_("u\tchange units (cylinders/sectors)"));
323 puts(_("\tu\tchange units (cylinders/sectors)")); 323 puts(_("w\twrite disklabel to disk"));
324 puts(_("\tw\twrite disklabel to disk"));
325#if !defined(__alpha__) 324#if !defined(__alpha__)
326 puts(_("\tx\tlink BSD partition to non-BSD partition")); 325 puts(_("x\tlink BSD partition to non-BSD partition"));
327#endif 326#endif
328} 327}
329 328
@@ -633,13 +632,15 @@ xbsd_create_disklabel(void)
633static int 632static int
634edit_int(int def, char *mesg) 633edit_int(int def, char *mesg)
635{ 634{
635 mesg = xasprintf("%s (%d): ", mesg, def);
636 do { 636 do {
637 fputs(mesg, stdout); 637 if (!read_line(mesg))
638 printf(" (%d): ", def); 638 goto ret;
639 if (!read_line())
640 return def;
641 } while (!isdigit(*line_ptr)); 639 } while (!isdigit(*line_ptr));
642 return atoi(line_ptr); 640 def = atoi(line_ptr);
641 ret:
642 free(mesg);
643 return def;
643} 644}
644 645
645static void 646static void
@@ -718,10 +719,9 @@ xbsd_write_bootstrap(void)
718 else 719 else
719 dkbasename = "wd"; 720 dkbasename = "wd";
720 721
721 printf(_("Bootstrap: %sboot -> boot%s (%s): "), 722 snprintf(path, sizeof(path), "Bootstrap: %sboot -> boot%s (%s): ",
722 dkbasename, dkbasename, dkbasename); 723 dkbasename, dkbasename, dkbasename);
723 if (read_line()) { 724 if (read_line(path)) {
724 line_ptr[strlen(line_ptr)-1] = '\0';
725 dkbasename = line_ptr; 725 dkbasename = line_ptr;
726 } 726 }
727 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename); 727 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);