Bash: trick program into thinking stdout is an interactive terminal

bash, pipe, shell

Solution

I assume that the program will call the glibc function `isatty()` to check whether stdout is a terminal or not. That's common for programs which use colorized output on terminals or other features of an ANSI terminal like cursor positioning or line erasing / redrawing.

You can trick the program using the LD_PRELOAD environment variable. LD_PRELOAD is handled by the ELF linker and tells that a dynamic library should be loaded before all others. Using this feature it is possible to override library functions, in your case the glibc function `isatty()`. You can follow this article for example.

I've prepared an example for you:

First create the file libisatty.c:

/**
 * Overrides the glibc function. Will always return true.
 *
 * Note: Although this should be ok for most applications it can
 * lead to unwanted side effects. It depends on the question
 * why the programm calls isatty()
 */
int isatty(int param) {
    return 1;
}

and compile it as a shared lib:

gcc -shared -o libisatty.so  libisatty.c

It should build fine.

Now it's time to test the library. :) I've used the command `ls --color=auto` for tests. `ls` calls `isatty()` to decide whether it should colorize it's output or not. If the output is redirected to a file or a pipe it won't be colorized. You can test this easily using the following commands:

ls --color=auto        # should give you colorized output
ls --color=auto | cat  # will give you monochrome output

Now we'll try the second command again using the LD_PRELOAD environment var:

LD_PRELOAD=./libisatty.so ls --color=auto | cat

You should see colorized output.

btw cool usename: uʍop ǝpısdn !!:D

Problem

I want to run a program's output through a pipe, but it apparently behaves differently when it detects `stdout` is not an interactive shell. How can I trick it into writing through the pipe just as it would in regular circumstances?

Original source

Related problems