diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/acl.c | 70 | ||||
-rw-r--r-- | src/acl.h | 3 | ||||
-rw-r--r-- | src/cmdline.opt | 22 | ||||
-rw-r--r-- | src/comp.c | 817 | ||||
-rw-r--r-- | src/ctl.c | 4 | ||||
-rw-r--r-- | src/depmap.c | 28 | ||||
-rw-r--r-- | src/inetd.c | 7 | ||||
-rw-r--r-- | src/limits.c | 11 | ||||
-rw-r--r-- | src/pies.c | 535 | ||||
-rw-r--r-- | src/pies.h | 57 | ||||
-rw-r--r-- | src/prog.h | 7 | ||||
-rw-r--r-- | src/progman.c | 538 | ||||
-rw-r--r-- | src/sysvinit.c | 43 | ||||
-rw-r--r-- | src/userprivs.c | 23 |
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\ @@ -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); +} @@ -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, ¤t_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]; +} + + + + + @@ -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 ( |