hush: add support for set -x
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 16 Jul 2010 10:35:35 +0000 (12:35 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 16 Jul 2010 10:35:35 +0000 (12:35 +0200)
function                                             old     new   delta
run_pipe                                            1442    1568    +126
dump_cmd_in_x_mode                                     -     126    +126
builtin_trap                                         441     462     +21
pseudo_exec_argv                                     171     187     +16
reset_traps_to_defaults                              214     229     +15
check_and_run_traps                                  227     232      +5
hush_exit                                             98     101      +3
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 6/0 up/down: 312/0)             Total: 312 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/hush.c

index 14f8f2422597f514efb9ea541a07892697a99be9..7640bd6ba72205061af51885b16c57e3a9330c86 100644 (file)
@@ -532,6 +532,7 @@ struct globals {
        smallint flag_return_in_progress;
 #endif
        smallint fake_mode;
+       smallint x_mode;
        smallint exiting; /* used to prevent EXIT trap recursion */
        /* These four support $?, $#, and $1 */
        smalluint last_exitcode;
@@ -3692,6 +3693,31 @@ static void execvp_or_die(char **argv)
        _exit(127); /* bash compat */
 }
 
+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;
+               int len;
+               int n;
+
+               len = 3;
+               n = 0;
+               while (argv[n])
+                       len += strlen(argv[n++]) + 1;
+               buf = xmalloc(len);
+               buf[0] = '+';
+               p = buf + 1;
+               n = 0;
+               while (argv[n])
+                       p += sprintf(p, " %s", argv[n++]);
+               *p++ = '\n';
+               *p = '\0';
+               fputs(buf, stderr);
+               free(buf);
+       }
+}
+
 #if BB_MMU
 #define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
        pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
@@ -3714,6 +3740,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
        char **new_env;
 
        new_env = expand_assignments(argv, assignment_cnt);
+       dump_cmd_in_x_mode(new_env);
 
        if (!argv[assignment_cnt]) {
                /* Case when we are here: ... | var=val | ...
@@ -3742,6 +3769,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
                nommu_save->argv = argv;
 #endif
        }
+       dump_cmd_in_x_mode(argv);
 
 #if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
        if (strchr(argv[0], '/') != NULL)
@@ -4239,13 +4267,19 @@ static NOINLINE int run_pipe(struct pipe *pi)
                        rcode = setup_redirects(command, squirrel);
                        restore_redirects(squirrel);
                        /* Set shell variables */
+                       if (G.x_mode)
+                               bb_putchar_stderr('+');
                        while (*argv) {
                                p = expand_string_to_string(*argv);
+                               if (G.x_mode)
+                                       fprintf(stderr, " %s", p);
                                debug_printf_exec("set shell var:'%s'->'%s'\n",
                                                *argv, p);
                                set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
                                argv++;
                        }
+                       if (G.x_mode)
+                               bb_putchar_stderr('\n');
                        /* Redirect error sets $? to 1. Otherwise,
                         * if evaluating assignment value set $?, retain it.
                         * Try "false; q=`exit 2`; echo $?" - should print 2: */
@@ -4305,6 +4339,8 @@ static NOINLINE int run_pipe(struct pipe *pi)
                        rcode = setup_redirects(command, squirrel);
                        if (rcode == 0) {
                                new_env = expand_assignments(argv, command->assignment_cnt);
+                               dump_cmd_in_x_mode(new_env);
+                               dump_cmd_in_x_mode(argv_expanded);
                                old_vars = set_vars_and_save_old(new_env);
                                if (!funcp) {
                                        debug_printf_exec(": builtin '%s' '%s'...\n",
@@ -4346,6 +4382,8 @@ static NOINLINE int run_pipe(struct pipe *pi)
                                rcode = setup_redirects(command, squirrel);
                                if (rcode == 0) {
                                        new_env = expand_assignments(argv, command->assignment_cnt);
+                                       dump_cmd_in_x_mode(new_env);
+                                       dump_cmd_in_x_mode(argv_expanded);
                                        old_vars = set_vars_and_save_old(new_env);
                                        debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
                                                argv_expanded[0], argv_expanded[1]);
@@ -6932,7 +6970,7 @@ static int set_mode(const char cstate, const char mode)
        int state = (cstate == '-' ? 1 : 0);
        switch (mode) {
                case 'n': G.fake_mode = state; break;
-               case 'x': /*G.debug_mode = state;*/ break;
+               case 'x': G.x_mode = state; break;
                default:  return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;