使用EOL模拟STDIN的输入

时间:2016-01-25 05:50:28

标签: c bash user-input stdin eol

我正在测试一种模拟应用程序特定输入的方法。 这是应用程序:

#include <stdio.h>

int main()
{
        int num1;
        char buffer[6] = {0};

        scanf("%d", &num1);
        read(0, buffer, 6);

        printf("num1 = %d\n", num1);

        for(num1=0; num1 < 6; num1++)
        {
                printf("%02X\n", buffer[num1]);
        }

        return 0;
}

我正在尝试使用以下bash命令模拟输入:

echo -ne "1337\\x0A\\x31\\x02\\x03\\x04\\x05\\x06" | ./test

我得到的输出如下:

num1 = 1337
00
00
00
00
00
00

如您所见,缓冲区未填充传递给STDIN的值。

修改 以下功能仅用于说明混合i / o函数中输入自动化的概念,我通过逆向工程二进制文件获得此功能,是否可以自动输入?

感谢您的帮助。

谢谢,

3 个答案:

答案 0 :(得分:1)

您正在混合scanf()section 3 man page)和read()section 2 man page)。 scanf()系列函数执行缓冲读写。第2节read()是无缓冲的。您尝试使用read()读取的字节已经被读取并放入缓冲区scanf()正在使用。

如果您注释掉scanf()行,并将命令更改为

    echo -ne "\\x0A\\x31\\x02\\x03\\x04\\x05\\x06" | ./test

你会得到

num1 = 0
0A
31
02
03
04
05

所以只需使用缓冲函数或无缓冲函数。选一个。

答案 1 :(得分:0)

永远不要将像scanf这样的stdio函数与低级别的io函数(如read)混合使用。 Stdio维护一个缓冲区以提高效率,如果在调用scanf时有任何额外数据可用,它可能会读取它以填充缓冲区。

使用fread而不是read。另外,不要忘记检查这些功能的返回值。

答案 2 :(得分:0)

这里发生了什么?

  • echo正在使用您在命令行中放置的完全相同的字符进行写入(因为您使用-n标志它不会输出最终的\n字符。
  • 您在管道上使用scanf(),因此首先读取完整缓冲区,然后扫描缓冲区以获取整数。它执行n = read(0, buffer, BUFSIZ);返回11作为读取到scanf的字符数,然后scanf扫描缓冲区,返回1337作为读取的数字,并将所有字符留在缓冲区中。
  • 然后你做一个返回0的read(0, buffer, 6);,并且没有用数据初始化缓冲区。
  • 然后将先前未初始化的缓冲区内容打印到stdout。

fifos(或管道)与输入端子的行为完全不同。当您按下enter键时,终端驱动程序只会读取完成,读取以获取一个输入行读取的实际字符数。使用fifo执行此操作时,将阻止读取器进程,直到将足够的字符(读取请求的实际数量)提供给进程,然后通过读取返回该数字(实际上是请求的字符数)。

如果您有预先检查read(2)返回值的预防措施,则应获取实际的字符数(0应为scanf(3)  已经吃掉了完整的缓冲区,因为它在第一次读取时小于BUFSIZ常数