【问题标题】:Stdin redirection in custom shell in C?C中自定义shell中的标准输入重定向?
【发布时间】:2025-11-23 07:20:02
【问题描述】:

所以,基本上,我正在用 C 语言创建自己的 shell,它可以处理重定向。我的标准输出重定向正常,但我的标准输入重定向不起作用。

我正在尝试为示例重定向标准输入:

            hw9> cat < out.txt
            hw9> grep if < out.txt

我的代码:

            if(strcmp(token[i],"<")==0)
            {
                token[i]=NULL;
                int fd0;

                if ((fd0 = open(token[i + 1], O_RDONLY)) < 0)
                {
                    perror("Couldn't open input file");
                    exit(0);
                }
                close(0);
                // dup2() copies content of fdo in input of preceeding file
                dup2(fd0, 0); // STDIN_FILENO here can be replaced by 0

                close(fd0); // necessary
            }

这是我检查和执行标准输入重定向的 if 块,但这似乎不起作用。 cat out.txt 的预期输出是 "helloo",这应该与 cat &lt; out.txt 的输出相同,因为重定向将对应于 cat out.txt。但是cat &lt; out.txt 没有给出任何输出。文件out.txt的内容是"helloo"

hw9> cat out.txt

Tokens:
[0] 'cat'
[1] 'out.txt'
"helloo"
hw9> cat < out.txt

Tokens:
[0] 'cat'
[1] '<'
[2] 'out.txt'
hw9>

如您所见,第一次调用提供了预期的正确输出,但第二次调用未证明任何输出。 如果您需要更多信息,请告诉我。我尝试了多种其他方法,但似乎没有任何效果。提前致谢!

编辑:我让它工作了!我的错误是在 if 块之外调用 execvp()。我在 if 块内调用它,它似乎工作!谢谢大家!

最终代码:

            if(strcmp(token[i],"<")==0)
            {
                token[i]=NULL;
                int fd0;

                if ((fd0 = open(token[i + 1], O_RDONLY)) < 0)
                {
                    perror("Couldn't open input file");
                    exit(0);
                }
                close(0);
                // dup2() copies content of fdo in input of preceeding file
                dup2(fd0, 0); // STDIN_FILENO here can be replaced by 0
                close(fd0); // necessary
                execvp(*token, token);
                perror("execvp");

            }

【问题讨论】:

  • Redirection inside call to execvp() not working,请提供A Minimal, Complete, and Verifiable Example (MCVE)。这个问题似乎与第一个链接重复,但您没有提供足够的信息来做出决定。
  • “似乎不起作用”还不足以继续下去。请注意,您被要求提供的 MCVE 应包含对实际观察到的行为的详细描述,以及该行为与您想要的行为有何不同。
  • 代码看起来不错,除了使用 0 而不是 STDIN_FILENO。 close(0) 是多余的 and inferiordup2close 可能会失败,但前提是参数无效。不能多说,看prev cmets。
  • 我不认为它与上面的链接重复,因为我想知道我的代码有什么问题,而不是尝试不同的方法。

标签: c shell


【解决方案1】:

据我所知,您的代码没有任何问题。错误可能在其他地方,也许您正在调用exec。例如,

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
    int fd0;
    char *args[3] = { NULL };
    args[0] = argv[1];

    if (strcmp(argv[2], "<") == 0) {
        if ((fd0 = open(argv[3], O_RDONLY)) < 0) {
            perror("open");
            exit(1);
        }

        dup2(fd0, STDIN_FILENO);
        close(fd0);

        execvp(argv[1], args);

    } else {
        args[1] = argv[2];
        execvp(argv[1], args);
    }

    return EXIT_SUCCESS;
}

调用上面的test.out我看到了预期的输出,调用没有重定向,

./test.out cat test.c

并且带有重定向(引用是因为 shell 会进行自己的重定向)

./test.out cat '<' test.c

【讨论】:

  • 非常感谢您显示在哪里可以致电 execvp()。我在if-else 块之外调用execvp(),这就是它可能不起作用的原因。它现在正在工作!