I was trying to solve this problem for school project but I couldn't understand how to open and close the read and write within the pipe: the question is: Create a C program that executes the following command ls| sort -r using pipe and creation of a fork() and dup()
Asked
Active
Viewed 467 times
-4
-
1What have you tried so far? – vmt Dec 29 '20 at 18:13
-
To create a pipe: `int fd[2]; pipe(fd);` To close one side: `close(fd[n])` To write to one side: `write(fd[1], b, s)`. To read: `read(fd[0], b, s)` – William Pursell Dec 29 '20 at 18:19
-
I posted my work can you have a look on it? – mary Dec 30 '20 at 11:00
2 Answers
0
I don't normally condone the posting of solutions to homework problems, but there's enough bad code available on the internet that I thought I would post what I consider to be not terrible code. Perhaps I'm being presumptuous to think that, but:
/* Execute ls | sort -r */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <err.h>
static void xpipe(int *fd) { if( pipe(fd) == -1 ){ err(1, "pipe"); } }
static void xdup2(int a, int b) { if( dup2(a, b) == -1 ){ err(1, "dup2"); } }
static void xclose(int fd) { if( close(fd) == -1 ){ err(1, "close"); } }
static void
execute(int *fd, char **cmd, int w)
{
switch( fork() ){
case -1:
err(EXIT_FAILURE, "fork");
case 0:
xdup2(fd[w], w);
xclose(fd[0]);
xclose(fd[1]);
execvp(cmd[0], cmd);
perror("execvp");
exit(EXIT_FAILURE);
}
}
int
main(void)
{
int rv = EXIT_SUCCESS;
char *ls[] = { "ls", NULL };
char *sort[] = { "sort", "-r", NULL };
int fd[2];
xpipe(fd);
execute(fd, ls, 1);
execute(fd, sort, 0);
xclose(fd[0]);
xclose(fd[1]);
for( int i = 0; i < 2; i++ ){
int status;
wait(&status);
if( ! WIFEXITED(status) || WEXITSTATUS(status) ){
rv = EXIT_FAILURE;
}
}
return rv;
}

William Pursell
- 204,365
- 48
- 270
- 300
-
thank you for giving time to my issue. Actually, my problem is when it comes to using the exec system calls. I know that some ends of the pipe should be opened and closed before using the exec yet I don't know what should be closed and what should be opened. Your code seemed to be more professional and sophisticated than what I should be handing back. I will post the code that I thought could be right – mary Dec 30 '20 at 10:55
-
To figure out which file descriptors to close, you should count. Before you call `exec*`, you want to have only 3 open file descriptors, and they should be 0, 1, and 2. That means you want to dup any pipe ends appropriately and close everything (including the pipe ends that were dup'd--you don't need or want to have 2 of them, so close one after it is dup'd). – William Pursell Dec 30 '20 at 13:25
0
int main(int argc, char*argv[])
{
int fd[2];
pid_t p1,p2;
pipe(fd);
if (pipe(fd)==-1){
perror("Erreur pipe");
exit();
}
p1=fork();
if (p1==-1){
perror("Erreur fork");
exit();
}
else if (p1==0) {
close(fd[0]);
dup2(fd[1],1);
execlp("ls","ls",argv[1],0);
}
p2=fork();
if (p2==-1){
perror("Erreur fork");
exit();
}
else if (p2==0){
close(fd[1]);
dup2(fd[0],0);
execlp("sort","-r",NULL);
}
waitpid(p1,nullptr,0);
close(fd[1]);
waitpid(p2,nullptr,0);
return 0;
}
// can you have a look at this and tell me if it would work?

mary
- 1