I've been trying to implement a piping structure in a shell program and it works if I do simple commands, such as "hello | rev"
But it hangs when I try to do "head -c 1000000 /dev/urandom | wc -c" (Ignore quotes)
My implementation is:
int fd[2];
pipe(fd);
// IN CHILD
// Piping for the first command
if (isPiped && (e == list_begin(&p->commands)))
{
close(fd[0]);
dup2(fd[1], 1);
close(fd[1]);
}
// Last command in the pipe
else if (isPiped && (list_next(e) == list_tail(&p->commands)))
{
close(fd[1]);
dup2(fd[0], 0);
close(fd[0]);
}
// IN PARENT
if (isPiped && (e == list_begin(&p->commands)))
{
close(fd[1]);
}
else if (isPiped && (list_next(e) == list_tail(&p->commands)))
{
close(fd[0]);
}
I've been taught to always close a file descriptor after I'm done using it, and I thought that's what I'm doing - but I'm having a file descriptor leak somewhere and I can't figure out where. I've been trying to do many combination of closing and dup2'ing the fd, but to no avail.
To further give a complete question, this is the main relevant code:
The way I'm doing it is to use a list structure that adds each command/job onto a list. The variable "e" is an element of the list.
int main(int ac, char *argv[]) {
int numPipes = list_size(&commands) - 1;
bool isPiped = false;
if (numPipes > 0)
isPiped = true;
int fd[2];
pipe(fd);
pid_t pid = fork();
// In child
if (pid == 0)
{
if (isPiped && (e == list_begin(&p->commands)))
{
close(fd[0]);
dup2(fd[1], 1);
close(fd[1]);
}
// Last command in the pipe
else if (isPiped && (list_next(e) == list_tail(&p->commands)))
{
close(fd[1]);
dup2(fd[0], 0);
close(fd[0]);
}
// command is a struct. I have it set up so that the terminal can read in what the user inputs
execvp(command->argv[0], command->arg);
}
// In parent
if (isPiped && (e == list_begin(&p->commands)))
{
close(fd[1]);
}
else if (isPiped && (list_next(e) == list_tail(&p->commands)))
{
close(fd[0]);
}
int status;
waitpid(-1, &status, WUNTRACED);
}
That's all there is to my pipe algorithm. The rest are just for other built in jobs, such as foreground, background, kill commands and io redirection. Thanks so much!