【发布时间】:2015-10-28 15:31:51
【问题描述】:
假设我们有一个名为myprog的程序:
#include <stdio.h>
#include <stdlib.h>
void main(){
char buffer[32];
gets(buffer);
system("/bin/sh");
}
- 它占用缓冲区的空间
- 它等待来自标准输入的数据并将其复制到缓冲区中,直到找到换行符
- 它将shell作为子进程执行,然后它将等待来自标准输入的命令
所以我们有 2 条指令将从标准输入中查找数据。
假设我们想将这个数据重定向到其他程序的标准输出到myprog的标准输入,我们以echo和cat为例。
$ cat > cmds
ls
$ { echo "My string" ; cat cmds ; } | ./myprog
file1 file2 cmds myprog
到目前为止一切顺利:echo 在“我的字符串”的末尾自动添加一个换行符,这会导致 gets 停止读取,/bin/sh 从 cat 的输出中读取。
但让我们尝试其他解决方案:
echo "My string" ls | ./myprogprintf "My string\nls\n" | ./myprog{echo "My string" ; echo ls ; } | ./myprog
这些解决方案似乎都不起作用。
使用单个文件和单个调用 cat 都不起作用:
$ cat > file
My string
ls
$ cat file | ./myprog
为什么会这样?每种情况究竟会发生什么?
【问题讨论】:
-
你是怎么编译的?如果不清楚,则该脚本不编译就无法运行。它会产生任何错误消息吗?
-
我要猜测标准输入和计时上的缓冲。
gets也很可怕。 -
好吧,#1 应该失败;它只输出一行。
-
Re: 定时,注意
cat是一个外部程序,cat在“我的字符串”输出和文件内容输出之间有一点延迟。在所有其他示例中,bashinternals 用于输出两行。这意味着gets可能不仅仅是读取第一行并将其缓冲以供下次调用gets,这意味着/bin/sh没有获得您期望的数据。您可以通过将/bin/sh替换为cat来确认,以查看调用system时标准输入中的实际内容。 -
@l0b0 你什么意思?我用一个简单的
gcc myprog.c -o myprog@EtanReisner 编译程序我知道这很可怕,这只是一个例子。 @chepner您是对的,第一个显然是错误的,我的错误。在使用system("cat")并查看缓冲区的内容之后,您的时间安排也是正确的,我可以看到像{ echo "My string" ; sleep 1 ; echo ls ; }这样的东西可以正常工作。谢谢。另一方面,{echo "My string" ; echo ls ; }导致gets仅将"My string"存储到缓冲区中。ls是否仍然进入gets的输入而不被复制?