c - 在 Linux : unconsumed input is sent to bash 中使用系统调用 READ 读取 STDIN

标签 c linux bash assembly system-calls

以下程序(64 位 YASM)从标准输入读取 4 个字节并退出:

    section .data
buf   db "               "      ; Just allocate 16 bytes for string
    section .text
    global _start
_start:
    mov rax, 0                  ; READ syscall
    mov rdi, 0                  ; STDIN
    mov rsi, buf                ; Address of the string
    mov rdx, 4                  ; How many bytes to read
    syscall
    ; Exit:
    mov rax, 60
    mov rdi, 0
    syscall

一次编译

yasm -f elf64 -l hello.lst -o input.o input.asm
ld -o input input.o

如果像这样运行

./input

例如,123456\n 作为用户输入,它将消耗 1234,但发送结束位 56\n bash 。因此,bash 将尝试运行命令 56...谢天谢地没有成功。但想象一下,如果输入是 1234rm -f *。但是,如果我使用重定向或管道提供输入,例如,

echo "123456" | ./input

56 不会发送到 bash。

那么,如何防止将未使用的输入发送到 bash?在遇到某种形式的 EOF 之前,我是否需要继续使用它?这甚至是预期的行为吗?

同样的事情发生在 C 程序中:

#include <unistd.h>

int main()
{
    char buf[16];
    read(0, buf, 4);
    return 0;
}

(我只是想知道 C 运行时是否以某种方式清除了 STDIN,但没有,它没有)

最佳答案

是的,这是正常行为。您不消耗的任何东西都可用于下一个过程。你知道当你做一些慢的事情时你可以提前输入,当慢的事情完成时 shell 将运行你输入的内容吗?这里也是一样。

没有万能的解决方案。这实际上与用户期望有关。他们希望您的程序消耗多少输入?这就是您应该阅读的内容。

  • 您的程序是否像 read 这样的单行提示?然后,您应该通过下一个 \n 字符读取整行输入。在不过度阅读的情况下做到这一点的最简单方法是一次阅读 1 个字符。如果您进行批量读取,您可能会错误地使用下一行的一部分。

  • 您的程序是否像 catsedgrep 这样的过滤器?然后你应该一直读到 EOF。

  • 您的程序是否完全不像 echogcc 从 stdin 读取?然后你应该不理会 stdin 并且不消耗任何东西,将输入留给下一个程序。

正好消耗 4 个字节是不寻常的,但对于提示输入 4 位 PIN 且不需要用户按 Enter 的交互式程序来说可能是合理的行为。

关于c - 在 Linux : unconsumed input is sent to bash 中使用系统调用 READ 读取 STDIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62325098/

相关文章:

c - 如何将字符串从字符数组传递到指针字符数组?

c - 从证书中提取公共(public)证书

c,如何使用ptrace命令获取线程局部变量的偏移量?

linux - 将 w 输出重定向到文件

c - 是否总是需要返回声明?

linux - 什么 linux 命令行工具从字符串的开头提取所有字符子字符串?

linux - 管道 grep 匹配 less (或类似)

bash - 如何从 Cygwin 调用 bat/cmd 文件并继承变量?

bash - 根据 "git diff",我如何改进我的重置 Git 文件的解决方案,这些文件显示为已修改但没有更改?

bash - 脚本终止后删除文件