For the past few days I have been attempting to write my own shell implementation but I seem to have gotten stuck on getting pipes to work properly. I am able to parse a li
Try reading the source code of Bash to see how they did it.
The general process would add error handling to this base process (pseudocode):
pipe(fds)
if (fork() is child) {
dup2(fds[1], 1)
close(fds[0])
close(fds[1])
exec("ls")
}
if (fork() is child) {
dup2(fds[0], 0)
close(fds[0])
close(fds[1])
exec("sort")
}
close(fds[0])
close(fds[1])
wait()
Create the pipe first. Then fork the child processes so they inherit it. Remap the file descriptors to 0 (stdin) and 1 (stdout) so the processes read and write the appropriate places. Close any remaining file descriptor you don't want the child processes to see or block on when the work is finished. Exec the actual child processes. Wait for them to finish, and you're done!
well, I don't have an answer, but I am working on the same problem atm. I will share what i have. It works for the two commands, but after it is done running, i/o are broken. in a strange way i haven't been able to figure out yet. call the plumber!
void pipeCommand(char** cmd1, char** cmd2) {
int fds[2]; // file descriptors
pipe(fds);
int oldIn, oldOut;
// child process #1
if (fork() == 0) {
// Reassign stdin to fds[0] end of pipe.
oldIn = dup(STDIN_FILENO);
dup2(fds[0], STDIN_FILENO);
close(fds[1]);
close(fds[0]);
// Execute the second command.
execvp(cmd2[0], cmd2);
// child process #2
} else if ((fork()) == 0) {
oldOut = dup(STDOUT_FILENO);
// Reassign stdout to fds[1] end of pipe.
dup2(fds[1], STDOUT_FILENO);
close(fds[0]);
close(fds[1]);
// Execute the first command.
execvp(cmd1[0], cmd1);
// parent process
} else
wait(NULL);
dup2(oldIn, STDIN_FILENO);
dup2(oldOut, STDOUT_FILENO);
close(oldOut);
close(oldIn);
}
I have a feeling it has to do with what am or am not doing after the wait()