Please find below a patch to allow one to direct the xtrace output of a shell to an alternate file descriptor. It can be used as such:
$ XTRACE_FD=4 ./bash -x [script] 4>bash.debug or in a script: exec 4>bash.debug XTRACE_FD=4 set -x who This is very useful for separating the stderr of the shell and it's children from the shell's xtrace output. Please advise if this patch is acceptable and if it will be merged or whether it needs work or otherwise. Thanx, b. diff -ur bash-3.1/externs.h bash-3.1-xtrace_hack/externs.h --- bash-3.1/externs.h 2005-11-11 23:10:52.000000000 -0500 +++ bash-3.1-xtrace_hack/externs.h 2006-07-28 13:49:58.000000000 -0400 @@ -51,6 +51,7 @@ #endif /* set -x support */ +extern void set_xtrace_stream __P((void)); extern char *indirection_level_string __P((void)); extern void xtrace_print_assignment __P((char *, char *, int, int)); extern void xtrace_print_word_list __P((WORD_LIST *, int)); diff -ur bash-3.1/flags.c bash-3.1-xtrace_hack/flags.c --- bash-3.1/flags.c 2004-07-16 21:19:42.000000000 -0400 +++ bash-3.1-xtrace_hack/flags.c 2006-07-28 14:41:41.000000000 -0400 @@ -287,6 +287,10 @@ break; #endif + case 'x': + if (on_or_off == FLAG_ON) + set_xtrace_stream(); + break; } return (old_value); diff -ur bash-3.1/print_cmd.c bash-3.1-xtrace_hack/print_cmd.c --- bash-3.1/print_cmd.c 2005-07-04 13:05:54.000000000 -0400 +++ bash-3.1-xtrace_hack/print_cmd.c 2006-07-28 15:11:43.000000000 -0400 @@ -51,6 +51,7 @@ #endif extern int indirection_level; +extern FILE *xtrace_stream; static int indentation; static int indentation_amount = 4; @@ -116,6 +117,42 @@ /* A buffer to indicate the indirection level (PS4) when set -x is enabled. */ static char indirection_string[100]; +void +set_xtrace_stream() { + static lastfd = -1; + SHELL_VAR *v = find_variable("XTRACE_FD"); + char *c; + int fd; + + if (!v) + { + xtrace_stream = stderr; + return; + } + + c = v->value; + fd = atoi(c); + + if (fd < 0) + { + report_error (_("invalid descriptor in $XTRACE_FD, using stderr")); + xtrace_stream = stderr; + return; + } + + if (fd == lastfd) + return; + + if (!(xtrace_stream = fdopen(fd, "a"))) + { + report_error (_("invalid file descriptor in $XTRACE_FD, using stderr")); + xtrace_stream = stderr; + return; + } + + lastfd = fd; +} + /* Print COMMAND (a command tree) on standard output. */ void print_command (command) @@ -380,7 +417,7 @@ char *nval; if (xflags) - fprintf (stderr, "%s", indirection_level_string ()); + fprintf (xtrace_stream, "%s", indirection_level_string ()); /* VALUE should not be NULL when this is called. */ if (*value == '\0' || assign_list) @@ -393,14 +430,14 @@ nval = value; if (assign_list) - fprintf (stderr, "%s=(%s)\n", name, nval); + fprintf (xtrace_stream, "%s=(%s)\n", name, nval); else - fprintf (stderr, "%s=%s\n", name, nval); + fprintf (xtrace_stream, "%s=%s\n", name, nval); if (nval != value) FREE (nval); - fflush (stderr); + fflush (xtrace_stream); } /* A function to print the words of a simple command when set -x is on. */ @@ -413,29 +450,30 @@ char *t, *x; if (xtflags) - fprintf (stderr, "%s", indirection_level_string ()); + fprintf (xtrace_stream, "%s", indirection_level_string ()); for (w = list; w; w = w->next) { t = w->word->word; if (t == 0 || *t == '\0') - fprintf (stderr, "''%s", w->next ? " " : ""); + fprintf (xtrace_stream, "''%s", w->next ? " " : ""); else if (sh_contains_shell_metas (t)) { x = sh_single_quote (t); - fprintf (stderr, "%s%s", x, w->next ? " " : ""); + fprintf (xtrace_stream, "%s%s", x, w->next ? " " : ""); free (x); } else if (ansic_shouldquote (t)) { x = ansic_quote (t, 0, (int *)0); - fprintf (stderr, "%s%s", x, w->next ? " " : ""); + fprintf (xtrace_stream, "%s%s", x, w->next ? " " : ""); free (x); } else - fprintf (stderr, "%s%s", t, w->next ? " " : ""); + fprintf (xtrace_stream, "%s%s", t, w->next ? " " : ""); } - fprintf (stderr, "\n"); + fprintf (xtrace_stream, "\n"); + fflush (xtrace_stream); } static void @@ -458,8 +496,8 @@ xtrace_print_for_command_head (for_command) FOR_COM *for_command; { - fprintf (stderr, "%s", indirection_level_string ()); - fprintf (stderr, "for %s in ", for_command->name->word); + fprintf (xtrace_stream, "%s", indirection_level_string ()); + fprintf (xtrace_stream, "for %s in ", for_command->name->word); xtrace_print_word_list (for_command->map_list, 0); } @@ -512,8 +550,8 @@ xtrace_print_select_command_head (select_command) SELECT_COM *select_command; { - fprintf (stderr, "%s", indirection_level_string ()); - fprintf (stderr, "select %s in ", select_command->name->word); + fprintf (xtrace_stream, "%s", indirection_level_string ()); + fprintf (xtrace_stream, "select %s in ", select_command->name->word); xtrace_print_word_list (select_command->map_list, 0); } @@ -581,8 +619,9 @@ xtrace_print_case_command_head (case_command) CASE_COM *case_command; { - fprintf (stderr, "%s", indirection_level_string ()); - fprintf (stderr, "case %s in\n", case_command->word->word); + fprintf (xtrace_stream, "%s", indirection_level_string ()); + fprintf (xtrace_stream, "case %s in\n", case_command->word->word); + fflush (xtrace_stream); } static void @@ -756,24 +795,25 @@ char *arg1, *arg2; { command_string_index = 0; - fprintf (stderr, "%s", indirection_level_string ()); - fprintf (stderr, "[[ "); + fprintf (xtrace_stream, "%s", indirection_level_string ()); + fprintf (xtrace_stream, "[[ "); if (invert) - fprintf (stderr, "! "); + fprintf (xtrace_stream, "! "); if (type == COND_UNARY) { - fprintf (stderr, "%s ", op->word); - fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''"); + fprintf (xtrace_stream, "%s ", op->word); + fprintf (xtrace_stream, "%s", (arg1 && *arg1) ? arg1 : "''"); } else if (type == COND_BINARY) { - fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''"); - fprintf (stderr, " %s ", op->word); - fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''"); + fprintf (xtrace_stream, "%s", (arg1 && *arg1) ? arg1 : "''"); + fprintf (xtrace_stream, " %s ", op->word); + fprintf (xtrace_stream, "%s", (arg2 && *arg2) ? arg2 : "''"); } - fprintf (stderr, " ]]\n"); + fprintf (xtrace_stream, " ]]\n"); + fflush (xtrace_stream); } #endif /* COND_COMMAND */ @@ -785,11 +825,12 @@ { WORD_LIST *w; - fprintf (stderr, "%s", indirection_level_string ()); - fprintf (stderr, "(( "); + fprintf (xtrace_stream, "%s", indirection_level_string ()); + fprintf (xtrace_stream, "(( "); for (w = list; w; w = w->next) - fprintf (stderr, "%s%s", w->word->word, w->next ? " " : ""); - fprintf (stderr, " ))\n"); + fprintf (xtrace_stream, "%s%s", w->word->word, w->next ? " " : ""); + fprintf (xtrace_stream, " ))\n"); + fflush (xtrace_stream); } #endif diff -ur bash-3.1/shell.c bash-3.1-xtrace_hack/shell.c --- bash-3.1/shell.c 2005-09-04 22:32:08.000000000 -0400 +++ bash-3.1-xtrace_hack/shell.c 2006-07-28 13:49:29.000000000 -0400 @@ -163,6 +163,9 @@ /* Non-zero is the recursion depth for commands. */ int indirection_level = 0; +/* the file descriptor to print xtrace info to. */ +FILE *xtrace_stream = (FILE *)NULL; + /* The name of this shell, as taken from argv[0]. */ char *shell_name = (char *)NULL; -- My other computer is your Microsoft Windows server. Brian J. Murrell
signature.asc
Description: This is a digitally signed message part
_______________________________________________ Bug-bash mailing list Bug-bash@gnu.org http://lists.gnu.org/mailman/listinfo/bug-bash