当我使用 '|' 或"<"时,c++ 究竟会发生什么
What exactly happens when I use '|' or '<', c++
我有一个非常简单的程序:
void main()
{
fgets(buf,133,stdin);
printf( buf);
system("/bin/dash");
}
当我启动程序时,一切正常,我可以输入任何我想要的,然后我有一个shell。但是如果我做
$ echo 'blabla' | ./test
以便自动填充缓冲区(不需要用键盘输入任何内容),shell被执行,但是/bin/ls可以正常工作。(显然显示命令工作正常)
如果我删除fgets行,并执行相同的命令,它可以工作,但将'blabla'作为/bin/dash的参数。然而,添加一个空字符或返回'xd'以模拟我的键盘在fgets中的返回不工作
我想了解当我在c++程序中使用'|'符号时会发生什么。我认为这是解决方案,自动填写扫描和忘记没有任何人工交互,我做错了,还是有其他的解决方案?
谢谢。
Debian、c++、c++
当您在shell中执行echo 'blabla' | ./test
时,shell将启动echo
进程,并将其标准输出管道连接到./test
的标准输入管道。这与c++无关:这些管道是大多数操作系统的一个特性,几乎每个进程都有它们。
当您的程序执行system
时,您正在创建一个(或多个)连接到相同的标准输入管道的新进程。因此,如果该管道中有一些数据(来自echo
命令)未被test
读取,则可以由由system
启动的进程读取。
使用echo
和管道是向fgets
和scanf
提供输入的好方法。将数据传递给程序的另一种方法是使用环境变量或命令行参数,但是您需要修改代码来检查这些东西。
如果我理解正确的话,您是想同时向fgets
和shell提供输入,但是当您使用管道时发现shell没有接收到任何输入。
这是因为libc将为fgets
缓冲输入数据。
它不是读取blablan
中的7个字节并将其余的传递给shell,而是读取最多4096个字节(取决于系统),并使用剩余的4089个字节用于将来对stdin的fgets
/f*
调用。该数据将存储在程序内部,并且不会被从底层流读取的其他进程(如被调用的shell)使用。
当你以交互方式运行并在键盘上键入时,只有7个字节当您按enter键时可用,因此缓冲区只填充了7个字节。因此,您键入的其余数据对shell是可用的。您可以在有bug的程序中模拟相同的效果,在输入中策略性地放置延迟:
{ echo "for fgets"; sleep 1; echo "ls"; } | ./foo
您可以通过将缓冲区大小设置为1字节来解决这个问题,这样fgets
就不会读取不必要的内容:
#include <stdio.h>
char input_buffer[1];
void main(int argc, char** argv)
{
char buf[133];
setvbuf(stdin, input_buffer, _IOFBF, 1);
fgets(buf,133,stdin);
printf( buf);
system("/bin/dash");
}
现在你可以用管道运行它,没有延迟:
$ echo -e "for fgetsnls"
for fgets
ls
$ gcc foo.c -o foo
$ echo -e "for fgetsnls" | ./foo
for fgets
Desktop Downloads foo.c Pictures Steam Videos
Documents foo Music Public Templates win
- 传递给std::function template的template参数究竟代表什么
- C++关于指针和使用函数将它们启动到堆的行为究竟是什么?
- 究竟如何工作范围?
- 当使用对象名称后带有 [] 的类对象时,您究竟会传入什么.C++
- 哪种方式更快?究竟发生了什么,我们没有看到什么?
- 当我使用 void 函数的返回值(通过强制转换函数指针)时,究竟会发生什么?
- 串行端口写入究竟如何从缓冲区实际写入数据?
- DrawShadow 中的 Elevation 究竟有什么作用?
- 究竟是什么设置了_WIN32或_WIN64预处理器?
- 我的重复检查代码中的错误究竟在哪里?
- GCC 的 -Wpsabi 选项究竟有什么作用?压制它意味着什么?
- 这个编译器错误究竟希望我执行什么?
- 查找表究竟是如何工作的,以及如何实现它们
- 在陈述"Implementation-defined"时,什么样的软件是"Implementation"的一部分?究竟什么是"Implementation"?
- 变量或标识符存储在C++中究竟在哪里?
- 究竟什么是"位填充"或"填充位"?
- 究竟发生了什么,我们需要在 c++ 中双重调度/访客
- 内存分配究竟是如何发生的,Java和C如何交互以跟踪同一对象?
- std::async 究竟是如何执行的?
- 根据标准,究竟什么是"declaration of an object"