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>
This commit is contained in:
parent
4b70c926bc
commit
aa449c927d
129
shell/hush.c
129
shell/hush.c
@ -954,9 +954,6 @@ struct globals {
|
||||
unsigned func_nest_level; /* solely to prevent "local v" in non-functions */
|
||||
# endif
|
||||
struct function *top_func;
|
||||
#endif
|
||||
#if ENABLE_HUSH_MODE_X
|
||||
unsigned x_mode_depth;
|
||||
#endif
|
||||
/* Signal and trap handling */
|
||||
#if ENABLE_HUSH_FAST
|
||||
@ -993,6 +990,15 @@ struct globals {
|
||||
#if ENABLE_HUSH_MEMLEAK
|
||||
unsigned long memleak_value;
|
||||
#endif
|
||||
#if ENABLE_HUSH_MODE_X
|
||||
unsigned x_mode_depth;
|
||||
/* "set -x" output should not be redirectable with subsequent 2>FILE.
|
||||
* We dup fd#2 to x_mode_fd when "set -x" is executed, and use it
|
||||
* for all subsequent output.
|
||||
*/
|
||||
int x_mode_fd;
|
||||
o_string x_mode_buf;
|
||||
#endif
|
||||
#if HUSH_DEBUG
|
||||
int debug_indent;
|
||||
#endif
|
||||
@ -1660,6 +1666,12 @@ static int move_HFILEs_on_redirect(int fd, int avoid_fd)
|
||||
}
|
||||
fl = fl->next_hfile;
|
||||
}
|
||||
#if ENABLE_HUSH_MODE_X
|
||||
if (G.x_mode_fd > 0 && fd == G.x_mode_fd) {
|
||||
G.x_mode_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
|
||||
return 1; /* "found and moved" */
|
||||
}
|
||||
#endif
|
||||
return 0; /* "not in the list" */
|
||||
}
|
||||
#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
|
||||
@ -2903,6 +2915,11 @@ static void o_addstr(o_string *o, const char *str)
|
||||
o_addblock(o, str, strlen(str));
|
||||
}
|
||||
|
||||
static void o_addstr_with_NUL(o_string *o, const char *str)
|
||||
{
|
||||
o_addblock(o, str, strlen(str) + 1);
|
||||
}
|
||||
|
||||
#if !BB_MMU
|
||||
static void nommu_addchr(o_string *o, int ch)
|
||||
{
|
||||
@ -2913,10 +2930,36 @@ static void nommu_addchr(o_string *o, int ch)
|
||||
# define nommu_addchr(o, str) ((void)0)
|
||||
#endif
|
||||
|
||||
static void o_addstr_with_NUL(o_string *o, const char *str)
|
||||
#if ENABLE_HUSH_MODE_X
|
||||
static void x_mode_addchr(int ch)
|
||||
{
|
||||
o_addblock(o, str, strlen(str) + 1);
|
||||
o_addchr(&G.x_mode_buf, ch);
|
||||
}
|
||||
static void x_mode_addstr(const char *str)
|
||||
{
|
||||
o_addstr(&G.x_mode_buf, str);
|
||||
}
|
||||
static void x_mode_addblock(const char *str, int len)
|
||||
{
|
||||
o_addblock(&G.x_mode_buf, str, len);
|
||||
}
|
||||
static void x_mode_prefix(void)
|
||||
{
|
||||
int n = G.x_mode_depth;
|
||||
do x_mode_addchr('+'); while (--n >= 0);
|
||||
}
|
||||
static void x_mode_flush(void)
|
||||
{
|
||||
int len = G.x_mode_buf.length;
|
||||
if (len <= 0)
|
||||
return;
|
||||
if (G.x_mode_fd > 0) {
|
||||
G.x_mode_buf.data[len] = '\n';
|
||||
full_write(G.x_mode_fd, G.x_mode_buf.data, len + 1);
|
||||
}
|
||||
G.x_mode_buf.length = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
|
||||
@ -8030,31 +8073,26 @@ static void execvp_or_die(char **argv)
|
||||
}
|
||||
|
||||
#if ENABLE_HUSH_MODE_X
|
||||
static void print_optionally_squoted(FILE *fp, const char *str)
|
||||
static void x_mode_print_optionally_squoted(const char *str)
|
||||
{
|
||||
unsigned len;
|
||||
const char *cp;
|
||||
|
||||
cp = str;
|
||||
if (str[0] != '{' && str[0] != '(') for (;;) {
|
||||
if (!*cp) {
|
||||
/* string has no special chars */
|
||||
fputs(str, fp);
|
||||
return;
|
||||
}
|
||||
if (*cp == '\\') break;
|
||||
if (*cp == '\'') break;
|
||||
if (*cp == '"') break;
|
||||
if (*cp == '$') break;
|
||||
if (*cp == '!') break;
|
||||
if (*cp == '*') break;
|
||||
if (*cp == '[') break;
|
||||
if (*cp == ']') break;
|
||||
#if ENABLE_HUSH_TICK
|
||||
if (*cp == '`') break;
|
||||
#endif
|
||||
if (isspace(*cp)) break;
|
||||
cp++;
|
||||
|
||||
/* the set of chars which-cause-string-to-be-squoted mimics bash */
|
||||
/* test a char with: bash -c 'set -x; echo "CH"' */
|
||||
if (str[strcspn(str, "\\\"'`$(){}[]<>;#&|~*?!^"
|
||||
" " "\001\002\003\004\005\006\007"
|
||||
"\010\011\012\013\014\015\016\017"
|
||||
"\020\021\022\023\024\025\026\027"
|
||||
"\030\031\032\033\034\035\036\037"
|
||||
)
|
||||
] == '\0'
|
||||
) {
|
||||
/* string has no special chars */
|
||||
x_mode_addstr(str);
|
||||
return;
|
||||
}
|
||||
|
||||
cp = str;
|
||||
@ -8062,13 +8100,16 @@ static void print_optionally_squoted(FILE *fp, const char *str)
|
||||
/* print '....' up to EOL or first squote */
|
||||
len = (int)(strchrnul(cp, '\'') - cp);
|
||||
if (len != 0) {
|
||||
fprintf(fp, "'%.*s'", len, cp);
|
||||
x_mode_addchr('\'');
|
||||
x_mode_addblock(cp, len);
|
||||
x_mode_addchr('\'');
|
||||
cp += len;
|
||||
}
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
/* string contains squote(s), print them as \' */
|
||||
fprintf(fp, "\\'");
|
||||
x_mode_addchr('\\');
|
||||
x_mode_addchr('\'');
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
@ -8078,19 +8119,19 @@ static void dump_cmd_in_x_mode(char **argv)
|
||||
unsigned n;
|
||||
|
||||
/* "+[+++...][ cmd...]\n\0" */
|
||||
n = G.x_mode_depth;
|
||||
do bb_putchar_stderr('+'); while ((int)(--n) >= 0);
|
||||
x_mode_prefix();
|
||||
n = 0;
|
||||
while (argv[n]) {
|
||||
if (argv[n][0] == '\0')
|
||||
fputs(" ''", stderr);
|
||||
else {
|
||||
bb_putchar_stderr(' ');
|
||||
print_optionally_squoted(stderr, argv[n]);
|
||||
x_mode_addchr(' ');
|
||||
if (argv[n][0] == '\0') {
|
||||
x_mode_addchr('\'');
|
||||
x_mode_addchr('\'');
|
||||
} else {
|
||||
x_mode_print_optionally_squoted(argv[n]);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
bb_putchar_stderr('\n');
|
||||
x_mode_flush();
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -8885,17 +8926,14 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
||||
#if ENABLE_HUSH_MODE_X
|
||||
if (G_x_mode) {
|
||||
char *eq;
|
||||
if (i == 0) {
|
||||
unsigned n = G.x_mode_depth;
|
||||
do
|
||||
bb_putchar_stderr('+');
|
||||
while ((int)(--n) >= 0);
|
||||
}
|
||||
if (i == 0)
|
||||
x_mode_prefix();
|
||||
x_mode_addchr(' ');
|
||||
eq = strchrnul(p, '=');
|
||||
fprintf(stderr, " %.*s=", (int)(eq - p), p);
|
||||
if (*eq)
|
||||
print_optionally_squoted(stderr, eq + 1);
|
||||
bb_putchar_stderr('\n');
|
||||
if (*eq) eq++;
|
||||
x_mode_addblock(p, (eq - p));
|
||||
x_mode_print_optionally_squoted(eq);
|
||||
x_mode_flush();
|
||||
}
|
||||
#endif
|
||||
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)
|
||||
break;
|
||||
case 'x':
|
||||
IF_HUSH_MODE_X(G_x_mode = state;)
|
||||
IF_HUSH_MODE_X(if (G.x_mode_fd <= 0) G.x_mode_fd = dup_CLOEXEC(2, 10);)
|
||||
break;
|
||||
case 'o':
|
||||
if (!o_opt) {
|
||||
|
Loading…
Reference in New Issue
Block a user