aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-08-23 08:36:01 +0300
committerSergey Poznyakoff <gray@gnu.org>2016-08-25 22:29:47 +0300
commita60dcd92df15705bb84f644c99fd166e101dc681 (patch)
tree883906dc48ff03ca96a0b63ef8ee28dc10bcb150
parent6f39bd7e00acee689ce9a8a3916888a815242557 (diff)
downloaddirevent-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.c141
-rw-r--r--src/direvent.h89
-rw-r--r--src/ev_inotify.c40
-rw-r--r--src/ev_kqueue.c10
-rw-r--r--src/fnpat.c111
-rw-r--r--src/handler.c90
-rw-r--r--src/progman.c133
-rw-r--r--src/watcher.c69
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;

Return to:

Send suggestions and report system problems to the System administrator.