I'm trying to process input through different child process from one parent. I can make it though the first 3 children, but after that, I can't seem to get any input into or anything of out sort.
Here is my code.
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
int main(int argc, char** argv)
{
pid_t pid;
int pipes_1[2];
int pipes_2[2];
pipe(pipes_1);
pipe(pipes_2);
switch(pid=fork())
{
case 0:
dup2(pipes_1[0], 0);//copy stdin onto pipe 1 read
dup2(pipes_2[1], 1);//copy stdout onto pipe 2 write
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
execlp("sed", "sed","s/[^a-zA-Z]/ /g", "test.txt", (char*)NULL);
break;
default:
break;
}
switch(pid = fork())
{
case 0:
dup2(pipes_2[0],0); //copy std onto pipes 2 read
dup2(pipes_1[1],1);
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
execlp("tr", "tr", "[A-Z]", "[a-z]", (char*)NULL);
break;
default:
break;
}
switch(pid=fork())
{
case 0:
dup2(pipes_1[0], 0);
dup2(pipes_2[1], 1);
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
execlp("awk", "awk", "{for(i = 1; i <= NF; i++) {print $i;}}", (char*)NULL);
break;
default:
break;
}
switch(pid=fork())
{
case 0:
dup2(pipes_2[0], 0);
//dup2(pipes_1[1], 1);
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
execlp("sort", "sort", (char*)NULL);
default:
break;
}
wait();
return 0;
}
I know the formatting is bad. But can you see what I'm doing wrong? I think it may have something to do with only using two pipes.
EDIT: Updated code with 4 pipes.
int main(int argc, char** argv)
{
pid_t pid;
int pipes_1[2];
int pipes_2[2];
int pipes_3[2];
int pipes_4[2];
pipe(pipes_1);
pipe(pipes_2);
pipe(pipes_3);
pipe(pipes_4);
switch(pid=fork())
{
case 0:
dup2(pipes_1[0], 0);//copy stdin onto pipe 1 read
dup2(pipes_2[1], 1);//copy stdout onto pipe 2 write
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
execlp("sed", "sed","s/[^a-zA-Z]/ /g", "test.txt", (char*)NULL);
break;
default:
break;
}
switch(pid = fork())
{
case 0:
dup2(pipes_2[0],0); //copy std onto pipes 2 read
dup2(pipes_3[1],1);
close(pipes_3[0]);
close(pipes_3[1]);
close(pipes_2[0]);
close(pipes_2[1]);
execlp("tr", "tr", "[A-Z]", "[a-z]", (char*)NULL);
break;
default:
break;
}
switch(pid=fork())
{
case 0:
dup2(pipes_3[0], 0);
dup2(pipes_4[1], 1);
close(pipes_3[0]);
close(pipes_3[1]);
close(pipes_4[0]);
close(pipes_4[1]);
execlp("awk", "awk", "{for(i = 1; i <= NF; i++) {print $i;}}", (char*)NULL);
break;
default:
break;
}*/
switch(pid=fork())
{
case 0:
dup2(pipes_4[0], 0);
//dup2(pipes_1[1], 1);
close(pipes_4[0]);
close(pipes_4[1]);
//close(pipes_2[0]);
//close(pipes_2[1]);
execlp("sort", "sort", (char*)NULL);
default:
break;
}
wait();
return 0;
}
You seem to have a pipeline:
sed … | tr … | awk … | sort
You create just two pipes, where three are needed. Create the third pipe and handle it correctly, and you'll be OK.
Adapting second code. Note that only three pipes are needed for four processes (and in general N-1 pipes are needed for N processes).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
static inline void error(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(void)
{
int pid;
int pipes_1[2];
int pipes_2[2];
int pipes_3[2];
pipe(pipes_1);
pipe(pipes_2);
pipe(pipes_3);
if ((pid = fork()) == 0)
{
dup2(pipes_1[1], 1);
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
close(pipes_3[0]);
close(pipes_3[1]);
execlp("sed", "sed", "s/[^a-zA-Z]/ /g", "test.txt", (char *)NULL);
error("Failed to exec sed");
}
printf("sed: %d\n", pid);
if ((pid = fork()) == 0)
{
dup2(pipes_1[0], 0);
dup2(pipes_2[1], 1);
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
close(pipes_3[0]);
close(pipes_3[1]);
execlp("tr", "tr", "[A-Z]", "[a-z]", (char *)NULL);
error("Failed to exec tr");
}
printf("tr: %d\n", pid);
if ((pid = fork()) == 0)
{
dup2(pipes_2[0], 0);
dup2(pipes_3[1], 1);
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
close(pipes_3[0]);
close(pipes_3[1]);
execlp("awk", "awk", "{for(i = 1; i <= NF; i++) {print $i;}}", (char *)NULL);
error("Failed to exec awk");
}
printf("awk: %d\n", pid);
if ((pid = fork()) == 0)
{
dup2(pipes_3[0], 0);
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
close(pipes_3[0]);
close(pipes_3[1]);
execlp("sort", "sort", (char *)NULL);
error("Failed to exec sort");
}
printf("sort: %d\n", pid);
close(pipes_1[0]);
close(pipes_1[1]);
close(pipes_2[0]);
close(pipes_2[1]);
close(pipes_3[0]);
close(pipes_3[1]);
int status;
int corpse;
while ((corpse = wait(&status)) > 0)
printf("PID %d died 0x%.4X\n", corpse, status);
return 0;
}
Sample input:
Happy Go Lucky!
PENULTIMATE DESTINY#
missing all upper-case=
What gives?
Digital 023123098 Diarrhea
Sample output:
sed: 74841
tr: 74842
awk: 74843
sort: 74844
PID 74841 died 0x0000
PID 74842 died 0x0000
PID 74843 died 0x0000
all
case
destiny
diarrhea
digital
gives
go
happy
lucky
missing
penultimate
upper
what
PID 74844 died 0x0000
The process ID information is primarily diagnostic. If you pipe the output of the program to a filter, you will get different output (because of buffering, etc), but the difference is in the sequence in which the sorted data appears vs the diagnostics. Print the diagnostics to standard error, or add a fflush(stdout) after each printf() and you'll get something similar to the shown output more routinely.
Related
Im trying to make a code that pass the argument 1 as the name of the user whose process used you want to see, Im using pipes to get the users with getent, then I pass the result to greep argv[1] to search in that result for the user of the parameter and then pass it to ps -fu to get the process of that user but Im only getting the process of the user1 (main user) and I don't know why, thank you.
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define error(a) {perror(a); exit(1);};
int main(int argc, char *argv[])
{
if(argc != 2)
{
error("Incorrect number of arguments");
}
int pfd1[2], pfd2[2], pid;
if(pipe(pfd1) != 0){error("First pipe");}
switch(pid = fork())
{
case -1: error("fork");
case 0:
if(close(1)==-1){error ("close");}
if(dup(pfd1[1]) != 1){error("dup");}
close(pfd1[0]); close(pfd1[1]);
execlp("getent", "getent", "passwd",NULL);
error("getent");
}
close(pfd1[1]);
if(pipe(pfd2) != 0){error("Second pipe");}
switch(pid = fork())
{
case -1: error("fork");
case 0:
close(pfd2[0]);
if(close(0)==-1){error("close");}
if(dup(pfd1[0]) != 0){error("dup");}
close(pfd1[0]);
if(close(1)==-1){error("close");}
if(dup(pfd2[1]) !=1){error("dup");}
close(pfd2[1]);
execlp("grep", "grep", argv[1], NULL);
error("grep");
}
printf("Parent: grep(%d) process launched\n", pid);
close(pfd1[0]);
close(pfd2[1]);
switch(pid = fork())
{
case -1: error("fork");
case 0:
if(close(0)==-1){error("close");}
if(dup(pfd2[0]) !=0){error("dup")};
execlp("ps", "ps", "-fu", NULL);
error("ps");
}
close(pfd2[0]);
while ((pid = wait(NULL)) != -1)
{
printf("Parent: %d process finished\n", pid);
}
return 0;
}
wow.. this is highlevel for me .. i worked with i ex:
ps aux | grep -v root | grep nginx | cut -d\ -f1 | sort | uniq
ps aux | grep -v root | grep apache | cut -d\ -f1 | sort | uniq
thanx for your inspiration ..
Enough with two pipes, one for the ps aux and another for the grep user to filter the results
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define error(a) {perror(a); exit(1);};
int main(int argc, char *argv[])
{
if(argc != 2){error("Incorrect number of arguments")};
int pfd[2], pid;
char user[100];
sprintf(user, "%s", argv[1]);
if (pipe(pfd) == -1) error("pipe");
printf("parent: pipe created, channels: READ=%d and WRITE=%d\n", pfd[0], pfd[1]);
switch (pid = fork()) {
case -1: error("fork");
case 0: /* 1st child: who */
printf("1st child process created\n");
if (close(1) == -1) error("close");
if (dup(pfd[1]) != 1) error("dup");
close(pfd[0]); close(pfd[1]);
execlp("ps", "ps", "aux", NULL);
error("execlp");
}
printf("parent: ps(%d) process launched\n", pid);
switch (pid = fork())
{
case -1: error("fork");
case 0: /* 2nd child process: wc -l */
printf("2nd child process created\n");
if (close(0) == -1) error("close");
if (dup(pfd[0]) != 0) error("grep");
close(pfd[0]); close(pfd[1]);
execlp("grep", "grep", user, NULL);
error("execlp");
}
printf("parent: grep(%d) process launched\n", pid);
close(pfd[0]); close(pfd[1]);
while ((pid = wait(NULL)) != -1)
{
printf("parent: %d process finished\n", pid);
}
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MSGSIZE 64
char msgbuf[MSGSIZE];
int main() {
int p1[2];
int p2[2];
int nread;
int choice = 0;
pid_t child_a, child_b;
if (pipe(p1) == -1) {
printf("error in creating pipe\n");
exit(-1);
}
if (pipe(p2) == -1) {
printf("error in creating pipe\n");
exit(-1);
}
child_a = fork();
if (child_a == 0) {
while (1) {
dup2(p1[0], STDIN_FILENO);
read(STDIN_FILENO, msgbuf, MSGSIZE);
printf("%d receives message: %s\n", getpid(), msgbuf);
close(p1[0]);
close(p1[1]);
}
} else {
child_b = fork();
if (child_b == 0) {
while (1) {
dup2(p2[0], STDIN_FILENO);
read(STDIN_FILENO, msgbuf, MSGSIZE);
printf("%d receives message: %s\n", getpid(), msgbuf);
close(p2[0]);
close(p2[1]);
}
} else {
while (1) {
printf("<child_to_receive_msg> <message>\n");
scanf("%d %s", &choice, msgbuf);
switch (choice) {
case 1:
usleep(250);
write(p1[1], msgbuf, MSGSIZE);
break;
case 2:
usleep(250);
write(p2[1], msgbuf, MSGSIZE);
break;
default:
printf("Process does not exist");
break;
case -1:
close(p1[0]);
close(p2[0]);
printf("parent waiting");
wait(NULL);
exit(0);
}
}
}
}
return 0;
}
In the above program I have a parent making two child processes belonging to that same parent. The user writes to the parent process which pipes the message to be read by either child 1 or child 2. It keeps doing this continuously unless the user inputs -1.
The problem is that case in my switch statement doesn't get executed and instead the program hangs. I think I have my pipes closed at the correct places.
You need to send some signal to your child process to inform then to terminate before waiting for them to exit. You should define some pre-defined message which means its time for child to terminate. Check below code. Here pre-defined message is "-1". You should choose your own which doesn't conflict with your application's real data.
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define MSGSIZE 64
char msgbuf[MSGSIZE];
int main() {
int p1[2];
int p2[2];
int nread;
int choice = 0;
pid_t child_a, child_b;
if (pipe(p1) == -1) {
printf("error in creating pipe\n");
exit(-1);
}
if (pipe(p2) == -1) {
printf("error in creating pipe\n");
exit(-1);
}
child_a = fork();
if (child_a == 0) {
while (1) {
dup2(p1[0], STDIN_FILENO);
read(STDIN_FILENO, msgbuf, MSGSIZE);
printf("%d receives message: %s\n", getpid(), msgbuf);
close(p1[0]);
close(p1[1]);
if (strcmp(msgbuf, "-1") == 0) { // check if time to end
break;
}
}
} else {
child_b = fork();
if (child_b == 0) {
while (1) {
dup2(p2[0], STDIN_FILENO);
read(STDIN_FILENO, msgbuf, MSGSIZE);
printf("%d receives message: %s\n", getpid(), msgbuf);
close(p2[0]);
close(p2[1]);
if (strcmp(msgbuf, "-1") == 0) { // check if time to end
break;
}
}
} else {
while (1) {
printf("<child_to_receive_msg> <message>\n");
scanf("%d %s", &choice, msgbuf);
switch (choice) {
case 1:
usleep(250);
write(p1[1], msgbuf, MSGSIZE);
break;
case 2:
usleep(250);
write(p2[1], msgbuf, MSGSIZE);
break;
default:
printf("Process does not exist\n");
break;
case -1:
strcpy(msgbuf, "-1");
write(p1[1], msgbuf, MSGSIZE); // send message to end
close(p1[0]);
close(p2[0]);
printf("parent waiting\n");
wait(NULL);
exit(0);
}
}
}
}
return 0;
}
First, you need to start performing error checking. Check the man page of the calls you make. Add checks in your code to detect errors. When they return an error, use perror and exit(EXIT_FAILURE);.
Second, you need to start paying attention to the values returned by read and write since they could be less than expected. These need to be called in a loop.
For example, for read, you'd use the following:
#include <errno.h>
#include <limits.h>
// Returns the number of bytes read.
// EOF was reached if the number of bytes read is less than requested.
// On error, returns -1 and sets errno.
ssize_t read_fixed_amount(int fd, char *buf, size_t size) {
if (size > SSIZE_MAX) {
errno = EINVAL;
return -1;
}
ssize_t bytes_read = 0;
while (size > 0) {
ssize_t rv = read(fd, buf, size);
if (rv < 0)
return -1;
if (rv == 0)
return bytes_read;
size -= rv;
bytes_read += rv;
buf += rv;
}
return bytes_read;
}
It would be used something like this:
ssize_t bytes_read = read_fixed_amount(fd, buf, size);
if (bytes_read < 0) {
perror("read");
exit(EXIT_FAILURE);
}
if (bytes_read == 0) {
printf("EOF reached\n");
exit(EXIT_SUCCESS);
}
if (bytes_read != size) {
fprintf(stderr, "read: Premature EOF.\n");
exit(EXIT_FAILURE);
}
Third, reading from the pipe will only return EOF once all file descriptors of the write end of the pipes have been closed.
Right after the fork, the parent should do
close(p1[0]);
close(p2[0]);
Right after the fork, child 1 should do
close(p1[1]);
close(p2[0]);
close(p2[1]);
Right after the fork, child 2 should do
close(p1[0]);
close(p1[1]);
close(p2[1]);
Fourth, there's this monstrosity:
while (1) {
dup2(p1[0], STDIN_FILENO);
read(STDIN_FILENO, msgbuf, MSGSIZE);
...
close(p1[0]);
close(p1[1]);
}
Really? Infinite loop. Attempt to repeatedly make STDIN a dup of p1[0]. Duping of a closed descriptor.
This should appear before the loop:
dup2(p1[0], STDIN_FILENO);
close(p1[0]);
Or you could skip those two call and simply read from p1[0] instead of STDIN_FILENO.
As for the infinite loop, it goes back to the second point. Check the value returned by read.
Fifth, you only wait for one child to finish, but there are two children to wait for. You need to call wait twice.
I'm trying to make a program that executes the following commands connecting the output of one to the input of the next using pipes and taking two arguments DIR (directory) and ARG (filetype, example: jpg).
ls DIR -laR | grep ARG | sort
Here's the code:
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Invalid arguments. <dir> <arg>\n");
exit(1);
}
int pipe_fd1[2];
int pipe_fd2[2];
pid_t ls_pid, grep_pid;
int status;
pipe(pipe_fd1);
pipe(pipe_fd2);
ls_pid = fork();
if (ls_pid == 0) { //first child ls DIR -laR
dup2(pipe_fd1[1], STDOUT_FILENO);
close(pipe_fd1[0]);
execlp("ls", "ls", argv[1], "-laR", NULL);
} else if (ls_pid > 0) {
grep_pid = fork();
if (grep_pid == 0) { //second child grep ARG
dup2(pipe_fd1[0], STDIN_FILENO);
dup2(pipe_fd2[1], STDOUT_FILENO);
close(pipe_fd1[1]);
close(pipe_fd2[0]);
waitpid(ls_pid, &status, 0);
execlp("grep", "grep", argv[2], NULL);
} else if (grep_pid > 0) { //parent sort
dup2(pipe_fd2[0], STDIN_FILENO);
close(pipe_fd2[1]);
waitpid(grep_pid, &status, 0);
execlp("sort", "sort", NULL);
}
}
return 0;
}
It seems to be stuck? Not sure why?
You never close pipe_fd1 on the parent, so grep and sort doen't know when to stop reading input: because the pipe read and write ends are never closed on the parent, the reader blocks waiting for more input that will never arrive. You need to close it.
Also, you don't need waitpid(): the way pipes work ensures that input flows linearly and in order throughout the pipe.
Here's the working version with these issues addressed:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Invalid arguments. <dir> <arg>\n");
exit(1);
}
int pipe_fd1[2];
int pipe_fd2[2];
pid_t ls_pid, grep_pid;
pipe(pipe_fd1);
ls_pid = fork();
if (ls_pid == 0) { //first child ls DIR -laR
dup2(pipe_fd1[1], STDOUT_FILENO);
close(pipe_fd1[0]);
execlp("ls", "ls", argv[1], "-laR", NULL);
} else if (ls_pid > 0) {
dup2(pipe_fd1[0], STDIN_FILENO);
close(pipe_fd1[1]);
pipe(pipe_fd2);
grep_pid = fork();
if (grep_pid == 0) { //second child grep ARG
dup2(pipe_fd2[1], STDOUT_FILENO);
close(pipe_fd2[0]);
execlp("grep", "grep", argv[2], NULL);
} else if (grep_pid > 0) { //parent sort
dup2(pipe_fd2[0], STDIN_FILENO);
close(pipe_fd2[1]);
execlp("sort", "sort", NULL);
}
}
return 0;
}
Question is simple
I've searched around but I couldn't find the solution
char *data1;
char *data2;
pid_t pid = fork();
int stat;
if (pid == 0){
execlp("Program B");
} else {
wait(&stat);
if (WIFEXITED(stat))
printf("%d\n", WEXITSTATUS(stat));
}
the thing is I need to send data1 and data2 to Program B as stdin
but I couldn't find the solution
how can I deal with this?
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
char *data1 = "First message.\n";
char *data2 = "What the rest of the world has been waiting for.\n";
pid_t pid;
int p[2];
if (pipe(p) < 0)
perror("pipe() failed");
else if ((pid = fork()) < 0)
perror("fork() failed");
else if (pid == 0)
{
dup2(p[0], STDIN_FILENO);
close(p[0]);
close(p[1]);
execlp("cat", "cat", (char *)0);
perror("execlp() failed");
}
else
{
close(p[0]);
write(p[1], data1, strlen(data1));
write(p[1], data2, strlen(data2));
close(p[1]);
int status;
int corpse = wait(&status);
if (WIFEXITED(status))
printf("%d exited with status %d\n", corpse, WEXITSTATUS(status));
}
return 0;
}
Note how many closes are necessary.
Building a pipe to stdin is the way to go,
Like
char *data1;
char *data2;
int stat;
pid_t pid;
if( pipe(pfd) < 0 ) {
perror("pipe");
return 1;
}
pid = fork();
if (pid == 0)
{
// Close the writing end of the pipe
close(pfd[1]);
execlp("Program B");
}
else if(pid==-1)
{
perror("fork");
}
else
{
// Write to the pipe.
if (write(pfd[1], "This is my data \n", 16) != 16)
perror("write");
close(pfd[1]);
wait(&stat);
if (WIFEXITED(stat))
printf("%d\n", WEXITSTATUS(stat));
}
You can provide data as argument list to the new process.
Syntax:- int execlp(const char *path, const char *arg0, ..., NULL);
So your call can look something like this
// convert the input data into string format i.e data1 and data2 should be strings
execlp("Program B","Program B",data1,data2,NULL);
In program B use appropriately to convert it into whatever type you want to.
I want to set up 2 pipes in my program. I have 1 pipe working fine, but I don't know where to place the second pipe.
The pseudo code of my setup is shown below,
Here is it with curly braces sorry about that
//the first pipe:
pipe(pipe1)
//the second pipe:
pipe(pipe2)
pid = fork()
if(pid == 0) {
dup2(pipe1[1], 1)
close(pipe1[0])
execvp(beforepipe)
}
if(pid > 0) { //everything below is in here
pid2 = fork()
if(pid2 == 0){
//pipe1
dup2(pipe1[0],0)
dup2(out,1)
close(pipe1[1])
execvp(afterpipe)
//pipe2 does not work might need to be placed in different area
dup2(pipe1[1],1)
close(pipe1[0])
execvp(beforepipe1)
}
if(pid2 > 0){
close(pipe[0])
close(pipe[1])
wait() //this is an infinite for loop
pid3 = fork()
if(pid3 == 0){
dup2(pipe2[0],0)
dup2(out,1)
close(pipe2[1])
execvp(afterpipe2)
}
if(pid3 > 0) {
close(pipe2[0])
close(pipe2[1])
wait()
}
}
The position of the second pipe is in the wrong place or the code is altogether wrong.
Any suggestions?
Your main problem is that you are not closing anywhere near enough file descriptors. Given a file input1 in the current directory containing your string "eschew obfuscation\", this code works for me (but note how many file descriptors have to be closed!).
Rule of thumb: if a pipe is dup2()d or dup()d to standard input or output, close both file pipe file descriptors.
Example code (with debug tracing in place):
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* command pipeline: cat input1 | tr a-z A-Z | tr \\ q */
int main(void)
{
int pipe1[2];
int pipe2[2];
pid_t pid1;
char *cmd1[] = { "cat", "input1", 0 };
char *cmd2[] = { "tr", "a-z", "A-Z", 0 };
char *cmd3[] = { "tr", "\\", "q", 0 };
if (pipe(pipe1) != 0 || pipe(pipe2) != 0)
{
perror("pipe failed");
return 1;
}
pid1 = fork();
if (pid1 < 0)
{
perror("fork 1 failed");
return 1;
}
if (pid1 == 0)
{
/* Child 1 - cat */
dup2(pipe1[1], 1);
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[0]);
close(pipe2[1]);
execvp(cmd1[0], cmd1);
perror("failed to execute cmd1");
return 1;
}
printf("pid 1 = %d\n", pid1);
fflush(stdout);
pid_t pid2 = fork();
if (pid2 < 0)
{
perror("fork 2 failed");
return 1;
}
if (pid2 == 0)
{
/* Child 2 - tr a-z A-Z */
dup2(pipe1[0], 0);
dup2(pipe2[1], 1);
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[0]);
close(pipe2[1]);
execvp(cmd2[0], cmd2);
perror("failed to execute cmd2");
return 1;
}
printf("pid 2 = %d\n", pid2);
fflush(stdout);
pid_t pid3 = fork();
if (pid3 < 0)
{
perror("fork 3 failed");
return 1;
}
if (pid3 == 0)
{
/* Child 3 - tr \\ q */
dup2(pipe2[0], 0);
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[0]);
close(pipe2[1]);
execvp(cmd3[0], cmd3);
perror("failed to execute cmd3");
return 1;
}
printf("pid 3 = %d\n", pid3);
fflush(stdout);
/* Parent - wait for the kids to all die */
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[0]);
close(pipe2[1]);
pid_t corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("Child %d died status 0x%.4X\n", corpse, status);
return 0;
}
execvp(afterpipe)
//pipe2 does not work might need to be placed in different area
dup2(pipe1[1],1)
close(pipe1[0])
execvp(beforepipe1)
I think the execvp() didnot return. So the code below the execvp() is irrelevent.