所以我在C中实现了一个多流水线的shell。就我测试而言,似乎一切正常。我是根据Github Example
构建的现在我正在尝试在我的流水线命令中实现I / O重定向,但我不确定如何完成此任务。我正在阅读的这本书也没有深入探讨多流水线shell的C实现。
假设我想给出如下命令:
ls -l | grep something_i_want_to_find | wc > output.txt
也许还附加了
ls -l | grep something_i_want_to_find | wc >> output.txt
当我遇到重定向操作符时,我的管道将在第3个命令点失败。
我也在阅读SO Link。第一个答案中的一条评论提及"重定向到文件,添加到最后一个阶段:if (file_fd != 1) { dup2(file_fd, 1); close(file_fd); }
"我知道他们想要去哪里,但我不知道如何围绕我的管道代码实现这个。
这是我的代码:
保存命令令牌的结构
struct command
{
char **argv;
};
Pipline功能
void pipeline(struct command *cmds, int numPipes)
{
pid_t pid;
int status;
int fd[2]; // Each pipe has 2 file descriptors
int i;
int in = STDIN_FILENO;
/* Loop for number of pipes */
for (i = 0; i < numPipes; i++)
{
int fd[2];
pid_t pid; // Child's pid
if (pipe(fd) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
else if ((pid = fork()) == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if (pid == 0) // Child
{
closeFD(fd[0]);
redirect(in, STDIN_FILENO);
redirect(fd[1], STDOUT_FILENO);
execvp(cmds[i].argv[0], (char * const *)cmds[i].argv);
}
else // Parent
{
assert(pid > 0);
close(fd[1]);
close(in);
in = fd[0];
}
}
// CODE FROM SO LINK - if (file_fd != 1) { dup2(file_fd, 1); close(file_fd); }
redirect(in, STDIN_FILENO);
redirect(STDOUT_FILENO,STDOUT_FILENO);
for (i = 0; i < numPipes; i++)
{
wait(NULL);
}
/* Execute the last stage with the current process. */
execvp (cmds[i].argv[0], (char * const *)cmds[i].argv);
}
关闭FD的功能
void closeFD(int fd)
{
if ((close(fd)) == -1)
{
perror("close");
exit(EXIT_FAILURE);
}
}
重定向FD的功能
void redirect (int oldfd, int newfd)
{
if (oldfd != newfd)
{
if (dup2(oldfd, newfd) != -1)
{
if ((close(oldfd)) == -1)
{
perror("close");
exit(EXIT_FAILURE);
}
}
else
{
perror("dup2");
exit(EXIT_FAILURE);
}
}
}
当我输入ls -l | grep driver | wc > output.txt
时,我的输出看起来像这样
ls -l | grep driver | wc > output.txt
Command: ls
Options: -l
Pipe
Command: grep
Arguments: driver
Pipe
Command: wc
File Redirection: >
File: output.txt
wc: >: open: No such file or directory
1 3 25 output.txt
1 3 25 total
正如您所看到的,我正在识别重定向符号,但这是在一个不同函数的解析器中完成的,如果需要我可以提供。重定向符号确实存储在struct command **cmds
向量中。我怎样才能完成管道内的I / O重定向?