diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-08-13 11:25:23 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-08-13 11:35:38 +0300 |
commit | d2af4ef108bf21776df4b3acb40ef549158f6f47 (patch) | |
tree | 193f035812adbfe1fbd0c7f149624a2dcd1116df | |
parent | 964e8af04d3c708333077a13ea71750f7d87c952 (diff) | |
download | direvent-d2af4ef108bf21776df4b3acb40ef549158f6f47.tar.gz direvent-d2af4ef108bf21776df4b3acb40ef549158f6f47.tar.bz2 |
Clean-up handler initialization routines.
In particular, this change allows for placing several environ statements
in a single watcher statement. Such environ statements accumulate.
* src/config.c (eventconf): Simplify the structure.
(handler_alloc): Take a pointer to struct handler as
argument.
(handler_envrealloc): New function.
(handler_free): Rename to handler_listent_free. All uses updated.
(handler_free): New function.
(eventconf_flush,cb_option,cb_user): Reflect changes to struct
eventconf
(cb_environ): Likewise. Reallocate env as necessary.
* doc/direvent.texi: Document the change.
* NEWS: Document the changes.
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | doc/direvent.texi | 2 | ||||
-rw-r--r-- | src/config.c | 171 |
3 files changed, 103 insertions, 81 deletions
@@ -1,2 +1,2 @@ -direvent -- history of user-visible changes. 2016-08-12 +direvent -- history of user-visible changes. 2016-08-13 Copyright (C) 2012-2016 Sergey Poznyakoff @@ -8,2 +8,11 @@ Version 5.1.90 (Git) +* Fix watcher removal on BSD-like systems. + +* Configuration changes + +** multiple environ statements + +Multiple environ statements can be used within a single watcher block. +Such statements accumulate. + diff --git a/doc/direvent.texi b/doc/direvent.texi index 91a5921..6781ac5 100644 --- a/doc/direvent.texi +++ b/doc/direvent.texi @@ -1107,2 +1107,4 @@ before assignment. @end table + +Multiple @code{environ} statements accumulate. @end deffn diff --git a/src/config.c b/src/config.c index a54dd79..e98dc0f 100644 --- a/src/config.c +++ b/src/config.c @@ -148,16 +148,16 @@ static struct grecs_keyword syslog_kw[] = { -struct eventconf { - struct grecs_list *pathlist; - event_mask eventmask; - struct grecs_list *fnames; - char *command; - uid_t uid; /* Run as this user (unless 0) */ - gid_t *gidv; /* Run with these groups' privileges */ - size_t gidc; /* Number of elements in gidv */ - unsigned timeout; - int flags; - char **env; -}; +static struct handler * +handler_alloc(struct handler *orig) +{ + struct handler *hp = emalloc(sizeof(*hp)); + *hp = *orig; + hp->refcnt = 0; + return hp; +} -static struct eventconf eventconf; +static void +handler_ref(struct handler *hp) +{ + ++hp->refcnt; +} @@ -175,34 +175,23 @@ envfree(char **env) -static void -eventconf_init() -{ - memset(&eventconf, 0, sizeof eventconf); - eventconf.timeout = DEFAULT_TIMEOUT; -} +/* Reallocate environment of handler HP to accomodate COUNT more + entries (not bytes) plus a final NULL entry. -static void -eventconf_free() + Return offset of the first unused entry. +*/ +static size_t +handler_envrealloc(struct handler *hp, size_t count) { - grecs_list_free(eventconf.pathlist); - grecs_list_free(eventconf.fnames); - free(eventconf.command); - free(eventconf.gidv); - envfree(eventconf.env); -} - -static struct handler * -handler_alloc(struct eventconf const *eventconf) -{ - struct handler *hp = emalloc(sizeof(*hp)); - hp->ev_mask = eventconf->eventmask; - hp->fnames = eventconf->fnames; - hp->flags = eventconf->flags; - hp->timeout = eventconf->timeout; - hp->prog = eventconf->command; - hp->uid = eventconf->uid; - hp->gidc = eventconf->gidc; - hp->gidv = eventconf->gidv; - hp->env = eventconf->env; - hp->refcnt = 0; - return hp; + size_t i; + + if (!hp->env) { + hp->env = ecalloc(count + 1, sizeof(hp->env[0])); + i = 0; + } else { + for (i = 0; hp->env[i]; i++) + ; + hp->env = erealloc(hp->env, + (i + count + 1) * sizeof(hp->env[0])); + memset(hp->env + i, 0, (count + 1) * sizeof(hp->env[0])); + } + return i; } @@ -210,5 +199,8 @@ handler_alloc(struct eventconf const *eventconf) static void -handler_ref(struct handler *hp) +handler_free(struct handler *hp) { - ++hp->refcnt; + grecs_list_free(hp->fnames); + free(hp->prog); + free(hp->gidv); + envfree(hp->env); } @@ -219,6 +211,4 @@ handler_unref(struct handler *hp) if (hp && --hp->refcnt) { - grecs_list_free(hp->fnames); - free(hp->prog); - free(hp->gidv); - envfree(hp->env); + handler_free(hp); + free(hp); } @@ -227,3 +217,3 @@ handler_unref(struct handler *hp) static void -handler_free(void *p) +handler_listent_free(void *p) { @@ -270,3 +260,3 @@ direvent_handler_list_create(void) hlist->list = grecs_list_create(); - hlist->list->free_entry = handler_free; + hlist->list->free_entry = handler_listent_free; hlist->refcnt = 1; @@ -302,2 +292,24 @@ direvent_handler_list_append(direvent_handler_list_t hlist, struct handler *hp) + +struct eventconf { + struct grecs_list *pathlist; + struct handler handler; +}; + +static struct eventconf eventconf; + +static void +eventconf_init(void) +{ + memset(&eventconf, 0, sizeof eventconf); + eventconf.handler.timeout = DEFAULT_TIMEOUT; +} + +static void +eventconf_free(void) +{ + grecs_list_free(eventconf.pathlist); + handler_free(&eventconf.handler); +} + void @@ -306,3 +318,3 @@ eventconf_flush(grecs_locus_t *loc) struct grecs_list_entry *ep; - struct handler *hp = handler_alloc(&eventconf); + struct handler *hp = handler_alloc(&eventconf.handler); @@ -344,3 +356,3 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node, } - if (!eventconf.command) { + if (!eventconf.handler.prog) { grecs_error(&node->locus, 0, @@ -349,4 +361,4 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node, } - if (evtnullp(&eventconf.eventmask)) - evtsetall(&eventconf.eventmask); + if (evtnullp(&eventconf.handler.ev_mask)) + evtsetall(&eventconf.handler.ev_mask); if (err == 0) @@ -595,4 +607,5 @@ cb_user(enum grecs_callback_command cmd, grecs_node_t *node, - eventconf.uid = pw->pw_uid; - get_user_groups(uv->v.string, gid, &eventconf.gidc, &eventconf.gidv); + eventconf.handler.uid = pw->pw_uid; + get_user_groups(uv->v.string, gid, + &eventconf.handler.gidc, &eventconf.handler.gidv); @@ -619,11 +632,11 @@ cb_option(enum grecs_callback_command cmd, grecs_node_t *node, if (strcmp(vp->v.string, "nowait") == 0) - eventconf.flags |= HF_NOWAIT; + eventconf.handler.flags |= HF_NOWAIT; else if (strcmp(vp->v.string, "wait") == 0) - eventconf.flags &= ~HF_NOWAIT; + eventconf.handler.flags &= ~HF_NOWAIT; else if (strcmp(vp->v.string, "stdout") == 0) - eventconf.flags |= HF_STDOUT; + eventconf.handler.flags |= HF_STDOUT; else if (strcmp(vp->v.string, "stderr") == 0) - eventconf.flags |= HF_STDERR; + eventconf.handler.flags |= HF_STDERR; else if (strcmp(vp->v.string, "shell") == 0) - eventconf.flags |= HF_SHELL; + eventconf.handler.flags |= HF_SHELL; else @@ -641,3 +654,3 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, struct grecs_list_entry *ep; - int i; + int i, j; @@ -649,5 +662,5 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, return 1; - eventconf.env = ecalloc(2, sizeof(eventconf.env[0])); - eventconf.env[0] = estrdup(val->v.string); - eventconf.env[1] = NULL; + i = handler_envrealloc(&eventconf.handler, 1); + eventconf.handler.env[i] = estrdup(val->v.string); + eventconf.handler.env[i+1] = NULL; break; @@ -655,5 +668,4 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, case GRECS_TYPE_ARRAY: - eventconf.env = ecalloc(val->v.arg.c + 1, - sizeof(eventconf.env[0])); - for (i = 0; i < val->v.arg.c; i++) { + j = handler_envrealloc(&eventconf.handler, val->v.arg.c); + for (i = 0; i < val->v.arg.c; i++, j++) { if (assert_grecs_value_type(&val->v.arg.v[i]->locus, @@ -662,5 +674,5 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, return 1; - eventconf.env[i] = estrdup(val->v.arg.v[i]->v.string); + eventconf.handler.env[j] = estrdup(val->v.arg.v[i]->v.string); } - eventconf.env[i] = NULL; + eventconf.handler.env[j] = NULL; break; @@ -668,5 +680,4 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, case GRECS_TYPE_LIST: - eventconf.env = ecalloc(val->v.list->count + 1, - sizeof(eventconf.env[0])); - for (i = 0, ep = val->v.list->head; ep; ep = ep->next, i++) { + j = handler_envrealloc(&eventconf.handler, val->v.list->count); + for (ep = val->v.list->head; ep; ep = ep->next, j++) { grecs_value_t *vp = ep->data; @@ -675,5 +686,5 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, return 1; - eventconf.env[i] = estrdup(vp->v.string); + eventconf.handler.env[j] = estrdup(vp->v.string); } - eventconf.env[i] = NULL; + eventconf.handler.env[j] = NULL; } @@ -793,9 +804,9 @@ static struct grecs_keyword watcher_kw[] = { { "event", NULL, N_("Events to watch for"), - grecs_type_string, GRECS_LIST, &eventconf.eventmask, 0, + grecs_type_string, GRECS_LIST, &eventconf.handler.ev_mask, 0, cb_eventlist }, { "file", N_("regexp"), N_("Files to watch for"), - grecs_type_string, GRECS_LIST, &eventconf.fnames, 0, + grecs_type_string, GRECS_LIST, &eventconf.handler.fnames, 0, cb_file_pattern }, { "command", NULL, N_("Command to execute on event"), - grecs_type_string, GRECS_DFLT, &eventconf.command }, + grecs_type_string, GRECS_DFLT, &eventconf.handler.prog }, { "user", N_("name"), N_("Run command as this user"), @@ -804,3 +815,3 @@ static struct grecs_keyword watcher_kw[] = { { "timeout", N_("seconds"), N_("Timeout for the command"), - grecs_type_uint, GRECS_DFLT, &eventconf.timeout }, + grecs_type_uint, GRECS_DFLT, &eventconf.handler.timeout }, { "option", NULL, N_("List of additional options"), |