struct child_wait *child_wait;
struct timeout *to_kill;
+ char *bin_path;
+
pid_t pid;
int status;
bool exited:1;
out_fd = dev_null_fd;
if (in_fd != STDIN_FILENO && dup2(in_fd, STDIN_FILENO) < 0)
- i_fatal("dup2(stdin) failed: %m");
+ i_fatal("program %s: dup2(stdin) failed: %m", bin_path);
if (out_fd != STDOUT_FILENO && dup2(out_fd, STDOUT_FILENO) < 0)
- i_fatal("dup2(stdout) failed: %m");
+ i_fatal("program %s: dup2(stdout) failed: %m", bin_path);
if (in_fd != STDIN_FILENO && in_fd != dev_null_fd && close(in_fd) < 0)
- i_error("close(in_fd) failed: %m");
+ i_error("program %s: close(in_fd) failed: %m", bin_path);
if (out_fd != STDOUT_FILENO && out_fd != dev_null_fd &&
(out_fd != in_fd) && close(out_fd) < 0)
- i_error("close(out_fd) failed: %m");
+ i_error("program %s: close(out_fd) failed: %m", bin_path);
/* Drop stderr if requested */
if (drop_stderr) {
- if (dup2(dev_null_fd, STDERR_FILENO) < 0)
- i_fatal("dup2(stderr) failed: %m");
+ if (dup2(dev_null_fd, STDERR_FILENO) < 0) {
+ i_fatal("program %s: "
+ "dup2(stderr) failed: %m", bin_path);
+ }
}
/* Setup extra fds */
i_assert(efd[1] != STDOUT_FILENO);
i_assert(efd[1] != STDERR_FILENO);
if (efd[0] != efd[1]) {
- if (dup2(efd[0], efd[1]) < 0)
- i_fatal("dup2(extra_fd=%d) failed: %m",
- efd[1]);
+ if (dup2(efd[0], efd[1]) < 0) {
+ i_fatal("program %s"
+ "dup2(extra_fd=%d) failed: %m",
+ bin_path, efd[1]);
+ }
}
}
for(efd = extra_fds; *efd != -1; efd += 2) {
if (efd[0] != efd[1] && efd[0] != STDIN_FILENO &&
efd[0] != STDOUT_FILENO &&
efd[0] != STDERR_FILENO) {
- if (close(efd[0]) < 0)
- i_error("close(extra_fd=%d) failed: %m",
- efd[1]);
+ if (close(efd[0]) < 0) {
+ i_error("program %s"
+ "close(extra_fd=%d) failed: %m",
+ bin_path, efd[1]);
+ }
}
}
}
/* create normal I/O fds */
if (pclient->input != NULL) {
if (pipe(fd_in) < 0) {
- i_error("pipe(in) failed: %m");
+ e_error(pclient->event, "pipe(in) failed: %m");
return -1;
}
}
if (pclient->output != NULL) {
if (pipe(fd_out) < 0) {
- i_error("pipe(out) failed: %m");
+ e_error(pclient->event, "pipe(out) failed: %m");
return -1;
}
}
child_extra_fds = t_new(int, xfd_count * 2 + 1);
for(i = 0; i < xfd_count; i++) {
if (pipe(extra_fd) < 0) {
- i_error("pipe(extra=%d) failed: %m",
+ e_error(pclient->event,
+ "pipe(extra=%d) failed: %m",
extra_fd[1]);
return -1;
}
/* fork child */
if ((plclient->pid = fork()) == (pid_t)-1) {
- i_error("fork() failed: %m");
+ e_error(pclient->event, "fork() failed: %m");
/* clean up */
if (fd_in[0] >= 0 && close(fd_in[0]) < 0) {
- i_error("close(pipe:in:rd) failed: %m");
+ e_error(pclient->event,
+ "close(pipe:in:rd) failed: %m");
}
if (fd_in[1] >= 0 && close(fd_in[1]) < 0) {
- i_error("close(pipe:in:wr) failed: %m");
+ e_error(pclient->event,
+ "close(pipe:in:wr) failed: %m");
}
if (fd_out[0] >= 0 && close(fd_out[0]) < 0) {
- i_error("close(pipe:out:rd) failed: %m");
+ e_error(pclient->event,
+ "close(pipe:out:rd) failed: %m");
}
if (fd_out[1] >= 0 && close(fd_out[1]) < 0) {
- i_error("close(pipe:out:wr) failed: %m");
+ e_error(pclient->event,
+ "close(pipe:out:wr) failed: %m");
}
for(i = 0; i < xfd_count; i++) {
if (close(child_extra_fds[i * 2]) < 0) {
- i_error("close(pipe:extra=%d:wr) failed: %m",
+ e_error(pclient->event,
+ "close(pipe:extra=%d:wr) failed: %m",
child_extra_fds[i * 2 + 1]);
}
if (close(parent_extra_fds[i]) < 0) {
- i_error("close(pipe:extra=%d:rd) failed: %m",
+ e_error(pclient->event,
+ "close(pipe:extra=%d:rd) failed: %m",
child_extra_fds[i * 2 + 1]);
}
}
if (plclient->pid == 0) {
/* child */
- if (fd_in[1] >= 0 && close(fd_in[1]) < 0)
- i_error("close(pipe:in:wr) failed: %m");
- if (fd_out[0] >= 0 && close(fd_out[0]) < 0)
- i_error("close(pipe:out:rd) failed: %m");
+ if (fd_in[1] >= 0 && close(fd_in[1]) < 0) {
+ e_error(pclient->event,
+ "close(pipe:in:wr) failed: %m");
+ }
+ if (fd_out[0] >= 0 && close(fd_out[0]) < 0) {
+ e_error(pclient->event,
+ "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",
+ e_error(pclient->event,
+ "close(pipe:extra=%d:rd) failed: %m",
child_extra_fds[i * 2 + 1]);
}
}
RESTRICT_ACCESS_FLAG_ALLOW_ROOT : 0),
pclient->set.home);
- exec_child(pclient->path, pclient->args, &pclient->envs,
+ exec_child(plclient->bin_path, pclient->args, &pclient->envs,
fd_in[0], fd_out[1], child_extra_fds,
pclient->set.drop_stderr);
i_unreached();
}
/* parent */
- if (fd_in[0] >= 0 && close(fd_in[0]) < 0)
- i_error("close(pipe:in:rd) failed: %m");
- if (fd_out[1] >= 0 && close(fd_out[1]) < 0)
- i_error("close(pipe:out:wr) failed: %m");
+ program_client_set_label(pclient,
+ t_strdup_printf("exec:%s (%d)", plclient->bin_path,
+ plclient->pid));
+
+ if (fd_in[0] >= 0 && close(fd_in[0]) < 0) {
+ e_error(pclient->event, "close(pipe:in:rd) failed: %m");
+ }
+ if (fd_out[1] >= 0 && close(fd_out[1]) < 0) {
+ e_error(pclient->event, "close(pipe:out:wr) failed: %m");
+ }
if (fd_in[1] >= 0) {
net_set_nonblock(fd_in[1], TRUE);
pclient->fd_out = fd_in[1];
}
for(i = 0; i < xfd_count; i++) {
if (close(child_extra_fds[i * 2]) < 0) {
- i_error("close(pipe:extra=%d:wr) failed: %m",
+ e_error(pclient->event,
+ "close(pipe:extra=%d:wr) failed: %m",
child_extra_fds[i * 2 + 1]);
}
net_set_nonblock(parent_extra_fds[i], TRUE);
/* Shutdown output; program stdin will get EOF */
if (fd_out >= 0 && close(fd_out) < 0) {
- i_error("close(%s) failed: %m", pclient->path);
+ e_error(pclient->event,
+ "close(fd_out) failed: %m");
return -1;
}
return 1;
int exit_code = WEXITSTATUS(plclient->status);
if (exit_code != 0) {
- i_info("program `%s' terminated with non-zero exit code %d",
- pclient->path, exit_code);
+ e_info(pclient->event,
+ "Terminated with non-zero exit code %d",
+ exit_code);
pclient->exit_code = PROGRAM_CLIENT_EXIT_FAILURE;
} else {
pclient->exit_code = PROGRAM_CLIENT_EXIT_SUCCESS;
} else if (WIFSIGNALED(plclient->status)) {
/* Killed with a signal */
if (plclient->sent_term) {
- i_error("program `%s' was forcibly terminated with signal %d",
- pclient->path, WTERMSIG(plclient->status));
+ e_error(pclient->event,
+ "Forcibly terminated with signal %d",
+ WTERMSIG(plclient->status));
} else {
- i_error("program `%s' terminated abnormally, signal %d",
- pclient->path, WTERMSIG(plclient->status));
+ e_error(pclient->event,
+ "Terminated abnormally with signal %d",
+ WTERMSIG(plclient->status));
}
} else if (WIFSTOPPED(plclient->status)) {
/* Stopped */
- i_error("program `%s' stopped, signal %d",
- pclient->path, WSTOPSIG(plclient->status));
+ e_error(pclient->event,
+ "Stopped with signal %d",
+ WSTOPSIG(plclient->status));
} else {
/* Something else */
- i_error("program `%s' terminated abnormally, return status %d",
- pclient->path, plclient->status);
+ e_error(pclient->event,
+ "Terminated abnormally with status %d",
+ plclient->status);
}
program_client_disconnected(pclient);
static void
program_client_local_kill_now(struct program_client_local *plclient)
{
+ struct program_client *pclient = &plclient->client;
+
if (plclient->child_wait != NULL) {
/* no need for this anymore */
child_wait_free(&plclient->child_wait);
/* kill it brutally now: it should die right away */
if (kill(plclient->pid, SIGKILL) < 0) {
- i_error("failed to send SIGKILL signal to program `%s'",
- plclient->client.path);
+ e_error(pclient->event,
+ "Failed to send SIGKILL signal to program");
} else if (waitpid(plclient->pid, &plclient->status, 0) < 0) {
- i_error("waitpid(%s) failed: %m",
- plclient->client.path);
+ e_error(pclient->event, "waitpid(%d) failed: %m",
+ plclient->pid);
}
}
static void
program_client_local_kill(struct program_client_local *plclient)
{
+ struct program_client *pclient = &plclient->client;
+
/* time to die */
timeout_remove(&plclient->to_kill);
if (plclient->sent_term) {
/* Timed out again */
- if (plclient->client.debug) {
- i_debug("program `%s' (%d) did not die after %d milliseconds: "
- "sending KILL signal",
- plclient->client.path, plclient->pid, KILL_TIMEOUT);
- }
+ e_debug(pclient->event,
+ "Program did not die after %d milliseconds",
+ KILL_TIMEOUT);
program_client_local_kill_now(plclient);
program_client_local_exited(plclient);
return;
}
- if (plclient->client.debug)
- i_debug("program `%s'(%d) execution timed out after %u milliseconds: "
- "sending TERM signal", plclient->client.path, plclient->pid,
- plclient->client.set.input_idle_timeout_msecs);
+ e_debug(pclient->event,
+ "Execution timed out after %u milliseconds: "
+ "Sending TERM signal",
+ pclient->set.input_idle_timeout_msecs);
/* send sigterm, keep on waiting */
plclient->sent_term = TRUE;
/* Kill child gently first */
if (kill(plclient->pid, SIGTERM) < 0) {
- i_error("failed to send SIGTERM signal to program `%s'",
- plclient->client.path);
+ e_error(pclient->event,
+ "Failed to send SIGTERM signal to program");
(void)kill(plclient->pid, SIGKILL);
program_client_local_exited(plclient);
return;
runtime < pclient->set.input_idle_timeout_msecs)
timeout = pclient->set.input_idle_timeout_msecs - runtime;
- if (pclient->debug) {
- i_debug("waiting for program `%s' to finish after %lu msecs",
- pclient->path, runtime);
- }
+ e_debug(pclient->event,
+ "Waiting for program to finish after %lu msecs", runtime);
force = force ||
(timeout == 0 && pclient->set.input_idle_timeout_msecs > 0);
const struct program_client_settings *set)
{
struct program_client_local *plclient;
+ const char *label;
pool_t pool;
+ label = t_strconcat("exec:", bin_path, NULL);
+
pool = pool_alloconly_create("program client local", 1024);
plclient = p_new(pool, struct program_client_local, 1);
- program_client_init(&plclient->client, pool, bin_path, args, set);
+ program_client_init(&plclient->client, pool, label, args, set);
plclient->client.connect = program_client_local_connect;
plclient->client.close_output = program_client_local_close_output;
plclient->client.switch_ioloop = program_client_local_switch_ioloop;
plclient->client.disconnect = program_client_local_disconnect;
plclient->client.destroy = program_client_local_destroy;
+ plclient->bin_path = p_strdup(pool, bin_path);
plclient->pid = -1;
child_wait_init();
pool_t pool;
struct program_client_settings set;
- char *path;
const char **args;
ARRAY_TYPE(const_string) envs;
+ struct event *event;
+
int fd_in, fd_out;
struct io *io;
struct timeout *to;
bool destroying:1;
};
+void program_client_set_label(struct program_client *pclient,
+ const char *label);
+
void program_client_init(struct program_client *pclient, pool_t pool,
- const char *path,
+ const char *initial_label,
const char *const *args,
const struct program_client_settings *set);
struct program_client_remote {
struct program_client client;
- const char *hostname;
+ const char *address;
struct dns_lookup_settings dns_set;
struct dns_lookup *lookup;
unsigned int ips_count;
bool noreply:1;
bool resolved:1;
+ bool have_hostname:1;
};
static void
if (o_stream_send(pclient->raw_program_output,
str_data(str), str_len(str)) < 0) {
- i_error("write(%s) failed: %s",
+ e_error(pclient->event,
+ "write(%s) failed: %s",
o_stream_get_name(pclient->raw_program_output),
o_stream_get_error(pclient->raw_program_output));
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
(struct program_client_remote *)pclient;
int fd;
- if (pclient->set.debug)
- i_debug("Trying to connect %s", pclient->path);
+ e_debug(pclient->event, "Trying to connect");
timeout_remove(&prclient->to_retry);
- if ((fd = net_connect_unix(pclient->path)) < 0) {
+ if ((fd = net_connect_unix(prclient->address)) < 0) {
switch (errno) {
case EACCES:
- i_error("%s",
+ e_error(pclient->event, "%s",
eacces_error_get("net_connect_unix",
- pclient->path));
+ prclient->address));
return -1;
case EAGAIN:
prclient->to_retry = timeout_add_short(100,
program_client_unix_reconnect, prclient);
return 0;
default:
- i_error("net_connect_unix(%s) failed: %m",
- pclient->path);
+ e_error(pclient->event,
+ "net_connect_unix(%s) failed: %m",
+ prclient->address);
return -1;
}
}
io_remove(&pclient->io);
timeout_remove(&pclient->to);
- i_error("connect(%s) failed: timeout in %u milliseconds",
- pclient->path,
+ e_error(pclient->event, "connect(%s) failed: "
+ "Timeout in %u milliseconds", prclient->address,
pclient->set.client_connect_timeout_msecs);
/* set error to timeout here */
io_remove(&pclient->io);
if ((errno = net_geterror(pclient->fd_out)) != 0) {
- i_error("connect(%s) failed: %m",
- pclient->path);
+ e_error(pclient->event, "connect(%s) failed: %m",
+ prclient->address);
/* disconnect and try again */
i_close_fd(&pclient->fd_out);
program_client_net_connect_real(struct program_client_remote *prclient)
{
struct program_client *pclient = &prclient->client;
- const char *str;
+ const char *address, *label;
timeout_remove(&pclient->to);
i_assert(prclient->ips_count > 0);
- if (net_ipport2str(prclient->ips, prclient->port, &str) < 0)
+ if (net_ipport2str(prclient->ips, prclient->port, &address) < 0)
i_unreached();
- pclient->path = p_strdup(pclient->pool, str);
+ label = t_strconcat("tcp:", address, NULL);
+ program_client_set_label(pclient, label);
- if (pclient->debug) {
- i_debug("Trying to connect %s (timeout %u msecs)",
- pclient->path,
- pclient->set.client_connect_timeout_msecs);
- }
+ e_debug(pclient->event, "Trying to connect (timeout %u msecs)",
+ pclient->set.client_connect_timeout_msecs);
/* try to connect */
int fd;
if ((fd = net_connect_ip(prclient->ips, prclient->port,
(prclient->ips->family == AF_INET ?
&net_ip4_any : &net_ip6_any))) < 0) {
- i_error("connect(%s) failed: %m", pclient->path);
+ e_error(pclient->event, "connect(%s) failed: %m", address);
prclient->to_retry = timeout_add_short(0,
program_client_net_connect_again, prclient);
return;
pclient->error = PROGRAM_CLIENT_ERROR_NONE;
if (--prclient->ips_left == 0) {
- if (prclient->ips_count > 1)
- i_error("program-client-net: "
- "%s: No addresses left to try",
- prclient->hostname);
+ if (prclient->ips_count > 1) {
+ e_error(pclient->event,
+ "No IP addresses left to try");
+ }
program_client_fail(pclient,
error != PROGRAM_CLIENT_ERROR_NONE ?
error :
struct program_client *pclient = &prclient->client;
if (result->ret != 0) {
- i_error("program-client-net: Cannot resolve '%s': %s",
- pclient->path,
- result->error);
+ e_error(pclient->event, "Cannot resolve `%s': %s",
+ prclient->address, result->error);
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_OTHER);
return;
}
struct ip_addr ip;
if (prclient->ips != NULL) {
- prclient->hostname = p_strdup(pclient->pool,
- net_ip2addr(prclient->ips));
- } else if (net_addr2ip(pclient->path, &ip) == 0) {
- prclient->hostname = p_strdup(pclient->pool,
- net_ip2addr(&ip));
+ /* nothing to do */
+ } else if (net_addr2ip(prclient->address, &ip) == 0) {
prclient->resolved = TRUE;
prclient->ips = p_new(pclient->pool, struct ip_addr, 1);
*prclient->ips = ip;
prclient->ips_count = 1;
} else {
prclient->resolved = FALSE;
- prclient->hostname = p_strdup(pclient->pool, pclient->path);
if (pclient->set.dns_client_socket_path != NULL) {
prclient->dns_set.dns_client_socket_path =
pclient->set.dns_client_socket_path;
prclient->dns_set.timeout_msecs =
pclient->set.client_connect_timeout_msecs;
- dns_lookup(pclient->path, &prclient->dns_set,
+ dns_lookup(prclient->address, &prclient->dns_set,
program_client_net_connect_resolved,
prclient, &prclient->lookup);
return 0;
unsigned int ips_count;
int err;
/* guess we do it here then.. */
- if ((err = net_gethostbyname(pclient->path,
+ if ((err = net_gethostbyname(prclient->address,
&ips, &ips_count)) != 0) {
- i_error("program-client-remote: "
- "Cannot resolve '%s': %s",
- pclient->path,
+ e_error(pclient->event,
+ "Cannot resolve `%s': %s",
+ prclient->address,
net_gethosterror(err));
- return -1;
+ return -1;
}
prclient->ips_count = ips_count;
prclient->ips = p_memdup(pclient->pool,
if (fd_in >= 0) {
if (shutdown(fd_out, SHUT_WR) < 0 &&
errno != ENOTCONN) {
- i_error("shutdown(%s, SHUT_WR) failed: %m",
- pclient->path);
+ e_error(pclient->event,
+ "shutdown(fd_out, SHUT_WR) failed: %m");
return -1;
}
} else {
bool noreply)
{
struct program_client_remote *prclient;
+ const char *label;
pool_t pool;
+ label = t_strconcat("unix:", socket_path, NULL);
+
pool = pool_alloconly_create("program client unix", 1024);
prclient = p_new(pool, struct program_client_remote, 1);
- program_client_init(&prclient->client, pool, socket_path, args, set);
+ program_client_init(&prclient->client, pool, label, args, set);
prclient->client.connect = program_client_unix_connect;
prclient->client.close_output = program_client_remote_close_output;
prclient->client.disconnect = program_client_remote_disconnect;
prclient->client.switch_ioloop = program_client_remote_switch_ioloop;
+ prclient->address = p_strdup(pool, socket_path);
prclient->noreply = noreply;
return &prclient->client;
bool noreply)
{
struct program_client_remote *prclient;
+ const char *label;
pool_t pool;
+ label = t_strdup_printf("tcp:%s:%u", host, port);
+
pool = pool_alloconly_create("program client net", 1024);
prclient = p_new(pool, struct program_client_remote, 1);
- program_client_init(&prclient->client, pool, host, args, set);
+ program_client_init(&prclient->client, pool, label, args, set);
prclient->client.connect = program_client_net_connect_init;
prclient->client.close_output = program_client_remote_close_output;
prclient->client.disconnect = program_client_remote_disconnect;
prclient->client.set.use_dotstream = TRUE;
+ prclient->address = p_strdup(pool, host);
prclient->port = port;
+ prclient->have_hostname = TRUE;
prclient->noreply = noreply;
return &prclient->client;
}
bool noreply)
{
struct program_client_remote *prclient;
+ const char *label;
pool_t pool;
i_assert(ips != NULL && ips_count > 0);
+ if (net_ipport2str(ips, port, &label) < 0)
+ i_unreached();
+ label = t_strconcat("tcp:", label, NULL);
+
pool = pool_alloconly_create("program client net", 1024);
prclient = p_new(pool, struct program_client_remote, 1);
- program_client_init(&prclient->client, pool, net_ip2addr(ips),
- args, set);
+ program_client_init(&prclient->client, pool, label, args, set);
prclient->client.connect = program_client_net_connect_init;
prclient->client.close_output = program_client_remote_close_output;
prclient->client.disconnect = program_client_remote_disconnect;
prclient->client.switch_ioloop = program_client_remote_switch_ioloop;
prclient->client.set.use_dotstream = TRUE;
+ prclient->address = p_strdup(pool, net_ip2addr(ips));
prclient->ips = p_memdup(pool, ips,
sizeof(struct ip_addr)*ips_count);
prclient->ips_count = ips_count;
#define MAX_OUTPUT_BUFFER_SIZE 16384
#define MAX_OUTPUT_MEMORY_BUFFER (1024*128)
+void program_client_set_label(struct program_client *pclient,
+ const char *label)
+{
+ event_set_append_log_prefix(pclient->event,
+ t_strconcat("program ", label, ": ", NULL));
+}
+
static void
program_client_callback(struct program_client *pclient, int result,
void *context)
static void
program_client_timeout(struct program_client *pclient)
{
- i_error("program `%s' execution timed out (> %u msecs)",
- pclient->path, pclient->set.input_idle_timeout_msecs);
+ e_error(pclient->event,
+ "Execution timed out (> %u msecs)",
+ pclient->set.input_idle_timeout_msecs);
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_RUN_TIMEOUT);
}
static void
program_client_connect_timeout(struct program_client *pclient)
{
- i_error("program `%s' socket connection timed out (> %u msecs)",
- pclient->path, pclient->set.client_connect_timeout_msecs);
+ e_error(pclient->event,
+ "Connection timed out (> %u msecs)",
+ pclient->set.client_connect_timeout_msecs);
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_CONNECT_TIMEOUT);
}
/* flush the output */
if ((ret=o_stream_finish(output)) < 0) {
- i_error("write(%s) failed: %s",
+ e_error(pclient->event,
+ "write(%s) failed: %s",
o_stream_get_name(output),
o_stream_get_error(output));
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
case IOSTREAM_PUMP_STATUS_INPUT_EOF:
break;
case IOSTREAM_PUMP_STATUS_INPUT_ERROR:
- i_error("read(%s) failed: %s",
+ e_error(pclient->event,
+ "read(%s) failed: %s",
i_stream_get_name(input),
i_stream_get_error(input));
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
return;
case IOSTREAM_PUMP_STATUS_OUTPUT_ERROR:
- i_error("write(%s) failed: %s",
+ e_error(pclient->event,
+ "write(%s) failed: %s",
o_stream_get_name(output),
o_stream_get_error(output));
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
return;
if (ret < 0) {
if (input->stream_errno != 0) {
- i_error("read(%s) failed: %s",
+ e_error(pclient->event,
+ "read(%s) failed: %s",
i_stream_get_name(input),
i_stream_get_error(input));
program_client_fail(pclient,
case IOSTREAM_PUMP_STATUS_INPUT_EOF:
break;
case IOSTREAM_PUMP_STATUS_INPUT_ERROR:
- i_error("read(%s) failed: %s",
+ e_error(pclient->event,
+ "read(%s) failed: %s",
i_stream_get_name(input),
i_stream_get_error(input));
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
return;
case IOSTREAM_PUMP_STATUS_OUTPUT_ERROR:
- i_error("write(%s) failed: %s",
+ e_error(pclient->event,
+ "write(%s) failed: %s",
o_stream_get_name(output),
o_stream_get_error(output));
program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
}
void program_client_init(struct program_client *pclient, pool_t pool,
- const char *path,
- const char *const *args,
+ const char *initial_label, const char *const *args,
const struct program_client_settings *set)
{
pclient->pool = pool;
- pclient->path = p_strdup(pool, path);
if (args != NULL)
pclient->args = p_strarray_dup(pool, args);
pclient->set = *set;
pclient->debug = set->debug;
pclient->fd_in = -1;
pclient->fd_out = -1;
+
+ pclient->event = event_create(set->event);
+ if ((set != NULL && set->debug))
+ event_set_forced_debug(pclient->event, TRUE);
+ program_client_set_label(pclient, initial_label);
}
void program_client_set_input(struct program_client *pclient,
if (pclient->destroy != NULL)
pclient->destroy(pclient);
+ event_unref(&pclient->event);
+
pool_unref(&pclient->pool);
}
const char *dns_client_socket_path;
const char *home;
+ /* Event to use for the program client. */
+ struct event *event;
+
bool allow_root:1;
bool debug:1;
bool drop_stderr:1;