aboutsummaryrefslogtreecommitdiff
path: root/src/progman.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2016-01-21 08:31:31 +0200
committerSergey Poznyakoff <gray@gnu.org>2016-01-21 08:31:31 +0200
commit0c930fc6d3fde82e800c685ec1df92ddfa23fe09 (patch)
tree1494ff68c9006d3e1a9d6ab5b3b2a5e2f66a47ca /src/progman.c
parent2040ea870ae411472a73d0bee49fb7c4a774ad93 (diff)
downloadpies-0c930fc6d3fde82e800c685ec1df92ddfa23fe09.tar.gz
pies-0c930fc6d3fde82e800c685ec1df92ddfa23fe09.tar.bz2
Cleanup: redo configuration file handling and dependency tracking.
Implement clean configuration reload on SIGHUP. Use SIGUSR1 to restart the program (previously initiated by SIGHUP). * src/Makefile.am (pies_SOURCES): Add comp.c * src/comp.c: New file. * src/acl.c (pies_acl_free): Don't coredump on NULL arg. (_parse_from): Set cmp function for the sockaddr list. (_acl_common_section_parser): Set cmp function for the ACL (pies_acl_cmp): New function. * src/acl.h (pies_acl_cmp): New proto. * src/cmdline.opt: Remove option --dump-prereq. Add options --trace-prereq and --trace-depend. * src/ctl.c: Use prog_tag to access tag of struct prog. * src/depmap.c (depmap_clear) (depmap_clear_all): New functions. * src/inetd.c (inetd_conf_file): Don't register prog right away. This is done later in component_config_commit. (inetd_parse_conf): Rename to inetd_config_parse. * src/limits.c (limits_cmp): New function. * src/pies.c (config_file): Replace with struct config_syntax. (str_to_config_syntax): Return a pointer to struct config_syntax. (add_config): Rename to config_file_add. (config_file_add_type): New function. (return_code_keywords, create_action): Change handling of actions. (return_code_section_parser): Likewise. (component_verify, component_create) (component_free, component_finish): Move to comp.c (config_parse): Remove. (pies_config_parse): New function. (pies_read_config,pies_reload): New function. (pies_reload): Rename to request_reload. (pies_status): Rename to request_status. (pies_stop): Rename to request_stop. (main): Change configuration file handling. SIGHUP reloads configuration, instead of restarting the program. (default_sigv,sig_handler): Handle SIGUSR1. * src/pies.h (component): New members: prev, next, listidx, arridx, ref_count, prog. Remove act_head, act_tail, act_temp. Add new prototypes. * src/prog.h (prog): Remove tag and prereq. * src/progman.c (prog_tag): New function. (destroy_prog): Update component reference count. (register_redir): Likewise. (register_prog0): Take one argument. Update component reference count. (register_prog): Update comp->prog (prog_rebuild_prerequisites): Remove. (component_fixup_depend): Remove. (fixup_prerequisites,rebuild_prerequisites) (print_dep,progman_dump_prereq) (progman_dump_depmap,progman_build_depmap): Remove. (prog_start_prerequisites): Scan depmap to find prerequisites. (prog_stop_dependents): Likewise. (progman_wait): Remove. (progman_wait_until): New function. (progman_stop): Rewrite using progman_wait_until. (react): Rewrite using grecs_list * src/sysvinit.c: Use prog_tag when needed. * src/userprivs.c (pies_privs_cmp, pies_privs_free): New functions. * grecs: Update. * lib/safe_strcmp.c: New file. * lib/Makefile.am: Add safe_strcmp.c * lib/libpies.h (safe_strcmp): New proto.
Diffstat (limited to 'src/progman.c')
-rw-r--r--src/progman.c538
1 files changed, 190 insertions, 348 deletions
diff --git a/src/progman.c b/src/progman.c
index 0079149..4f63d9a 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -14,25 +14,23 @@
You should have received a copy of the GNU General Public License
along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
#include "pies.h"
#include "prog.h"
-static size_t numcomp;
static struct prog *proghead, *progtail;
-static pies_depmap_t depmap;
static int recompute_alarm;
static struct grecs_symtab *conn_tab;
struct prog *
progman_locate (const char *name)
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
- if (strcmp (prog->tag, name) == 0)
+ if (strcmp (prog_tag (prog), name) == 0)
break;
return prog;
}
void
progman_foreach (int (*filter) (struct prog *, void *data), void *data)
@@ -70,13 +68,13 @@ prog_lookup_by_pid (pid_t pid)
struct prog *
prog_lookup_by_tag (const char *tag)
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
- if (strcmp (prog->tag, tag) == 0)
+ if (strcmp (prog_tag (prog), tag) == 0)
break;
return prog;
}
struct prog *
prog_lookup_by_service (const char *service)
@@ -92,13 +90,13 @@ prog_lookup_by_service (const char *service)
struct component *
progman_lookup_component (const char *tag)
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
- if (IS_COMPONENT (prog) && strcmp (prog->tag, tag) == 0)
+ if (IS_COMPONENT (prog) && strcmp (prog_tag (prog), tag) == 0)
return prog->v.p.comp;
return NULL;
}
struct component *
progman_lookup_tcpmux (const char *service, const char *master)
@@ -126,12 +124,29 @@ prog_lookup_by_idx (unsigned idx)
return prog;
}
void prog_stop (struct prog *prog, int sig);
static int prog_start_prerequisites (struct prog *prog);
+char const *
+prog_tag (struct prog const *prog)
+{
+ switch (prog->type)
+ {
+ case TYPE_COMPONENT:
+ return prog->v.p.comp->tag;
+
+ case TYPE_REDIRECTOR:
+ return prog->v.r.tag;
+
+ case TYPE_COMMAND:
+ return prog->v.c.tag;
+ }
+ abort ();
+ }
+
void
link_prog (struct prog *pp, int prepend)
{
if (prepend)
{
if (proghead)
@@ -155,12 +170,13 @@ link_prog (struct prog *pp, int prepend)
}
void
unlink_prog (struct prog *pp)
{
struct prog *x;
+
if ((x = pp->prev))
x->next = pp->next;
else
proghead = pp->next;
if ((x = pp->next))
x->prev = pp->prev;
@@ -169,69 +185,69 @@ unlink_prog (struct prog *pp)
}
void
destroy_prog (struct prog **pp)
{
struct prog *p = *pp;
+
+ unlink_prog (p);
switch (p->type)
{
case TYPE_COMPONENT:
+ component_ref_decr (p->v.p.comp);
+ if (p->v.p.status == status_listener)
+ deregister_socket (p->v.p.socket);
break;
-
+
case TYPE_REDIRECTOR:
{
struct prog *master = p->v.r.master;
+ component_ref_decr (master->v.p.comp);
if (p == master->v.p.redir[0])
master->v.p.redir[0] = NULL;
else if (p == master->v.p.redir[1])
master->v.p.redir[1] = NULL;
/* else
logmsg (LOG_NOTICE, _("orphan redirector: %s"), p->tag);*/
+ free (p->v.r.tag);
}
break;
-
+
case TYPE_COMMAND:
+ free (p->v.c.tag);
free (p->v.c.command);
}
- unlink_prog (*pp);
- free (*pp);
+ free (p);
*pp = NULL;
}
static char *
redir_tag (struct prog *master, int type)
{
static char *redirstr[2] = { "stdout", "stderr" };
char *str = NULL;
size_t len = 0;
+ char const *tag = prog_tag (master);
if (type < ARRAY_SIZE(redirstr))
- grecs_asprintf (&str, &len, "%s/%s", master->tag, redirstr[type]);
+ grecs_asprintf (&str, &len, "%s/%s", tag, redirstr[type]);
else
- grecs_asprintf (&str, &len, "%s/%d", master->tag, type);
+ grecs_asprintf (&str, &len, "%s/%d", tag, type);
return str;
}
static struct prog *
register_redir (int type, struct prog *master)
{
char *tag = redir_tag (master, type);
- char *pstr;
- struct prog *pp = grecs_zalloc (sizeof (*pp) + strlen (tag) + 1 +
- 2 * sizeof (char**));
+ struct prog *pp = grecs_zalloc (sizeof (*pp));
pp->type = TYPE_REDIRECTOR;
- pstr = (char *) (pp + 1);
- pp->tag = pstr;
- strcpy (pp->tag, tag);
- pstr += strlen (pp->tag) + 1;
- free (tag);
+ pp->v.r.tag = tag;
pp->v.r.master = master;
- pp->prereq = (char**)pstr;
- pp->prereq[0] = master->tag;
- pp->prereq[1] = NULL;
link_prog (pp, 1);
+ component_ref_incr (master->v.p.comp);
return pp;
}
void
update_redir (int type, struct prog *master, pid_t pid)
{
@@ -245,107 +261,52 @@ update_redir (int type, struct prog *master, pid_t pid)
pp = register_redir (type, master);
master->v.p.redir[type] = pp;
pp->pid = pid;
}
static struct prog *
-register_prog0 (struct component *comp, unsigned index)
+register_prog0 (struct component *comp)
{
struct prog *newp;
newp = grecs_zalloc (sizeof (*newp));
newp->type = TYPE_COMPONENT;
- newp->tag = comp->tag;
newp->pid = 0;
newp->facility = comp->facility;
newp->v.p.comp = comp;
- newp->v.p.idx = index;
newp->v.p.socket = -1;
if (comp->flags & CF_DISABLED)
newp->v.p.status = status_disabled;
else if (comp->mode == pies_comp_inetd)
newp->v.p.status = status_listener;
if (comp->mode != pies_comp_exec)
comp->redir[RETR_OUT].type = redir_null;
link_prog (newp, 0);
+ component_ref_incr (comp);
return newp;
}
void
register_prog (struct component *comp)
{
- register_prog0 (comp, numcomp++);
+ comp->prog = register_prog0 (comp);
}
void
register_command (char *tag, char *command, pid_t pid)
{
struct prog *newp = grecs_zalloc (sizeof (*newp));
newp->type = TYPE_COMMAND;
- newp->tag = tag;
newp->pid = pid;
+ newp->v.c.tag = grecs_strdup (tag);
newp->v.c.command = command;
link_prog (newp, 0);
}
-void
-prog_rebuild_prerequisites (struct prog *prog)
-{
- struct component *comp = prog->v.p.comp;
- struct prog *p;
- int dep_all = 0;
- size_t depc = 0;
-
- if (comp->prereq)
- {
- depc = grecs_list_size (comp->prereq);
- if (depc == 1)
- {
- const char *item = grecs_list_index (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)
- {
- grecs_list_free (comp->prereq);
- comp->prereq = NULL;
- }
- }
- }
-
- if (depc == 0)
- return;
-
- prog->prereq = grecs_calloc (depc + 1, sizeof (prog->prereq[0]));
-
- depc = 0;
- if (comp->prereq)
- {
- if (dep_all)
- {
- for (p = proghead; p; p = p->next)
- if (p->type == TYPE_COMPONENT)
- prog->prereq[depc++] = p->tag;
- }
- else
- {
- struct grecs_list_entry *ep;
-
- for (ep = comp->prereq->head; ep; ep = ep->next)
- prog->prereq[depc++] = (char*) ep->data;
- }
- }
- prog->prereq[depc] = NULL;
-}
-
int
progman_running_p ()
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
@@ -470,27 +431,27 @@ open_redirector (struct prog *master, int stream)
signal_setup (redir_exit);
close (p[1]);
fp = fdopen (p[0], "r");
if (fp == NULL)
_exit (1);
- openlog (master->tag, LOG_PID, master->facility);
+ openlog (prog_tag (master), LOG_PID, master->facility);
prio = master->v.p.comp->redir[stream].v.prio;
while (getline (&buf, &size, fp) > 0)
syslog (prio, "%s", buf);
_exit (0);
case -1:
logmsg (LOG_CRIT,
_("cannot run redirector `%s': fork failed: %s"),
- master->tag, strerror (errno));
+ prog_tag (master), strerror (errno));
return -1;
default:
debug (1, (_("redirector for %s started, pid=%lu"),
- master->tag, (unsigned long) pid));
+ prog_tag (master), (unsigned long) pid));
update_redir (stream, master, pid);
close (p[0]);
return p[1];
}
}
@@ -953,13 +914,13 @@ check_spawn_rate (struct prog *prog)
if (check_rate (prog, TESTTIME, MAXSPAWN))
{
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_tag (prog), SLEEPTIME / 60);
return 1;
}
return 0;
}
static int
@@ -970,13 +931,13 @@ check_connection_rate (struct prog *prog)
if (max_rate && check_rate (prog, 60, max_rate))
{
logmsg (LOG_NOTICE,
ngettext ("%s is starting too often, disabled for %d minute",
"%s is starting too often, disabled for %d minutes",
SLEEPTIME / 60),
- prog->tag, SLEEPTIME / 60);
+ prog_tag (prog), SLEEPTIME / 60);
return 1;
}
return 0;
}
@@ -1008,13 +969,13 @@ prog_start_prologue (struct prog *prog)
{
if (prog->v.p.comp->dir)
{
debug (1, (_("chdir %s"), prog->v.p.comp->dir));
if (chdir (prog->v.p.comp->dir))
logmsg (LOG_ERR, _("%s: cannot change to directory %s: %s"),
- prog->tag, prog->v.p.comp->dir, strerror (errno));
+ prog_tag (prog), prog->v.p.comp->dir, strerror (errno));
}
environ_setup (prog->v.p.comp->env ?
prog->v.p.comp->env :
((prog->v.p.comp->flags & CF_SOCKENV) ? sockenv_hint : NULL));
if (init_process)
@@ -1022,13 +983,13 @@ prog_start_prologue (struct prog *prog)
DEBUG_ENVIRON (4);
pies_priv_setup (&prog->v.p.comp->privs);
if (prog->v.p.comp->umask)
umask (prog->v.p.comp->umask);
- set_limits (prog->tag,
+ set_limits (prog_tag (prog),
prog->v.p.comp->limits ?
prog->v.p.comp->limits : pies_limits);
if (debug_level >= 1)
{
int i;
@@ -1054,22 +1015,22 @@ prog_execute (struct prog *prog)
}
execvp (prog->v.p.comp->program ?
prog->v.p.comp->program : prog->v.p.comp->argv[0],
prog->v.p.comp->argv);
openlog (log_tag, LOG_PID, prog->v.p.comp->facility);
- syslog (LOG_CRIT, _("cannot start `%s': %s"), prog->tag,
+ syslog (LOG_CRIT, _("cannot start `%s': %s"), prog_tag (prog),
strerror (errno));
_exit (EX_SOFTWARE);
}
void
progman_run_comp (struct component *comp, int fd,
union pies_sockaddr_storage *sa, socklen_t salen)
{
- struct prog *prog = register_prog0 (comp, -1);
+ struct prog *prog = register_prog0 (comp);
prog->v.p.socket = fd;
prog->v.p.sa_storage = *sa;
prog->v.p.sa_len = salen;
prog->v.p.cclass = conn_class_lookup (comp->tag, sa, salen);
prog_start_prologue (prog);
prog_sockenv (prog);
@@ -1090,13 +1051,13 @@ prog_start (struct prog *prog)
{
if (!init_process)
{
if (prog->v.p.status != status_disabled)
{
logmsg (LOG_NOTICE, "disabling sysvinit component %s",
- prog->tag);
+ prog_tag (prog));
prog->v.p.status = status_disabled;
}
return;
}
debug (1, ("ok to start %s", prog->v.p.comp->tag));
}
@@ -1144,20 +1105,20 @@ prog_start (struct prog *prog)
return;
default:
break;
}
- debug (1, (_("starting %s"), prog->tag));
+ debug (1, (_("starting %s"), prog_tag (prog)));
if (prog->v.p.comp->rmfile)
{
debug (1, (_("unlinking %s"), prog->v.p.comp->rmfile));
if (unlink (prog->v.p.comp->rmfile) && errno != ENOENT)
logmsg (LOG_ERR, _("%s: cannot remove file `%s': %s"),
- prog->tag, prog->v.p.comp->rmfile, strerror (errno));
+ prog_tag (prog), prog->v.p.comp->rmfile, strerror (errno));
}
if (prog->v.p.comp->builtin && prog->v.p.comp->builtin->single_process)
{
prog->v.p.comp->builtin->fun (prog->v.p.socket, prog->v.p.comp);
return;
@@ -1256,13 +1217,13 @@ prog_start (struct prog *prog)
prog_execute (prog);
case -1:
logmsg (LOG_CRIT,
_("cannot run `%s': fork failed: %s"),
- prog->tag, strerror (errno));
+ prog_tag (prog), strerror (errno));
break;
default:
if (prog->v.p.comp->mode == pies_comp_pass_fd)
{
pass_fd (prog->v.p.comp->pass_fd_socket, prog->v.p.socket,
@@ -1276,21 +1237,22 @@ prog_start (struct prog *prog)
}
else if (prog->v.p.comp->mode == pies_comp_accept ||
prog->v.p.comp->mode == pies_comp_inetd ||
prog->v.p.comp->mode == pies_comp_pass_fd)
close (prog->v.p.socket);
else if (is_sysvinit (prog->v.p.comp))
- sysvinit_acct (SYSV_ACCT_PROC_START, "", prog->tag, pid, "");
+ sysvinit_acct (SYSV_ACCT_PROC_START, "", prog_tag (prog), pid, "");
if (redir[RETR_OUT] != -1)
close (redir[RETR_OUT]);
if (redir[RETR_ERR])
close (redir[RETR_ERR]);
prog->pid = pid;
prog->v.p.status = status_enabled;
- debug (1, (_("%s started, pid=%lu"), prog->tag, (unsigned long) pid));
+ debug (1, (_("%s started, pid=%lu"), prog_tag (prog),
+ (unsigned long) pid));
}
}
int
check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
pies_identity_t identity)
@@ -1358,13 +1320,13 @@ _prog_accept (struct prog *p)
return 1;
}
if (debug_level >= 1)
{
char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
- logmsg (LOG_DEBUG, _("%s wants %s"), s, p->tag);
+ logmsg (LOG_DEBUG, _("%s wants %s"), s, prog_tag (p));
free (s);
}
if (check_acl (p->v.p.comp->acl, (struct sockaddr *)&addr, addrlen, NULL)
|| check_acl (pies_acl, (struct sockaddr *)&addr, addrlen, NULL))
{
@@ -1376,28 +1338,28 @@ _prog_accept (struct prog *p)
if (p->v.p.comp->max_instances &&
p->v.p.num_instances >= p->v.p.comp->max_instances)
{
char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
logmsg (LOG_ERR,
_("%s: access from %s denied: too many instances running"),
- p->tag, s);
+ prog_tag (p), s);
free (s);
fd_report (fd, p->v.p.comp->max_instances_message);
close (fd);
return 1;
}
- pcclass = conn_class_lookup (p->tag, &addr, addrlen);
+ pcclass = conn_class_lookup (prog_tag (p), &addr, addrlen);
if (p->v.p.comp->max_ip_connections &&
pcclass->count >= p->v.p.comp->max_ip_connections)
{
char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
logmsg (LOG_ERR,
_("%s: access from %s denied: "
"too many connections from that ip"),
- p->tag, s);
+ prog_tag (p), s);
free (s);
fd_report (fd, p->v.p.comp->max_ip_connections_message);
close (fd);
return 1;
}
@@ -1410,13 +1372,13 @@ _prog_accept (struct prog *p)
pcclass->count++;
if (debug_level > 1)
conn_class_report (LOG_DEBUG, pcclass);
- pinst = register_prog0 (p->v.p.comp, -1);
+ pinst = register_prog0 (p->v.p.comp);
pinst->v.p.socket = fd;
pinst->v.p.listener = p;
pinst->v.p.sa_storage = addr;
pinst->v.p.sa_len = addrlen;
pinst->v.p.cclass = pcclass;
prog_start (pinst);
@@ -1429,24 +1391,24 @@ _prog_accept (struct prog *p)
static int
_prog_wait (struct prog *p)
{
struct prog *pinst;
- debug (1, (_("someone wants %s"), p->tag));
+ debug (1, (_("someone wants %s"), prog_tag (p)));
if (p->v.p.comp->max_instances
&& p->v.p.num_instances >= p->v.p.comp->max_instances)
{
logmsg (LOG_ERR,
_("%s: too many instances running, dropping connection"),
- p->tag);
+ prog_tag (p));
return 1;
}
- pinst = register_prog0 (p->v.p.comp, -1);
+ pinst = register_prog0 (p->v.p.comp);
pinst->v.p.socket = p->v.p.socket;
pinst->v.p.listener = p;
prog_start (pinst);
pinst->v.p.socket = -1;
@@ -1462,182 +1424,25 @@ progman_accept (int socket, void *data)
if (p->v.p.comp->socket_type == SOCK_STREAM
&& !(p->v.p.comp->flags & CF_WAIT))
return _prog_accept (p);
return _prog_wait (p);
}
-
-
-void
-component_fixup_depend (struct component *comp)
-{
- struct grecs_list_entry *ep;
-
- if (comp->depend == NULL)
- return;
-
- for (ep = comp->depend->head; ep; ep = ep->next)
- {
- const char *tag = ep->data;
- struct component *tgt;
-
- tgt = progman_lookup_component (tag);
- if (!tgt)
- {
- logmsg (LOG_ERR,
- _("component %s declares dependency target %s, "
- "which is not declared"),
- comp->tag, tag);
- continue;
- }
- if (!tgt->prereq)
- {
- tgt->prereq = grecs_list_create();
- }
- /* FIXME: memory allocation */
- grecs_list_append (tgt->prereq, grecs_strdup (comp->tag));
- }
- grecs_list_free (comp->depend);
- comp->depend = NULL;
-}
-
-void
-fixup_prerequisites ()
-{
- struct prog *prog;
-
- for (prog = proghead; prog; prog = prog->next)
- if (IS_COMPONENT (prog))
- component_fixup_depend (prog->v.p.comp);
-}
-
-void
-rebuild_prerequisites ()
-{
- struct prog *prog;
- for (prog = proghead; prog; prog = prog->next)
- if (IS_COMPONENT (prog))
- prog_rebuild_prerequisites (prog);
-}
-
-void
-print_dep (struct prog *prog)
-{
- pies_depmap_pos_t pos;
- size_t n;
-
- logmsg_printf (LOG_NOTICE, "%s -> ", prog->tag);
- for (n = depmap_first (depmap, depmap_col, prog->v.p.idx, &pos);
- n != (size_t)-1;
- n = depmap_next (depmap, pos))
- {
- struct prog *dp = prog_lookup_by_idx (n);
- logmsg_printf (LOG_NOTICE, "%s -> ", dp->tag);
- }
- depmap_end (pos);
- logmsg_printf (LOG_NOTICE, "%s\n", prog->tag);
-}
-
-void
-progman_dump_prereq ()
-{
- struct prog *prog;
- for (prog = proghead; prog; prog = prog->next)
- if (prog->prereq)
- {
- int i;
- printf ("%s:", prog->tag);
- for (i = 0; prog->prereq[i]; i++)
- printf (" %s", prog->prereq[i]);
- printf ("\n");
- }
-}
-
-void
-progman_dump_depmap ()
-{
- struct prog *prog;
- size_t i, j;
-
- printf ("%s:\n", _("Dependency map"));
- printf (" ");
- for (i = 0; i < numcomp; i++)
- printf (" %2lu", (unsigned long)i);
- printf ("\n");
- for (i = 0; i < numcomp; i++)
- {
- printf ("%2lu ", (unsigned long)i);
- for (j = 0; j < numcomp; j++)
- printf (" %c ", depmap_isset (depmap, i, j) ? 'X' : ' ');
- printf ("\n");
- }
- printf ("\n%s:\n", _("Legend"));
- for (i = 0; i < numcomp; i++)
- {
- prog = prog_lookup_by_idx (i);
- if (prog)
- printf ("%2lu: %s\n", (unsigned long)i, prog->tag);
- }
-}
-
-int
-progman_build_depmap ()
-{
- int rc = 0;
- size_t i;
- struct prog *prog;
- pies_depmap_t dp;
-
- fixup_prerequisites ();
- rebuild_prerequisites ();
- depmap = depmap_alloc (numcomp);
- for (prog = proghead; prog; prog = prog->next)
- if (prog->prereq)
- {
- 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;
- logmsg (LOG_ERR, _("component %s depends on %s, "
- "which is not declared"),
- prog->tag, prog->prereq[i]);
- rc++;
- }
- else
- depmap_set (depmap, prog->v.p.idx, dep->v.p.idx);
- }
- }
- dp = depmap_copy (depmap);
- depmap_tc (dp);
- for (i = 0; i < numcomp; i++)
- if (depmap_isset (dp, i, i))
- {
- prog = prog_lookup_by_idx (i);
- logmsg (LOG_ERR, _("component %s depends on itself"), prog->tag);
- print_dep (prog);
- prog->v.p.status = status_disabled;
- rc++;
- }
- free (dp);
- return rc;
-}
-
void
progman_create_sockets ()
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
{
if (IS_COMPONENT (prog))
{
struct component *comp = prog->v.p.comp;
- if (comp->mode == pies_comp_inetd && !ISCF_TCPMUX (comp->flags))
+ if (comp->mode == pies_comp_inetd && !ISCF_TCPMUX (comp->flags)
+ && prog->v.p.socket == -1)
{
int fd = create_socket (comp->socket_url,
comp->socket_type,
comp->privs.user, comp->umask);
if (fd == -1)
prog->v.p.status = status_disabled;
@@ -1722,13 +1527,13 @@ check_stopping (struct prog *prog, time_t now)
{
if (now - prog->v.p.timestamp >= shutdown_timeout)
{
if (prog->pid == 0)
logmsg (LOG_EMERG,
_("INTERNAL ERROR: attempting to kill unexisting process %s"),
- prog->tag);
+ prog_tag (prog));
else if (prog->v.p.comp->flags & CF_SIGGROUP)
kill (-prog->pid, SIGKILL);
else
kill (prog->pid, SIGKILL);
}
else
@@ -1787,29 +1592,34 @@ progman_wake_sleeping (int onalrm)
progman_recompute_alarm ();
}
static int
prog_start_prerequisites (struct prog *prog)
{
- int i;
- int ret;
-
+ int ret = 0;
+ pies_depmap_pos_t pos;
+ struct component *comp;
+ int warned = 0;
+
if (prog->v.p.status == status_disabled)
return 1;
- if (!prog->prereq)
- return 0; /* Ok to startup */
- 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_COMPONENT (dp)) /* Skip redirectors */
- continue;
- if (prog->v.p.comp->flags & CF_PRECIOUS)
+ for (comp = component_depmap_first (depmap_col, prog->v.p.comp->arridx, &pos);
+ comp;
+ comp = component_depmap_next (pos))
+ {
+ struct prog *p;
+
+ if (!comp->prog || comp->flags & CF_PRECIOUS)
continue;
- switch (dp->v.p.status)
+ if (!warned)
+ {
+ debug (1, ("starting prerequisites of %s", prog_tag (prog)));
+ warned = 1;
+ }
+ p = comp->prog;
+ switch (p->v.p.status)
{
case status_enabled:
if (prog->pid != 0)
continue;
break;
@@ -1822,24 +1632,26 @@ prog_start_prerequisites (struct prog *prog)
case status_sleeping:
/* FIXME: What to do in this case? */
break;
case status_stopping:
- check_stopping (dp, time (NULL));
+ check_stopping (p, time (NULL));
ret = 1;
continue;
case status_finished:
continue;
}
- prog_start (dp);
- if (dp->v.p.comp->mode == pies_comp_once ||
- !(dp->v.p.status == status_enabled && dp->pid))
+ prog_start (p);
+ if (p->v.p.comp->mode == pies_comp_once ||
+ !(p->v.p.status == status_enabled && p->pid))
ret = 1;
}
+ depmap_end (pos);
+
return ret;
}
void
prog_stop_redirectors (struct prog *prog)
{
@@ -1849,27 +1661,27 @@ prog_stop_redirectors (struct prog *prog)
prog_stop (prog->v.p.redir[RETR_ERR], SIGTERM);
}
void
prog_stop_dependents (struct prog *prog)
{
+ struct component *comp;
pies_depmap_pos_t pos;
- size_t n;
int warned = 0;
prog_stop_redirectors (prog);
- for (n = depmap_first (depmap, depmap_row, prog->v.p.idx, &pos);
- n != (size_t)-1;
- n = depmap_next (depmap, pos))
+ for (comp = component_depmap_first (depmap_row, prog->v.p.comp->arridx, &pos);
+ comp;
+ comp = component_depmap_next (pos))
{
- struct prog *dp = prog_lookup_by_idx (n);
+ struct prog *dp = comp->prog;
if (!dp) /* should not happen */
continue;
if (!warned && dp->pid)
{
- debug (1, ("stopping dependencies of %s", prog->tag));
+ debug (1, ("stopping dependencies of %s", prog_tag (prog)));
warned = 1;
}
prog_stop (dp, SIGTERM);
}
depmap_end (pos);
}
@@ -1885,13 +1697,13 @@ prog_stop (struct prog *prog, int sig)
{
prog->v.p.status = status_stopping;
prog->v.p.timestamp = time (NULL);
recompute_alarm = 1;
}
}
- debug (1, ("stopping %s (%lu)", prog->tag, (unsigned long) prog->pid));
+ debug (1, ("stopping %s (%lu)", prog_tag (prog), (unsigned long) prog->pid));
if (prog->type == TYPE_COMPONENT && prog->v.p.comp->flags & CF_SIGGROUP)
kill (-prog->pid, sig);
else
kill (prog->pid, sig);
}
@@ -1905,36 +1717,42 @@ prog_stop_all (int sig)
if (IS_COMPONENT (prog)
&& (prog->v.p.status == status_enabled
|| prog->v.p.status == status_stopping))
prog_stop (prog, sig);
}
-static int
-progman_wait ()
+int
+progman_wait_until (int (*cond) (void *), void *data)
{
time_t start = time (NULL);
do
{
progman_cleanup (1);
- if (progman_running_count () == 0)
+ if (cond && cond (data))
return 0;
sleep (1);
}
while (time (NULL) - start < shutdown_timeout);
return 1;
}
+static int
+no_children_left (void *p)
+{
+ return progman_running_count () == 0;
+}
+
void
progman_stop ()
{
prog_stop_all (SIGTERM);
- if (progman_wait ())
+ if (progman_wait_until (no_children_left, NULL))
{
prog_stop_all (SIGKILL);
- progman_wait ();
+ progman_wait_until (no_children_left, NULL);
}
}
static void
print_status (const char *tag, pid_t pid, int status, int expect_term)
{
@@ -2334,13 +2152,13 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
if (pid == 0)
{
debug (1, (_("executing %s"), act->command));
/* Child */
setsid ();
setenv ("PIES_VERSION", PACKAGE_VERSION, 1);
- setenv ("PIES_COMPONENT", prog->tag, 1);
+ setenv ("PIES_COMPONENT", prog_tag (prog), 1);
setenv ("PIES_PID", umaxtostr (child_pid, buf), 1);
if (retcode & STATUS_SIG_BIT)
setenv ("PIES_SIGNAL", umaxtostr (STATUS_CODE (retcode), buf), 1);
else
setenv ("PIES_STATUS", umaxtostr (STATUS_CODE (retcode), buf), 1);
@@ -2362,66 +2180,73 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
}
static void
react (struct prog *prog, int status, pid_t pid)
{
unsigned retcode;
- struct action *act = prog->v.p.comp->act_head;
-
- if (!act)
- act = default_component.act_head;
+ struct grecs_list *list = prog->v.p.comp->act_list;
+
+ if (!list)
+ list = default_component.act_list;
if (WIFEXITED (status))
{
retcode = WEXITSTATUS (status);
- debug (1, (_("%s: terminated with code %d"), prog->tag, retcode));
+ debug (1, (_("%s: terminated with code %d"), prog_tag (prog), retcode));
}
else if (WIFSIGNALED (status))
{
retcode = WTERMSIG (status);
- debug (1, (_("%s: terminated on signal %d"), prog->tag, retcode));
+ debug (1, (_("%s: terminated on signal %d"), prog_tag (prog), retcode));
retcode |= STATUS_SIG_BIT;
}
else
{
- debug (1, (_("%s: unrecognized termination status"), prog->tag));
+ debug (1, (_("%s: unrecognized termination status"), prog_tag (prog)));
/* Enforce default action: */
- act = NULL;
+ list = NULL;
}
-
- for (; act; act = act->next)
+
+ if (list)
{
- if (status_matches_p (act, retcode))
+ struct grecs_list_entry *ep;
+ for (ep = list->head; ep; ep = ep->next)
{
- if (act->command)
+ struct action *act = ep->data;
+
+ if (status_matches_p (act, retcode))
{
- run_command (act, prog, retcode, pid);
- }
+ if (act->command)
+ {
+ run_command (act, prog, retcode, pid);
+ }
- switch (act->act)
- {
- case action_restart:
- if (prog->v.p.comp->mode != pies_comp_inetd)
- prog_start (prog);
- break;
+ switch (act->act)
+ {
+ case action_restart:
+ if (prog->v.p.comp->mode != pies_comp_inetd)
+ prog_start (prog);
+ break;
- case action_disable:
- logmsg (LOG_NOTICE, _("disabling component %s"), prog->tag);
- prog->v.p.status = status_disabled;
- /* FIXME:
- if (prog->v.p.comp->mode == pies_comp_inetd)
- disable_socket (prog->v.p.socket);
- */
+ case action_disable:
+ logmsg (LOG_NOTICE, _("disabling component %s"),
+ prog_tag (prog));
+ prog->v.p.status = status_disabled;
+ /* FIXME:
+ if (prog->v.p.comp->mode == pies_comp_inetd)
+ disable_socket (prog->v.p.socket);
+ */
+ }
+ if (act->addr)
+ notify (prog_tag (prog), status, act);
+ break;
}
- if (act->addr)
- notify (prog->tag, status, act);
- break;
}
}
- if (!act && prog->v.p.comp->mode != pies_comp_inetd)
+ if (!list && prog->v.p.comp->mode != pies_comp_inetd)
/* Default action: */
prog_start (prog);
}
void
@@ -2438,13 +2263,13 @@ progman_cleanup (int expect_term)
continue;
}
prog->pid = 0;
switch (prog->type)
{
case TYPE_COMPONENT:
- print_status (prog->tag, pid, status, expect_term);
+ print_status (prog_tag (prog), pid, status, expect_term);
if (prog->v.p.comp->mode == pies_comp_inetd)
{
struct prog *listener = prog->v.p.listener;
listener->v.p.num_instances--;
if (prog->v.p.cclass)
@@ -2458,47 +2283,64 @@ progman_cleanup (int expect_term)
prog->v.p.cclass = NULL;
}
}
prog_stop_redirectors (prog);
destroy_prog (&prog);
- react (listener, status, pid);
- if (listener->v.p.comp->flags & CF_WAIT)
- enable_socket (listener->v.p.socket);
- }
- else if (prog->v.p.comp->mode >= pies_mark_sysvinit)
- {
- sysvinit_acct (SYSV_ACCT_PROC_STOP, "", prog->tag, pid, "");
- prog->v.p.status = status_finished;
+ if (listener->v.p.num_instances == 0
+ && !component_is_active (prog->v.p.comp))
+ destroy_prog (&listener);
+ else
+ {
+ if (!expect_term)
+ react (listener, status, pid);
+ if (listener->v.p.comp->flags & CF_WAIT)
+ enable_socket (listener->v.p.socket);
+ }
}
else
{
- if (is_sysvinit (prog->v.p.comp))
- sysvinit_acct (SYSV_ACCT_PRO