aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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 (