Please enhance the function indirection_level_string() in print_cmd.c so that the value of the 'x' flag is preserved over the call to decode_prompt_string(). This will permit the use of function indirection_level_string() as a tool to track usage of system calls by shell scripts.
For example, this code prints the script location of every fork(). ----- // bash-syspose.c - interpose so that bash shell prints $PS4 upon syscall // Copyright 2011 John Reiser, BitWagon Software LLC. All rights reserved. // Licensed under GNU General Public License, version 3 (GPLv3). // // Requires: change indirection_level_string() in bash/print_cmd.c // to preserve 'x' flag around decode_prompt_string(): /* --- bash-4.2/print_cmd.c 2011-09-08 13:27:53.877244584 -0700 +++ new/print_cmd.c 2011-09-08 13:29:34.088991764 -0700 @@ -426,9 +426,9 @@ if (ps4 == 0 || *ps4 == '\0') return (indirection_string); - change_flag ('x', FLAG_OFF); + int const old = change_flag ('x', FLAG_OFF); ps4 = decode_prompt_string (ps4); - change_flag ('x', FLAG_ON); + if (old) change_flag ('x', FLAG_ON); if (ps4 == 0 || *ps4 == '\0') return (indirection_string); */ // Build: gcc -shared -o bash-syspose.so -g -O -fPIC bash-syspose.c // Run: LD_PRELOAD=./bash-syspose.so bash ... # "unset LD_PRELOAD" ASAP! // EXAMPLE: (insert near beginning of shell script) // unset LD_PRELOAD // export PS4=' ${FUNCNAME[0]}@$LINENO < ${BASH_SOURCE[1]##*/}:${BASH_LINENO[0]} :' // // Obviously other syscalls could be handled, too. #define _GNU_SOURCE 1 /* need RTLD_NEXT from dlfcn.h */ #include <dlfcn.h> #include <stdlib.h> #include <string.h> // weak: Test to prevent crash if no such function, such as when // LD_PRELOAD remains set and a child process of bash invokes a // random executable that does a fork(). extern char const *indirection_level_string(void) __attribute__((weak)); int fork(void) { static int (*real_fork)(void); if (!real_fork) real_fork = (int (*)(void)) dlsym(RTLD_NEXT, "fork"); // Avoid infinite recursion in case evaluating PS4 does a fork(). static int recur; char const *ils = 0; if (!recur++ && indirection_level_string) { ils = indirection_level_string(); // evaluate $PS4 } if (!--recur && ils) { write(2, ils, strlen(ils)); write(2, "fork\n", 5); } // The child might want to remove us (bash-syspose) from LD_PRELOAD. // But it is ugly, so rely on 'weak' for now. return (*real_fork)(); } // end-of-file bash-syspose.c ----- --