diff -up mksh/exec.c.fixtrace mksh/exec.c --- mksh/exec.c.fixtrace 2013-04-26 23:23:09.000000000 +0200 +++ mksh/exec.c 2017-10-10 12:11:30.472249513 +0200 @@ -138,11 +138,6 @@ execute(struct op * volatile t, /* Allow option parsing (bizarre, but POSIX) */ timex_hook(t, &up); ap = (const char **)up; - if (Flag(FXTRACE)) { - shf_puts(substitute(str_val(global("PS4")), 0), - shl_out); - Flag(FXTRACE) = 2; - } if (ap[0]) tp = findcom(ap[0], FC_BI|FC_FUNC); } @@ -637,6 +632,8 @@ comexec(struct op *t, struct tbl * volat l_assign = e->loc; if (Flag(FEXPORT)) type_flags |= EXPORT; + if (Flag(FXTRACE)) + change_xtrace(2, false); for (i = 0; t->vars[i]; i++) { /* do NOT lookup in the new var/fn block just created */ e->loc = l_expand; @@ -650,9 +647,9 @@ comexec(struct op *t, struct tbl * volat ++ccp; if (*ccp == '=') ++ccp; - shf_write(cp, ccp - cp, shl_out); - print_value_quoted(shl_out, ccp); - shf_putc(' ', shl_out); + shf_write(cp, ccp - cp, shl_xtrace); + print_value_quoted(shl_xtrace, ccp); + shf_putc(' ', shl_xtrace); } /* but assign in there as usual */ typeset(cp, type_flags, 0, 0, 0); @@ -661,17 +658,16 @@ comexec(struct op *t, struct tbl * volat } if (Flag(FXTRACE)) { + change_xtrace(2, false); if (ap[rv = 0]) { xtrace_ap_loop: - print_value_quoted(shl_out, ap[rv]); + print_value_quoted(shl_xtrace, ap[rv]); if (ap[++rv]) { - shf_putc(' ', shl_out); + shf_putc(' ', shl_xtrace); goto xtrace_ap_loop; } } - shf_putc('\n', shl_out); - Flag(FXTRACE) = 1; - shf_flush(shl_out); + change_xtrace(1, false); } if ((cp = *ap) == NULL) { @@ -754,9 +750,9 @@ comexec(struct op *t, struct tbl * volat getopts_reset(1); } - old_xflag = Flag(FXTRACE); - Flag(FXTRACE) |= tp->flag & TRACE ? 1 : 0; - + old_xflag = Flag(FXTRACE) ? 1 : 0; + change_xtrace((Flag(FXTRACEREC) ? old_xflag : 0) | + ((tp->flag & TRACE) ? 1 : 0), false); old_inuse = tp->flag & FINUSE; tp->flag |= FINUSE; @@ -765,9 +761,11 @@ comexec(struct op *t, struct tbl * volat execute(tp->val.t, flags & XERROK, NULL); i = LRETURN; } + kshname = old_kshname; - Flag(FXTRACE) = old_xflag; + change_xtrace(old_xflag, false); tp->flag = (tp->flag & ~FINUSE) | old_inuse; + /* * Were we deleted while executing? If so, free the * execution tree. TODO: Unfortunately, the table entry @@ -1308,8 +1306,11 @@ iosetup(struct ioword *iop, struct tbl * iotmp.name = (iotype == IOHERE) ? NULL : cp; iotmp.flag |= IONAMEXP; - if (Flag(FXTRACE) == 2) - fptreef(shl_out, 0, "%R", &iotmp); + if (Flag(FXTRACE)) { + change_xtrace(2, false); + fptreef(shl_xtrace, 0, "%R", &iotmp); + change_xtrace(1, false); + } switch (iotype) { case IOREAD: diff -up mksh/main.c.fixtrace mksh/main.c --- mksh/main.c.fixtrace 2013-05-02 22:22:08.000000000 +0200 +++ mksh/main.c 2013-07-21 20:47:44.000000000 +0200 @@ -332,6 +343,11 @@ main_init(int argc, const char *argv[], */ Flag(FBRACEEXPAND) = 1; + /* + * Turn on "set -x" inheritance by default. + */ + Flag(FXTRACEREC) = 1; + #ifndef MKSH_NO_CMDLINE_EDITING /* * Set edit mode to emacs by default, may be overridden @@ -1373,7 +1393,7 @@ initio(void) /* force buffer allocation */ shf_fdopen(1, SHF_WR, shl_stdout); shf_fdopen(2, SHF_WR, shl_out); - shf_fdopen(2, SHF_WR, shl_spare); + shf_fdopen(2, SHF_WR, shl_xtrace); #ifdef DF if ((lfp = getenv("SDMKSH_PATH")) == NULL) { if ((lfp = getenv("HOME")) == NULL || *lfp != '/') diff -up mksh/misc.c.fixtrace mksh/misc.c --- mksh/misc.c.fixtrace 2013-05-02 22:22:09.000000000 +0200 +++ mksh/misc.c 2017-10-10 12:11:30.472249513 +0200 @@ -229,8 +229,12 @@ void change_flag(enum sh_flag f, int what, bool newset) { unsigned char oldval; - unsigned char newval; + unsigned char newval = (newset ? 1 : 0); + if (f == FXTRACE) { + change_xtrace(newval, true); + return; + } oldval = Flag(f); Flag(f) = newval = (newset ? 1 : 0); #ifndef MKSH_UNEMPLOYED @@ -286,6 +290,37 @@ change_flag(enum sh_flag f, int what, bo } } +void +change_xtrace(unsigned char newval, bool dosnapshot) +{ + if (!dosnapshot && newval == Flag(FXTRACE)) + return; + + if (Flag(FXTRACE) == 2) { + shf_putc('\n', shl_xtrace); + Flag(FXTRACE) = 1; + shf_flush(shl_xtrace); + } + + if (!dosnapshot && Flag(FXTRACE) == 1) + switch (newval) { + case 1: + return; + case 2: + goto changed_xtrace; + } + + shf_flush(shl_xtrace); + if (shl_xtrace->fd != 2) + close(shl_xtrace->fd); + if (!newval || (shl_xtrace->fd = savefd(2)) == -1) + shl_xtrace->fd = 2; + + changed_xtrace: + if ((Flag(FXTRACE) = newval) == 2) + shf_puts(substitute(str_val(global("PS4")), 0), shl_xtrace); +} + /* * Parse command line and set command arguments. Returns the index of * non-option arguments, -1 if there is an error. @@ -444,8 +479,10 @@ parse_args(const char **argv, (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') && argv[go.optind][1] == '\0') { /* lone - clears -v and -x flags */ - if (argv[go.optind][0] == '-') - Flag(FVERBOSE) = Flag(FXTRACE) = 0; + if (argv[go.optind][0] == '-') { + Flag(FVERBOSE) = 0; + change_xtrace(0, false); + } /* set skips lone - or + option */ go.optind++; } diff -up mksh/sh_flags.h.fixtrace mksh/sh_flags.h --- mksh/sh_flags.h.fixtrace 2013-05-02 22:28:40.000000000 +0200 +++ mksh/sh_flags.h 2017-10-10 12:11:30.472249513 +0200 @@ -45,6 +45,9 @@ FN("gmacs", FGMACS, 0, OF_ANY) /* ./. reading EOF does not exit */ FN("ignoreeof", FIGNOREEOF, 0, OF_ANY) +/* ./. inherit -x flag */ +FN("inherit-xtrace", FXTRACEREC, 0, OF_ANY) + /* -i interactive shell */ FN("interactive", FTALKING, 'i', OF_CMDLINE) diff -up mksh/sh.h.fixtrace mksh/sh.h --- mksh/sh.h.fixtrace 2013-05-03 00:00:17.000000000 +0200 +++ mksh/sh.h 2017-10-10 12:11:30.472249513 +0200 @@ -837,7 +837,7 @@ struct temp { * stdio and our IO routines */ -#define shl_spare (&shf_iob[0]) /* for c_read()/c_print() */ +#define shl_xtrace (&shf_iob[0]) /* for set -x */ #define shl_stdout (&shf_iob[1]) #define shl_out (&shf_iob[2]) #ifdef DF @@ -1905,6 +1905,7 @@ void initctypes(void); size_t option(const char *); char *getoptions(void); void change_flag(enum sh_flag, int, bool); +void change_xtrace(unsigned char, bool); int parse_args(const char **, int, bool *); int getn(const char *, int *); int gmatchx(const char *, const char *, bool);