-
Notifications
You must be signed in to change notification settings - Fork 0
/
pipe.c
94 lines (87 loc) · 3.47 KB
/
pipe.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
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pipe.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: rjobert <rjobert@student.42barcelo> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/07/25 09:36:38 by rjobert #+# #+# */
/* Updated: 2023/08/01 20:04:09 by rjobert ### ########.fr */
/* */
/* ************************************************************************** */
#include "pipex.h"
int main(int argc, char *argv[], char *env[])
{
int pipefd[2];
int pid;
if (argc != 5)
exit_error(EXIT_FAILURE, "please enter 4 arguments", NULL, NULL);
if (pipe(pipefd) == -1)
exit_error(errno, strerror(errno), NULL, NULL);
pid = fork();
if (pid == -1)
exit_error(errno, strerror(errno), NULL, NULL);
if (pid == 0)
child_process(pipefd, argv, env);
else
parent_process(pipefd, argv, env);
close(pipefd[0]);
close(pipefd[1]);
exit(EXIT_SUCCESS);
}
/*parent process doing from read-end to output.txt)
1 - close the write end of the pipe as we don't use it
(we read from the pipe pipefd[0])
2 - we clone the stdin we are streaming data from with the read-end of the pipe
and we then close (pipefd[0]) to avoid to many duplicate fd refering the same
open file table
3 - we open the output txt file (all possible openings and full permission)
we will direct the output to, we clone STDOUT with it so that our cmdline
function stdout exec will redirect to the fd (STDOUT is now the fd)
4 - we close our output file fd to avoid duplicate
5 - we can now use the exec function piping from pipfd[0] = STDIN and
piping out to STDOUT = outputfile's fd
*/
void parent_process(int *pipefd, char *argv[], char *env[])
{
int status;
int fd;
fd = open(argv[4], O_WRONLY | O_TRUNC | O_CREAT, 0666);
if (fd == -1)
exit_error(1, strerror(errno), argv[4], NULL);
waitpid(-1, &status, WNOHANG);
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
dup2(fd, STDOUT_FILENO);
close (fd);
build_exec(argv[3], env, fd);
}
/*child process doing from inutfile to the write-end
1 - close the read-end of the pipe as we don't use it
(we write to pipefd[1])
2 - we clone the stdout as we are deviating STDOUT to stream data to
the write-end of the pipe and we then close (pipefd[0]) to avoid to many
duplicate fd refering the same open file table
3 - we open the input txt file (the file we stream data from - so readonly),
we clone STDIN with it so that our cmdline function stdin exec will be replaced
by fd (STDIN is now the fd)
4 - we close our output file fd to avoid duplicate
5 - we can now use the exec function piping from pipfd[0] = STDIN and piping out
to STDOUT = outputfile's fd
6 - wait for the child to finish it's process to avoid to create a
orphan after done writing
*/
void child_process(int *pipefd, char *argv[], char *env[])
{
int fd;
fd = open(argv[1], O_RDONLY, 0666);
if (fd == -1)
exit_error(errno, strerror(errno), argv[1], NULL);
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
dup2(fd, STDIN_FILENO);
close(fd);
build_exec(argv[2], env, fd);
}