I'm trying to replicate this bash command: ps aux | grep bash
ps aux | grep bash
to C language. I have written something but it doesn't seem to work. The result is literally that nothing happens, the prompt is printed again in bash. This is the code:
int main()
{
int pid;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if (pid = fork() == -1){
perror("fork error");
exit(1);
}
if (pid == 0)
{
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
exit(1);
}
else
{
dup2(pip[1], 1);
close(pip[0]);
close(pip[1]);
execvp("ps", argexec2);
perror("exec2 failed\n");
exit(1);
}
In the child process, if execvp() fails, don't call exit() but _ exit() otherwise the inherited I/O contexts may trigger duplicate I/O flushes and several other undesirable things.
. "==" has a higher precedence than "=". This makes your statement fail here:
if (pid = fork() == -1)
Add parenthesis:
if ((pid = fork()) == -1)
Here is your program with the fixes:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
int pid;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if ((pid = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid == 0) {
// Child process
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
_exit(1);
} else {
// Father process
dup2(pip[1], 1);
close(pip[0]);
close(pip[1]);
execvp("ps", argexec2);
perror("exec2 failed\n");
exit(1);
}
return 0;
}
But actually, if you want to make it like the shell, you are supposed to wait for the end of the commands before exiting the program and return the exit code of the last process in the pipe. So, the father should launch two processes and wait for their end:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
int main(void)
{
int status1, status2;
int pid1, pid2;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};
if (pipe(pip) == -1){
perror("pipe error \n");
exit(1);
}
if ((pid1 = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid1 == 0) {
// Child process#1
dup2(pip[0], 0);
close(pip[1]);
close(pip[0]);
execvp("grep", argexec1);
perror("exec1 failed\n");
_exit(2);
} else {
// Father process
if ((pid2 = fork()) == -1){
perror("fork error");
exit(1);
}
if (pid2 == 0) {
// Child process#2
dup2(pip[1], 1);
close(pip[1]);
close(pip[0]);
execvp("ps", argexec2);
perror("exec2 failed\n");
_exit(2);
} else {
// Father process
close(pip[0]);
close(pip[1]);
// Wait for the end of the programs
if (-1 == waitpid(pid1, &status1, 0)) {
perror("wait1 error");
exit(1);
}
if (-1 == waitpid(pid2, &status2, 0)) {
perror("wait2 error");
exit(1);
}
// Return the exit code of the last program in the pipe
if (WIFEXITED(status1)) {
return WEXITSTATUS(status1);
} else {
// The process may have received a signal, return the whole status...
return status1;
}
}
}
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.