diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-01-22 07:21:38 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-01-22 07:21:38 +0000 |
commit | 145366b9719857c48f9a7ada7d7e0ff8edfbd0de (patch) | |
tree | 2f115293c25e7ee9307f268ec198e2cf486ff070 | |
parent | 5c7a4f79ea56b11e0e9927dc51268d7049aadf2e (diff) | |
download | busybox-w32-145366b9719857c48f9a7ada7d7e0ff8edfbd0de.tar.gz busybox-w32-145366b9719857c48f9a7ada7d7e0ff8edfbd0de.tar.bz2 busybox-w32-145366b9719857c48f9a7ada7d7e0ff8edfbd0de.zip |
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.
git-svn-id: svn://busybox.net/trunk/busybox@17446 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | include/libbb.h | 36 | ||||
-rw-r--r-- | shell/Kbuild | 10 | ||||
-rw-r--r-- | shell/ash.c | 106 | ||||
-rw-r--r-- | shell/cmdedit.c | 316 | ||||
-rw-r--r-- | shell/cmdedit.h | 21 | ||||
-rw-r--r-- | shell/hush.c | 13 | ||||
-rw-r--r-- | shell/lash.c | 14 | ||||
-rw-r--r-- | shell/msh.c | 26 | ||||
-rw-r--r-- | util-linux/fdisk.c | 309 | ||||
-rw-r--r-- | util-linux/fdisk_osf.c | 46 |
10 files changed, 459 insertions, 438 deletions
diff --git a/include/libbb.h b/include/libbb.h index 0b066d1bd..f990b0ebd 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -583,6 +583,42 @@ extern unsigned long long bb_makedev(unsigned int major, unsigned int minor); | |||
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 | ||
593 | struct 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 | }; | ||
603 | enum { | ||
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 | }; | ||
612 | typedef struct line_input_t line_input_t; | ||
613 | line_input_t *new_line_input_t(int flags); | ||
614 | int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state); | ||
615 | #else | ||
616 | int 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 |
588 | enum { COMM_LEN = TASK_COMM_LEN }; | 624 | enum { COMM_LEN = TASK_COMM_LEN }; |
diff --git a/shell/Kbuild b/shell/Kbuild index eb0199ee2..9c60698f7 100644 --- a/shell/Kbuild +++ b/shell/Kbuild | |||
@@ -5,8 +5,8 @@ | |||
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 | ||
7 | lib-y:= | 7 | lib-y:= |
8 | lib-$(CONFIG_ASH) += ash.o | 8 | lib-y += cmdedit.o |
9 | lib-$(CONFIG_HUSH) += hush.o | 9 | lib-$(CONFIG_ASH) += ash.o |
10 | lib-$(CONFIG_LASH) += lash.o | 10 | lib-$(CONFIG_HUSH) += hush.o |
11 | lib-$(CONFIG_MSH) += msh.o | 11 | lib-$(CONFIG_LASH) += lash.o |
12 | lib-$(CONFIG_FEATURE_COMMAND_EDITING) += cmdedit.o | 12 | lib-$(CONFIG_MSH) += msh.o |
diff --git a/shell/ash.c b/shell/ash.c index 2db3302c7..8afdf3d21 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -92,7 +92,6 @@ | |||
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 **); | |||
1238 | static int getoptscmd(int, char **); | 1237 | static int getoptscmd(int, char **); |
1239 | #endif | 1238 | #endif |
1240 | static int hashcmd(int, char **); | 1239 | static int hashcmd(int, char **); |
1241 | #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET | 1240 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET |
1242 | static int helpcmd(int argc, char **argv); | 1241 | static 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 | 6044 | static line_input_t *line_input_state; |
6050 | #ifdef CONFIG_ASH_EXPAND_PRMT | 6045 | //static SKIP_ASH_EXPAND_PRMT(const) char *cmdedit_prompt; |
6051 | static char *cmdedit_prompt; | ||
6052 | #else | ||
6053 | static const char *cmdedit_prompt; | 6046 | static const char *cmdedit_prompt; |
6054 | #endif | ||
6055 | static void putprompt(const char *s) | 6047 | static 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 |
6065 | static void putprompt(const char *s) | 6057 | static 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 | |||
6071 | static int preadfd(void) | 6073 | static 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 | ||
6077 | retry: | 6079 | retry: |
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 |
8006 | state4: /* 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 | ||
11903 | static int helpcmd(int argc, char **argv) | 11909 | static 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 | ||
11966 | out: | 11964 | out: |
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 | ||
13494 | static arith_t arith (const char *expr, int *perrcode) | 13492 | static 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 | ||
63 | static line_input_t *state; | ||
71 | 64 | ||
72 | /* Current termios and the previous termios before starting sh */ | ||
73 | static struct termios initial_settings, new_settings; | 65 | static struct termios initial_settings, new_settings; |
74 | 66 | ||
75 | static | 67 | static volatile unsigned cmdedit_termw = 80; /* actual terminal width */ |
76 | volatile unsigned cmdedit_termw = 80; /* actual terminal width */ | ||
77 | |||
78 | 68 | ||
79 | static int cmdedit_x; /* real x terminal position */ | 69 | static int cmdedit_x; /* real x terminal position */ |
80 | static int cmdedit_y; /* pseudoreal y terminal position */ | 70 | static int cmdedit_y; /* pseudoreal y terminal position */ |
81 | static int cmdedit_prmt_len; /* length of prompt (without colors etc) */ | 71 | static int cmdedit_prmt_len; /* length of prompt (without colors etc) */ |
82 | 72 | ||
83 | static int cursor; | 73 | static unsigned cursor; |
84 | static int len; | 74 | static unsigned command_len; |
85 | static char *command_ps; | 75 | static char *command_ps; |
86 | static SKIP_FEATURE_SH_FANCY_PROMPT(const) char *cmdedit_prompt; | 76 | static const char *cmdedit_prompt; |
87 | 77 | ||
88 | #if ENABLE_FEATURE_SH_FANCY_PROMPT | 78 | #if ENABLE_FEATURE_SH_FANCY_PROMPT |
89 | static char *hostname_buf; | 79 | static 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) */ |
143 | static void input_end(void) | 133 | static 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) | |||
200 | static void put_prompt(void) | 190 | static 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 */ |
286 | static void input_forward(void) | 276 | static 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 | ||
376 | const char *cmdedit_path_lookup; | ||
377 | #endif | ||
378 | static int path_parse(char ***p, int flags) | 365 | static 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 */ |
743 | static void input_tab(int *lastWasTab) | 729 | static 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 | ||
863 | static char *history[MAX_HISTORY+1]; /* history + current */ | 854 | /* state->flags is already checked to be nonzero */ |
864 | /* saved history lines */ | ||
865 | static int n_history; | ||
866 | /* current pointer to history line */ | ||
867 | static int cur_history; | ||
868 | |||
869 | static void get_previous_history(void) | 855 | static 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 | ||
878 | static int get_next_history(void) | 864 | static 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 */ | ||
893 | void load_history(const char *fromfile) | 880 | void 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 */ | ||
927 | void save_history(const char *tofile) | 914 | void 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 */ | 933 | static 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 |
963 | static int vi_mode; | ||
964 | |||
965 | void setvimode(int viflag) | ||
966 | { | ||
967 | vi_mode = viflag; | ||
968 | } | ||
969 | |||
970 | static void | 982 | static void |
971 | vi_Word_motion(char *command, int eat) | 983 | vi_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 | ||
1062 | enum { 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 | 1288 | int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *st) | |
1279 | int 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 | |||
1754 | line_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 | ||
1764 | int 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 | |||
5 | int cmdedit_read_input(char* promptStr, char* command); | ||
6 | |||
7 | #if ENABLE_ASH | ||
8 | extern const char *cmdedit_path_lookup; | ||
9 | #endif | ||
10 | |||
11 | #if ENABLE_FEATURE_COMMAND_SAVEHISTORY | ||
12 | void load_history(const char *fromfile); | ||
13 | void save_history(const char *tofile); | ||
14 | #endif | ||
15 | |||
16 | #if ENABLE_FEATURE_COMMAND_EDITING_VI | ||
17 | void 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 | ||
886 | static line_input_t *line_input_state; | ||
887 | #endif | ||
888 | |||
886 | static void get_user_input(struct in_str *i) | 889 | static 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 | ||
643 | static line_input_t *line_input_state; | ||
644 | #endif | ||
645 | |||
644 | static int get_command(FILE * source, char *command) | 646 | static 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 |
781 | static char *current_prompt; | 780 | static 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 | ||
790 | static line_input_t *line_input_state; | ||
791 | #endif | ||
792 | |||
790 | int msh_main(int argc, char **argv) | 793 | int 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) | |||
291 | static char line_buffer[LINE_LENGTH]; | 291 | static char line_buffer[LINE_LENGTH]; |
292 | static char *line_ptr; | 292 | static char *line_ptr; |
293 | 293 | ||
294 | /* read line; return 0 or first char */ | 294 | /* read line; return 0 or first printable char */ |
295 | static int | 295 | static int |
296 | read_line(void) | 296 | read_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) | |||
309 | static char | 313 | static char |
310 | read_nonempty(const char *mesg) | 314 | read_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 | ||
318 | static char | 320 | static char |
319 | read_maybe_empty(const char *mesg) | 321 | read_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 | ||
330 | static int | 331 | static 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) | |||
718 | static void | 719 | static void |
719 | menu(void) | 720 | menu(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) | |||
793 | static void | 784 | static void |
794 | xmenu(void) | 785 | xmenu(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 | ||
902 | void list_types(const struct systypes *sys) | 884 | static 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) | |||
308 | static void | 308 | static void |
309 | bsd_menu(void) | 309 | bsd_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) | |||
633 | static int | 632 | static int |
634 | edit_int(int def, char *mesg) | 633 | edit_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 | ||
645 | static void | 646 | static 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); |