]> git.itanic.dy.fi Git - rrdd/blob - process.c
Add support for executing process while piping std{in,out} to parent
[rrdd] / process.c
1 #include "process.h"
2
3 int child_count = 0;
4
5 int run(const char *cmd, char *const argv[])
6 {
7         int child, error;
8         child = fork();
9         if (child < 0) {
10                 error = errno;
11                 fprintf(stderr, "fork() failed: %s\n", strerror(error));
12                 return -1;
13         }
14
15         if (child) {
16                 printf("Forked child %d\n", child);
17                 child_count++;
18                 return child;
19         }
20
21         execvp(cmd, argv);
22         error = errno;
23         printf("Failed to execv command %s: %s\n", cmd, strerror(error));
24         exit(1);
25         return 0;
26 }
27
28 int harvest_zombies(int pid)
29 {
30         int status;
31
32         if (child_count == 0)
33                 return 0;
34
35         pid = waitpid(pid, &status, 0);
36         if (status == 0)
37                 printf("pid %d: terminated with exit code %d\n", pid, status);
38
39         child_count--;
40         return 1;
41 }
42
43 /*
44  * Runs a command cmd with params argv, connects stdin and stdout to
45  * readfd and writefd
46  *
47  * Returns the pid of the executed process
48  */
49 int run_piped(const char *cmd, char *const argv[], int *readfd, int *writefd)
50 {
51         int rfd[2], wfd[2], error, pid;
52
53         if (pipe(rfd)) {
54                 error = errno;
55                 fprintf(stderr, "pipe() failed: %s\n", strerror(error));
56                 return -1;
57         }
58
59         if (pipe(wfd)) {
60                 error = errno;
61                 fprintf(stderr, "pipe() failed: %s\n", strerror(error));
62                 return -1;
63         }
64
65         pid = fork();
66         if (pid < 0) {
67                 printf("parent\n");
68                 error = errno;
69                 fprintf(stderr, "fork() failed: %s\n", strerror(error));
70                 return -1;
71         }
72
73         if (pid) {
74                 close(rfd[1]);
75                 close(wfd[0]);
76                 *readfd = rfd[0];
77                 *writefd = wfd[1];
78                 return pid;
79         }
80
81         close(rfd[0]);
82         close(wfd[1]);
83         dup2(wfd[0], STDIN_FILENO);
84         dup2(rfd[1], STDOUT_FILENO);
85
86         /* Now we have redirected both stdin and stdout to parent process */
87         execvp(cmd, argv);
88         error = errno;
89         printf("Failed to execv command %s: %s\n", cmd, strerror(error));
90         exit(1);
91         return 0;
92 }
93
94 /*
95  * Runs a command cmd with params argv, connects stdin and stdout to
96  * readfd and writefd
97  *
98  * Returns the pid of the executed process
99  */
100 int run_piped_stream(const char *cmd, char *const argv[],
101                      FILE **readf, FILE **writef)
102 {
103         int rfd, wfd, pid, error;
104
105         pid = run_piped(cmd, argv, &rfd, &wfd);
106
107         if (readf) {
108                 *readf = fdopen(rfd, "r");
109                 if (*readf == NULL) {
110                         error = errno;
111                         fprintf(stderr,
112                                 "Error opening file stream for fd %d: %s\n",
113                                 rfd, strerror(error));
114                         return -1;
115                 }
116         }
117
118         if (writef) {
119                 *writef = fdopen(wfd, "w");
120                 if (*writef == NULL) {
121                         error = errno;
122                         fprintf(stderr,
123                                 "Error opening file stream for fd %d: %s\n",
124                                 wfd, strerror(error));
125                         return -1;
126                 }
127         }
128
129         return pid;
130 }