如何欺骗stdin是终端(而不是重定向文件)的程序?

时间:2013-02-25 01:36:06

标签: bash terminal stdin

我正在进行标准重定向:

$ cat file.txt | /usr/bin/program

但是如果我直接在终端和复制粘贴输入中运行它,程序的行为会有所不同。 当输入是终端时,它显示进度条。无论如何,我想要进度条。

简而言之,我如何“欺骗”输入来自终端的程序而不是从文件重定向?

3 个答案:

答案 0 :(得分:4)

使用expect程序可能最简单;它为你做了大部分必要的工作。

必要的工作是繁琐的。它涉及使用伪ttys,它是寻找终端等程序的设备。如果您打算自己动手,那么您需要知道的POSIX系统调用是:

posix_openpt()接口相对较新(问题6,与问题4,版本2相比,列出的其他功能)。如果你的系统没有posix_openpt(),你需要自己找一本Unix书籍(可能是Stevens或Rochkind)来了解如何打开pty的主方面,或阅读你的系统手册相当仔细。但是,上面链接中posix_openpt()的基本原理也可能有所帮助 - 它还有使用其他功能的指南。 Linux有posix_openpt(); Mac OS X也是如此,通常推断BSD系统。

书籍:

答案 1 :(得分:3)

我假设程序将调用glibc函数isatty()来检查stdin / stdout是否是终端。对于在终端上使用彩色输出或ANSI终端的其他功能(如光标定位或线擦除/重绘)的程序而言,这是常见的。

您可以使用LD_PRELOAD环境变量欺骗程序。 LD_PRELOAD由ELF链接器处理,并告知动态库应该在之前加载所有其他动态库。使用此功能可以覆盖库函数,例如glibc函数isatty()

这是一个例子:

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;
}

生成文件

# Make the shared Library
lib: libisatty.c
    gcc -shared -Wl,-soname,libisatty.so.1 -o libisatty.so.1.0  libisatty.c 
    ln -s libisatty.so.1.0 libisatty.so.1
    ln -s libisatty.so.1 libisatty.so

运行:

make lib

它应该构建良好,我已经在Ubuntu12.04 AMD 64上进行了测试。

现在是时候测试库了。 :)我已经使用命令ls --color=auto进行测试。 ls调用isatty()来决定是否应该将其输出着色。如果将输出重定向到文件或管道,则不会将其着色。您可以使用以下命令轻松测试:

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

现在我们将使用LD_PRELOAD环境var再次尝试第二个命令:

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

你应该看到彩色输出。

答案 2 :(得分:2)

你需要使用伪tty来获得你想要的效果。 'man pty'会告诉你更多关于它的信息。