aboutsummaryrefslogtreecommitdiff
path: root/src/progman.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/progman.c')
-rw-r--r--src/progman.c557
1 files changed, 296 insertions, 261 deletions
diff --git a/src/progman.c b/src/progman.c
index 9383aae..cee6775 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -1,21 +1,21 @@
-/* This file is part of Mailfromd.
+/* This file is part of Pies.
Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3 of the License, or (at your
- option) any later version.
+ Pies is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
- This program is distributed in the hope that it will be useful,
+ Pies is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program. If not, see <http://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU General Public License
+ along with Pies. If not, see <http://www.gnu.org/licenses/>. */
#include "pies.h"
#define TYPE_COMPONENT 0
#define TYPE_RETR 1
@@ -169,19 +169,17 @@ destroy_prog (struct prog **pp)
}
static char *
redir_tag (struct prog *master, int type)
{
static char *redirstr[2] = { "stdout", "stderr" };
- char *str = NULL;
- if (type < MU_ARRAY_SIZE(redirstr))
- asprintf (&str, "%s/%s", master->tag, redirstr[type]);
+ char *str;
+ if (type < ARRAY_SIZE(redirstr))
+ str = xasprintf ("%s/%s", master->tag, redirstr[type]);
else
- asprintf (&str, "%s/%d", master->tag, type);
- if (!str)
- xalloc_die ();
+ str = xasprintf ("%s/%d", master->tag, type);
return str;
}
static struct prog *
register_redir (int type, struct prog *master)
{
@@ -258,26 +256,28 @@ prog_rebuild_prerequisites (struct prog *prog)
struct prog *p;
int dep_all = 0;
size_t depc = 0;
if (comp->prereq)
{
- mu_list_count (comp->prereq, &depc);
+ depc = gl_list_size (comp->prereq);
if (depc == 1)
{
- char *item;
- mu_list_get (comp->prereq, 0, (void**)&item);
+ const char *item = gl_list_get_at (comp->prereq, 0);
if (strcmp (item, "all") == 0)
{
dep_all = 1;
for (p = proghead; p; p = p->next)
if (p->type == TYPE_COMPONENT)
depc++;
}
else if (strcmp (item, "none") == 0)
- mu_list_destroy (&comp->prereq);
+ {
+ gl_list_free (comp->prereq);
+ comp->prereq = NULL;
+ }
}
}
if (depc == 0)
return;
@@ -291,22 +291,19 @@ prog_rebuild_prerequisites (struct prog *prog)
for (p = proghead; p; p = p->next)
if (p->type == TYPE_COMPONENT)
prog->prereq[depc++] = p->tag;
}
else
{
- mu_iterator_t itr = NULL;
- mu_list_get_iterator (comp->prereq, &itr);
- for (mu_iterator_first (itr), depc = 0;
- !mu_iterator_is_done (itr); mu_iterator_next (itr), depc++)
+ const void *p;
+ gl_list_iterator_t itr = gl_list_iterator (comp->prereq);
+ while (gl_list_iterator_next (&itr, &p, NULL))
{
- char *str;
- mu_iterator_current (itr, (void**)&str);
- prog->prereq[depc] = str;
+ prog->prereq[depc++] = (char*) p;
}
- mu_iterator_destroy (&itr);
+ gl_list_iterator_free (&itr);
}
}
prog->prereq[depc] = NULL;
}
void
@@ -338,15 +335,15 @@ redirect_to_file (struct prog *master, int stream)
{
struct passwd *pw;
int fd = open (master->v.p.comp->redir[stream].v.file, O_RDWR|O_CREAT,
0644 & ~master->v.p.comp->umask);
if (fd == -1)
{
- mu_error (_("cannot open output file %s: %s"),
+ logmsg (LOG_ERR, _("cannot open output file %s: %s"),
master->v.p.comp->redir[stream].v.file,
- mu_strerror (errno));
+ strerror (errno));
return -1;
}
/* Fix file ownership */
pw = getpwnam (master->v.p.comp->privs.user);
if (pw)
chown (master->v.p.comp->redir[stream].v.file, pw->pw_uid, pw->pw_gid);
@@ -402,15 +399,15 @@ open_redirector (struct prog *master, int stream)
prio = master->v.p.comp->redir[stream].v.prio;
while (getline (&buf, &size, fp) > 0)
syslog (prio, "%s", buf);
_exit (0);
case -1:
- mu_diag_output (MU_DIAG_CRIT,
+ logmsg (LOG_CRIT,
_("cannot run redirector `%s': fork failed: %s"),
- master->tag, mu_strerror (errno));
+ master->tag, strerror (errno));
return -1;
default:
update_redir (stream, master, pid);
close (p[0]);
return p[1];
@@ -589,13 +586,13 @@ prog_start (struct prog *prog)
prog->v.p.count = 0;
prog->v.p.timestamp = now;
}
if (prog->v.p.count > MAXSPAWN)
{
- mu_error (ngettext (
+ logmsg (LOG_NOTICE, ngettext (
"%s is respawning too fast, disabled for %d minute",
"%s is respawning too fast, disabled for %d minutes",
SLEEPTIME / 60),
prog->tag, SLEEPTIME / 60);
prog->v.p.timestamp = now;
prog->v.p.status = status_sleeping;
@@ -606,18 +603,18 @@ prog_start (struct prog *prog)
switch (prog->v.p.comp->mode)
{
case pies_comp_exec:
break;
case pies_comp_pass_fd:
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, _("unlinking %s\n"),
- prog->v.p.comp->pass_fd_socket);
+ debug (1, (_("unlinking %s"), prog->v.p.comp->pass_fd_socket));
if (unlink (prog->v.p.comp->pass_fd_socket) && errno != ENOENT)
{
- mu_error (_("cannot unlink %s: %s"), prog->v.p.comp->pass_fd_socket,
- mu_strerror (errno));
+ logmsg (LOG_ERR, _("cannot unlink %s: %s"),
+ prog->v.p.comp->pass_fd_socket,
+ strerror (errno));
return;
}
/* fall through */
case pies_comp_accept:
prog->v.p.socket = create_socket (prog->v.p.comp->socket_url,
@@ -627,13 +624,13 @@ prog_start (struct prog *prog)
{
prog->v.p.status = status_disabled;
return;
}
if (listen (prog->v.p.socket, 8))
{
- mu_error ("listen: %s", mu_strerror (errno));
+ logmsg (LOG_ERR, "listen: %s", strerror (errno));
close (prog->v.p.socket);
prog->v.p.socket = -1;
prog->v.p.status = status_disabled;
return;
}
break;
@@ -641,66 +638,65 @@ prog_start (struct prog *prog)
case pies_comp_inetd:
/* Wait until an incoming connection is requested */
if (prog->v.p.socket == -1)
return;
}
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, _("starting %s\n"), prog->tag);
+ debug (1, (_("starting %s"), prog->tag));
if (prog->v.p.comp->rmfile)
{
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, _("unlinking %s\n"),
- prog->v.p.comp->rmfile);
+ debug (1, (_("unlinking %s"), prog->v.p.comp->rmfile));
if (unlink (prog->v.p.comp->rmfile) && errno != ENOENT)
- mu_error (_("%s: cannot remove file `%s': %s"),
- prog->tag, prog->v.p.comp->rmfile, mu_strerror (errno));
+ logmsg (LOG_ERR, _("%s: cannot remove file `%s': %s"),
+ prog->tag, prog->v.p.comp->rmfile, strerror (errno));
}
redir[RETR_OUT] = open_redirector (prog, RETR_OUT);
redir[RETR_ERR] = open_redirector (prog, RETR_ERR);
switch (pid = fork ())
{
/* The child branch. */
case 0:
signal_setup (SIG_DFL);
if (prog->v.p.comp->dir)
{
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, _("chdir %s\n"),
- prog->v.p.comp->dir);
+ debug (1, (_("chdir %s"), prog->v.p.comp->dir));
if (chdir (prog->v.p.comp->dir))
- mu_error (_("%s: cannot change to directory %s: %s"),
- prog->tag, prog->v.p.comp->dir, mu_strerror (errno));
+ logmsg (LOG_ERR, _("%s: cannot change to directory %s: %s"),
+ prog->tag, prog->v.p.comp->dir, strerror (errno));
}
environ = env_setup (prog->v.p.comp->env);
- if (mu_debug_check_level (pies_debug, MU_DEBUG_TRACE4))
+ if (debug_level >= 4)
{
int i;
for (i = 0; environ[i]; i++)
- __MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE4, "%s ", environ[i]);
- mu_debug_printf (pies_debug, MU_DEBUG_TRACE4, "\n");
+ logmsg_printf (LOG_DEBUG, "%s ", environ[i]);
+ logmsg_printf (LOG_DEBUG, "\n");
}
- mf_priv_setup (&prog->v.p.comp->privs);
+
+ pies_priv_setup (&prog->v.p.comp->privs);
if (prog->v.p.comp->umask)
umask (prog->v.p.comp->umask);
set_limits (prog->tag,
prog->v.p.comp->limits ?
prog->v.p.comp->limits : pies_limits);
- if (mu_debug_check_level (pies_debug, MU_DEBUG_TRACE1))
+ if (debug_level >= 1)
{
- char *cmdline;
- if (mu_argcv_string (prog->v.p.argc, prog->v.p.comp->argv,
- &cmdline) == 0)
+ int i;
+ logmsg_printf (LOG_DEBUG, "executing");
+ for (i = 0; i < prog->v.p.argc; i++)
{
- __MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1,
- "executing %s\n", cmdline);
- free (cmdline);
+ /* FIXME: quote */
+ logmsg_printf (LOG_DEBUG, " %s", prog->v.p.comp->argv[i]);
}
+ logmsg_printf (LOG_DEBUG, "\n");
}
switch (prog->v.p.comp->mode)
{
case pies_comp_pass_fd:
case pies_comp_exec:
@@ -743,21 +739,21 @@ prog_start (struct prog *prog)
close (i);
}
execvp (prog->v.p.comp->program ?
prog->v.p.comp->program : prog->v.p.comp->argv[0],
prog->v.p.comp->argv);
- openlog (MU_LOG_TAG (), LOG_PID, mu_log_facility);
+ openlog (log_tag, LOG_PID, prog->v.p.comp->facility);
syslog (LOG_CRIT, _("cannot start `%s': %s"), prog->tag,
- mu_strerror (errno));
+ strerror (errno));
_exit (EX_SOFTWARE);
case -1:
- mu_diag_output (MU_DIAG_CRIT,
+ logmsg (LOG_CRIT,
_("cannot run `%s': fork failed: %s"),
- prog->tag, mu_strerror (errno));
+ prog->tag, strerror (errno));
break;
default:
if (prog->v.p.comp->mode == pies_comp_pass_fd)
{
sleep(1);
@@ -768,54 +764,35 @@ prog_start (struct prog *prog)
close (prog->v.p.socket);
prog->pid = pid;
prog->v.p.status = status_enabled;
}
}
-int
-pies_check_acl (mu_acl_t acl, struct sockaddr *s, int salen)
+static int
+check_acl (pies_acl_t acl, struct sockaddr *s, int salen)
{
- mu_acl_result_t res;
+ struct acl_input input;
int rc;
if (!acl)
return 0;
- rc = mu_acl_check_sockaddr (acl, s, salen, &res);
- if (rc)
+ input.addr = s;
+ input.addrlen = salen;
+ input.user = NULL;
+ input.groups = NULL;
+
+ rc = pies_acl_check (acl, &input, 1);
+ if (rc == 0)
{
- char *p = mu_sockaddr_to_astr (s, salen);
- mu_error (_("access from %s blocked: cannot check ACLs: %s"),
- p, mu_strerror (rc));
+ char *p = sockaddr_to_astr (s, salen);
+ logmsg (LOG_ERR, _("access from %s blocked"), p);
free (p);
return 1;
}
- switch (res)
- {
- case mu_acl_result_undefined:
- {
- char *p = mu_sockaddr_to_astr (s, salen);
- mu_diag_output (MU_DIAG_INFO,
- _("%s: undefined ACL result; access allowed"),
- p);
- free (p);
- }
- break;
-
- case mu_acl_result_accept:
- break;
-
- case mu_acl_result_deny:
- {
- char *p = mu_sockaddr_to_astr (s, salen);
- mu_error (_("Access from %s blocked."), p);
- free (p);
- return 1;
- }
- }
return 0;
}
int
progman_accept (int socket)
{
@@ -828,84 +805,85 @@ progman_accept (int socket)
} addr;
socklen_t addrlen = sizeof addr;
fd = accept (socket, (struct sockaddr*) &addr, &addrlen);
if (fd == -1)
{
- mu_error (_("accept failed: %s"), mu_strerror (errno));
+ logmsg (LOG_ERR, _("accept failed: %s"), strerror (errno));
return 1;
}
p = prog_lookup_by_socket (socket);
if (!p)
{
- mu_error (_("INTERNAL ERROR: no matching prog for fd %d"), socket);
+ logmsg (LOG_EMERG,
+ _("INTERNAL ERROR: no matching prog for fd %d"), socket);
close (fd);
return 1;
}
- if (mu_debug_check_level (pies_debug, MU_DEBUG_TRACE1))
+ if (debug_level >= 1)
{
- char *s = mu_sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
- __MU_DEBUG2 (pies_debug, MU_DEBUG_TRACE1, "%s wants %s\n", s, p->tag);
+ char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
+ logmsg (LOG_DEBUG, "%s wants %s", s, p->tag);
free (s);
}
-
- if (pies_check_acl (p->v.p.comp->acl, (struct sockaddr *)&addr, addrlen)
- || pies_check_acl (pies_acl, (struct sockaddr *)&addr, addrlen))
+
+ if (check_acl (p->v.p.comp->acl, (struct sockaddr *)&addr, addrlen)
+ || check_acl (pies_acl, (struct sockaddr *)&addr, addrlen))
{
close (fd);
return 1;
}
-
+
p = register_prog0 (p->v.p.comp, -1);
p->v.p.socket = fd;
prog_start (p);
close (fd);
p->v.p.socket = -1;
return 0;
}
void
component_fixup_depend (struct component *comp)
{
- mu_iterator_t itr;
+ const void *p;
+ gl_list_iterator_t itr;
if (comp->depend == NULL)
return;
- mu_list_get_iterator (comp->depend, &itr);
- for (mu_iterator_first (itr);
- !mu_iterator_is_done (itr); mu_iterator_next (itr))
+ itr = gl_list_iterator (comp->depend);
+ while (gl_list_iterator_next (&itr, &p, NULL))
{
- char *tag;
+ const char *tag = p;
struct component *tgt;
- mu_iterator_current (itr, (void**)&tag);
tgt = progman_lookup_component (tag);
if (!tgt)
{
- mu_error (_("component %s declares dependency target %s, "
- "which is not declared"),
- comp->tag, tag);
+ logmsg (LOG_ERR,
+ _("component %s declares dependency target %s, "
+ "which is not declared"),
+ comp->tag, tag);
continue;
}
if (!tgt->prereq)
{
- int rc = mu_list_create (&tgt->prereq);
- if (rc)
- {
- mu_error (_("cannot create list: %s"), mu_strerror (rc));
- continue;
- }
+ tgt->prereq = gl_list_create_empty(&gl_linked_list_implementation,
+ NULL,
+ NULL,
+ NULL,
+ false);
}
/* FIXME: memory allocation */
- mu_list_append (tgt->prereq, xstrdup (comp->tag));
+ gl_list_add_last (tgt->prereq, xstrdup (comp->tag));
}
- mu_list_destroy (&comp->depend);
+ gl_list_free (comp->depend);
+ comp->depend = NULL;
}
void
fixup_prerequisites ()
{
struct prog *prog;
@@ -927,21 +905,21 @@ rebuild_prerequisites ()
void
print_dep (struct prog *prog)
{
pies_depmap_pos_t pos;
unsigned n;
- mu_diag_printf (MU_DIAG_NOTICE, "%s -> ", prog->tag);
+ logmsg_printf (LOG_NOTICE, "%s -> ", prog->tag);
for (n = depmap_first (depmap, depmap_col, prog->idx, &pos);
n != (unsigned)-1;
n = depmap_next (depmap, pos))
{
struct prog *dp = prog_lookup_by_idx (n);
- mu_diag_printf (MU_DIAG_NOTICE, "%s -> ", dp->tag);
+ logmsg_printf (LOG_NOTICE, "%s -> ", dp->tag);
}
- mu_diag_printf (MU_DIAG_NOTICE, "%s\n", prog->tag);
+ logmsg_printf (LOG_NOTICE, "%s\n", prog->tag);
}
void
progman_dump_prereq ()
{
struct prog *prog;
@@ -1000,13 +978,13 @@ progman_build_depmap ()
for (i = 0; prog->prereq[i]; i++)
{
struct prog *dep = prog_lookup_by_tag (prog->prereq[i]);
if (!dep)
{
prog->v.p.status = status_disabled;
- mu_error (_("component %s depends on %s, "
+ logmsg (LOG_ERR, _("component %s depends on %s, "
"which is not declared"),
prog->tag, prog->prereq[i]);
rc++;
}
else
depmap_set (depmap, prog->idx, dep->idx);
@@ -1015,13 +993,13 @@ progman_build_depmap ()
dp = depmap_copy (depmap);
depmap_tc (dp);
for (i = 0; i < numprog; i++)
if (depmap_isset (dp, i, i))
{
prog = prog_lookup_by_idx (i);
- mu_error (_("component %s depends on itself"), prog->tag);
+ logmsg (LOG_ERR, _("component %s depends on itself"), prog->tag);
print_dep (prog);
prog->v.p.status = status_disabled;
rc++;
}
free (dp);
return rc;
@@ -1062,13 +1040,13 @@ progman_recompute_alarm ()
{
struct prog *prog;
time_t now = time (NULL);
time_t alarm_time = 0, x;
recompute_alarm = 0;
- MU_DEBUG (pies_debug, MU_DEBUG_TRACE2, "Recomputing alarm settings\n");
+ debug (2, ("Recomputing alarm settings"));
for (prog = proghead; prog; prog = prog->next)
if (IS_PROG (prog))
{
switch (prog->v.p.status)
{
case status_sleeping:
@@ -1084,27 +1062,26 @@ progman_recompute_alarm ()
break;
default:
break;
}
}
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE2, "alarm=%lu\n",
- (unsigned long)alarm_time);
+ debug (2, ("alarm=%lu", (unsigned long)alarm_time));
if (alarm_time)
alarm (alarm_time);
}
void
progman_start ()
{
struct prog *prog;
recompute_alarm = 0;
- MU_DEBUG (pies_debug, MU_DEBUG_TRACE1, "Starting components\n");
+ debug (1, ("Starting components"));
for (prog = proghead; prog; prog = prog->next)
if (IS_PROG (prog)
&& ((prog->v.p.status == status_enabled && prog->pid == 0)
|| prog->v.p.status == status_sleeping))
prog_start (prog);
}
@@ -1112,14 +1089,15 @@ progman_start ()
static void
check_stopping (struct prog *prog, time_t now)
{
if (now - prog->v.p.timestamp >= shutdown_timeout)
{
if (prog->pid == 0)
- mu_error (_("INTERNAL ERROR: attempting to kill unexisting process %s"),
- prog->tag);
+ logmsg (LOG_EMERG,
+ _("INTERNAL ERROR: attempting to kill unexisting process %s"),
+ prog->tag);
else
kill (prog->pid, SIGKILL);
}
else
recompute_alarm = 1;
}
@@ -1127,14 +1105,13 @@ check_stopping (struct prog *prog, time_t now)
void
progman_wake_sleeping ()
{
struct prog *prog;
time_t now = time (NULL);
- MU_DEBUG (pies_debug, MU_DEBUG_TRACE1,
- "Managing sleeping/stopping components\n");
+ debug (1, ("Managing sleeping/stopping components"));
for (prog = proghead; prog; prog = prog->next)
if (IS_PROG (prog))
{
switch (prog->v.p.status)
{
@@ -1171,14 +1148,13 @@ prog_start_prerequisites (struct prog *prog)
int i;
int ret;
unsigned settle_timeout = 0;
if (!prog->prereq)
return 0; /* Ok to startup */
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, "Starting prerequisites of %s\n",
- prog->tag);
+ debug (1, ("Starting prerequisites of %s", prog->tag));
ret = 0;
for (i = 0; prog->prereq[i]; i++)
{
struct prog *dp = prog_lookup_by_tag (prog->prereq[i]);
if (!IS_PROG (dp)) /* Skip redirectors */
continue;
@@ -1241,15 +1217,13 @@ prog_stop_dependents (struct prog *prog)
{
struct prog *dp = prog_lookup_by_idx (n);
if (!dp) /* should not happen */
continue;
if (!warned && dp->pid)
{
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1,
- "Stopping dependencies of %s\n",
- prog->tag);
+ debug (1, ("Stopping dependencies of %s", prog->tag));
warned = 1;
}
prog_stop (dp, SIGTERM);
}
free (pos);
}
@@ -1265,25 +1239,22 @@ prog_stop (struct prog *prog, int sig)
{
prog->v.p.status = status_stopping;
prog->v.p.timestamp = time (NULL);
recompute_alarm = 1;
}
}
- MU_DEBUG2 (pies_debug, MU_DEBUG_TRACE1,
- "Stopping %s (%lu)\n",
- prog->tag, (unsigned long) prog->pid);
+ debug (1, ("Stopping %s (%lu)", prog->tag, (unsigned long) prog->pid));
kill (prog->pid, sig);
}
static void
prog_stop_all (int sig)
{
struct prog *prog;
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1,
- "Stopping all components (signal %d)\n", sig);
+ debug (1, ("Stopping all components (signal %d)", sig));
for (prog = progtail; prog; prog = prog->prev)
if (IS_PROG (prog)
&& (prog->v.p.status == status_enabled
|| prog->v.p.status == status_stopping))
prog_stop (prog, sig);
}
@@ -1307,158 +1278,235 @@ progman_stop ()
static void
print_status (char *tag, pid_t pid, int status, int expect_term)
{
if (WIFEXITED (status))
{
if (WEXITSTATUS (status) == 0)
- MU_DEBUG2 (pies_debug, MU_DEBUG_TRACE1,
- _("%s (%lu) exited successfully\n"),
- tag, (unsigned long) pid);
+ debug (1, (_("%s (%lu) exited successfully"),
+ tag, (unsigned long) pid));
else
- mu_diag_output (MU_DIAG_ERR,
+ logmsg (LOG_ERR,
_("%s (%lu) failed with status %d"),
tag, (unsigned long) pid,
WEXITSTATUS (status));
}
else if (WIFSIGNALED (status))
{
int prio;
if (expect_term && WTERMSIG (status) == SIGTERM)
- prio = MU_DIAG_DEBUG;
+ prio = LOG_DEBUG;
else
- prio = MU_DIAG_ERR;
+ prio = LOG_ERR;
- mu_diag_output (prio,
+ logmsg (prio,
_("%s (%lu) terminated on signal %d"),
tag, (unsigned long) pid,
WTERMSIG (status));
}
else if (WIFSTOPPED (status))
- mu_diag_output (MU_DIAG_ERR,
+ logmsg (LOG_ERR,
_("%s (%lu) stopped on signal %d"),
tag, (unsigned long) pid,
WSTOPSIG (status));
#ifdef WCOREDUMP
else if (WCOREDUMP (status))
- mu_diag_output (MU_DIAG_ERR,
+ logmsg (LOG_ERR,
_("%s (%lu) dumped core"),
tag, (unsigned long) pid);
#endif
else
- mu_diag_output (MU_DIAG_ERR,
+ logmsg (LOG_ERR,
_("%s (%lu) terminated with unrecognized status"),
tag, (unsigned long) pid);
}
-static void
-send_msg (mu_address_t rcpt, mu_message_t msg)
+static int
+wait_for_child (pid_t pid)
{
- mu_mailer_t mailer;
- int rc;
- const char *s;
+ int rc = 127;
+ int wait_status;
- mu_address_sget_email (rcpt, 1, &s);
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, "Sending email to %s\n", s);
+ while (waitpid (pid, &wait_status, 0) == -1)
+ if (errno != EINTR)
+ {
+ logmsg (LOG_ERR, _("waitpid failed: %s"), strerror (errno));
+ return EX_OSERR;
+ }
- rc = mu_mailer_create (&mailer, NULL);
- if (rc)
+ if (WIFSIGNALED (wait_status))
{
- const char *mailer_url;
- mu_mailer_get_url_default (&mailer_url);
+ int sig = WTERMSIG (wait_status);
+ logmsg (LOG_ERR, _("child died with signal %d"), sig);
+ }
+ else if (WIFEXITED (wait_status))
+ {
+ rc = WEXITSTATUS (wait_status);
+ if (rc != 0)
+ logmsg (LOG_ERR, _("child returned status %d"), rc);
+ }
+ return rc;
+}
- mu_error (_("Cannot create mailer `%s': %s"),
- mailer_url, mu_strerror (rc));
+void
+send_msg (char *rcpts, const char *msg_text)
+{
+ int i;
+ pid_t pid;
+ struct wordsplit ws;
+ int p[2];
+ size_t size;
+
+ ws.ws_offs = 3; /* sendmail -oi -t */
+ ws.ws_delim = ",";
+ if (wordsplit (rcpts, &ws,
+ WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM | WRDSF_DOOFFS))
+ {
+ logmsg (LOG_ERR,
+ _("cannot parse recipient address list (%s)"),
+ rcpts);
return;
}
-
- /* FIXME: mailer flags? */
- rc = mu_mailer_open (mailer, 0);
- if (rc)
+
+ ws.ws_wordv[0] = "/usr/sbin/sendmail"; /* FIXME: path */
+ ws.ws_wordv[1] = "-oi";
+ ws.ws_wordv[2] = "-t";
+ for (i = 0; i < ws.ws_wordc; i++)
+ {
+ char *arg = ws.ws_wordv[3 + i];
+ size_t len;
+
+ while (*arg && c_isblank (*arg))
+ arg++;
+ len = strlen (arg);
+ if (len > 0)
+ {
+ while (len > 0 && c_isblank(arg[len - 1]))
+ len--;
+ }
+ if (len == 0)
+ continue; //FIXME
+ if (arg[0] == '<' && arg[len-1] == '>')
+ {
+ arg++;
+ len -= 2;
+ }
+ if (len == 0)
+ continue; //FIXME
+ memmove (ws.ws_wordv[3 + i], arg, len);
+ ws.ws_wordv[3 + i][len] = 0;
+ }
+
+ /* Fork a child: */
+ pid = fork ();
+ if (pid <= 0)
+ wordsplit_free (&ws);
+
+ if (pid < 0)
{
- const char *mailer_url;
- mu_mailer_get_url_default (&mailer_url);
+ logmsg (LOG_ERR,
+ _("cannot send mail: fork failed: %s"), strerror (errno));
+ return;
+ }
+
+ if (pid == 0)
+ //FIXME: SIGCHLD Handler? */
+ return;
- mu_mailer_destroy(&mailer);
- mu_error (_("opening mailer `%s' failed: %s"),
- mailer_url, mu_strerror (rc));
+ /* Child process */
+ /* ============= */
+ signal (SIGCHLD, SIG_DFL);
+ signal (SIGPIPE, SIG_DFL);
+
+ if (pipe (p))
+ {
+ logmsg (LOG_ERR, _("cannot send mail: pipe failed: %s"),
+ strerror (errno));
+ wordsplit_free (&ws);
+ exit (EX_OSERR);
+ }
+
+ pid = fork ();
+ if (pid <= 0)
+ wordsplit_free (&ws);
+
+ if (pid < 0)
+ {
+ logmsg (LOG_ERR,
+ _("cannot send mail: fork failed: %s"), strerror (errno));
return;
}
-
- rc = mu_mailer_send_message (mailer, msg, NULL, rcpt);
- mu_mailer_destroy (&mailer);
- if (rc)
- mu_error (_("cannot send message: %s"), mu_strerror (rc));
+
+ if (pid)
+ {
+ /* Grand-child */
+ /* =========== */
+ if (p[0] != 0 && p[1] != 0)
+ close (0);
+ close (p[1]);
+ dup2 (p[0], 0);
+ execv (ws.ws_wordv[0], ws.ws_wordv);
+ exit (127);
+ }
+
+ /* Child again */
+ close (p[0]);
+
+ size = strlen (msg_text);
+ while (size)
+ {
+ ssize_t rc = write (p[1], msg_text, size);
+ if (rc <= 0)
+ {
+ logmsg (LOG_ERR, _("cannot write to pipe: %s"),
+ rc == 0 ? "EOF" : strerror (errno));
+ break;
+ }
+ size -= rc;
+ msg_text += rc;
+ }
+ close (p[1]);
+
+ exit (wait_for_child (pid));
}
static const char default_termination_message[] =
"From: <>\n"
"X-Agent: ${canonical-program-name} (${package} ${version})\n"
"Subject: Component ${component} terminated with code ${retcode}.\n"
"\n";
static void
-vartab_define_project (mu_vartab_t vtab)
-{
- static struct {
- char *name;
- char *value;
- } ptab[] = {
- { "canonical-program-name", "pies" },
- { "package", PACKAGE },
- { "version", PACKAGE_VERSION },
- { "mu-version", MAILUTILS_VERSION },
- { NULL }
- };
- int i;
-
- for (i = 0; ptab[i].name; i++)
- mu_vartab_define (vtab, ptab[i].name, ptab[i].value, 1);
-}
-
-
-static void
notify (const char *tag, int status, struct action *act)
{
- mu_vartab_t vtab;
+ struct metadef mdef[] =
+ {
+ { "canonical-program-name", "pies" },
+ { "package", PACKAGE },
+ { "version", PACKAGE_VERSION },
+#define COMPONENT_IDX 3
+ { "component", NULL },
+#define RETCODE_IDX 4
+ { "retcode", NULL },
+#define PROGRAM_NAME_IDX 5
+ { "program-name", NULL },
+ { NULL }
+ };
+
char *msg_text = NULL;
- mu_message_t msg = NULL;
- mu_stream_t stream = NULL;
- int rc;
char buf[INT_BUFSIZE_BOUND (uintmax_t)];
- mu_vartab_create (&vtab);
- mu_vartab_define (vtab, "component", tag, 1);
- mu_vartab_define (vtab, "retcode", umaxtostr (status, buf), 1);
- mu_vartab_define (vtab, "program-name", mu_program_name, 1);
- vartab_define_project (vtab);
- rc = mu_vartab_expand (vtab,
- act->message ?
- act->message : default_termination_message,
- &msg_text);
- mu_vartab_destroy (&vtab);
- if (rc)
- {
- mu_error (_("cannot expand message body: %s"), mu_strerror (rc));
- /* FIXME: Notify anyway? */
- return;
- }
+ mdef[COMPONENT_IDX].value = (char*) tag;
+ mdef[RETCODE_IDX].value = umaxtostr (status, buf);
+ mdef[PROGRAM_NAME_IDX].value = (char*) program_name;
+ msg_text = meta_expand_string (act->message ?
+ act->message : default_termination_message,
+ mdef, NULL);
- rc = mu_message_create (&msg, NULL);
- if (rc)
- {
- mu_error (_("cannot create message: %s"), mu_strerror (rc));
- free (msg_text);
- }
-
- mu_message_get_stream (msg, &stream);
- mu_stream_write (stream, msg_text, strlen (msg_text), 0, NULL);
+ send_msg (act->addr, msg_text);
free (msg_text);
-
- send_msg (act->addr, msg);
- mu_message_destroy (&msg, mu_message_get_owner (msg));
}
static int
status_matches_p (struct action *act, unsigned status)
{
int i;
@@ -1484,22 +1532,21 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
saved_handler = signal (SIGPIPE, SIG_IGN);
pid = fork ();
if (pid == (pid_t) -1)
{
- mu_error ("fork: %s", mu_strerror (errno));
+ logmsg (LOG_ERR, "fork: %s", strerror (errno));
return;
}
if (pid == 0)
{
int i;
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1,
- _("executing %s\n"), act->command);
+ debug (1, (_("executing %s"), act->command));
/* Child */
setenv ("PIES_VERSION", PACKAGE_VERSION, 1);
setenv ("PIES_COMPONENT", prog->tag, 1);
setenv ("PIES_PID", umaxtostr (child_pid, buf), 1);
if (retcode & STATUS_SIG_BIT)
setenv ("PIES_SIGNAL", umaxtostr (STATUS_CODE (retcode), buf), 1);
@@ -1519,13 +1566,13 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
}
/* Master */
while (waitpid (pid, &status, 0) == -1)
if (errno != EINTR)
{
- mu_error ("waitpid: %s", mu_strerror (errno));
+ logmsg (LOG_ERR, "waitpid: %s", strerror (errno));
break;
}
signal (SIGPIPE, saved_handler);
print_status (act->command, pid, status, 1);
}
@@ -1537,13 +1584,13 @@ progman_cleanup (int expect_term)
int status;
while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
{
struct prog *prog = prog_lookup_by_pid (pid);
if (!prog)
{
- mu_diag_output (MU_DIAG_NOTICE,
+ logmsg (LOG_NOTICE,
_("subprocess %lu finished"),
(unsigned long) pid);
continue;
}
print_status (prog->tag, prog->pid, status, expect_term);
prog->pid = 0;
@@ -1589,13 +1636,13 @@ progman_cleanup (int expect_term)
{
case action_restart:
prog_start (prog);
break;
case action_disable:
- mu_diag_output (MU_DIAG_NOTICE,
+ logmsg (LOG_NOTICE,
_("disabling component %s: "
"exited with code %d"),
prog->tag, status);
prog->v.p.status = status_disabled;
}
if (act->addr)
@@ -1610,14 +1657,13 @@ progman_cleanup (int expect_term)
}
}
}
else
{
/* It was a redirector of an already finished inetd process. */
- MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1,
- _("removing inetd redirector %s\n"), prog->tag);
+ debug (1, (_("removing inetd redirector %s"), prog->tag));
destroy_prog (&prog);
}
}
if (!expect_term)
/* This will also recompute alarm settings, if necessary */
@@ -1626,13 +1672,13 @@ progman_cleanup (int expect_term)
void
progman_stop_component (const char *name)
{
struct prog *prog;
- mu_diag_output (MU_DIAG_INFO, _("stopping component `%s'"), name);
+ logmsg (LOG_INFO, _("stopping component `%s'"), name);
for (prog = proghead; prog; prog = prog->next)
if (IS_PROG (prog) && strcmp (prog->tag, name) == 0)
{
switch (prog->v.p.status)
{
case status_enabled:
@@ -1643,46 +1689,46 @@ progman_stop_component (const char *name)
case status_disabled:
if (!prog->v.p.comp->disabled)
prog->v.p.status = status_enabled;
break;
default:
- mu_diag_output (MU_DIAG_INFO,
+ logmsg (LOG_INFO,
_("stopping component `%s': "
"component not started"),
name);
}
}
}
void
progman_dump_stats (const char *filename)
{
FILE *fp;
struct prog *prog;
- char *s;
- int rc;
char *tmpfile = NULL;
asprintf (&tmpfile, "%s.%lu", filename, (unsigned long) getpid ());
if (!tmpfile)
{
- mu_error ("%s", mu_strerror (ENOMEM));
+ logmsg (LOG_ERR, "%s", strerror (ENOMEM));
return;
}
- mu_diag_output (MU_DIAG_INFO, _("dumping statistics to `%s'"), tmpfile);
+ logmsg (LOG_INFO, _("dumping statistics to `%s'"), tmpfile);
fp = fopen (tmpfile, "w");
if (!fp)
{
- mu_error (_("cannot open file `%s' for writing: %s"),
- tmpfile, mu_strerror (errno));
+ logmsg (LOG_ERR, _("cannot open file `%s' for writing: %s"),
+ tmpfile, strerror (errno));
return;
}
for (prog = proghead; prog; prog = prog->next)
{
+ int i;
+
switch (prog->type)
{
case TYPE_COMPONENT:
fprintf (fp, "component %s ", prog->tag);
if (prog->pid)
{
@@ -1701,21 +1747,16 @@ progman_dump_stats (const char *filename)
else if (prog->v.p.status == status_disabled)
fprintf (fp, _("[disabled]"));
else if (prog->v.p.status == status_listener)
fprintf (fp, _("[listener]"));
else
fprintf (fp, _("[not running]"));
- if (rc = mu_argcv_string (prog->v.p.argc, prog->v.p.comp->argv, &s))
- {
- mu_error (_("cannot convert argument list: %s"),
- mu_strerror (rc));
- }
- else
+ for (i = 0; i < prog->v.p.argc; i++)
{
- fprintf (fp, " %s", s);
- free (s);
+ /* FIXME: quote as appropriate */
+ fprintf (fp, " %s