-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpipe_multi_branch.c
110 lines (91 loc) · 2.59 KB
/
pipe_multi_branch.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
* usage: ./a.out input_file text_pattern
* Executes the command "cat input_file | grep text_pattern | cut -b 1-10".
* Note only minimal error checking is done for simplicity/shortness of code.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <wait.h>
int main(int argc, char **argv)
{
int status;
int i;
if (argc == 3)
{
// arguments for commands
char *cat_args[] = {"cat", argv[1], NULL};
char *grep_args[] = {"grep", argv[2], NULL};
char *cut_args[] = {"cut", "-b", "1-10", NULL};
// file descriptors for 2 pipes: fd1 for cat-to-grep, fd2 for grep-to-cut
int fd1[2], fd2[2];
// make pipe for cat to grep
pipe(fd1);
// fd1[0] = read end of cat->grep pipe (read by grep)
// fd1[1] = write end of cat->grep pipe (written by cat)
// make pipe for grep to cut
pipe(fd2);
// fd2[0] = read end of grep->cut pipe (read by cut)
// fd2[1] = write end of grep->cut pipe (written by grep)
// fork the first child (to execute cat)
if (fork() == 0)
{
// duplicate write end of cat->grep pipe to stdout
dup2(fd1[1], 1);
// close both ends of all created fd# pipes (very important!)
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
close(fd2[1]);
execvp(*cat_args, cat_args);
}
else // parent (assume no error)
{
// fork second child (to execute grep)
if (fork() == 0)
{
// duplicate read end of cat->grep pipe to stdin (of grep)
dup2(fd1[0], 0);
// duplicate write end of grep->cut pipe to stdout (of grep)
dup2(fd2[1], 1);
// close both ends of all created fd# pipes (very important!)
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
close(fd2[1]);
execvp(*grep_args, grep_args);
}
else // parent (assume no error)
{
// fork third child (to execute cut)
if (fork() == 0)
{
// duplicate read end of grep->cut pipe to stadin (of cut)
dup2(fd2[0], 0);
// close both ends of all created fd# pipes (very important!)
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
close(fd2[1]);
execvp(*cut_args, cut_args);
}
}
}
// only the parent gets here, close all pipes and wait for 3 children to finish
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
close(fd2[1]);
for (i = 0; i < 3; i++)
{
wait(&status);
}
}
else
{
printf("usage: %s input_file text_pattern\n", argv[0]);
}
return 0;
}