I am trying to learn how to use the pipe() command in C, and trying to create a test program to duplicate the functionality of ls | grep ".c"
, if I were to enter this into a linux terminal. If I enter this into the terminal, I only get test.c
as a result.
My code is as follows:
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "fcntl.h"
int main(int argc, char** argv)
{
int pipefd[2];
int childpid,childpid2;
char* cmd[3]={"ls",NULL,NULL};
char* cmd2[3]={"grep",".c",NULL};
pipe(pipefd);
if(childpid=fork()){
//parent
}else{
//child
//write
close(pipefd[0]);
dup2(pipefd[1],STDOUT_FILENO);
execvp("ls", cmd);
}
if(childpid2=fork()){
}
else{
close(pipefd[1]);
dup2(pipefd[0],STDIN_FILENO);
execvp("grep",cmd2);
}
close(pipefd[0]);
close(pipefd[1]);
return 0;
}
This code returns me the following results ($ is the terminal prompt):
$a.out
$test.c
(blank line)
The program doesn't complete, but hangs until I quit it. What problems do I have? How can I mimic the terminal? I'm new to C, and using a premade template of a program, so forgive me if there are glaring mistakes.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char** argv)
{
int pipefd[2];
int childpid,childpid2;
char* cmd[3]={"ls",NULL,NULL};
char* cmd2[3]={"grep",".c",NULL};
pipe(pipefd);
if(childpid=fork()){
//parent
close(pipefd[1]);
dup2(pipefd[0],STDIN_FILENO);
execvp("grep",cmd2);
}else{
//child
//write
close(pipefd[0]);
dup2(pipefd[1],STDOUT_FILENO);
execvp("ls", cmd);
}
return 0;
}
Actually the program exits right away — in fact, the parent process exits before the children run, which is why there's a shell prompt before "test.c".
You can improve things a bit by adding this in your parent:
wait(childpid);
wait(childpid2);
which will make the parent exit after both children.
Your program quits immediately, while your processes run in the background. They overwrite the prompt, and makes you think the program is still running even though the shell is waiting for your input (press enter or type a command blindly and see.
You only see test.c
because that's the only matching file in your directory (also note that you're checking for "filenames containing c anywhere except the first character", not "ending in .c" which would be grep '\.c$'
).
The simple fix is to add:
wait(NULL); wait(NULL);
right before your return 0
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With