+
+int HTTPInput::open_child_process(const string &cmdline)
+{
+ int devnullfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
+ if (devnullfd == -1) {
+ log_perror("/dev/null");
+ return -1;
+ }
+
+ int pipefd[2];
+ if (pipe2(pipefd, O_CLOEXEC) == -1) {
+ log_perror("pipe2()");
+ close(devnullfd);
+ return -1;
+ }
+
+ // Point stdout to us, stdin to /dev/null, and stderr remains where it is
+ // (probably the systemd log). All other file descriptors should be marked
+ // as close-on-exec, and should thus not leak into the child.
+ posix_spawn_file_actions_t actions;
+ posix_spawn_file_actions_init(&actions);
+ posix_spawn_file_actions_adddup2(&actions, devnullfd, 0);
+ posix_spawn_file_actions_adddup2(&actions, pipefd[1], 1);
+
+ pid_t child_pid;
+ char * const argv[] = {
+ strdup("/bin/sh"),
+ strdup("-c"),
+ strdup(path.c_str()),
+ nullptr
+ };
+ int err = posix_spawn(&child_pid, "/bin/sh", &actions, /*attrp=*/nullptr, argv, /*envp=*/nullptr);
+ posix_spawn_file_actions_destroy(&actions);
+ free(argv[0]);
+ free(argv[1]);
+ free(argv[2]);
+ close(pipefd[1]);
+
+ if (err == 0) {
+ return pipefd[0];
+ } else {
+ log_perror(cmdline.c_str());
+ close(pipefd[0]);
+ return -1;
+ }
+}