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