78
#define PIPE_READ 0
79
#define PIPE_WRITE 1
80
81
-/* custom_popene flag definitions */
82
-#define FLAG_CREATE_PIPE 1 // Create a pipe like popen() when set, otherwise set stdout to /dev/null
83
-#define FLAG_CLOSE_FD 2 // Close all file descriptors other than STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO
81
+static inline void convert_argv_to_string(char *dst, size_t size, const char *spawn_argv[]) {
82
+ int i;
83
+ for(i = 0; spawn_argv[i] ;i++) {
84
+ if(i == 0) snprintfz(dst, size, "%s", spawn_argv[i]);
85
+ else {
86
+ size_t len = strlen(dst);
87
+ snprintfz(&dst[len], size - len, " '%s'", spawn_argv[i]);
88
+ }
89
+ }
90
+}
91
92
/*
86
- * Returns -1 on failure, 0 on success. When FLAG_CREATE_PIPE is set, on success set the FILE *fp pointer.
93
+ * Returns -1 on failure, 0 on success. When POPEN_FLAG_CREATE_PIPE is set, on success set the FILE *fp pointer.
94
*/
88
-static inline int custom_popene(const char *command, volatile pid_t *pidptr, char **env, uint8_t flags, FILE **fpp) {
95
+static int custom_popene(volatile pid_t *pidptr, char **env, uint8_t flags, FILE **fpp, const char *command, const char *spawn_argv[]) {
96
+ // create a string to be logged about the command we are running
97
+ char command_to_be_logged[2048];
98
+ convert_argv_to_string(command_to_be_logged, sizeof(command_to_be_logged), spawn_argv);
99
+ // info("custom_popene() running command: %s", command_to_be_logged);
100
+
101
FILE *fp = NULL;
102
int ret = 0; // success by default
103
int pipefd[2], error;
104
pid_t pid;
93
- char *const spawn_argv[] = {
94
- "sh",
95
- "-c",
96
- (char *)command,
97
- NULL
98
- };
105
posix_spawnattr_t attr;
106
posix_spawn_file_actions_t fa;
107
102
- if (flags & FLAG_CREATE_PIPE) {
108
+ if (flags & POPEN_FLAG_CREATE_PIPE) {
109
if (pipe(pipefd) == -1)
110
return -1;
111
if ((fp = fdopen(pipefd[PIPE_READ], "r")) == NULL) {
113
}
114
}
115
110
- if (flags & FLAG_CLOSE_FD) {
116
+ if (flags & POPEN_FLAG_CLOSE_FD) {
117
// Mark all files to be closed by the exec() stage of posix_spawn()
118
int i;
119
for (i = (int) (sysconf(_SC_OPEN_MAX) - 1); i >= 0; i--) {
123
}
124
125
if (!posix_spawn_file_actions_init(&fa)) {
120
- if (flags & FLAG_CREATE_PIPE) {
126
+ if (flags & POPEN_FLAG_CREATE_PIPE) {
127
// move the pipe to stdout in the child
128
if (posix_spawn_file_actions_adddup2(&fa, pipefd[PIPE_WRITE], STDOUT_FILENO)) {
129
error("posix_spawn_file_actions_adddup2() failed");
156
// Take the lock while we fork to ensure we don't race with SIGCHLD
157
// delivery on a process which exits quickly.
158
myp_add_lock();
153
- if (!posix_spawn(&pid, "/bin/sh", &fa, &attr, spawn_argv, env)) {
159
+ if (!posix_spawn(&pid, command, &fa, &attr, (char * const*)spawn_argv, env)) {
160
*pidptr = pid;
161
myp_add_locked(pid);
156
- debug(D_CHILDS, "Spawned command: '%s' on pid %d from parent pid %d.", command, pid, getpid());
162
+ debug(D_CHILDS, "Spawned command: \"%s\" on pid %d from parent pid %d.", command_to_be_logged, pid, getpid());
163
} else {
164
myp_add_unlock();
159
- error("Failed to spawn command: '%s' from parent pid %d.", command, getpid());
160
- if (flags & FLAG_CREATE_PIPE) {
165
+ error("Failed to spawn command: \"%s\" from parent pid %d.", command_to_be_logged, getpid());
166
+ if (flags & POPEN_FLAG_CREATE_PIPE) {
167
fclose(fp);
168
}
169
ret = -1;
170
}
165
- if (flags & FLAG_CREATE_PIPE) {
171
+ if (flags & POPEN_FLAG_CREATE_PIPE) {
172
close(pipefd[PIPE_WRITE]);
173
if (0 == ret) // on success set FILE * pointer
168
- *fpp = fp;
174
+ if(fpp) *fpp = fp;
175
}
176
177
if (!error) {
187
error_after_posix_spawn_file_actions_init:
188
if (posix_spawn_file_actions_destroy(&fa))
189
error("posix_spawn_file_actions_destroy");
190
+
191
error_after_pipe:
185
- if (flags & FLAG_CREATE_PIPE) {
192
+ if (flags & POPEN_FLAG_CREATE_PIPE) {
193
if (fp)
194
fclose(fp);
195
else
200
return -1;
201
}
202
203
+int custom_popene_variadic_internal_dont_use_directly(volatile pid_t *pidptr, char **env, uint8_t flags, FILE **fpp, const char *command, ...) {
204
+ // convert the variable list arguments into what posix_spawn() needs
205
+ // all arguments are expected strings
206
+ va_list args;
207
+ int args_count;
208
+
209
+ // count the number variable parameters
210
+ // the variable parameters are expected NULL terminated
211
+ {
212
+ const char *s;
213
+
214
+ va_start(args, command);
215
+ args_count = 0;
216
+ while ((s = va_arg(args, const char *))) args_count++;
217
+ va_end(args);
218
+ }
219
+
220
+ // create a string pointer array as needed by posix_spawn()
221
+ // variable array in the stack
222
+ const char *spawn_argv[args_count + 1];
223
+ {
224
+ const char *s;
225
+ va_start(args, command);
226
+ int i;
227
+ for (i = 0; i < args_count; i++) {
228
+ s = va_arg(args, const char *);
229
+ spawn_argv[i] = s;
230
+ }
231
+ spawn_argv[args_count] = NULL;
232
+ va_end(args);
233
+ }
234
+
235
+ return custom_popene(pidptr, env, flags, fpp, command, spawn_argv);
236
+}
237
+
238
// See man environ
239
extern char **environ;
240
294
295
FILE *mypopen(const char *command, volatile pid_t *pidptr) {
296
FILE *fp = NULL;
255
- (void)custom_popene(command, pidptr, environ, FLAG_CREATE_PIPE | FLAG_CLOSE_FD, &fp);
297
+ const char *spawn_argv[] = {
298
+ "sh",
299
+ "-c",
300
+ command,
301
+ NULL
302
+ };
303
+ (void)custom_popene(pidptr, environ, POPEN_FLAG_CREATE_PIPE|POPEN_FLAG_CLOSE_FD, &fp, "/bin/sh", spawn_argv);
304
return fp;
305
}
306
307
FILE *mypopene(const char *command, volatile pid_t *pidptr, char **env) {
308
FILE *fp = NULL;
261
- (void)custom_popene(command, pidptr, env, FLAG_CREATE_PIPE | FLAG_CLOSE_FD, &fp);
309
+ const char *spawn_argv[] = {
310
+ "sh",
311
+ "-c",
312
+ command,
313
+ NULL
314
+ };
315
+ (void)custom_popene( pidptr, env, POPEN_FLAG_CREATE_PIPE|POPEN_FLAG_CLOSE_FD, &fp, "/bin/sh", spawn_argv);
316
return fp;
317
}
318
319
// returns 0 on success, -1 on failure
320
int netdata_spawn(const char *command, volatile pid_t *pidptr) {
267
- return custom_popene(command, pidptr, environ, 0, NULL);
321
+ const char *spawn_argv[] = {
322
+ "sh",
323
+ "-c",
324
+ command,
325
+ NULL
326
+ };
327
+ return custom_popene( pidptr, environ, POPEN_FLAG_NONE, NULL, "/bin/sh", spawn_argv);
328
}
329
330
int custom_pclose(FILE *fp, pid_t pid) {