-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpipes.c
More file actions
89 lines (74 loc) · 2.41 KB
/
pipes.c
File metadata and controls
89 lines (74 loc) · 2.41 KB
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
/* Functionality that extends popen. */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "pipes.h"
/* Shell to use when opening a file read/write. */
#define SHELL "/bin/sh"
/* Basically popen(path, "rw"), but popen doesn't let you do this. */
static int popen_rw(const char *path, int *read_fd, int *write_fd) {
/* What we're going to do is create two pipes that we'll use as the read
* and write file descriptors. Stdout and stdin, repsectively, in the
* opened process need to connect to these pipes.
*/
int input[2], output[2];
if (pipe(input) != 0 || pipe(output) != 0) {
return -1;
}
/* Flush standard streams to avoid aberrations after forking. This
* shouldn't really be required as we aren't using any of these anyway.
*/
fflush(stdout); fflush(stderr); fflush(stdin);
pid_t pid = fork();
if (pid == -1) {
close(input[0]);
close(input[1]);
close(output[0]);
close(output[1]);
return -1;
} else if (pid == 0) {
/* We are the child. */
/* Close the ends of the pipe we don't need. */
close(input[1]); close(output[0]);
/* Overwrite our stdin and stdout such that they connect to the pipes.
*/
if (dup2(input[0], STDIN_FILENO) < 0 || dup2(output[1], STDOUT_FILENO) < 0) {
exit(1);
}
/* Overwrite our image with the command to execute. Note that exec will
* only return if it fails.
*/
(void)execl(SHELL, "sh", "-c", path, NULL);
exit(1);
} else {
/* We are the parent. */
/* Close the ends of the pipe we don't need. */
close(input[0]); close(output[1]);
/* Pack the file descriptors we do need into the handle. */
*read_fd = output[0];
*write_fd = input[1];
return 0;
}
/* Unreachable. */
}
int pipe_open(char *command, char *mode, int *read_fd, int *write_fd) {
if (!strcmp(mode, "r")) {
FILE *f = popen(command, "r");
if (f == NULL) {
return -1;
}
*read_fd = fileno(f);
return 0;
} else if (!strcmp(mode, "w")) {
FILE *f = popen(command, "w");
if (f == NULL) {
return -1;
}
*write_fd = fileno(f);
return 0;
}
/* "rw" */
return popen_rw(command, read_fd, write_fd);
}