diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-07-28 12:13:58 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-07-28 12:13:58 +0200 |
commit | aa449c927d1d84092f9654e45ab9f68847e81226 (patch) | |
tree | 3ae7ea620aa9498cac9d8f2efac73a90ecdf52a6 | |
parent | 4b70c926bcbfaf6df6e21c98ea096b0db8629095 (diff) | |
download | busybox-w32-aa449c927d1d84092f9654e45ab9f68847e81226.tar.gz busybox-w32-aa449c927d1d84092f9654e45ab9f68847e81226.tar.bz2 busybox-w32-aa449c927d1d84092f9654e45ab9f68847e81226.zip |
hush: make "set -x" output don't redirectable when fd#2 redirected
function old new delta
x_mode_print_optionally_squoted - 120 +120
x_mode_flush - 68 +68
save_fd_on_redirect 208 243 +35
x_mode_prefix - 27 +27
x_mode_addblock - 23 +23
x_mode_addchr - 17 +17
dump_cmd_in_x_mode 110 85 -25
run_pipe 1919 1890 -29
print_optionally_squoted 145 - -145
------------------------------------------------------------------------------
(add/remove: 5/1 grow/shrink: 1/2 up/down: 290/-199) Total: 91 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 129 |
1 files changed, 84 insertions, 45 deletions
diff --git a/shell/hush.c b/shell/hush.c index ac8467fb4..9676819fa 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -955,9 +955,6 @@ struct globals { | |||
955 | # endif | 955 | # endif |
956 | struct function *top_func; | 956 | struct function *top_func; |
957 | #endif | 957 | #endif |
958 | #if ENABLE_HUSH_MODE_X | ||
959 | unsigned x_mode_depth; | ||
960 | #endif | ||
961 | /* Signal and trap handling */ | 958 | /* Signal and trap handling */ |
962 | #if ENABLE_HUSH_FAST | 959 | #if ENABLE_HUSH_FAST |
963 | unsigned count_SIGCHLD; | 960 | unsigned count_SIGCHLD; |
@@ -993,6 +990,15 @@ struct globals { | |||
993 | #if ENABLE_HUSH_MEMLEAK | 990 | #if ENABLE_HUSH_MEMLEAK |
994 | unsigned long memleak_value; | 991 | unsigned long memleak_value; |
995 | #endif | 992 | #endif |
993 | #if ENABLE_HUSH_MODE_X | ||
994 | unsigned x_mode_depth; | ||
995 | /* "set -x" output should not be redirectable with subsequent 2>FILE. | ||
996 | * We dup fd#2 to x_mode_fd when "set -x" is executed, and use it | ||
997 | * for all subsequent output. | ||
998 | */ | ||
999 | int x_mode_fd; | ||
1000 | o_string x_mode_buf; | ||
1001 | #endif | ||
996 | #if HUSH_DEBUG | 1002 | #if HUSH_DEBUG |
997 | int debug_indent; | 1003 | int debug_indent; |
998 | #endif | 1004 | #endif |
@@ -1660,6 +1666,12 @@ static int move_HFILEs_on_redirect(int fd, int avoid_fd) | |||
1660 | } | 1666 | } |
1661 | fl = fl->next_hfile; | 1667 | fl = fl->next_hfile; |
1662 | } | 1668 | } |
1669 | #if ENABLE_HUSH_MODE_X | ||
1670 | if (G.x_mode_fd > 0 && fd == G.x_mode_fd) { | ||
1671 | G.x_mode_fd = xdup_CLOEXEC_and_close(fd, avoid_fd); | ||
1672 | return 1; /* "found and moved" */ | ||
1673 | } | ||
1674 | #endif | ||
1663 | return 0; /* "not in the list" */ | 1675 | return 0; /* "not in the list" */ |
1664 | } | 1676 | } |
1665 | #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU | 1677 | #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU |
@@ -2903,6 +2915,11 @@ static void o_addstr(o_string *o, const char *str) | |||
2903 | o_addblock(o, str, strlen(str)); | 2915 | o_addblock(o, str, strlen(str)); |
2904 | } | 2916 | } |
2905 | 2917 | ||
2918 | static void o_addstr_with_NUL(o_string *o, const char *str) | ||
2919 | { | ||
2920 | o_addblock(o, str, strlen(str) + 1); | ||
2921 | } | ||
2922 | |||
2906 | #if !BB_MMU | 2923 | #if !BB_MMU |
2907 | static void nommu_addchr(o_string *o, int ch) | 2924 | static void nommu_addchr(o_string *o, int ch) |
2908 | { | 2925 | { |
@@ -2913,10 +2930,36 @@ static void nommu_addchr(o_string *o, int ch) | |||
2913 | # define nommu_addchr(o, str) ((void)0) | 2930 | # define nommu_addchr(o, str) ((void)0) |
2914 | #endif | 2931 | #endif |
2915 | 2932 | ||
2916 | static void o_addstr_with_NUL(o_string *o, const char *str) | 2933 | #if ENABLE_HUSH_MODE_X |
2934 | static void x_mode_addchr(int ch) | ||
2917 | { | 2935 | { |
2918 | o_addblock(o, str, strlen(str) + 1); | 2936 | o_addchr(&G.x_mode_buf, ch); |
2919 | } | 2937 | } |
2938 | static void x_mode_addstr(const char *str) | ||
2939 | { | ||
2940 | o_addstr(&G.x_mode_buf, str); | ||
2941 | } | ||
2942 | static void x_mode_addblock(const char *str, int len) | ||
2943 | { | ||
2944 | o_addblock(&G.x_mode_buf, str, len); | ||
2945 | } | ||
2946 | static void x_mode_prefix(void) | ||
2947 | { | ||
2948 | int n = G.x_mode_depth; | ||
2949 | do x_mode_addchr('+'); while (--n >= 0); | ||
2950 | } | ||
2951 | static void x_mode_flush(void) | ||
2952 | { | ||
2953 | int len = G.x_mode_buf.length; | ||
2954 | if (len <= 0) | ||
2955 | return; | ||
2956 | if (G.x_mode_fd > 0) { | ||
2957 | G.x_mode_buf.data[len] = '\n'; | ||
2958 | full_write(G.x_mode_fd, G.x_mode_buf.data, len + 1); | ||
2959 | } | ||
2960 | G.x_mode_buf.length = 0; | ||
2961 | } | ||
2962 | #endif | ||
2920 | 2963 | ||
2921 | /* | 2964 | /* |
2922 | * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side. | 2965 | * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side. |
@@ -8030,31 +8073,26 @@ static void execvp_or_die(char **argv) | |||
8030 | } | 8073 | } |
8031 | 8074 | ||
8032 | #if ENABLE_HUSH_MODE_X | 8075 | #if ENABLE_HUSH_MODE_X |
8033 | static void print_optionally_squoted(FILE *fp, const char *str) | 8076 | static void x_mode_print_optionally_squoted(const char *str) |
8034 | { | 8077 | { |
8035 | unsigned len; | 8078 | unsigned len; |
8036 | const char *cp; | 8079 | const char *cp; |
8037 | 8080 | ||
8038 | cp = str; | 8081 | cp = str; |
8039 | if (str[0] != '{' && str[0] != '(') for (;;) { | 8082 | |
8040 | if (!*cp) { | 8083 | /* the set of chars which-cause-string-to-be-squoted mimics bash */ |
8041 | /* string has no special chars */ | 8084 | /* test a char with: bash -c 'set -x; echo "CH"' */ |
8042 | fputs(str, fp); | 8085 | if (str[strcspn(str, "\\\"'`$(){}[]<>;#&|~*?!^" |
8043 | return; | 8086 | " " "\001\002\003\004\005\006\007" |
8044 | } | 8087 | "\010\011\012\013\014\015\016\017" |
8045 | if (*cp == '\\') break; | 8088 | "\020\021\022\023\024\025\026\027" |
8046 | if (*cp == '\'') break; | 8089 | "\030\031\032\033\034\035\036\037" |
8047 | if (*cp == '"') break; | 8090 | ) |
8048 | if (*cp == '$') break; | 8091 | ] == '\0' |
8049 | if (*cp == '!') break; | 8092 | ) { |
8050 | if (*cp == '*') break; | 8093 | /* string has no special chars */ |
8051 | if (*cp == '[') break; | 8094 | x_mode_addstr(str); |
8052 | if (*cp == ']') break; | 8095 | return; |
8053 | #if ENABLE_HUSH_TICK | ||
8054 | if (*cp == '`') break; | ||
8055 | #endif | ||
8056 | if (isspace(*cp)) break; | ||
8057 | cp++; | ||
8058 | } | 8096 | } |
8059 | 8097 | ||
8060 | cp = str; | 8098 | cp = str; |
@@ -8062,13 +8100,16 @@ static void print_optionally_squoted(FILE *fp, const char *str) | |||
8062 | /* print '....' up to EOL or first squote */ | 8100 | /* print '....' up to EOL or first squote */ |
8063 | len = (int)(strchrnul(cp, '\'') - cp); | 8101 | len = (int)(strchrnul(cp, '\'') - cp); |
8064 | if (len != 0) { | 8102 | if (len != 0) { |
8065 | fprintf(fp, "'%.*s'", len, cp); | 8103 | x_mode_addchr('\''); |
8104 | x_mode_addblock(cp, len); | ||
8105 | x_mode_addchr('\''); | ||
8066 | cp += len; | 8106 | cp += len; |
8067 | } | 8107 | } |
8068 | if (*cp == '\0') | 8108 | if (*cp == '\0') |
8069 | break; | 8109 | break; |
8070 | /* string contains squote(s), print them as \' */ | 8110 | /* string contains squote(s), print them as \' */ |
8071 | fprintf(fp, "\\'"); | 8111 | x_mode_addchr('\\'); |
8112 | x_mode_addchr('\''); | ||
8072 | cp++; | 8113 | cp++; |
8073 | } | 8114 | } |
8074 | } | 8115 | } |
@@ -8078,19 +8119,19 @@ static void dump_cmd_in_x_mode(char **argv) | |||
8078 | unsigned n; | 8119 | unsigned n; |
8079 | 8120 | ||
8080 | /* "+[+++...][ cmd...]\n\0" */ | 8121 | /* "+[+++...][ cmd...]\n\0" */ |
8081 | n = G.x_mode_depth; | 8122 | x_mode_prefix(); |
8082 | do bb_putchar_stderr('+'); while ((int)(--n) >= 0); | ||
8083 | n = 0; | 8123 | n = 0; |
8084 | while (argv[n]) { | 8124 | while (argv[n]) { |
8085 | if (argv[n][0] == '\0') | 8125 | x_mode_addchr(' '); |
8086 | fputs(" ''", stderr); | 8126 | if (argv[n][0] == '\0') { |
8087 | else { | 8127 | x_mode_addchr('\''); |
8088 | bb_putchar_stderr(' '); | 8128 | x_mode_addchr('\''); |
8089 | print_optionally_squoted(stderr, argv[n]); | 8129 | } else { |
8130 | x_mode_print_optionally_squoted(argv[n]); | ||
8090 | } | 8131 | } |
8091 | n++; | 8132 | n++; |
8092 | } | 8133 | } |
8093 | bb_putchar_stderr('\n'); | 8134 | x_mode_flush(); |
8094 | } | 8135 | } |
8095 | } | 8136 | } |
8096 | #else | 8137 | #else |
@@ -8885,17 +8926,14 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8885 | #if ENABLE_HUSH_MODE_X | 8926 | #if ENABLE_HUSH_MODE_X |
8886 | if (G_x_mode) { | 8927 | if (G_x_mode) { |
8887 | char *eq; | 8928 | char *eq; |
8888 | if (i == 0) { | 8929 | if (i == 0) |
8889 | unsigned n = G.x_mode_depth; | 8930 | x_mode_prefix(); |
8890 | do | 8931 | x_mode_addchr(' '); |
8891 | bb_putchar_stderr('+'); | ||
8892 | while ((int)(--n) >= 0); | ||
8893 | } | ||
8894 | eq = strchrnul(p, '='); | 8932 | eq = strchrnul(p, '='); |
8895 | fprintf(stderr, " %.*s=", (int)(eq - p), p); | 8933 | if (*eq) eq++; |
8896 | if (*eq) | 8934 | x_mode_addblock(p, (eq - p)); |
8897 | print_optionally_squoted(stderr, eq + 1); | 8935 | x_mode_print_optionally_squoted(eq); |
8898 | bb_putchar_stderr('\n'); | 8936 | x_mode_flush(); |
8899 | } | 8937 | } |
8900 | #endif | 8938 | #endif |
8901 | debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p); | 8939 | debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p); |
@@ -9691,6 +9729,7 @@ static int set_mode(int state, char mode, const char *o_opt) | |||
9691 | break; | 9729 | break; |
9692 | case 'x': | 9730 | case 'x': |
9693 | IF_HUSH_MODE_X(G_x_mode = state;) | 9731 | IF_HUSH_MODE_X(G_x_mode = state;) |
9732 | IF_HUSH_MODE_X(if (G.x_mode_fd <= 0) G.x_mode_fd = dup_CLOEXEC(2, 10);) | ||
9694 | break; | 9733 | break; |
9695 | case 'o': | 9734 | case 'o': |
9696 | if (!o_opt) { | 9735 | if (!o_opt) { |