/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file
*/
#include "lib.h"
#include "lib-signals.h"
#include "env-util.h"
#include "execv-const.h"
#include "array.h"
#include "net.h"
#include "istream.h"
#include "ostream.h"
#include "restrict-access.h"
#include "child-wait.h"
#include "time-util.h"
#include "program-client-private.h"
#include <unistd.h>
#include <fcntl.h>
#include <grp.h>
struct program_client_local {
int status;
};
static
void program_client_local_waitchild(const struct child_wait_status *,
struct program_client_local *);
static
static
static
{
if (in_fd < 0)
in_fd = dev_null_fd;
if (out_fd < 0)
i_fatal("dup2(stdin) failed: %m");
i_fatal("dup2(stdout) failed: %m");
i_error("close(in_fd) failed: %m");
i_error("close(out_fd) failed: %m");
/* Drop stderr if requested */
if (drop_stderr) {
i_fatal("dup2(stderr) failed: %m");
}
/* Setup extra fds */
int *efd;
i_fatal("dup2(extra_fd=%d) failed: %m",
efd[1]);
}
}
efd[0] != STDOUT_FILENO &&
efd[0] != STDERR_FILENO) {
i_error("close(extra_fd=%d) failed: %m",
efd[1]);
}
}
}
/* Compose argv */
}
(void) array_append_space(&exec_args);
/* Setup environment */
env_clean();
if (array_is_created(envs)) {
const char *const *env;
}
}
/* Execute */
}
static
struct program_client_local *plclient)
{
else
}
static
{
(struct program_client_local *)pclient;
unsigned int xfd_count = 0, i;
/* create normal I/O fds */
i_error("pipe(in) failed: %m");
return -1;
}
}
i_error("pipe(out) failed: %m");
return -1;
}
}
/* create pipes for additional output through side-channel fds */
if (xfd_count > 0) {
for(i = 0; i < xfd_count; i++) {
i_error("pipe(extra=%d) failed: %m",
extra_fd[1]);
return -1;
}
parent_extra_fds[i] = extra_fd[0];
}
}
}
/* fork child */
i_error("fork() failed: %m");
/* clean up */
i_error("close(pipe:in:rd) failed: %m");
}
i_error("close(pipe:in:wr) failed: %m");
}
i_error("close(pipe:out:rd) failed: %m");
}
i_error("close(pipe:out:wr) failed: %m");
}
for(i = 0; i < xfd_count; i++) {
i_error("close(pipe:extra=%d:wr) failed: %m",
}
if (close(parent_extra_fds[i]) < 0) {
i_error("close(pipe:extra=%d:rd) failed: %m",
}
}
return -1;
}
/* child */
i_error("close(pipe:in:wr) failed: %m");
i_error("close(pipe:out:rd) failed: %m");
for(i = 0; i < xfd_count; i++) {
if (close(parent_extra_fds[i]) < 0) {
i_error("close(pipe:extra=%d:rd) failed: %m",
}
}
/* if we want to allow root, then we will not drop
root privileges */
i_unreached();
}
/* parent */
i_error("close(pipe:in:rd) failed: %m");
i_error("close(pipe:out:wr) failed: %m");
if (fd_in[1] >= 0) {
}
if (fd_out[0] >= 0) {
}
for(i = 0; i < xfd_count; i++) {
i_error("close(pipe:extra=%d:wr) failed: %m",
}
}
plclient);
return program_client_connected(pclient);
}
static
{
/* Shutdown output; program stdin will get EOF */
return -1;
}
return 1;
}
static
{
/* Evaluate child exit status */
/* Exited */
if (exit_code != 0) {
i_info("program `%s' terminated with non-zero exit code %d",
} else {
}
/* Killed with a signal */
i_error("program `%s' was forcibly terminated with signal %d",
} else {
i_error("program `%s' terminated abnormally, signal %d",
}
/* Stopped */
i_error("program `%s' stopped, signal %d",
} else {
/* Something else */
i_error("program `%s' terminated abnormally, return status %d",
}
}
static
{
/* time to die */
/* no need for this anymore */
/* Timed out again */
i_debug("program `%s' (%d) did not die after %d milliseconds: "
"sending KILL signal",
}
/* Kill it brutally now, it should die right away */
i_error("failed to send SIGKILL signal to program `%s'",
i_error("waitpid(%s) failed: %m",
}
return;
}
i_debug("program `%s'(%d) execution timed out after %u milliseconds: "
/* send sigterm, keep on waiting */
/* Kill child gently first */
i_error("failed to send SIGTERM signal to program `%s'",
return;
}
}
static
{
(struct program_client_local *) pclient;
return;
}
if (pid < 0) {
/* program never started */
return;
}
/* make sure it hasn't already been reaped */
return;
}
/* Calculate timeout */
i_debug("waiting for program `%s' to finish after %lu msecs",
}
if (!force) {
if (timeout > 0)
plclient);
} else {
}
}
static
{
}
static
{
(struct program_client_local *)pclient;
}
struct program_client *
const char *const *args,
const struct program_client_settings *set)
{
}