尝试使用 dup2() 和 open() 以及 execv() 将文件重定向到标准输入时出现问题

Having issues trying to redirect file to stdin using dup2() and open() and execv()

编辑:问题是 echo 显然没有从 stdin 读取。谢谢@Jonathan Leffler

我有一个编程练习,我的代码如下:

int processProgram(char **tokens, int requireWait) {
    char *cmd = tokens[0];
    if (access(cmd, R_OK) == -1) {
        printf("%s not found\n", cmd);
        return -1;
    }

    int index = 1;
    char *iterator = tokens[index];
    int inputTokenIndex = 0;
    // Look for a < to figure out where the redirection is
    while (iterator != NULL) {
        if (strcmp(iterator, "<") == 0) {                      // <---- THIS IS WHERE I ATTEMPT TO FIND THE INDEX OF "<"
            if (access(tokens[index + 1], R_OK) == -1) {
                printf("%s does not exist\n", tokens[index + 1]);
                return -1;
            }
            // set null at <
            tokens[index] = NULL;
            inputTokenIndex = index + 1;
            break;
        }
        index++;
        iterator = tokens[index];
    }
    // basically create a struct to store pids and stuff....
    processList *process = addNewProcess();
    int childPid = fork();
    if (childPid == 0) {
        // is the child
        if (inputTokenIndex > 0) {
            // if previously strcmp "<" is true
            // set redirection for input....
            int fd = open(tokens[inputTokenIndex], O_RDONLY);   // <----- THIS IS WHERE I DO THE REDIRECTING FOR STDIN!
            dup2(fd, STDIN_FILENO);
            close(fd);
        }
        // start from where inputTokenIndex could have left off
        // since > is always at least after < in our test cases
        index = inputTokenIndex + 1;
        iterator = tokens[index];
        while (iterator != NULL) {                            // <--- LOOKING FOR ">" and "2>", CURRENTLY THIS WORKS FINE
            // look for output redirection FROM previous while loop onwards
            int out = 0;
            if (strcmp(iterator, ">") == 0) {
                // stdout
                out = STDOUT_FILENO;
            } else if (strcmp(iterator, "2>") == 0) {
                // stderr
                out = STDERR_FILENO;
            }
            if (out != 0) {
                int fd = open(tokens[index + 1], O_WRONLY | O_TRUNC | O_CREAT, 0777);
                dup2(fd, out);
                tokens[index] = NULL;
                close(fd);
            }
            index++;
            iterator = tokens[index];
        }
        
        int value = execv(cmd, tokens);                  // <----- EXEC IS HERE!!
        if (value == -1) {
            exit(errno);
        }
        exit(0);
    } else {
        int status;
        if (requireWait == 1) {
            // wait for process to finish
            process->pid = childPid;
            wait(&status);
            process->running = 0;
            process->status = status;
            if (status != 0) {
                printf("%s failed", cmd);
            }
        } else {
            process->pid = childPid;
            printf("Child[%d] in background\n", childPid);
            // no return should be expected
            status = 0;
        }
        return status;
    }
}

想法是使用 < 和 >

模拟 linux 重定向

tokens 是提供给 shell.

的字符串数组

向“a.txt”打招呼的示例调用:/bin/echo hello > ./a.txt

问题

它不适用于重定向,即“/bin/echo < ./a.txt”会像没有传入参数一样回显,这是一个空行。 “/bin/sleep < ./a.txt”表示当文件不为空时没有参数传入。

文件 a.txt 是使用此程序创建的。完整的例子是

/bin/echo 你好 > ./a.txt

/bin/echo < ./a.txt

其中第一个命令成功创建并写入a.txt,但第二个命令只产生一个空行

你能帮上什么忙

假设标记是正确的,并且文件名存在,为什么 execv() 调用不接受来自我重定向的文件名的输入????

感谢您阅读本文!!

正如我在 中指出的那样,echo 命令不读取标准输入,因此您无法判断 echo 的输入重定向是否成功(或使用 sleep)。

使用读取标准输入的命令 — cat 是最简单的示例,但 trsed 可能是明智的选择。