I've doing custom shell for an assignment, and I wanted to implement the pseudo code from emphemient here for multiple piping. However, my code is still hanging on the read end of the pipe (in my test command, I do echo hello | wc
and it's hanging on wc
).
Is my implementation incorrect based on the pseudocode? I think I close the pipes properly
void piped()
{
// test command
char args[] = "echo hello | wc";
int status;
pid_t pid;
int cmdsRun = 0;
int newfds[2];
int oldfds[2];
char *nextCmd;
char *prevCmd = NULL;
char *cmdToken;
char *cmdSavePter;
cmdToken = strtok_r(args, "|", &cmdSavePter);
while (cmdToken)
{
nextCmd = strtok_r(NULL, "|", &cmdSavePter);
fprintf(stderr, "cmdToken: %s, nextCmd: %s, prev: %s\n", cmdToken, nextCmd, prevCmd);
struct command *commands = parseW(cmdToken);
// if next command make new pipes
if (nextCmd)
pipe(newfds);
// fork
pid = fork();
if (pid == 0) // child
{
// if there was prev cmd
if (prevCmd)
{
dup2(oldfds[0], STDIN_FILENO);
close(oldfds[0]);
close(oldfds[1]);
}
// if next cmd
if (nextCmd)
{
close(newfds[0]);
dup2(newfds[1], STDOUT_FILENO);
close(newfds[1]);
}
// this function simply execvps the commands
runSimple(commands);
}
else if (pid < 0)
{
perror("error");
exit(EXIT_FAILURE);
}
else // parent
{
// if there was a prev command
if (prevCmd)
{
close(oldfds[0]);
close(oldfds[1]);
}
// if next command
if (nextCmd)
{
memcpy(oldfds, newfds, sizeof(oldfds));
}
}
waitpid(pid, &status, 0);
prevCmd = cmdToken;
cmdToken = nextCmd;
cmdsRun++;
}
// parent: if multiple cmds, close
if (cmdsRun > 1)
{
close(oldfds[0]);
close(oldfds[1]);
}
}