aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/acl.c70
-rw-r--r--src/acl.h3
-rw-r--r--src/cmdline.opt22
-rw-r--r--src/comp.c817
-rw-r--r--src/ctl.c4
-rw-r--r--src/depmap.c28
-rw-r--r--src/inetd.c7
-rw-r--r--src/limits.c11
-rw-r--r--src/pies.c535
-rw-r--r--src/pies.h57
-rw-r--r--src/prog.h7
-rw-r--r--src/progman.c538
-rw-r--r--src/sysvinit.c43
-rw-r--r--src/userprivs.c23
15 files changed, 1367 insertions, 799 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3f29b4e..a637077 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,7 @@ bin_PROGRAMS = piesctl
pies_SOURCES = \
acl.c\
+ comp.c\
ctl.c\
depmap.c\
diag.c\
diff --git a/src/acl.c b/src/acl.c
index a96eb77..e7523f5 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -122,10 +122,13 @@ pies_acl_create (const char *name, grecs_locus_t *locus)
void
pies_acl_free (pies_acl_t acl)
{
- free (acl->name);
- grecs_locus_free (&acl->locus);
- grecs_list_free (acl->list);
- free (acl);
+ if (acl)
+ {
+ free (acl->name);
+ grecs_locus_free (&acl->locus);
+ grecs_list_free (acl->list);
+ free (acl);
+ }
}
static struct pies_sockaddr *
@@ -252,6 +255,19 @@ _parse_sockaddr (struct acl_entry *entry, const grecs_value_t *value)
return 0;
}
+static int
+sockaddr_cmp (void const *a, void const *b)
+{
+ struct pies_sockaddr const *ap = a;
+ struct pies_sockaddr const *bp = b;
+
+ if (ap->netmask != bp->netmask)
+ return 1;
+ if (ap->salen != bp->salen)
+ return 1;
+ return memcmp (&ap->sa, &bp->sa, ap->salen);
+}
+
static void
sockaddr_free (void *p)
{
@@ -285,6 +301,7 @@ _parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
}
entry->sockaddrs = grecs_list_create ();
+ entry->sockaddrs->cmp = sockaddr_cmp;
entry->sockaddrs->free_entry = sockaddr_free;
if (argv[0]->type == GRECS_TYPE_STRING)
{
@@ -433,7 +450,37 @@ parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl,
grecs_list_append (acl->list, entry);
return 0;
}
+
+static int
+acl_entry_cmp (void const *a, void const *b)
+{
+ struct acl_entry const *ap = a;
+ struct acl_entry const *bp = b;
+ size_t i;
+
+ if (ap->allow != bp->allow)
+ return 1;
+ if (ap->authenticated != bp->authenticated)
+ return 1;
+ if (pies_acl_cmp (ap->acl, bp->acl))
+ return 1;
+ if (ap->name_match != bp->name_match)
+ return 1;
+ if (ap->names && bp->names)
+ {
+ for (i = 0; ap->names[i]; i++)
+ if (!bp->names[i] || strcmp (ap->names[i], bp->names[i]))
+ return 1;
+ if (bp->names[i])
+ return 1;
+ }
+ else if (ap->names || bp->names)
+ return 1;
+
+ return grecs_list_compare (ap->sockaddrs, bp->sockaddrs);
+}
+
#define ACL_TAG_NONE 0
#define ACL_TAG_IGNORE 1
#define ACL_TAG_OPTIONAL 2
@@ -492,6 +539,11 @@ _acl_common_section_parser (enum grecs_callback_command cmd,
break;
case grecs_callback_section_end:
+ acl = *pacl;
+ if (acl->list)
+ acl->list->cmp = acl_entry_cmp;
+ break;
+
case grecs_callback_set_value:
break;
}
@@ -775,3 +827,13 @@ pies_acl_lookup (const char *name)
samp.name = (char *) name;
return grecs_symtab_lookup_or_install (acl_table, &samp, NULL);
}
+
+int
+pies_acl_cmp (struct pies_acl *a, struct pies_acl *b)
+{
+ if (!a)
+ return !!b;
+ else
+ return 1;
+ return grecs_list_compare (a->list, b->list);
+}
diff --git a/src/acl.h b/src/acl.h
index 757104d..db65e10 100644
--- a/src/acl.h
+++ b/src/acl.h
@@ -1,5 +1,5 @@
/* This file is part of GNU Pies
- Copyright (C) 2009-2013 Sergey Poznyakoff
+ Copyright (C) 2009-2016 Sergey Poznyakoff
GNU Pies is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@ struct acl_input
pies_acl_t pies_acl_create (const char *name, grecs_locus_t *locus);
void pies_acl_free (pies_acl_t acl);
+int pies_acl_cmp (struct pies_acl *a, struct pies_acl *b);
int pies_acl_check (pies_acl_t acl, struct acl_input *input, int result);
int parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl,
grecs_value_t *value);
diff --git a/src/cmdline.opt b/src/cmdline.opt
index f43d147..389cea7 100644
--- a/src/cmdline.opt
+++ b/src/cmdline.opt
@@ -26,7 +26,7 @@ GROUP(Operation Mode)
OPTION(config-file,c,FILE,
[<use FILE instead of the default configuration>])
BEGIN
- add_config (current_syntax, optarg);
+ config_file_add (current_syntax, optarg);
END
OPTION(config-help,,,
@@ -60,7 +60,7 @@ OPTION(inetd,i,,
BEGIN
if (!instance)
instance = "inetd";
- current_syntax = CONF_INETD;
+ current_syntax = &config_syntax_tab[CONF_INETD];
inetd_mode = 1;
END
@@ -91,7 +91,8 @@ END
OPTION(syntax,,[<{pies|meta1|inetd|inittab}>],
[<expect configuration files in the given syntax>])
BEGIN
- if (str_to_config_syntax (optarg, &current_syntax))
+ current_syntax = str_to_config_syntax (optarg);
+ if (!current_syntax)
{
logmsg (LOG_ERR, _("unknown syntax type: %s"), optarg);
exit (EX_USAGE);
@@ -152,7 +153,7 @@ OPTION(restart-component,R,,
[<restart components named in the command line>])
BEGIN
log_to_stderr_only = 1;
- command = COM_RESTART;
+ command = COM_RESTART_COMPONENT;
END
OPTION(status,s,,
@@ -178,11 +179,18 @@ BEGIN
command = COM_DUMP_DEPMAP;
END
-OPTION(dump-prereq,,,
- [<dump prerequisite charts>])
+OPTION(trace-depend,,,
+ [<trace dependencies>])
BEGIN
log_to_stderr_only = 1;
- command = COM_DUMP_PREREQ;
+ command = COM_TRACE_DEPEND;
+END
+
+OPTION(trace-prereq,,,
+ [<trace prerequisites>])
+BEGIN
+ log_to_stderr_only = 1;
+ command = COM_TRACE_PREREQ;
END
OPTION(source-info,,,
diff --git a/src/comp.c b/src/comp.c
new file mode 100644
index 0000000..6f8e11f
--- /dev/null
+++ b/src/comp.c
@@ -0,0 +1,817 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2016 Sergey Poznyakoff
+
+ GNU 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.
+
+ GNU 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "pies.h"
+#include "prog.h"
+#include <assert.h>
+
+struct complist
+{
+ struct component *head;
+ struct component *tail;
+};
+
+static struct complist comp_list[2];
+static int cur;
+
+static struct component **comp_array;
+static size_t comp_count;
+
+static pies_depmap_t depmap;
+
+static int
+next_index (void)
+{
+ return (cur + 1) % ARRAY_SIZE (comp_list);
+}
+
+static int
+prev_index (void)
+{
+ return (cur + ARRAY_SIZE (comp_list) - 1) % ARRAY_SIZE (comp_list);
+}
+
+void
+component_link (struct component *comp, struct component *ref, int before)
+{
+ if (!ref)
+ {
+ struct complist *list = &comp_list[comp->listidx];
+
+ comp->next = NULL;
+ comp->prev = list->tail;
+ if (list->tail)
+ list->tail->next = comp;
+ else
+ list->head = comp;
+ list->tail = comp;
+ }
+ else if (before)
+ component_link (comp, ref->prev, 0);
+ else
+ {
+ struct complist *list = &comp_list[comp->listidx];
+ struct component *x;
+
+ assert (comp->listidx == ref->listidx);
+
+ comp->prev = ref;
+
+ if ((x = ref->next))
+ x->prev = comp;
+ else
+ list->tail = comp;
+
+ ref->next = comp;
+ }
+}
+
+void
+component_unlink (struct component *comp)
+{
+ struct complist *list = &comp_list[comp->listidx];
+ struct component *x;
+
+ if ((x = comp->prev))
+ x->next = comp->next;
+ else
+ list->head = comp->next;
+ if ((x = comp->next))
+ x->prev = comp->prev;
+ else
+ list->tail = comp->prev;
+}
+
+struct component *
+component_lookup_tag (int idx, const char *tag)
+{
+ struct complist *list = &comp_list[idx];
+ struct component *comp;
+
+ for (comp = list->head; comp; comp = comp->next)
+ if (strcmp (comp->tag, tag) == 0)
+ break;
+
+ return comp;
+}
+
+ssize_t
+component_lookup_index (const char *tag)
+{
+ size_t i;
+
+ for (i = 0; i < comp_count; i++)
+ if (comp_array[i] && strcmp (comp_array[i]->tag, tag) == 0)
+ return i;
+ return -1;
+}
+
+struct component *
+component_create (const char *name)
+{
+ struct component *comp = component_lookup_tag (cur, name);
+ if (!comp)
+ {
+ comp = grecs_zalloc (sizeof (*comp));
+ comp->listidx = cur;
+ comp->facility = log_facility;
+ comp->redir[RETR_OUT].type = comp->redir[RETR_ERR].type = redir_null;
+ comp->tag = grecs_strdup (name);
+ comp->socket_type = SOCK_STREAM;
+ component_link (comp, NULL, 0);
+ }
+ return comp;
+}
+
+void
+component_free (struct component *comp)
+{
+ size_t i;
+
+ component_unlink (comp);
+ free (comp->tag);
+ free (comp->program);
+ if (comp->argv)
+ {
+ for (i = 0; i < comp->argc; i++)
+ free (comp->argv[i]);
+ free (comp->argv);
+ }
+ if (comp->env)
+ {
+ for (i = 0; comp->env[i]; i++)
+ free (comp->env[i]);
+ free (comp->env);
+ }
+ free (comp->dir);
+ grecs_list_free (comp->prereq);
+ grecs_list_free (comp->depend);
+ free (comp->rmfile);
+ pies_privs_free (&comp->privs);
+ free (comp->runlevels);
+ free_limits (comp->limits);
+ free (comp->runlevels);
+ free (comp->service);
+ pies_url_destroy (&comp->socket_url);
+ free (comp->pass_fd_socket);
+ free (comp->tcpmux);
+ free (comp->access_denied_message);
+ free (comp->max_instances_message);
+ free (comp->max_ip_connections_message);
+ free_redirector (&comp->redir[0]);
+ free_redirector (&comp->redir[1]);
+ grecs_list_free (comp->act_list);
+ pies_acl_free (comp->list_acl);
+ pies_acl_free (comp->adm_acl);
+ free (comp);
+}
+
+void
+component_ref_incr (struct component *comp)
+{
+ ++comp->ref_count;
+}
+
+void
+component_ref_decr (struct component *comp)
+{
+ assert (comp->ref_count > 0);
+ if (--comp->ref_count == 0)
+ component_free (comp);
+}
+
+static int
+argvcmp (char **a, char **b)
+{
+ size_t i;
+
+ if (!a != !b)
+ return 1;
+
+ for (i = 0; a[i]; i++)
+ if (!b[i] || strcmp (b[i], a[i]))
+ return 1;
+ return !!b[i];
+}
+
+static int
+urlcmp (struct pies_url *a, struct pies_url *b)
+{
+ if (!a)
+ return !!b;
+ else if (!b)
+ return 1;
+ return safe_strcmp (a->string, b->string);
+}
+
+static int
+redirector_cmp (struct redirector const *a, struct redirector const *b)
+{
+ if (a->type != b->type)
+ return 1;
+ switch (a->type)
+ {
+ case redir_null:
+ break;
+
+ case redir_syslog:
+ if (a->v.prio != b->v.prio)
+ return 1;
+ break;
+
+ case redir_file:
+ if (safe_strcmp (a->v.file, b->v.file))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+component_match (struct component *comp, struct component *ref)
+{
+#define MATCH(cond) do if (cond) return 1; while (0)
+#define EQ(memb) MATCH (comp->memb != ref->memb)
+#define FN(memb,fun) MATCH (fun (comp->memb, ref->memb))
+#define FNP(memb,fun) MATCH (fun (&comp->memb, &ref->memb))
+
+ EQ (mode);
+ FN (tag, safe_strcmp);
+ FN (program, safe_strcmp);
+ EQ (argc);
+ FN (argv, argvcmp);
+ FN (dir, safe_strcmp);
+ FN (prereq, grecs_list_compare);
+ FN (depend, grecs_list_compare);
+ EQ (flags);
+ EQ (max_instances);
+ FN (rmfile, safe_strcmp);
+ FNP (privs, pies_privs_cmp);
+ FN (limits, limits_cmp);
+ FN (runlevels, safe_strcmp);
+ EQ (max_rate);
+ EQ (max_ip_connections);
+ EQ (socket_type);
+ EQ (builtin);
+ FN (service, safe_strcmp);
+ FN (socket_url, urlcmp);
+ FN (pass_fd_socket, safe_strcmp);
+ EQ (pass_fd_timeout);
+ FN (acl, pies_acl_cmp);
+ FN (tcpmux, safe_strcmp);
+ EQ (facility);
+ FNP (redir[0], redirector_cmp);
+ FNP (redir[1], redirector_cmp);
+#undef MATCH
+#undef EQ
+#undef FN
+#undef FNP
+
+ return 0;
+}
+
+static struct component *
+complist_find_match (int idx, struct component *ref)
+{
+ struct complist *list = &comp_list[idx];
+ struct component *comp;
+
+ for (comp = list->head; comp && component_match (comp, ref);
+ comp = comp->next)
+ ;
+ return comp;
+}
+
+static void
+strasgn (char **dst, char **src)
+{
+ free (*dst);
+ *dst = *src;
+ *src = NULL;
+}
+
+void
+component_merge (struct component *comp, struct component *ref)
+{
+ strasgn (&comp->tag, &ref->tag);
+
+ strasgn (&comp->access_denied_message, &ref->access_denied_message);
+ strasgn (&comp->max_instances_message, &ref->max_instances_message);
+ strasgn (&comp->max_ip_connections_message,
+ &ref->max_ip_connections_message);
+
+ grecs_list_free (comp->act_list);
+ comp->act_list = ref->act_list;
+ ref->act_list = NULL;
+
+ pies_acl_free (comp->list_acl);
+ comp->list_acl = ref->list_acl;
+ ref->list_acl = NULL;
+
+ pies_acl_free (comp->adm_acl);
+ comp->adm_acl = ref->adm_acl;
+ ref->adm_acl = NULL;
+}
+
+int
+component_is_active (struct component *comp)
+{
+ return comp->listidx == cur;
+}
+
+void
+component_config_begin (void)
+{
+ cur = next_index ();
+}
+
+void
+component_config_rollback (void)
+{
+ struct complist *list = &comp_list[cur];
+ while (list->head)
+ component_free (list->head);
+ cur = prev_index ();
+}
+
+static int
+cb_terminate_prog (struct prog *prog, void *data)
+{
+ if (IS_COMPONENT (prog) && !component_is_active (prog->v.p.comp))
+ {
+ progman_stop_component (prog);
+ prog->v.p.comp->flags |= CF_DISABLED;
+ }
+ return 0;
+}
+
+static int
+cb_kill_prog (struct prog *prog, void *data)
+{
+ if (!(IS_COMPONENT (prog) && component_is_active (prog->v.p.comp)))
+ prog_stop (prog, SIGKILL);
+ return 0;
+}
+
+static int
+list_is_empty (void *p)
+{
+ struct complist *list = p;
+ return list->head == NULL;
+}
+
+static int
+list_str_cmp (const void *a, const void *b)
+{
+ return safe_strcmp (a, b);
+}
+
+static void
+component_log_dep (size_t idx)
+{
+ pies_depmap_pos_t pos;
+ size_t n;
+
+ logmsg_printf (LOG_NOTICE, "%s -> ", comp_array[idx]->tag);
+ for (n = depmap_first (depmap, depmap_col, idx, &pos);
+ n != (size_t)-1;
+ n = depmap_next (depmap, pos))
+ {
+ logmsg_printf (LOG_NOTICE, "%s -> ", comp_array[n]->tag);
+ }
+ depmap_end (pos);
+ logmsg_printf (LOG_NOTICE, "%s\n", comp_array[idx]->tag);
+}
+
+void
+component_build_depmap (void)
+{
+ size_t i;
+ pies_depmap_t dp;
+
+ free (depmap);
+ depmap = depmap_alloc (comp_count);
+ for (i = 0; i < comp_count; i++)
+ {
+ struct component *comp = comp_array[i];
+ struct grecs_list_entry *ep;
+
+ if (comp->prereq)
+ for (ep = comp->prereq->head; ep; ep = ep->next)
+ {
+ char const *tag = ep->data;
+ ssize_t tgt = component_lookup_index (tag);
+ if (tgt < 0)
+ {
+ logmsg (LOG_ERR,
+ _("component %s depends on %s, "
+ "which is not declared"),
+ comp->tag, tag);
+ component_free (comp);
+ comp_array[i] = NULL;
+ depmap_clear_all (depmap, depmap_row, i);
+ depmap_clear_all (depmap, depmap_col, i);
+ continue;
+ }
+ depmap_set (depmap, i, tgt);
+ }
+
+ if (comp->depend)
+ for (ep = comp->depend->head; ep; ep = ep->next)
+ {
+ char const *tag = ep->data;
+ ssize_t tgt = component_lookup_index (tag);
+ if (tgt < 0)
+ {
+ logmsg (LOG_ERR,
+ _("undefined component %s depends on %s"),
+ tag, comp->tag);
+ continue;
+ }
+ depmap_set (depmap, tgt, i);
+ }
+ }
+
+ dp = depmap_copy (depmap);
+ depmap_tc (dp);
+ for (i = 0; i < comp_count; i++)
+ if (depmap_isset (dp, i, i))
+ {
+ logmsg (LOG_ERR, _("component %s depends on itself"),
+ comp_array[i]->tag);
+ component_log_dep (i);
+ component_free (comp_array[i]);
+ comp_array[i] = NULL;
+ depmap_clear_all (depmap, depmap_row, i);
+ depmap_clear_all (depmap, depmap_col, i);
+ continue;
+ }
+ free (dp);
+}
+
+void
+component_config_commit (void)
+{
+ struct complist *list = &comp_list[cur];
+ struct component *comp, *match;
+ int prev = prev_index ();
+ size_t i;
+
+ /* Count available components and allocate array for them */
+ for (comp = list->head, i = 0; comp; comp = comp->next, i++)
+ /* FIXME: component_compute_prereq (comp) */;
+
+ comp_array = grecs_realloc (comp_array, i * sizeof (comp_array[0]));
+ comp_count = i;
+
+ /* Rearrange components, registering prog entries for the new ones */
+ for (comp = list->head, i = 0; comp; comp = comp->next, i++)
+ {
+ match = complist_find_match (prev, comp);
+ if (match)
+ {
+ component_merge (match, comp);
+ component_unlink (match);
+ match->listidx = cur;
+ component_link (match, comp, 1);
+ component_free (comp);
+ comp = match;
+ }
+ comp_array[i] = comp;
+ comp->arridx = i;
+ }
+
+ /* Terminate orphaned progs */
+ list = &comp_list[prev];
+ if (list->head)
+ {
+ progman_foreach (cb_terminate_prog, NULL);
+ if (progman_wait_until (list_is_empty, list))
+ {
+ progman_foreach (cb_kill_prog, NULL);
+ progman_wait_until (list_is_empty, list);
+ }
+ }
+
+ /* Build dependency map */
+ component_build_depmap ();
+
+ /* Register new progs */
+ for (comp = comp_list[cur].head; comp; comp = comp->next)
+ if (!comp->prog)
+ register_prog (comp);
+}
+
+static int
+component_verify (struct component *comp, grecs_locus_t *locus)
+{
+ int header = 0;
+ int i;
+#define COMPERR(func, fmt, arg) \
+ do \
+ { \
+ if (!header) \
+ { \
+ grecs_warning (locus, 0, _("in component %s:"), comp->tag); \
+ header = 1; \
+ } \
+ func (locus, 0, fmt, arg); \
+ } \
+ while (0)
+
+ if (comp->flags & CF_INTERNAL)
+ {
+ comp->mode = pies_comp_inetd;
+ if (!comp->service)
+ /* TRANSLATORS: do not translate quoted words, they are keywords. */
+ COMPERR (grecs_error,
+ "%s", _("`internal' used without `service'"));
+ else
+ {
+ comp->builtin = inetd_builtin_lookup (comp->service,
+ comp->socket_type);
+ if (!comp->builtin)
+ COMPERR (grecs_error,
+ "%s", _("unknown internal service"));
+ if (comp->argv)
+ /* TRANSLATORS: do not translate quoted words, they are
+ keywords. */
+ COMPERR (grecs_error,
+ "%s", _("`internal' used with `command'"));
+ }
+ }
+ else if (!comp->argv)
+ COMPERR (grecs_error,
+ "%s", _("missing command line"));
+
+ if (ISCF_TCPMUX (comp->flags))
+ {
+ comp->mode = pies_comp_inetd;
+ if ((comp->flags & (CF_TCPMUX | CF_TCPMUXPLUS))
+ == (CF_TCPMUX | CF_TCPMUXPLUS))
+ COMPERR (grecs_error,
+ "%s", _("both `tcpmux' and `tcpmuxplus' used"));
+ else if (!comp->service)
+ /* TRANSLATORS: do not translate quoted words, they are keywords. */
+ COMPERR (grecs_error,
+ "%s", _("`internal' used without `service'"));
+ }
+
+ if (comp->pass_fd_socket && comp->mode != pies_comp_pass_fd)
+ COMPERR (grecs_error,
+ "%s", _("pass-fd-socket ignored: wrong mode"));
+ switch (comp->mode)
+ {
+ case pies_comp_exec:
+ if (comp->socket_url)
+ COMPERR (grecs_error,
+ "%s", _("socket ignored: wrong mode"));
+ break;
+
+ case pies_comp_pass_fd:
+ if (!comp->pass_fd_socket)
+ COMPERR (grecs_error,
+ "%s", _("must supply pass-fd-socket in this mode"));
+ else if (comp->pass_fd_socket[0] != '/')
+ {
+ if (comp->dir)
+ {
+ char *p = mkfilename (comp->dir, comp->pass_fd_socket, NULL);
+ /*free (comp->pass_fd_socket);*/
+ comp->pass_fd_socket = p;
+ }
+ else
+ COMPERR (grecs_error,
+ "%s", _("pass-fd-socket must be an absolute "
+ "file name or chdir must be specified"));
+ }
+ /* Fall through */
+
+ case pies_comp_accept:
+ if (!comp->socket_url)
+ {
+ COMPERR (grecs_error,
+ "%s", _("socket must be specified in this mode"));
+ return 1;
+ }
+ break;
+
+ case pies_comp_inetd:
+ if (ISCF_TCPMUX (comp->flags))
+ {
+ pies_url_destroy (&comp->socket_url);
+ if (!comp->tcpmux)
+ {
+ COMPERR (grecs_warning,
+ "%s",
+ _("TCPMUX master not specified, assuming \"tcpmux\""));
+ comp->tcpmux = grecs_strdup ("tcpmux");
+ }
+ }
+ else if (comp->tcpmux)
+ {
+ comp->flags |= CF_TCPMUX;
+ pies_url_destroy (&comp->socket_url);
+ }
+ else if (!comp->socket_url)
+ {
+ COMPERR (grecs_error,
+ "%s", _("socket must be specified in this mode"));
+ return 1;
+ }
+ default:
+ /* FIXME: more checks perhaps */
+ break;
+ }
+
+ if (comp->mode == pies_comp_inetd)
+ {
+ if ((comp->flags & CF_WAIT) && comp->socket_type == SOCK_STREAM)
+ {
+ if (comp->max_instances)
+ COMPERR (grecs_error, "%s", _("max-instances ignored"));
+ else
+ comp->max_instances = 1;
+ }
+ }
+ else if (comp->flags & CF_WAIT)
+ {
+ /* TRANSLATORS: `wait' is a keywords, do not translate. */
+ COMPERR (grecs_error, "%s", _("wait is useless in this mode"));
+ comp->flags &= ~CF_WAIT;
+ }
+
+ if (comp->mode != pies_comp_exec
+ && comp->redir[RETR_OUT].type != redir_null)
+ {
+ COMPERR (grecs_error,
+ "%s", _("stdout translation invalid in this mode"));
+ comp->redir[RETR_OUT].type = redir_null;
+ }
+
+ for (i = RETR_OUT; i <= RETR_ERR; i++)
+ {
+ if (comp->redir[i].type == redir_file
+ && comp->redir[i].v.file[0] != '/')
+ {
+ if (comp->dir)
+ {
+ char *p = mkfilename (comp->dir, comp->redir[i].v.file, NULL);
+ free (comp->redir[i].v.file);
+ comp->redir[i].v.file = p;
+ }
+ else
+ COMPERR (grecs_error,
+ _("%s: must be an absolute "
+ "file name or chdir must be specified"),
+ comp->redir[i].v.file);
+ }
+ }
+
+ return header;
+#undef COMPERR
+}
+
+void
+component_finish (struct component *comp, grecs_locus_t *locus)
+{
+ if (comp->prereq)
+ comp->prereq->cmp = list_str_cmp;
+ if (comp->depend)
+ comp->depend->cmp = list_str_cmp;
+ if (comp->privs.groups)
+ comp->privs.groups->cmp = list_str_cmp;
+
+ if (component_verify (comp, locus))
+ {
+ component_free (comp);
+ }
+ else
+ {
+ size_t n = grecs_list_size (comp->prereq);
+ if (n == 1)
+ {
+ const char *item = grecs_list_index (comp->prereq, 0);
+ if (strcmp (item, "all") == 0)
+ {
+ struct component *p;
+
+ grecs_list_clear (comp->prereq);
+ for (p = comp->prev; p; p = p->prev)
+ grecs_list_push (comp->prereq, grecs_strdup (comp->tag));
+ }
+ else if (strcmp (item, "none") == 0)
+ {
+ grecs_list_free (comp->prereq);
+ comp->prereq = NULL;
+ }
+ }
+ }
+}
+
+struct component *
+component_get (size_t n)
+{
+ if (n >= comp_count)
+ return NULL;
+ return comp_array[n];
+}
+
+void
+components_dump_depmap (void)
+{
+ size_t i, j;
+
+ printf ("%s:\n", _("Dependency map"));
+ printf (" ");
+ for (i = 0; i < comp_count; i++)
+ printf (" %2lu", (unsigned long)i);
+ printf ("\n");
+ for (i = 0; i < comp_count; i++)
+ {
+ printf ("%2lu ", (unsigned long)i);
+ for (j = 0; j < comp_count; j++)
+ printf (" %c ", depmap_isset (depmap, i, j) ? 'X' : ' ');
+ printf ("\n");
+ }
+ printf ("\n%s:\n", _("Legend"));
+ for (i = 0; i < comp_count; i++)
+ printf ("%2lu: %s\n", (unsigned long)i, comp_array[i]->tag);
+}
+
+void
+component_trace (size_t idx, enum pies_depmap_direction dir)
+{
+ pies_depmap_pos_t pos;
+ size_t n;
+ int delim = ':';
+
+ logmsg_printf (LOG_NOTICE, "%s", comp_array[idx]->tag);
+ for (n = depmap_first (depmap, dir, idx, &pos);
+ n != (size_t)-1;
+ n = depmap_next (depmap, pos))
+ {
+ logmsg_printf (LOG_NOTICE, "%c %s", delim, comp_array[n]->tag);
+ delim = ',';
+ }
+ depmap_end (pos);
+ logmsg_printf (LOG_NOTICE, "\n");
+}
+
+void
+components_trace (char **argv, enum pies_depmap_direction dir)
+{
+ if (*argv)
+ for (; *argv; ++argv)
+ {
+ ssize_t idx = component_lookup_index (*argv);
+ if (idx < 0)
+ logmsg (LOG_ERR, "%s: no such component", *argv);
+ else
+ component_trace (idx, dir);
+ }
+ else
+ {
+ size_t i;
+
+ for (i = 0; i < comp_count; i++)
+ component_trace (i, dir);
+ }
+}
+
+struct component *
+component_depmap_first (enum pies_depmap_direction dir, size_t idx,
+ pies_depmap_pos_t *ppos)
+{
+ size_t n = depmap_first (depmap, dir, idx, ppos);
+ if (n == (size_t)-1)
+ return NULL;
+ return comp_array[n];
+}
+
+struct component *
+component_depmap_next (pies_depmap_pos_t pos)
+{
+ size_t n = depmap_next (depmap, pos);
+ if (n == (size_t)-1)
+ return NULL;
+ return comp_array[n];
+}
+
+
+
+
+
diff --git a/src/ctl.c b/src/ctl.c
index 11ec7b4..d3e6b64 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -1543,7 +1543,7 @@ pcond_eval (struct pcond_node *node, struct prog *p)
return 0;
case pcond_component:
- return strcmp (p->tag, node->v.tag) == 0;
+ return strcmp (prog_tag (p), node->v.tag) == 0;
case pcond_type:
return p->type == node->v.type;
@@ -1792,7 +1792,7 @@ selector (struct prog *prog, void *data)
if (auth_prog (prog, env->io) & env->allowed_state)
{
struct json_value *status = json_new_object ();
- json_object_set_string (status, "tag", prog->tag);
+ json_object_set_string (status, "tag", prog_tag (prog));
if (env->fun (status, prog) == 0)
env->success_count++;
json_array_append (env->result, status);
diff --git a/src/depmap.c b/src/depmap.c
index e4533e8..3259880 100644
--- a/src/depmap.c
+++ b/src/depmap.c
@@ -23,7 +23,7 @@
#define WORDSIZE(n) (((n) + BITS_PER_WORD - 1) / BITS_PER_WORD)
#define SETBIT(x, i) ((x)[(i)/BITS_PER_WORD] |= (1<<((i) % BITS_PER_WORD)))
-#define RESETBIT(x, i) ((x)[(i)/BITS_PER_WORD] &= ~(1<<((i) % BITS_PER_WORD)))
+#define CLRBIT(x, i) ((x)[(i)/BITS_PER_WORD] &= ~(1<<((i) % BITS_PER_WORD)))
#define BITISSET(x, i) (((x)[(i)/BITS_PER_WORD] & (1<<((i) % BITS_PER_WORD))) != 0)
void
@@ -118,6 +118,13 @@ depmap_set (pies_depmap_t dmap, size_t row, size_t col)
SETBIT (rptr, col);
}
+void
+depmap_clear (pies_depmap_t dmap, size_t row, size_t col)
+{
+ unsigned *rptr = depmap_rowptr (dmap, row);
+ CLRBIT (rptr, col);
+}
+
int
depmap_isset (pies_depmap_t dmap, size_t row, size_t col)
{
@@ -166,3 +173,22 @@ depmap_end (pies_depmap_pos_t pos)
{
grecs_free (pos);
}
+
+void
+depmap_clear_all (pies_depmap_t dmap, enum pies_depmap_direction dir,
+ size_t coord)
+{
+ size_t i;
+
+ switch (dir)
+ {
+ case depmap_row:
+ for (i = 0; i < dmap->nrows; i++)
+ depmap_clear (dmap, coord, i);
+ break;
+
+ case depmap_col:
+ for (i = 0; i < dmap->nrows; i++)
+ depmap_clear (dmap, i, coord);
+ }
+}
diff --git a/src/inetd.c b/src/inetd.c
index 3eb4470..ee16078 100644
--- a/src/inetd.c
+++ b/src/inetd.c
@@ -281,7 +281,7 @@ inetd_conf_file (const char *file)
if (ISCF_TCPMUX (comp->flags))
comp->tcpmux = mktag (address, "tcpmux");
comp->service = grecs_strdup (service);
- comp->privs.user = grecs_strdup (user); /* FIXME: memory leak */
+ comp->privs.user = grecs_strdup (user);
if (group)
{
comp->privs.groups = grecs_list_create ();
@@ -306,9 +306,6 @@ inetd_conf_file (const char *file)
comp->argv = grecs_calloc (comp->argc + 1, sizeof (comp->argv[0]));
comp->argv[0] = grecs_strdup (comp->program);
}
-
- if (progman_lookup_component (comp->tag) == NULL)
- register_prog (comp);
}
if (wsflags & WRDSF_REUSE)
@@ -380,7 +377,7 @@ inetd_conf_dir (const char *name)
}
int
-inetd_parse_conf (const char *file)
+inetd_config_parse (const char *file)
{
struct stat st;
diff --git a/src/limits.c b/src/limits.c
index a2c8ad9..7387b9d 100644
--- a/src/limits.c
+++ b/src/limits.c
@@ -304,4 +304,13 @@ free_limits (limits_record_t rec)
free (rec);
}
-
+int
+limits_cmp (limits_record_t a, limits_record_t b)
+{
+ if (!a)
+ return !!b;
+ else if (!b)
+ return 1;
+ return memcmp (a, b, sizeof (*a));
+}
+
diff --git a/src/pies.c b/src/pies.c
index 4a9ac9e..d3a9096 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -33,12 +33,13 @@ int init_process;
enum pies_command
{
COM_START,
- COM_RESTART,
+ COM_RESTART_COMPONENT,
COM_RELOAD,
COM_STATUS,
COM_STOP,
- COM_DUMP_PREREQ,
- COM_DUMP_DEPMAP
+ COM_DUMP_DEPMAP,
+ COM_TRACE_PREREQ,
+ COM_TRACE_DEPEND
};
enum pies_command command;
@@ -63,43 +64,42 @@ char *default_control_url[2] = {
DEFAULT_INIT_CONTROL_URL
};
-struct config_file
+struct config_syntax
{
- enum config_syntax syntax;
- char *name;
+ const char *name;
+ int (*parser) (char const *);
};
-struct grecs_list *config_list;
+static int pies_config_parse (char const *);
-struct config_syntax_descr
-{
- const char *name;
- enum config_syntax type;
+static struct config_syntax config_syntax_tab[] = {
+ [CONF_PIES] = { "pies" , pies_config_parse },
+ [CONF_META1] = { "meta1", meta1_config_parse },
+ [CONF_INETD] = { "inetd", inetd_config_parse },
+ [CONF_INITTAB] = { "inittab", inittab_parse },
};
-static struct config_syntax_descr config_syntax_tab[] = {
- { "pies" , CONF_PIES },
- { "meta1", CONF_META1 },
- { "inetd", CONF_INETD },
- { "inittab", CONF_INITTAB },
- { NULL }
+struct config_file
+{
+ struct config_syntax *syntax;
+ char *name;
};
-int
-str_to_config_syntax (const char *str, enum config_syntax *psynt)
+struct grecs_list *config_list;
+
+struct config_syntax *
+str_to_config_syntax (const char *str)
{
- struct config_syntax_descr *p;
- for (p = config_syntax_tab; p->name; p++)
- if (strcmp (p->name, str) == 0)
- {
- *psynt = p->type;
- return 0;
- }
- return 1;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE (config_syntax_tab); i++)
+ if (strcmp (config_syntax_tab[i].name, str) == 0)
+ return &config_syntax_tab[i];
+ return NULL;
}
void
-add_config (enum config_syntax syntax, const char *name)
+config_file_add (struct config_syntax *syntax, const char *name)
{
struct config_file *file = grecs_malloc (sizeof (file[0]));
file->syntax = syntax;
@@ -108,6 +108,12 @@ add_config (enum config_syntax syntax, const char *name)
config_list = grecs_list_create ();
grecs_list_append (config_list, file);
}
+
+void
+config_file_add_type (enum config_syntax_type syntax, const char *name)
+{
+ config_file_add (&config_syntax_tab[syntax], name);
+}
/* Logging */
static int
@@ -152,26 +158,26 @@ struct grecs_keyword return_code_keywords[] = {
N_("Specifies action to take when a component finishes with this "
"return code."),
grecs_type_string, GRECS_DFLT,
- NULL, offsetof (struct component, act_temp.act),
+ NULL, offsetof (struct action, act),
_cb_action,
},
{"notify",
N_("arg: emails"),
N_("Notify this address when a component terminates."),
grecs_type_string, GRECS_DFLT,
- NULL, offsetof (struct component, act_temp.addr)
+ NULL, offsetof (struct action, addr)
},
{"message",
NULL,
N_("Notification message text (with headers)."),
grecs_type_string, GRECS_DFLT,
- NULL, offsetof (struct component, act_temp.message),
+ NULL, offsetof (struct action, message),
NULL},
{"exec",
NULL,
N_("Execute this command."),
grecs_type_string, GRECS_DFLT,
- NULL, offsetof (struct component, act_temp.command),
+ NULL, offsetof (struct action, command),
NULL,
},
{NULL}
@@ -260,7 +266,7 @@ static struct tokendef sig_tokendef[] = {
#undef S
void
-free_action (struct action *act)
+action_free (struct action *act)
{
if (!act)
return;
@@ -273,11 +279,17 @@ free_action (struct action *act)
free (act);
}
+static void
+free_entry_action (void *act)
+{
+ action_free (act);
+}
+
static struct action *
create_action (struct component *comp,
- grecs_locus_t *locus,
- grecs_value_t *val, int argc,
- const char *(*getarg) (grecs_value_t *, int, grecs_locus_t *))
+ grecs_locus_t *locus,
+ grecs_value_t *val, int argc,
+ const char *(*getarg) (grecs_value_t *, int, grecs_locus_t *))
{
int i;
unsigned *retv;
@@ -348,11 +360,12 @@ create_action (struct component *comp,
act->nstat = retc;
act->status = retv;
}
- if (comp->act_tail)
- comp->act_tail->next = act;
- else
- comp->act_head = act;
- comp->act_tail = act;
+ if (!comp->act_list)
+ {
+ comp->act_list = grecs_list_create ();
+ comp->act_list->free_entry = free_entry_action;
+ }
+ grecs_list_append (comp->act_list, act);
return act;
}
@@ -423,18 +436,12 @@ return_code_section_parser (enum grecs_callback_command cmd,
count = grecs_list_size (value->v.list);
act = create_action (comp, locus, value, count, _get_list_arg);
}
- *(struct component **) cb_data = comp;
if (!act)
return 1;
- memset (&comp->act_temp, 0, sizeof (comp->act_temp));
+ *(struct action **) cb_data = act;
break;
case grecs_callback_section_end:
- act = comp->act_tail;
- act->act = comp->act_temp.act;
- act->addr = comp->act_temp.addr;
- act->message = comp->act_temp.message;
- act->command = comp->act_temp.command;
break;
case grecs_callback_set_value:
@@ -919,12 +926,12 @@ _cb_runlevels (enum grecs_callback_command cmd,
for (p = value->v.string; *p; p++)
{
if (!is_valid_runlevel (*p))
- {
- grecs_error (locus, 0, _("not a valid runlevel: %c"), *p);
- return 1;
- }
+ {
+ grecs_error (locus, 0, _("not a valid runlevel: %c"), *p);
+ return 1;
+ }
}
- *sptr = grecs_strdup(value->v.string);
+ *sptr = grecs_strdup (value->v.string);
for (p = *sptr; *p; p++)
*p = toupper (*p);
return 0;
@@ -1172,265 +1179,6 @@ find_component_keyword (const char *ident)
return NULL;
}
-static char *
-make_full_name (const char *dir, const char *file)
-{
- char *p;
- size_t len = strlen (dir);
-
- while (len > 0 && dir[len - 1] == '/')
- len--;
- p = grecs_malloc (len + 1 + strlen (file) + 1);
- memcpy (p, dir, len);
- p[len++] = '/';
- strcpy (p + len, file);
- return p;
-}
-
-static int
-component_verify (struct component *comp, grecs_locus_t *locus)
-{
- int header = 0;
- int i;
-#define COMPERR(func, fmt, arg) \
- do \
- { \
- if (!header) \
- { \
- grecs_warning (locus, 0, _("in component %s:"), comp->tag); \
- header = 1; \
- } \
- func (locus, 0, fmt, arg); \
- } \
- while (0)
-
- if (comp->flags & CF_INTERNAL)
- {
- comp->mode = pies_comp_inetd;
- if (!comp->service)
- /* TRANSLATORS: do not translate quoted words, they are keywords. */
- COMPERR (grecs_error,
- "%s", _("`internal' used without `service'"));
- else
- {
- comp->builtin = inetd_builtin_lookup (comp->service,
- comp->socket_type);
- if (!comp->builtin)
- COMPERR (grecs_error,
- "%s", _("unknown internal service"));
- if (comp->argv)
- /* TRANSLATORS: do not translate quoted words, they are
- keywords. */
- COMPERR (grecs_error,
- "%s", _("`internal' used with `command'"));
- }
- }
- else if (!comp->argv)
- COMPERR (grecs_error,
- "%s", _("missing command line"));
-
- if (ISCF_TCPMUX (comp->flags))
- {
- comp->mode = pies_comp_inetd;
- if ((comp->flags & (CF_TCPMUX | CF_TCPMUXPLUS))
- == (CF_TCPMUX | CF_TCPMUXPLUS))
- COMPERR (grecs_error,
- "%s", _("both `tcpmux' and `tcpmuxplus' used"));
- else if (!comp->service)
- /* TRANSLATORS: do not translate quoted words, they are keywords. */
- COMPERR (grecs_error,
- "%s", _("`internal' used without `service'"));
- }
-
- if (comp->pass_fd_socket && comp->mode != pies_comp_pass_fd)
- COMPERR (grecs_error,
- "%s", _("pass-fd-socket ignored: wrong mode"));
- switch (comp->mode)
- {
- case pies_comp_exec:
- if (comp->socket_url)
- COMPERR (grecs_error,
- "%s", _("socket ignored: wrong mode"));
- break;
-
- case pies_comp_pass_fd:
- if (!comp->pass_fd_socket)
- COMPERR (grecs_error,
- "%s", _("must supply pass-fd-socket in this mode"));
- else if (comp->pass_fd_socket[0] != '/')
- {
- if (comp->dir)
- {
- char *p = make_full_name (comp->dir, comp->pass_fd_socket);
- /*free (comp->pass_fd_socket);*/
- comp->pass_fd_socket = p;
- }
- else
- COMPERR (grecs_error,
- "%s", _("pass-fd-socket must be an absolute "
- "file name or chdir must be specified"));
- }
- /* Fall through */
-
- case pies_comp_accept:
- if (!comp->socket_url)
- {
- COMPERR (grecs_error,
- "%s", _("socket must be specified in this mode"));
- return 1;
- }
- break;
-
- case pies_comp_inetd:
- if (ISCF_TCPMUX (comp->flags))
- {
- pies_url_destroy (&comp->socket_url);
- if (!comp->tcpmux)
- {
- COMPERR (grecs_warning,
- "%s",
- _("TCPMUX master not specified, assuming \"tcpmux\""));
- comp->tcpmux = grecs_strdup ("tcpmux");
- }
- }
- else if (comp->tcpmux)
- {
- comp->flags |= CF_TCPMUX;
- pies_url_destroy (&comp->socket_url);
- }
- else if (!comp->socket_url)
- {
- COMPERR (grecs_error,
- "%s", _("socket must be specified in this mode"));
- return 1;
- }
- default:
- /* FIXME: more checks perhaps */
- break;
- }
-
- if (comp->mode == pies_comp_inetd)
- {
- if ((comp->flags & CF_WAIT) && comp->socket_type == SOCK_STREAM)
- {
- if (comp->max_instances)
- COMPERR (grecs_error, "%s", _("max-instances ignored"));
- else
- comp->max_instances = 1;
- }
- }
- else if (comp->flags & CF_WAIT)
- {
- /* TRANSLATORS: `wait' is a keywords, do not translate. */
- COMPERR (grecs_error, "%s", _("wait is useless in this mode"));
- comp->flags &= ~CF_WAIT;
- }
-
- if (comp->mode != pies_comp_exec
- && comp->redir[RETR_OUT].type != redir_null)
- {
- COMPERR (grecs_error,
- "%s", _("stdout translation invalid in this mode"));
- comp->redir[RETR_OUT].type = redir_null;
- }
-
- for (i = RETR_OUT; i <= RETR_ERR; i++)
- {
- if (comp->redir[i].type == redir_file
- && comp->redir[i].v.file[0] != '/')
- {
- if (comp->dir)
- {
- char *p = make_full_name (comp->dir, comp->redir[i].v.file);
- free (comp->redir[i].v.file);
- comp->redir[i].v.file = p;
- }
- else
- COMPERR (grecs_error,
- _("%s: must be an absolute "
- "file name or chdir must be specified"),
- comp->redir[i].v.file);
- }
- }
-
- return header;
-#undef COMPERR
-}
-
-struct component *
-component_create (const char *name)
-{
- struct component *comp = progman_lookup_component (name);
- if (!comp)
- {
- comp = grecs_zalloc (sizeof (*comp));
- comp->facility = log_facility;
- comp->redir[RETR_OUT].type = comp->redir[RETR_ERR].type = redir_null;
- comp->tag = grecs_strdup (name);
- comp->socket_type = SOCK_STREAM;
- }
- return comp;
-}
-
-void
-component_free (struct component *comp)
-{
- size_t i;
-
- free (comp->tag);
- free (comp->program);
- if (comp->argv)
- {
- for (i = 0; i < comp->argc; i++)
- free (comp->argv[i]);
- free (comp->argv);
- }
- if (comp->env)
- {
- for (i = 0; comp->env[i]; i++)
- free (comp->env[i]);
- free (comp->env);
- }
- free (comp->dir);
- grecs_list_free (comp->prereq);
- grecs_list_free (comp->depend);
- free (comp->rmfile);
- free_limits (comp->limits);
- free (comp->runlevels);
- free (comp->service);
- pies_url_destroy (&comp->socket_url);
- free (comp->pass_fd_socket);
- free (comp->tcpmux);
- free (comp->access_denied_message);
- free (comp->max_instances_message);
- free (comp->max_ip_connections_message);
- free_redirector (&comp->redir[0]);
- free_redirector (&comp->redir[1]);
- if (comp->act_head)
- {
- struct action *act;
-
- for (act = comp->act_head; act; act = act->next)
- free_action (act);
- }
-
- free (comp);
-}
-
-void
-component_finish (struct component *comp, grecs_locus_t *locus)
-{
- if (component_verify (comp, locus) == 0)
- {
- /* FIXME: The prog list is traversed twice for each component
- statement, this is suboptimal. */
- if (progman_lookup_component (comp->tag) == NULL)
- register_prog (comp);
- }
- else
- component_free (comp);
-}
-
static int
component_section_parser (enum grecs_callback_command cmd,
grecs_locus_t *locus,
@@ -1543,7 +1291,7 @@ _cb_include_inetd (enum grecs_callback_command cmd,
{
if (assert_grecs_value_type (locus, value, GRECS_TYPE_STRING))
return 1;
- return inetd_parse_conf (value->v.string);
+ return inetd_config_parse (value->v.string);
}
struct grecs_keyword pies_keywords[] = {
@@ -1722,24 +1470,14 @@ config_init ()
#endif
}
-static void
-config_error ()
-{
- if (!init_process)
- exit (EX_CONFIG);
-}
-
-void
-config_parse (char const *name)
+int
+pies_config_parse (char const *name)
{
struct grecs_node *node;
struct grecs_node *tree = grecs_parse (name);
if (!tree)
- {
- config_error ();
- return;
- }
+ return 1;
for (node = tree; node; node = node->next)
{
@@ -1750,9 +1488,11 @@ config_parse (char const *name)
}
if (grecs_tree_process (tree, pies_keywords))
- config_error ();
+ return 1;
grecs_tree_free (tree);
+
+ return 0;
}
void
@@ -1767,7 +1507,42 @@ config_help ()
pies_config_identity_mechanisms_help ();
}
-static enum config_syntax current_syntax = CONF_PIES;
+int
+pies_read_config (void)
+{
+ struct grecs_list_entry *ep;
+ int err = 0;
+
+ component_config_begin ();
+
+ for (ep = config_list->head; ep; ep = ep->next)
+ {
+ struct config_file *file = ep->data;
+ if (file->syntax->parser (file->name))
+ ++err;
+ }
+
+ if (err)
+ component_config_rollback ();
+
+ return err;
+}
+
+int
+pies_reload (void)
+{
+ int rc = pies_read_config ();
+ if (rc == 0)
+ {
+ component_config_commit ();
+ progman_create_sockets ();
+ progman_start ();
+ }
+
+ return rc;
+}
+
+static struct config_syntax *current_syntax = &config_syntax_tab[CONF_PIES];
#include "cmdline.h"
@@ -1796,12 +1571,17 @@ sig_handler (int sig)
case SIGINT:
case SIGTERM:
case SIGQUIT:
- action = ACTION_STOP;
logmsg (LOG_NOTICE, "received signal %d", sig);
+ action = ACTION_STOP;
break;
case SIGHUP:
logmsg (LOG_NOTICE, "received signal %d", sig);
+ action = ACTION_RELOAD;
+ break;
+
+ case SIGUSR1:
+ logmsg (LOG_NOTICE, "received signal %d", sig);
action = ACTION_RESTART;
break;
@@ -1836,6 +1616,7 @@ static int default_sigv[] = {
SIGQUIT,
SIGINT,
SIGHUP,
+ SIGUSR1,
SIGALRM,
SIGPIPE
};
@@ -1934,7 +1715,7 @@ pies_check_status (pid_t *ppid)
#define pies_control_url() control.url->string
-void
+int
request_restart_components (size_t cc, char **cv)
{
char **argv;
@@ -1949,7 +1730,7 @@ request_restart_components (size_t cc, char **cv)
argv[3 + i] = NULL;
execvp (argv[0], argv);
logmsg (LOG_ERR, "can't run piesctl: %s", strerror (errno));
- exit (EX_OSFILE);
+ return EX_OSFILE;
}
void
@@ -1969,7 +1750,7 @@ list_components (void)
int
-pies_reload ()
+request_reload ()
{
pid_t pid = pidfile_read (1);
@@ -1984,7 +1765,7 @@ pies_reload ()
}
int
-pies_status ()
+request_status ()
{
pid_t pid;
@@ -2014,7 +1795,7 @@ pies_status ()
}
int
-pies_stop ()
+request_stop ()
{
pid_t pid = pidfile_read (1);
@@ -2119,7 +1900,7 @@ set_conf_file_names (const char *base)
if (!config_list)
{
char *name = mkfilename (SYSCONFDIR, base, ".conf");
- add_config (current_syntax, name);
+ config_file_add (current_syntax, name);
free (name);
}
}
@@ -2196,8 +1977,9 @@ main (int argc, char **argv)
{
char *inittab = strtok (emu, ":");
char *piesinit = strtok (NULL, ":");
- add_config (CONF_INITTAB, inittab);
- add_config (CONF_PIES, piesinit ? piesinit : "/etc/pies.init");
+ config_file_add_type (CONF_INITTAB, inittab);
+ config_file_add_type (CONF_PIES,
+ piesinit ? piesinit : "/etc/pies.init");
init_fifo = getenv ("INIT_FIFO");
if (!init_fifo)
@@ -2205,12 +1987,12 @@ main (int argc, char **argv)
}
else
{
- add_config (CONF_INITTAB, "/etc/inittab");
- add_config (CONF_PIES, "/etc/pies.init");
+ config_file_add_type (CONF_INITTAB, "/etc/inittab");
+ config_file_add_type (CONF_PIES, "/etc/pies.init");
}
#else
- add_config (CONF_INITTAB, "/etc/inittab");
- add_config (CONF_PIES, "/etc/pies.init");
+ config_file_add_type (CONF_INITTAB, "/etc/inittab");
+ config_file_add_type (CONF_PIES, "/etc/pies.init");
#endif
for (index = 1; index < argc; index++)
{
@@ -2256,47 +2038,24 @@ main (int argc, char **argv)
}
exit (0);
}
- else
- for (ep = config_list->head; ep; ep = ep->next)
- {
- struct config_file *file = ep->data;
+ else if (pies_read_config ())
+ exit (EX_CONFIG);
- switch (file->syntax)
- {
- case CONF_PIES:
- config_parse (file->name);
- break;
-
- case CONF_INETD:
- if (inetd_parse_conf (file->name))
- config_error ();
- break;
-
- case CONF_META1:
- if (meta1_config_parse (file->name))
- config_error ();
- break;
-
- case CONF_INITTAB:
- if (inittab_parse (file->name))
- config_error ();
- break;
- }
- }
+ component_config_commit ();
set_state_file_names (instance);
set_mailer_argcv ();
if (lint_mode)
- {
- progman_build_depmap ();
- exit (0);
- }
+ exit (0);
/* Re-setup logging: it might have been reset in the config file */
diag_setup (log_to_stderr_only ? DIAG_TO_STDERR : 0);
- if (argc != index && command != COM_RESTART)
+ if (argc != index
+ && !(command == COM_RESTART_COMPONENT
+ || command == COM_TRACE_DEPEND
+ || command == COM_TRACE_PREREQ))
{
logmsg (LOG_ERR, "extra command line arguments");
exit (EX_CONFIG);
@@ -2314,32 +2073,35 @@ main (int argc, char **argv)
}
}
- progman_build_depmap ();
switch (command)
{
- case COM_RESTART:
+ case COM_RESTART_COMPONENT:
pies_priv_setup (&pies_privs);
if (pies_umask)
umask (pies_umask);
- request_restart_components (argc - index, argv + index);
+ exit (request_restart_components (argc - index, argv + index));
case COM_RELOAD:
- exit (pies_reload ());
+ exit (request_reload ());
case COM_STATUS:
- exit (pies_status ());
+ exit (request_status ());
case COM_STOP:
- exit (pies_stop ());
-
- case COM_DUMP_PREREQ:
- progman_dump_prereq ();
- exit (0);
+ exit (request_stop ());
case COM_DUMP_DEPMAP:
- progman_dump_depmap ();
+ components_dump_depmap ();
exit (0);
+ case COM_TRACE_DEPEND:
+ components_trace (argv + index, depmap_row);
+ exit (0);
+
+ case COM_TRACE_PREREQ:
+ components_trace (argv + index, depmap_col);
+ exit (0);
+
default:
pies_priv_setup (&pies_privs);
if (pies_umask)
@@ -2398,7 +2160,7 @@ main (int argc, char **argv)
if (argv[0][0] != '/')
logmsg (LOG_NOTICE,
_("not started as an absolute pathname; "
- "SIGHUP will not work"));
+ "restart will not work"));
signal_setup (sig_handler);
@@ -2424,6 +2186,11 @@ main (int argc, char **argv)
}
break;
+ case ACTION_RELOAD:
+ pies_reload ();
+ action = ACTION_CONT;
+ break;
+
case ACTION_STOP:
if (init_process)
{
diff --git a/src/pies.h b/src/pies.h
index e0d24d2..ad8e8ee 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -98,7 +98,6 @@ enum return_action
struct action
{
- struct action *next;
size_t nstat;
unsigned *status;
enum return_action act; /* Action to take when the component terminates */
@@ -202,8 +201,16 @@ enum pies_comp_mode
#define ISCF_TCPMUX(f) ((f) & (CF_TCPMUX | CF_TCPMUXPLUS))
+struct prog;
+
struct component
{
+ struct component *prev, *next; /* Components form doubly-linked list. */
+ int listidx; /* Index of the list. */
+ size_t arridx; /* Index of this component. */
+ size_t ref_count; /* Reference count. */
+ struct prog *prog; /* Prog associated with this component. */
+
enum pies_comp_mode mode;
char *tag; /* Entry tag (for diagnostics purposes) */
char *program; /* Program name */
@@ -217,7 +224,7 @@ struct component
size_t max_instances; /* Maximum number of simultaneously running
instances */
char *rmfile; /* Try to remove this file before starting */
- struct pies_privs privs; /* UID/GIDS+groups to run under */
+ struct pies_privs privs; /* UID/GIDS+groups to run as */
mode_t umask; /* Umask to install before starting */
limits_record_t limits; /* System limits */
@@ -249,8 +256,7 @@ struct component
int facility; /* Syslog facility. */
struct redirector redir[2]; /* Repeaters for stdout and stderr */
/* Actions to execute on various exit codes: */
- struct action *act_head, *act_tail;
- struct action act_temp; /* Auxiliary object used during configuration */
+ struct grecs_list *act_list;
/* ACLs for control interface */
pies_acl_t list_acl; /* List access control list */
pies_acl_t adm_acl; /* Administrative ACL (stop, start, etc.) */
@@ -262,6 +268,7 @@ enum pies_action {
ACTION_CONT,
ACTION_STOP,
ACTION_RESTART,
+ ACTION_RELOAD,
ACTION_CTRLALTDEL,
ACTION_KBREQUEST
};
@@ -289,7 +296,7 @@ extern size_t pies_master_argc;
extern char **pies_master_argv;
extern char *default_control_url[2];
-enum config_syntax
+enum config_syntax_type
{
CONF_PIES,
CONF_META1,
@@ -297,12 +304,16 @@ enum config_syntax
CONF_INITTAB
};
-int str_to_config_syntax (const char *str, enum config_syntax *psynt);
-void add_config (enum config_syntax syntax, const char *name);
+struct config_syntax;
+
+struct config_syntax *str_to_config_syntax (const char *str);
+void config_file_add (struct config_syntax *syntax, const char *name);
+void config_file_add_type (enum config_syntax_type syntax, const char *name);
void free_redirector (struct redirector *rp);
void pies_schedule_action (int act);
+void free_action (struct action *act);
void register_prog (struct component *comp);
int progman_running_p (void);
@@ -313,11 +324,10 @@ void progman_stop (void);
void progman_cleanup (int expect_term);
void progman_filter (int (*filter) (struct component *, void *data),
void *data);
+int progman_wait_until (int (*cond) (void *), void *data);
void progman_stop_tag (const char *name);
-void progman_dump_prereq (void);
-void progman_dump_depmap (void);
int progman_accept (int socket, void *data);
-int progman_build_depmap (void);
+
void progman_create_sockets (void);
struct component *progman_lookup_component (const char *tag);
struct component *progman_lookup_tcpmux (const char *service,
@@ -351,6 +361,11 @@ pies_depmap_t depmap_alloc (size_t count);
pies_depmap_t depmap_copy (pies_depmap_t dpm);
void depmap_set (pies_depmap_t dmap, size_t row, size_t col);
int depmap_isset (pies_depmap_t dmap, size_t row, size_t col);
+void depmap_clear (pies_depmap_t dmap, size_t row, size_t col);
+
+void depmap_clear_all (pies_depmap_t dmap, enum pies_depmap_direction dir,
+ size_t coord);
+
void depmap_tc (pies_depmap_t dmap);
size_t depmap_first (pies_depmap_t dmap, enum pies_depmap_direction dir,
size_t coord, pies_depmap_pos_t *ppos);
@@ -365,10 +380,25 @@ int socket_type_to_str (int socket_type, const char **pres);
struct component *component_create (const char *name);
void component_free (struct component *comp);
+void component_ref_incr (struct component *comp);
+void component_ref_decr (struct component *comp);
+
+void component_config_begin (void);
+void component_config_rollback (void);
+void component_config_commit (void);
+
+int component_is_active (struct component *comp);
void component_finish (struct component *comp, grecs_locus_t *locus);
struct grecs_keyword *find_component_keyword (const char *ident);
+void components_dump_depmap (void);
+void components_trace (char **argv, enum pies_depmap_direction dir);
+
+struct component *component_depmap_first (enum pies_depmap_direction dir,
+ size_t idx, pies_depmap_pos_t *ppos);
+struct component *component_depmap_next (pies_depmap_pos_t pos);
+
void pies_pause (void);
@@ -401,6 +431,7 @@ void enable_socket (int fd);
int parse_limits (limits_record_t *plrec, char *str, char **endp);
int set_limits (const char *name, limits_record_t lrec);
void free_limits (limits_record_t rec);
+int limits_cmp (limits_record_t a, limits_record_t b);
void meta1_parser_set_debug (void);
@@ -451,9 +482,13 @@ int switch_to_privs (uid_t uid, gid_t gid, struct grecs_list *retain_groups);
void pies_priv_setup (struct pies_privs *);
void pies_epriv_setup (struct pies_privs *);
+
+int pies_privs_cmp (struct pies_privs const *a, struct pies_privs const *b);
+void pies_privs_free (struct pies_privs *p);
+
/* inetd.c */
-int inetd_parse_conf (const char *file);
+int inetd_config_parse (const char *file);
/* inetd-bi.c */
struct inetd_builtin
diff --git a/src/prog.h b/src/prog.h
index 6590d4e..a29de04 100644
--- a/src/prog.h
+++ b/src/prog.h
@@ -46,8 +46,6 @@ struct prog
struct prog *next, *prev;
enum prog_type type;
pid_t pid; /* PID */
- char *tag; /* Entry tag (for diagnostics purposes) */
- char **prereq;
int facility;
union
{
@@ -60,7 +58,6 @@ struct prog
time_t timestamp; /* Time of last startup */
size_t failcount; /* Number of failed starts since timestamp */
enum prog_status status; /* Current component status */
- char *runlevels;
/* If status == status_listener: */
size_t num_instances; /* Number of running instances */
/* If comp->type == pies_comp_inetd && status == status_enabled */
@@ -72,11 +69,13 @@ struct prog
struct
{
+ char *tag;
struct prog *master;
} r;
struct
{
+ char *tag;
char *command;
} c;
} v;
@@ -88,3 +87,5 @@ struct prog *progman_locate (const char *name);
void progman_foreach (int (*filter) (struct prog *, void *data), void *data);
void prog_stop (struct prog *prog, int sig);
void progman_stop_component (struct prog *prog);
+
+char const *prog_tag (struct prog const *prog);
diff --git a/src/progman.c b/src/progman.c
index 0079149..4f63d9a 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -17,9 +17,7 @@
#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;
@@ -29,7 +27,7 @@ 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;
}
@@ -73,7 +71,7 @@ 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;
}
@@ -95,7 +93,7 @@ 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;
}
@@ -129,6 +127,23 @@ prog_lookup_by_idx (unsigned idx)
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)
{
@@ -158,6 +173,7 @@ void
unlink_prog (struct prog *pp)
{
struct prog *x;
+
if ((x = pp->prev))
x->next = pp->next;
else
@@ -172,28 +188,35 @@ 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;
}
@@ -203,10 +226,11 @@ 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;
}
@@ -214,21 +238,13 @@ 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;
}
@@ -248,17 +264,15 @@ update_redir (int type, struct prog *master, pid_t 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;
@@ -269,13 +283,14 @@ register_prog0 (struct component *comp, unsigned index)
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
@@ -283,66 +298,12 @@ 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 ()
{
@@ -473,7 +434,7 @@ open_redirector (struct prog *master, int stream)
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);
@@ -482,12 +443,12 @@ open_redirector (struct prog *master, int stream)
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];
@@ -956,7 +917,7 @@ check_spawn_rate (struct prog *prog)
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;
@@ -973,7 +934,7 @@ check_connection_rate (struct prog *prog)
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;
@@ -1011,7 +972,7 @@ prog_start_prologue (struct prog *prog)
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 ?
@@ -1025,7 +986,7 @@ prog_start_prologue (struct prog *prog)
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);
@@ -1057,7 +1018,7 @@ prog_execute (struct prog *prog)
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);
}
@@ -1066,7 +1027,7 @@ 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;
@@ -1093,7 +1054,7 @@ prog_start (struct prog *prog)
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;
@@ -1147,14 +1108,14 @@ prog_start (struct prog *prog)
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)
@@ -1259,7 +1220,7 @@ prog_start (struct prog *prog)
case -1:
logmsg (LOG_CRIT,
_("cannot run `%s': fork failed: %s"),
- prog->tag, strerror (errno));
+ prog_tag (prog), strerror (errno));
break;
default:
@@ -1279,7 +1240,7 @@ prog_start (struct prog *prog)
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]);
@@ -1287,7 +1248,8 @@ prog_start (struct prog *prog)
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));
}
}
@@ -1361,7 +1323,7 @@ _prog_accept (struct prog *p)
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);
}
@@ -1379,14 +1341,14 @@ _prog_accept (struct prog *p)
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)
{
@@ -1394,7 +1356,7 @@ _prog_accept (struct prog *p)
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);
@@ -1413,7 +1375,7 @@ _prog_accept (struct prog *p)
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;
@@ -1432,18 +1394,18 @@ _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);
@@ -1465,164 +1427,6 @@ progman_accept (int socket, void *data)
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 ()
@@ -1634,7 +1438,8 @@ progman_create_sockets ()
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,
@@ -1725,7 +1530,7 @@ check_stopping (struct prog *prog, time_t now)
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
@@ -1790,23 +1595,28 @@ progman_wake_sleeping (int onalrm)
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)
@@ -1825,18 +1635,20 @@ prog_start_prerequisites (struct prog *prog)
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;
}
@@ -1852,21 +1664,21 @@ prog_stop_redirectors (struct prog *prog)
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);
@@ -1888,7 +1700,7 @@ prog_stop (struct prog *prog, int sig)
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
@@ -1908,15 +1720,15 @@ prog_stop_all (int sig)
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);
}
@@ -1924,14 +1736,20 @@ progman_wait ()
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);
}
}
@@ -2337,7 +2155,7 @@ run_command (struct action *act, struct prog *prog, unsigned retcode,
/* 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);
@@ -2365,60 +2183,67 @@ 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);
}
@@ -2441,7 +2266,7 @@ progman_cleanup (int expect_term)
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;
@@ -2461,41 +2286,58 @@ progman_cleanup (int expect_term)
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_PROC_STOP, "", prog->tag, pid, "");
+ if (prog->v.p.comp->mode >= pies_mark_sysvinit)
+ {
+ sysvinit_acct (SYSV_ACCT_PROC_STOP, "", prog_tag (prog),
+ pid, "");
+ prog->v.p.status = status_finished;
+ }
+ else
+ {
+ if (is_sysvinit (prog->v.p.comp))
+ sysvinit_acct (SYSV_ACCT_PROC_STOP, "",
+ prog_tag (prog), pid, "");
- prog->v.p.status = (prog->v.p.comp->flags & CF_DISABLED)
+ prog->v.p.status =
+ (prog->v.p.comp->flags & CF_DISABLED)
? status_disabled : status_enabled;
- prog_stop_dependents (prog);
- if (!expect_term)
- react (prog, status, pid);
+ prog_stop_dependents (prog);
+ if (!expect_term)
+ react (prog, status, pid);
+ }
+
+ if (!component_is_active (prog->v.p.comp))
+ destroy_prog (&prog);
}
+
break;
case TYPE_REDIRECTOR:
/* It was a redirector of an already finished process. */
- print_status (prog->tag, pid, status,
+ print_status (prog_tag (prog), pid, status,
expect_term ||
(prog->v.r.master &&
prog->v.r.master->v.p.status == status_stopping));
debug (1, (_("removing redirector %s, pid=%lu"),
- prog->tag, (unsigned long)pid));
+ prog_tag (prog), (unsigned long)pid));
destroy_prog (&prog);
break;
case TYPE_COMMAND:
- print_status (prog->tag, pid, status, expect_term);
+ print_status (prog_tag (prog), pid, status, expect_term);
destroy_prog (&prog);
break;
}
@@ -2515,27 +2357,27 @@ progman_stop_component (struct prog *prog)
{
case status_enabled:
case status_listener:
- logmsg (LOG_INFO, _("stopping component `%s'"), prog->tag);
+ logmsg (LOG_INFO, _("stopping component `%s'"), prog_tag (prog));
prog_stop (prog, SIGTERM);
break;
case status_disabled:
if (!(prog->v.p.comp->flags & CF_DISABLED))
{
- logmsg (LOG_INFO, _("enabling component `%s'"), prog->tag);
+ logmsg (LOG_INFO, _("enabling component `%s'"), prog_tag (prog));
prog->v.p.status = status_enabled;
}
break;
case status_sleeping:
- logmsg (LOG_INFO, _("waking up component `%s'"), prog->tag);
+ logmsg (LOG_INFO, _("waking up component `%s'"), prog_tag (prog));
prog->v.p.failcount = 0;
break;
default:
logmsg (LOG_INFO,
_("stopping component `%s': component not started"),
- prog->tag);
+ prog_tag (prog));
}
}
}
diff --git a/src/sysvinit.c b/src/sysvinit.c
index 375a0d5..a4e0d63 100644
--- a/src/sysvinit.c
+++ b/src/sysvinit.c
@@ -1,5 +1,5 @@
/* This file is part of GNU Pies.
- Copyright (C) 2013 Sergey Poznyakoff
+ Copyright (C) 2013-2016 Sergey Poznyakoff
GNU Pies is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -279,7 +279,7 @@ runlevel_setup_prog (struct prog *prog, void *data)
prog->v.p.status = status_enabled;
else
prog->v.p.status = status_disabled;
- debug (1, ("%s: %s", prog->tag,
+ debug (1, ("%s: %s", prog_tag (prog),
prog->v.p.status == status_enabled ?
"enabled" : "disabled"));
}
@@ -876,16 +876,17 @@ inittab_parse (const char *file)
{
if (ws.ws_wordc >= 5)
{
- enum config_syntax synt;
+ struct config_syntax *synt =
+ str_to_config_syntax (ws.ws_wordv[3]);
- if (str_to_config_syntax (ws.ws_wordv[3], &synt))
+ if (!synt)
logmsg (LOG_ERR, "%s:%u: %s",
file, line_no, _("unknown syntax type"));
else
- add_config (synt, ws.ws_wordv[4]);
+ config_file_add (synt, ws.ws_wordv[4]);
}
else if (ws.ws_wordc == 4)
- add_config (CONF_PIES, ws.ws_wordv[3]);
+ config_file_add_type (CONF_PIES, ws.ws_wordv[3]);
}
else if (strcmp (ws.ws_wordv[2], "stop") == 0)
{
@@ -933,27 +934,9 @@ inittab_parse (const char *file)
continue;
}
- comp = calloc (1, sizeof (*comp));
- if (!comp)
- {
- logmsg (LOG_ERR, "%s:%u: %s", file, line_no,
- _("not enough memory"));
- err = 1;
- continue;
- }
-
+ comp = component_create (id);
comp->mode = ap->mode;
- comp->tag = strdup (id);
- comp->runlevels = strdup (runlevels);
-
- if (!comp->tag || !comp->runlevels)
- {
- component_free (comp);
- logmsg (LOG_ERR, "%s:%u: %s", file, line_no,
- _("not enough memory"));
- err = 1;
- continue;
- }
+ comp->runlevels = grecs_strdup (runlevels);
if (wordsplit (process, &ws, WRDSF_DEFFLAGS))
{
@@ -963,11 +946,8 @@ inittab_parse (const char *file)
err = 1;
continue;
}
- comp->argc = ws.ws_wordc;
- comp->argv = ws.ws_wordv;
- comp->program = strdup (ws.ws_wordv[0]);
- ws.ws_wordc = 0;
- ws.ws_wordv = NULL;
+ wordsplit_getwords (&ws, &comp->argc, &comp->argv);
+ comp->program = grecs_strdup (comp->argv[0]);
wordsplit_free (&ws);
comp->flags |= CF_SIGGROUP;
@@ -978,7 +958,6 @@ inittab_parse (const char *file)
err = 1;
continue;
}
- register_prog (comp);
}
free (buf);
diff --git a/src/userprivs.c b/src/userprivs.c
index 646421e..9f9724f 100644
--- a/src/userprivs.c
+++ b/src/userprivs.c
@@ -250,3 +250,26 @@ pies_epriv_setup (struct pies_privs *privs)
exit (EX_USAGE);
}
}
+
+int
+pies_privs_cmp (struct pies_privs const *a, struct pies_privs const *b)
+{
+ if (!a)
+ return !!b;
+ else if (!b)
+ return 1;
+ if (safe_strcmp (a->user, b->user))
+ return 1;
+ if (a->allgroups != b->allgroups)
+ return 1;
+ return grecs_list_compare (a->groups, b->groups);
+}
+
+void
+pies_privs_free (struct pies_privs *p)
+{
+ grecs_free (p->user);
+ grecs_list_free (p->groups);
+}
+
+

Return to:

Send suggestions and report system problems to the System administrator.