diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-08-23 08:36:01 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-08-25 22:29:47 +0300 |
commit | a60dcd92df15705bb84f644c99fd166e101dc681 (patch) | |
tree | 883906dc48ff03ca96a0b63ef8ee28dc10bcb150 | |
parent | 6f39bd7e00acee689ce9a8a3916888a815242557 (diff) | |
download | direvent-a60dcd92df15705bb84f644c99fd166e101dc681.tar.gz direvent-a60dcd92df15705bb84f644c99fd166e101dc681.tar.bz2 |
Further modify struct handler.
Instead of accomodating two types of functionality, the new struct handler
has a pointer to the function that is responsible for handling the event,
and a pointer to data for that function (closure). Additionally, a
pointer to deallocator function is also provided.
Existing functionality is reimplemented using this new struct. New
types of handlers can easily be added.
* src/config.c (eventconf)<ev_mask,fpat,prog_handler>: New members
<handler>: Remove.
All uses changed.
* src/direvent.h (filpatlist_t)
(event_handler_fn, handler_free_fn): New data types.
(handler): Remove union and type. Add two pointer to functions
that are to implement the functionality (run and free) and a pointer
to data for them.
(prog_handler): New struct.
(prog_handler_alloc,prog_handler_free)
(prog_handler_envrealloc)
(watchpoint_run_handlers): New protos.
(run_handler,filename_pattern_free)
(filename_pattern_match): Remove
(filpatlist_add, filpatlist_add_exact)
(filpatlist_destroy, filpatlist_match): New protos.
* src/ev_inotify.c (process_event): Use watchpoint_run_handlers
* src/ev_kqueue.c: Likewise.
* src/fnpat.c: Major rewrite.
* src/handler.c (handler_copy)
(handler_envrealloc,handler_add_pattern)
(handler_add_exact_filename): Remove
(handler_alloc): Change arguments.
(watchpoint_run_handlers): New function.
* src/progman.c (prog_handler_alloc)
(prog_handler_envrealloc): New functions.
* src/watcher.c: Reimplement sentinel watchers.
-rw-r--r-- | src/config.c | 141 | ||||
-rw-r--r-- | src/direvent.h | 89 | ||||
-rw-r--r-- | src/ev_inotify.c | 40 | ||||
-rw-r--r-- | src/ev_kqueue.c | 10 | ||||
-rw-r--r-- | src/fnpat.c | 111 | ||||
-rw-r--r-- | src/handler.c | 90 | ||||
-rw-r--r-- | src/progman.c | 133 | ||||
-rw-r--r-- | src/watcher.c | 69 |
8 files changed, 370 insertions, 313 deletions
diff --git a/src/config.c b/src/config.c index 1f8d26e..6ad3016 100644 --- a/src/config.c +++ b/src/config.c @@ -150,3 +150,5 @@ struct eventconf { struct grecs_list *pathlist; - struct handler handler; + event_mask ev_mask; + filpatlist_t fpat; + struct prog_handler prog_handler; }; @@ -158,5 +160,4 @@ eventconf_init(void) { - memset(&eventconf, 0, sizeof eventconf); - eventconf.handler.type = HANDLER_EXTERN; - eventconf.handler.prog_timeout = DEFAULT_TIMEOUT; + memset(&eventconf, 0, sizeof eventconf); + eventconf.prog_handler.timeout = DEFAULT_TIMEOUT; } @@ -167,3 +168,4 @@ eventconf_free(void) grecs_list_free(eventconf.pathlist); - handler_free(&eventconf.handler); + prog_handler_free(&eventconf.prog_handler); + filpatlist_destroy(&eventconf.fpat); } @@ -174,4 +176,6 @@ eventconf_flush(grecs_locus_t *loc) struct grecs_list_entry *ep; - struct handler *hp = handler_copy(&eventconf.handler); - + struct handler *hp = prog_handler_alloc(eventconf.ev_mask, + eventconf.fpat, + &eventconf.prog_handler); + for (ep = eventconf.pathlist->head; ep; ep = ep->next) { @@ -210,3 +214,3 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node, } - if (!eventconf.handler.prog_command) { + if (!eventconf.prog_handler.command) { grecs_error(&node->locus, 0, @@ -215,4 +219,4 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node, } - if (evtnullp(&eventconf.handler.ev_mask)) - evtsetall(&eventconf.handler.ev_mask); + if (evtnullp(&eventconf.ev_mask)) + evtsetall(&eventconf.ev_mask); if (err == 0) @@ -461,5 +465,5 @@ cb_user(enum grecs_callback_command cmd, grecs_node_t *node, - eventconf.handler.prog_uid = pw->pw_uid; + eventconf.prog_handler.uid = pw->pw_uid; get_user_groups(uv->v.string, gid, - &eventconf.handler.prog_gidc, &eventconf.handler.prog_gidv); + &eventconf.prog_handler.gidc, &eventconf.prog_handler.gidv); @@ -486,11 +490,11 @@ cb_option(enum grecs_callback_command cmd, grecs_node_t *node, if (strcmp(vp->v.string, "nowait") == 0) - eventconf.handler.prog_flags |= HF_NOWAIT; + eventconf.prog_handler.flags |= HF_NOWAIT; else if (strcmp(vp->v.string, "wait") == 0) - eventconf.handler.prog_flags &= ~HF_NOWAIT; + eventconf.prog_handler.flags &= ~HF_NOWAIT; else if (strcmp(vp->v.string, "stdout") == 0) - eventconf.handler.prog_flags |= HF_STDOUT; + eventconf.prog_handler.flags |= HF_STDOUT; else if (strcmp(vp->v.string, "stderr") == 0) - eventconf.handler.prog_flags |= HF_STDERR; + eventconf.prog_handler.flags |= HF_STDERR; else if (strcmp(vp->v.string, "shell") == 0) - eventconf.handler.prog_flags |= HF_SHELL; + eventconf.prog_handler.flags |= HF_SHELL; else @@ -516,5 +520,5 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, return 1; - i = handler_envrealloc(&eventconf.handler, 1); - eventconf.handler.prog_env[i] = estrdup(val->v.string); - eventconf.handler.prog_env[i+1] = NULL; + i = prog_handler_envrealloc(&eventconf.prog_handler, 1); + eventconf.prog_handler.env[i] = estrdup(val->v.string); + eventconf.prog_handler.env[i+1] = NULL; break; @@ -522,3 +526,3 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, case GRECS_TYPE_ARRAY: - j = handler_envrealloc(&eventconf.handler, val->v.arg.c); + j = prog_handler_envrealloc(&eventconf.prog_handler, val->v.arg.c); for (i = 0; i < val->v.arg.c; i++, j++) { @@ -528,5 +532,5 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, return 1; - eventconf.handler.prog_env[j] = estrdup(val->v.arg.v[i]->v.string); + eventconf.prog_handler.env[j] = estrdup(val->v.arg.v[i]->v.string); } - eventconf.handler.prog_env[j] = NULL; + eventconf.prog_handler.env[j] = NULL; break; @@ -534,3 +538,4 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, case GRECS_TYPE_LIST: - j = handler_envrealloc(&eventconf.handler, val->v.list->count); + j = prog_handler_envrealloc(&eventconf.prog_handler, + val->v.list->count); for (ep = val->v.list->head; ep; ep = ep->next, j++) { @@ -540,5 +545,5 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, return 1; - eventconf.handler.prog_env[j] = estrdup(vp->v.string); + eventconf.prog_handler.env[j] = estrdup(vp->v.string); } - eventconf.handler.prog_env[j] = NULL; + eventconf.prog_handler.env[j] = NULL; } @@ -548,71 +553,7 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node, static int -is_glob(char const *str) +file_name_pattern(filpatlist_t *fptr, grecs_value_t *val) { - return strcspn(str, "[]*?") < strlen(str); -} - -static int -file_name_pattern(struct handler *handler, grecs_value_t *val) -{ - char *arg; - int rc; - int flags = REG_EXTENDED|REG_NOSUB; - struct filename_pattern *pat; - if (assert_grecs_value_type(&val->locus, val, GRECS_TYPE_STRING)) return 1; - arg = val->v.string; - - pat = emalloc(sizeof(*pat)); - if (*arg == '!') { - pat->neg = 1; - ++arg; - } else - pat->neg = 0; - if (arg[0] == '/') { - char *q, *p; - - pat->type = PAT_REGEX; - - p = strchr(arg+1, '/'); - if (!p) { - grecs_error(&val->locus, 0, _("unterminated regexp")); - free(pat); - return 1; - } - for (q = p + 1; *q; q++) { - switch (*q) { - case 'b': - flags &= ~REG_EXTENDED; - break; - case 'i': - flags |= REG_ICASE; - break; - default: - grecs_error(&val->locus, 0, - _("unrecognized flag: %c"), *q); - free(pat); - return 1; - } - } - - *p = 0; - rc = regcomp(&pat->v.re, arg + 1, flags); - *p = '/'; - - if (rc) { - char errbuf[128]; - regerror(rc, &pat->v.re, errbuf, sizeof(errbuf)); - grecs_error(&val->locus, 0, "%s", errbuf); - filename_pattern_free(pat); - return 1; - } - } else { - pat->type = is_glob(arg) ? PAT_GLOB : PAT_EXACT; - pat->v.glob = estrdup(arg); - } - - handler_add_pattern(handler, pat); - - return 0; + return filpatlist_add(fptr, val->v.string, &val->locus); } @@ -624,3 +565,3 @@ cb_file_pattern(enum grecs_callback_command cmd, grecs_node_t *node, grecs_value_t *val = node->v.value; - struct handler *handler = varptr; + filpatlist_t *fpat = varptr; struct grecs_list_entry *ep; @@ -632,3 +573,3 @@ cb_file_pattern(enum grecs_callback_command cmd, grecs_node_t *node, case GRECS_TYPE_STRING: - file_name_pattern(handler, val); + file_name_pattern(fpat, val); break; @@ -637,3 +578,3 @@ cb_file_pattern(enum grecs_callback_command cmd, grecs_node_t *node, for (i = 0; i < val->v.arg.c; i++) - if (file_name_pattern(handler, val->v.arg.v[i])) + if (file_name_pattern(fpat, val->v.arg.v[i])) break; @@ -643,3 +584,3 @@ cb_file_pattern(enum grecs_callback_command cmd, grecs_node_t *node, for (ep = val->v.list->head; ep; ep = ep->next) - if (file_name_pattern(handler, + if (file_name_pattern(fpat, (grecs_value_t *) ep->data)) @@ -657,9 +598,9 @@ static struct grecs_keyword watcher_kw[] = { { "event", NULL, N_("Events to watch for"), - grecs_type_string, GRECS_LIST, &eventconf.handler.ev_mask, 0, + grecs_type_string, GRECS_LIST, &eventconf.ev_mask, 0, cb_eventlist }, { "file", N_("regexp"), N_("Files to watch for"), - grecs_type_string, GRECS_LIST, &eventconf.handler, 0, + grecs_type_string, GRECS_LIST, &eventconf.fpat, 0, cb_file_pattern }, { "command", NULL, N_("Command to execute on event"), - grecs_type_string, GRECS_DFLT, &eventconf.handler.prog_command }, + grecs_type_string, GRECS_DFLT, &eventconf.prog_handler.command }, { "user", N_("name"), N_("Run command as this user"), @@ -668,3 +609,3 @@ static struct grecs_keyword watcher_kw[] = { { "timeout", N_("seconds"), N_("Timeout for the command"), - grecs_type_uint, GRECS_DFLT, &eventconf.handler.prog_timeout }, + grecs_type_uint, GRECS_DFLT, &eventconf.prog_handler.timeout }, { "option", NULL, N_("List of additional options"), diff --git a/src/direvent.h b/src/direvent.h index faa1657..d69fa34 100644 --- a/src/direvent.h +++ b/src/direvent.h @@ -74,6 +74,12 @@ struct filename_pattern { -enum handler_type { - HANDLER_EXTERN, - HANDLER_SENTINEL -}; +typedef struct filpatlist *filpatlist_t; + +struct watchpoint; + +typedef int (*event_handler_fn) (struct watchpoint *wp, + event_mask *event, + const char *dir, + const char *file, + void *data); +typedef void (*handler_free_fn) (void *data); @@ -81,29 +87,8 @@ enum handler_type { struct handler { - size_t refcnt; /* Reference counter */ - event_mask ev_mask; /* Event mask */ - struct grecs_list *fnames; /* File name patterns */ - enum handler_type type; - union { - struct { - int flags; /* Handler flags */ - char *command; /* Handler command (with eventual - arguments) */ - 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; /* Handler timeout */ - char **env; /* Environment */ - } prog; - struct { - struct watchpoint *watchpoint; - } sentinel; - } v; -#define prog_flags v.prog.flags -#define prog_command v.prog.command -#define prog_uid v.prog.uid -#define prog_gidv v.prog.gidv -#define prog_gidc v.prog.gidc -#define prog_timeout v.prog.timeout -#define prog_env v.prog.env -#define sentinel_watchpoint v.sentinel.watchpoint + size_t refcnt; /* Reference counter */ + event_mask ev_mask; /* Event mask */ + filpatlist_t fnames; /* File name patterns */ + event_handler_fn run; + handler_free_fn free; + void *data; }; @@ -135,12 +120,23 @@ struct watchpoint { #define handler_matches_event(h,m,f,n) \ - (((h)->ev_mask.__cat2__(m,_mask) & (f)) && \ - filename_pattern_match((h)->fnames, n) == 0) + (((h)->ev_mask.__cat2__(m,_mask) & (f)) && \ + filpatlist_match((h)->fnames, n) == 0) -struct handler *handler_alloc(enum handler_type type); +struct handler *handler_alloc(event_mask ev_mask); void handler_free(struct handler *hp); -struct handler *handler_copy(struct handler *orig); -size_t handler_envrealloc(struct handler *hp, size_t count); - -void handler_add_pattern(struct handler *hp, struct filename_pattern *pat); -void handler_add_exact_filename(struct handler *hp, const char *filename); + +struct prog_handler { + int flags; /* Handler flags */ + char *command; /* Handler command (with eventual arguments) */ + 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; /* Handler timeout */ + char **env; /* Environment */ +}; + +struct handler *prog_handler_alloc(event_mask ev_mask, filpatlist_t fpat, + struct prog_handler *p); +void prog_handler_free(struct prog_handler *); +size_t prog_handler_envrealloc(struct prog_handler *hp, size_t count); + @@ -250,2 +246,6 @@ int watchpoint_pattern_match(struct watchpoint *dwp, const char *file_name); +void watchpoint_run_handlers(struct watchpoint *wp, int evflags, + const char *dirname, const char *filename); + + void setup_watchers(void); @@ -259,3 +259,3 @@ void watchpoint_suspend(struct watchpoint *dwp); void watchpoint_destroy(struct watchpoint *dwp); -struct watchpoint *watchpoint_install_sentinel(struct watchpoint *dwp); +int watchpoint_install_sentinel(struct watchpoint *dwp); @@ -294,4 +294,2 @@ void process_cleanup(int expect_term); void process_timeouts(void); -int run_handler(struct watchpoint *dp, struct handler *hp, event_mask *event, - const char *dir, const char *file); char **environ_setup(char **hint, char **kve); @@ -310,4 +308,7 @@ int sigv_set_action_tab(int sigc, struct sigtab *sigtab, struct sigaction *sa); -void filename_pattern_free(void *p); -int filename_pattern_match(struct grecs_list *lp, const char *name); +struct grecs_locus; +int filpatlist_add(filpatlist_t *fptr, char const *arg, struct grecs_locus *loc); +void filpatlist_add_exact(filpatlist_t *fptr, char const *arg); +void filpatlist_destroy(filpatlist_t *fptr); +int filpatlist_match(filpatlist_t fp, const char *name); diff --git a/src/ev_inotify.c b/src/ev_inotify.c index 7b2ee1d..d79b5f0 100644 --- a/src/ev_inotify.c +++ b/src/ev_inotify.c @@ -160,10 +160,7 @@ process_event(struct inotify_event *ep) { - struct watchpoint *dp; - struct handler *h; - handler_iterator_t itr; - event_mask m; + struct watchpoint *wpt; char *dirname, *filename; - dp = wpget(ep->wd); - if (!dp) { + wpt = wpget(ep->wd); + if (!wpt) { if (!(ep->mask & IN_IGNORED)) @@ -175,4 +172,4 @@ process_event(struct inotify_event *ep) if (ep->mask & IN_IGNORED) { - diag(LOG_NOTICE, _("%s deleted"), dp->dirname); - watchpoint_suspend(dp); + diag(LOG_NOTICE, _("%s deleted"), wpt->dirname); + watchpoint_suspend(wpt); return; @@ -191,3 +188,3 @@ process_event(struct inotify_event *ep) return; - } else if (!dp) { + } else if (!wpt) { if (ep->name) @@ -201,7 +198,7 @@ process_event(struct inotify_event *ep) - ev_log(ep->mask, dp); + ev_log(ep->mask, wpt); if (ep->mask & IN_CREATE) { - debug(1, ("%s/%s created", dp->dirname, ep->name)); - if (check_new_watcher(dp->dirname, ep->name) > 0) + debug(1, ("%s/%s created", wpt->dirname, ep->name)); + if (check_new_watcher(wpt->dirname, ep->name) > 0) return; @@ -210,18 +207,15 @@ process_event(struct inotify_event *ep) if (ep->len == 0) - filename = split_pathname(dp, &dirname); + filename = split_pathname(wpt, &dirname); else { - dirname = dp->dirname; + dirname = wpt->dirname; filename = ep->name; } - for_each_handler(dp, itr, h) { - if (handler_matches_event(h, sys, ep->mask, filename)) - run_handler(dp, h, - event_mask_init(&m, ep->mask, &h->ev_mask), - dirname, filename); - } - unsplit_pathname(dp); + + watchpoint_run_handlers(wpt, ep->mask, dirname, filename); + + unsplit_pathname(wpt); if (ep->mask & (IN_DELETE|IN_MOVED_FROM)) { - debug(1, ("%s/%s deleted", dp->dirname, ep->name)); - remove_watcher(dp->dirname, ep->name); + debug(1, ("%s/%s deleted", wpt->dirname, ep->name)); + remove_watcher(wpt->dirname, ep->name); } diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index 680fb42..a002182 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -208,9 +208,5 @@ process_event(struct kevent *ep) filename = split_pathname(dp, &dirname); - for_each_handler(dp, itr, h) { - if (handler_matches_event(h, sys, ep->fflags, filename)) { - run_handler(dp, h, - event_mask_init(&m, ep->fflags, &h->ev_mask), - dirname, filename); - } - } + + watchpoint_run_handlers(dp, ep->fflags, dirname, filename); + unsplit_pathname(dp); diff --git a/src/fnpat.c b/src/fnpat.c index 775a558..5a98053 100644 --- a/src/fnpat.c +++ b/src/fnpat.c @@ -20,3 +20,3 @@ -void +static void filename_pattern_free(void *p) @@ -35,4 +35,107 @@ filename_pattern_free(void *p) +struct filpatlist { + grecs_list_ptr_t list; +}; + +static int +is_glob(char const *str) +{ + return strcspn(str, "[]*?") < strlen(str); +} + +void +filpatlist_add_pattern(filpatlist_t *fptr, struct filename_pattern *pat) +{ + grecs_list_ptr_t list; + if (!*fptr) { + *fptr = emalloc(sizeof(*fptr)); + (*fptr)->list = grecs_list_create(); + (*fptr)->list->free_entry = filename_pattern_free; + } + list = (*fptr)->list; + grecs_list_append(list, pat); +} + +void +filpatlist_add_exact(filpatlist_t *fptr, char const *arg) +{ + struct filename_pattern *pat = emalloc(sizeof(*pat)); + + pat->neg = 0; + pat->type = PAT_EXACT; + pat->v.glob = estrdup(arg); + filpatlist_add_pattern(fptr, pat); +} + +int +filpatlist_add(filpatlist_t *fptr, char const *arg, grecs_locus_t *loc) +{ + int flags = REG_EXTENDED|REG_NOSUB; + struct filename_pattern *pat; + + pat = emalloc(sizeof(*pat)); + if (*arg == '!') { + pat->neg = 1; + ++arg; + } else + pat->neg = 0; + if (arg[0] == '/') { + int rc; + char *q, *p; + + pat->type = PAT_REGEX; + + p = strchr(arg+1, '/'); + if (!p) { + grecs_error(loc, 0, _("unterminated regexp")); + free(pat); + return 1; + } + for (q = p + 1; *q; q++) { + switch (*q) { + case 'b': + flags &= ~REG_EXTENDED; + break; + case 'i': + flags |= REG_ICASE; + break; + default: + grecs_error(loc, 0, + _("unrecognized flag: %c"), *q); + free(pat); + return 1; + } + } + + *p = 0; + rc = regcomp(&pat->v.re, arg + 1, flags); + *p = '/'; + + if (rc) { + char errbuf[128]; + regerror(rc, &pat->v.re, errbuf, sizeof(errbuf)); + grecs_error(loc, 0, "%s", errbuf); + filename_pattern_free(pat); + return 1; + } + } else { + pat->type = is_glob(arg) ? PAT_GLOB : PAT_EXACT; + pat->v.glob = estrdup(arg); + } + filpatlist_add_pattern(fptr, pat); + return 0; +} + +void +filpatlist_destroy(filpatlist_t *fptr) +{ + if (fptr && *fptr) { + grecs_list_free((*fptr)->list); + free(*fptr); + *fptr = NULL; + } +} + int -filename_pattern_match(struct grecs_list *lp, const char *name) +filpatlist_match(filpatlist_t fp, const char *name) { @@ -40,5 +143,5 @@ filename_pattern_match(struct grecs_list *lp, const char *name) - if (!lp) + if (!fp || !fp->list) return 0; - for (ep = lp->head; ep; ep = ep->next) { + for (ep = fp->list->head; ep; ep = ep->next) { struct filename_pattern *pat = ep->data; diff --git a/src/handler.c b/src/handler.c index 2d27824..f016829 100644 --- a/src/handler.c +++ b/src/handler.c @@ -20,61 +20,23 @@ struct handler * -handler_alloc(enum handler_type type) +handler_alloc(event_mask ev_mask) { struct handler *hp = ecalloc(1, sizeof(*hp)); - hp->type = type; hp->refcnt = 0; + hp->ev_mask = ev_mask; return hp; } - -struct handler * -handler_copy(struct handler *orig) -{ - struct handler *hp = emalloc(sizeof(*hp)); - *hp = *orig; - hp->refcnt = 0; - return hp; -} - -/* Reallocate environment of handler HP to accomodate COUNT more - entries (not bytes) plus a final NULL entry. - - Return offset of the first unused entry. -*/ -size_t -handler_envrealloc(struct handler *hp, size_t count) -{ - size_t i; - - if (!hp->prog_env) { - hp->prog_env = ecalloc(count + 1, sizeof(hp->prog_env[0])); - i = 0; - } else { - for (i = 0; hp->prog_env[i]; i++) - ; - hp->prog_env = erealloc(hp->prog_env, - (i + count + 1) * sizeof(hp->prog_env[0])); - memset(hp->prog_env + i, 0, (count + 1) * sizeof(hp->prog_env[0])); - } - return i; -} - + void -handler_add_pattern(struct handler *hp, struct filename_pattern *pat) +watchpoint_run_handlers(struct watchpoint *wp, int evflags, + const char *dirname, const char *filename) { - if (!hp->fnames) { - hp->fnames = grecs_list_create(); - hp->fnames->free_entry = filename_pattern_free; - } - grecs_list_append(hp->fnames, pat); -} + handler_iterator_t itr; + struct handler *hp; + event_mask m; -void -handler_add_exact_filename(struct handler *hp, const char *filename) -{ - struct filename_pattern *pat; - pat = emalloc(sizeof(*pat)); - pat->neg = 0; - pat->type = PAT_EXACT; - pat->v.glob = estrdup(filename); - handler_add_pattern(hp, pat); + for_each_handler(wp, itr, hp) { + if (handler_matches_event(hp, sys, evflags, filename)) + hp->run(wp, event_mask_init(&m, evflags, &hp->ev_mask), + dirname, filename, hp->data); + } } @@ -87,14 +49,2 @@ handler_ref(struct handler *hp) -static void -envfree(char **env) -{ - int i; - - if (!env) - return; - for (i = 0; env[i]; i++) - free(env[i]); - free(env); -} - void @@ -102,12 +52,5 @@ handler_free(struct handler *hp) { - grecs_list_free(hp->fnames); - switch (hp->type) { - case HANDLER_EXTERN: - free(hp->prog_command); - free(hp->prog_gidv); - envfree(hp->prog_env); - break; - case HANDLER_SENTINEL: - watchpoint_unref(hp->sentinel_watchpoint); - } + filpatlist_destroy(&hp->fnames); + if (hp->free) + hp->free(hp->data); } @@ -288 +231,2 @@ handler_list_remove(handler_list_t hlist, struct handler *hp) } + diff --git a/src/progman.c b/src/progman.c index 134deaf..10b014a 100644 --- a/src/progman.c +++ b/src/progman.c @@ -248,8 +248,8 @@ process_timeouts() int -switchpriv(struct handler *hp) +switchpriv(struct prog_handler *hp) { - if (hp->prog_uid == 0 || hp->prog_uid == getuid()) + if (hp->uid == 0 || hp->uid == getuid()) return 0; - if (setgroups(hp->prog_gidc, hp->prog_gidv) < 0) { + if (setgroups(hp->gidc, hp->gidv) < 0) { diag(LOG_CRIT, "setgroups: %s", @@ -258,6 +258,6 @@ switchpriv(struct handler *hp) } - if (setregid(hp->prog_gidv[0], hp->prog_gidv[0]) < 0) { + if (setregid(hp->gidv[0], hp->gidv[0]) < 0) { diag(LOG_CRIT, "setregid(%lu,%lu): %s", - (unsigned long) hp->prog_gidv[0], - (unsigned long) hp->prog_gidv[0], + (unsigned long) hp->gidv[0], + (unsigned long) hp->gidv[0], strerror(errno)); @@ -265,6 +265,6 @@ switchpriv(struct handler *hp) } - if (setreuid(hp->prog_uid, hp->prog_uid) < 0) { + if (setreuid(hp->uid, hp->uid) < 0) { diag(LOG_CRIT, "setreuid(%lu,%lu): %s", - (unsigned long) hp->prog_uid, - (unsigned long) hp->prog_uid, + (unsigned long) hp->uid, + (unsigned long) hp->uid, strerror(errno)); @@ -442,4 +442,4 @@ runcmd(const char *cmd, char **envhint, event_mask *event, const char *file, static int -run_handler_prog(struct handler *hp, event_mask *event, - const char *dirname, const char *file) +prog_handler_run(struct watchpoint *wp, event_mask *event, + const char *dirname, const char *file, void *data) { @@ -449,12 +449,14 @@ run_handler_prog(struct handler *hp, event_mask *event, struct process *p; + struct prog_handler *hp = data; - if (!hp->prog_command) + if (!hp->command) return 0; - debug(1, (_("starting %s, dir=%s, file=%s"), hp->prog_command, dirname, file)); - if (hp->prog_flags & HF_STDERR) - redir_fd[REDIR_ERR] = open_redirector(hp->prog_command, LOG_ERR, + debug(1, (_("starting %s, dir=%s, file=%s"), + hp->command, dirname, file)); + if (hp->flags & HF_STDERR) + redir_fd[REDIR_ERR] = open_redirector(hp->command, LOG_ERR, &redir_proc[REDIR_ERR]); - if (hp->prog_flags & HF_STDOUT) - redir_fd[REDIR_OUT] = open_redirector(hp->prog_command, LOG_INFO, + if (hp->flags & HF_STDOUT) + redir_fd[REDIR_OUT] = open_redirector(hp->command, LOG_INFO, &redir_proc[REDIR_OUT]); @@ -505,3 +507,3 @@ run_handler_prog(struct handler *hp, event_mask *event, signal_setup(SIG_DFL); - runcmd(hp->prog_command, hp->prog_env, event, file, hp->prog_flags & HF_SHELL); + runcmd(hp->command, hp->env, event, file, hp->flags & HF_SHELL); } @@ -510,5 +512,5 @@ run_handler_prog(struct handler *hp, event_mask *event, debug(1, (_("%s running; dir=%s, file=%s, pid=%lu"), - hp->prog_command, dirname, file, (unsigned long)pid)); + hp->command, dirname, file, (unsigned long)pid)); - p = register_process(PROC_HANDLER, pid, time(NULL), hp->prog_timeout); + p = register_process(PROC_HANDLER, pid, time(NULL), hp->timeout); @@ -516,3 +518,3 @@ run_handler_prog(struct handler *hp, event_mask *event, redir_proc[REDIR_OUT]->v.master = p; - redir_proc[REDIR_OUT]->timeout = hp->prog_timeout; + redir_proc[REDIR_OUT]->timeout = hp->timeout; } @@ -520,3 +522,3 @@ run_handler_prog(struct handler *hp, event_mask *event, redir_proc[REDIR_ERR]->v.master = p; - redir_proc[REDIR_ERR]->timeout = hp->prog_timeout; + redir_proc[REDIR_ERR]->timeout = hp->timeout; } @@ -527,3 +529,3 @@ run_handler_prog(struct handler *hp, event_mask *event, - if (hp->prog_flags & HF_NOWAIT) { + if (hp->flags & HF_NOWAIT) { return 0; @@ -532,3 +534,3 @@ run_handler_prog(struct handler *hp, event_mask *event, debug(1, (_("waiting for %s (%lu) to terminate"), - hp->prog_command, (unsigned long)pid)); + hp->command, (unsigned long)pid)); while (time(NULL) - p->start < 2 * p->timeout) { @@ -542,28 +544,71 @@ run_handler_prog(struct handler *hp, event_mask *event, -static int -run_sentinel(struct watchpoint *dp, struct handler *hp) +static void +envfree(char **env) { - watchpoint_init(hp->sentinel_watchpoint); - watchpoint_install_ptr(hp->sentinel_watchpoint); - handler_list_remove(dp->handler_list, hp); - return 0; + int i; + + if (!env) + return; + for (i = 0; env[i]; i++) + free(env[i]); + free(env); } -int -run_handler(struct watchpoint *dp, struct handler *hp, event_mask *event, - const char *dirname, const char *file) +void +prog_handler_free(struct prog_handler *hp) { - int rc; - switch (hp->type) { - case HANDLER_EXTERN: - rc = run_handler_prog(hp, event, dirname, file); - break; - case HANDLER_SENTINEL: - rc = run_sentinel(dp, hp); - break; - default: - abort(); + free(hp->command); + free(hp->gidv); + envfree(hp->env); +} + +static void +prog_handler_free_data(void *ptr) +{ + prog_handler_free((struct prog_handler *)ptr); +} + +struct handler * +prog_handler_alloc(event_mask ev_mask, filpatlist_t fpat, + struct prog_handler *p) +{ + struct handler *hp = handler_alloc(ev_mask); + struct prog_handler *mem; + + hp->fnames = fpat; + hp->run = prog_handler_run; + hp->free = prog_handler_free_data; + mem = emalloc(sizeof(*mem)); + *mem = *p; + hp->data = mem; + memset(p, 0, sizeof(*p)); + return hp; +} + +/* Reallocate environment of handler HP to accomodate COUNT more + entries (not bytes) plus a final NULL entry. + + Return offset of the first unused entry. +*/ +size_t +prog_handler_envrealloc(struct prog_handler *hp, size_t count) +{ + 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 rc; + return i; } + + + + diff --git a/src/watcher.c b/src/watcher.c index e0b4950..7ac3d86 100644 --- a/src/watcher.c +++ b/src/watcher.c @@ -189,4 +189,3 @@ watchpoint_suspend(struct watchpoint *wpt) { - struct watchpoint *sent = watchpoint_install_sentinel(wpt); - watchpoint_init(sent);//FIXME: error checking + watchpoint_install_sentinel(wpt);//FIXME: error checking watchpoint_destroy(wpt); @@ -216,3 +215,3 @@ convert_watcher(struct watchpoint *wpt) for_each_handler(wpt, itr, hp) - handler_add_exact_filename(hp, filename); + filpatlist_add_exact(&hp->fnames, filename); @@ -227,4 +226,29 @@ convert_watcher(struct watchpoint *wpt) } + +struct sentinel { + struct handler *hp; + struct watchpoint *watchpoint; +}; -struct watchpoint * +static int +sentinel_handler_run(struct watchpoint *wp, event_mask *event, + const char *dirname, const char *file, void *data) +{ + struct sentinel *sentinel = data; + + watchpoint_init(sentinel->watchpoint); + watchpoint_install_ptr(sentinel->watchpoint); + handler_list_remove(wp->handler_list, sentinel->hp); + return 0; +} + +static void +sentinel_handler_free(void *ptr) +{ + struct sentinel *sentinel = ptr; + watchpoint_unref(sentinel->watchpoint); + free(sentinel); +} + +int watchpoint_install_sentinel(struct watchpoint *wpt) @@ -235,2 +259,4 @@ watchpoint_install_sentinel(struct watchpoint *wpt) struct handler *hp; + event_mask ev_mask; + struct sentinel *sentinel; @@ -238,7 +264,16 @@ watchpoint_install_sentinel(struct watchpoint *wpt) sent = watchpoint_install(dirname, NULL); - hp = handler_alloc(HANDLER_SENTINEL); - getevt("CREATE", &hp->ev_mask); - hp->sentinel_watchpoint = wpt; + + getevt("CREATE", &ev_mask); + hp = handler_alloc(ev_mask); + hp->run = sentinel_handler_run; + hp->free = sentinel_handler_free; + + sentinel = emalloc(sizeof(*sentinel)); + sentinel->watchpoint = wpt; + sentinel->hp = hp; watchpoint_ref(wpt); - handler_add_exact_filename(hp, filename); + + hp->data = sentinel; + + filpatlist_add_exact(&hp->fnames, filename); handler_list_append(sent->handler_list, hp); @@ -246,4 +281,3 @@ watchpoint_install_sentinel(struct watchpoint *wpt) diag(LOG_NOTICE, _("installing CREATE sentinel for %s"), wpt->dirname); - watchpoint_init(sent); - return sent; + return watchpoint_init(sent); } @@ -263,4 +297,3 @@ watchpoint_init(struct watchpoint *wpt) if (errno == ENOENT) { - wpt = watchpoint_install_sentinel(wpt); - return 0; + return watchpoint_install_sentinel(wpt); } else { @@ -325,11 +358,11 @@ subwatcher_create(struct watchpoint *parent, const char *dirname, void -deliver_ev_create(struct watchpoint *dp, const char *name) +deliver_ev_create(struct watchpoint *wp, const char *name) { event_mask m = { GENEV_CREATE, 0 }; - struct handler *h; + struct handler *hp; handler_iterator_t itr; - for_each_handler(dp, itr, h) { - if (handler_matches_event(h, gen, GENEV_CREATE, name)) - run_handler(dp, h, &m, dp->dirname, name); + for_each_handler(wp, itr, hp) { + if (handler_matches_event(hp, gen, GENEV_CREATE, name)) + hp->run(wp, &m, wp->dirname, name, hp->data); } @@ -389,3 +422,3 @@ watchpoint_pattern_match(struct watchpoint *wpt, const char *file_name) for_each_handler(wpt, itr, hp) { - if (filename_pattern_match(hp->fnames, file_name) == 0) + if (filpatlist_match(hp->fnames, file_name) == 0) return 0; |