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

时间:2015-09-01 16:22:43

标签: c++ linux bash shell

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

void main()
{
    fgets(buf,133,stdin);
    printf( buf);
    system("/bin/dash");
}

当我启动程序时,一切正常,我可以输入任何我想要的东西然后我有一个shell。但是,如果我这样做

$ echo 'blabla' | ./test

为了自动填充buf(不用键盘输入任何内容),执行shell,但/ bin / ls工作正常。 (显然显示命令工作正常)

如果我删除fgets行,并执行相同的命令,它会起作用,但将'blabla'作为/ bin / dash的参数。但是,添加一个空字符或返回'\ xd'以模拟我的键盘在fgets中的返回不起作用

我想了解当我使用'|'时会发生什么我的c ++程序中的符号。我认为这是自动填充scanfs和fgets而无需任何人工干预的解决方案,我做错了还是还有其他解决方案?

谢谢。

Debian,C ++ g ++

2 个答案:

答案 0 :(得分:5)

在shell中执行echo 'blabla' | ./test时,shell将启动echo进程并将其标准输出管道连接到./test的标准输入管道。这与C ++无关:这些管道是大多数操作系统的一个特性,几乎每个进程都有它们。

当您的程序执行system时,您正在创建一个连接到相同标准输入管道的新流程(或多个流程)。因此,如果echo未读取该管道中的某些数据(来自test命令),则可以通过system启动的进程读取该数据。

使用echo和管道是向fgetsscanf提供输入的好方法。将数据传递给程序的另一种方法是使用环境变量或命令行参数,但是您需要修改代码以检查这些内容。

答案 1 :(得分:2)

如果我理解正确,您希望为fgets和shell提供输入,而是在管道传输时发现shell没有收到任何输入。

这是因为libc将缓冲fgets的输入数据。

不是读取blabla\n中的7个字节并将其余部分传递给shell,而是读取最多4096个字节(取决于系统),并将剩余的4089个字节用于将来fgets / {{1调用stdin。这些数据将存储在程序内部,并且不会被其他从底层流读取的进程使用,例如调用的shell。

当您以交互方式运行并在键盘上键入时,只有7个字节 当你按Enter键时可用,所以缓冲区只填充7个字节。因此,您输入的其余数据可供shell使用。你可以在你的错误程序中模拟相同的效果,并在输入中策略性地放置延迟:

f*

您可以通过将缓冲区大小设置为1个字节来避免此问题,以便{ echo "for fgets"; sleep 1; echo "ls"; } | ./foo 永远不会读取超过必要的内容:

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