[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RFE: indirection_level_string() preserves 'x' flag [PATCH]

From: John Reiser
Subject: RFE: indirection_level_string() preserves 'x' flag [PATCH]
Date: Thu, 08 Sep 2011 15:19:26 -0700
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv: Gecko/20110831 Fedora/3.1.12-2.fc14 Thunderbird/3.1.12

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=' address@hidden < ${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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]