当我使用 '|' 或"<"时,c++ 究竟会发生什么

What exactly happens when I use '|' or '<', c++

本文关键字:究竟 c++ 什么 lt      更新时间:2023-10-16

我有一个非常简单的程序:

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和管道是向fgetsscanf提供输入的好方法。将数据传递给程序的另一种方法是使用环境变量或命令行参数,但是您需要修改代码来检查这些东西。

如果我理解正确的话,您是想同时向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