summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-07-27 17:42:38 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-07-27 17:43:39 +0200
commit4b70c926bcbfaf6df6e21c98ea096b0db8629095 (patch)
treea3be088b3613fdb2f01d893e8f1be5ae5b4499de
parent9dda9270df3108bb85b29c6d382a3477aeb3344b (diff)
hush: make "set -x" output closer to bash
function old new delta print_optionally_squoted - 145 +145 run_pipe 1902 1919 +17 dump_cmd_in_x_mode 142 110 -32 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 162/-32) Total: 130 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/hush.c78
1 files changed, 60 insertions, 18 deletions
diff --git a/shell/hush.c b/shell/hush.c
index e9212cefc..ac8467fb4 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -8030,28 +8030,67 @@ static void execvp_or_die(char **argv)
}
#if ENABLE_HUSH_MODE_X
+static void print_optionally_squoted(FILE *fp, 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++;
+ }
+
+ cp = str;
+ for (;;) {
+ /* print '....' up to EOL or first squote */
+ len = (int)(strchrnul(cp, '\'') - cp);
+ if (len != 0) {
+ fprintf(fp, "'%.*s'", len, cp);
+ cp += len;
+ }
+ if (*cp == '\0')
+ break;
+ /* string contains squote(s), print them as \' */
+ fprintf(fp, "\\'");
+ cp++;
+ }
+}
static void dump_cmd_in_x_mode(char **argv)
{
if (G_x_mode && argv) {
- /* We want to output the line in one write op */
- char *buf, *p;
- unsigned len;
unsigned n;
- len = G.x_mode_depth + 3; /* "+[+++...][ cmd...]\n\0" */
- n = 0;
- while (argv[n])
- len += strlen(argv[n++]) + 1;
- p = buf = xmalloc(len);
+ /* "+[+++...][ cmd...]\n\0" */
n = G.x_mode_depth;
- do *p++ = '+'; while ((int)(--n) >= 0);
+ do bb_putchar_stderr('+'); while ((int)(--n) >= 0);
n = 0;
- while (argv[n])
- p += sprintf(p, " %s", argv[n++]);
- *p++ = '\n';
- *p = '\0';
- fputs(buf, stderr);
- free(buf);
+ while (argv[n]) {
+ if (argv[n][0] == '\0')
+ fputs(" ''", stderr);
+ else {
+ bb_putchar_stderr(' ');
+ print_optionally_squoted(stderr, argv[n]);
+ }
+ n++;
+ }
+ bb_putchar_stderr('\n');
}
}
#else
@@ -8845,13 +8884,18 @@ 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);
}
- fprintf(stderr, " %s", p);
+ eq = strchrnul(p, '=');
+ fprintf(stderr, " %.*s=", (int)(eq - p), p);
+ if (*eq)
+ print_optionally_squoted(stderr, eq + 1);
+ bb_putchar_stderr('\n');
}
#endif
debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p);
@@ -8861,8 +8905,6 @@ static NOINLINE int run_pipe(struct pipe *pi)
}
i++;
}
- if (G_x_mode)
- bb_putchar_stderr('\n');
/* Redirect error sets $? to 1. Otherwise,
* if evaluating assignment value set $?, retain it.
* Else, clear $?: