I'm trying to re-implement The pipe "|" operator.
The program will be executed as follows:
$ ./exe infile cmd cmd2 cmd3 cmdn outfile.
where at first i'm gonna read from infile process infile's data through the commands and finally pipe it to outfile.
IMPLEMENTAIONS:
My pseudo code looks like the following:
change infile descriptor to stdin.
loop each command.
pipe();
fork();
if (we're in the child process)
change stdin to read_end of pipe.
execute command.
else if (we're in the parent process)
change stdout to write_end of pipe.
execute command.
wait for child process.
change outfile descriptor to stdout.
CODE:
int infile_fd = open(args->infile, O_RDONLY);
dup2(infile_fd, STDIN_FILENO);
// how many commands
while(i < args->len)
{
// error handling stuff
args->cmds[i].cmd = check_exist(args->cmds[i], args);
if (pipe(args->cmds[i].fd) == -1)
{
perror("piping failed\n");
exit(EXIT_FAILURE);
}
if ((args->cmds[i].pid = fork()) == -1)
{
perror("fork failed\n");
exit(EXIT_FAILURE);
} else {
// child process
if (args->cmds[i].pid == 0)
{
close(args->cmds[i].fd[WRITE_END]);
dup2(args->cmds[i].fd[READ_END], STDIN_FILENO);
if (execve(args->cmds[i].cmd, args->cmds[i].flags, env) == -1)
{
perror("execve failed\n");
exit(EXIT_FAILURE);
}
i++;
}
else
{
// parent process
close(args->cmds[i].fd[READ_END]);
dup2(args->cmds[i].fd[WRITE_END], STDOUT_FILENO);
if (execve(args->cmds[i].cmd, args->cmds[i].flags, env) == -1)
{
perror("execve failed\n");
exit(EXIT_FAILURE);
}
wait(NULL);
i++;
}
}
}
int outfile_fd = open(args->outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
// change stdout to outfile
dup2(outfile_fd, STDOUT_FILENO);
OUTPUT:
- output is garbage, commands read data off the stack and start showing env variables.
EXPECTED OUTPUT:
- data first being read from "infile" and then passed through commands until the end of the piping channel at "outfile".
It would be silly to ask what am I doing wrong, because I'm probably doing it all wrong, so a better question: How can I do it right?