aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-08-20 12:24:41 +0300
committerSergey Poznyakoff <gray@gnu.org>2016-08-25 22:29:47 +0300
commit46ae038f21a0bb8b8cfe5361df6439cf572ad2cc (patch)
treeeaf78744a9e023fc8e1baadd8d5fff7f4f664cc3
parent4e4bacb23013880c5247ed53e81366f15d2a64ef (diff)
downloaddirevent-46ae038f21a0bb8b8cfe5361df6439cf572ad2cc.tar.gz
direvent-46ae038f21a0bb8b8cfe5361df6439cf572ad2cc.tar.bz2
Initial preparation for having distinct handler types.
* src/direvent.h (pattern_type): New enum, instead of PAT_* defines. (filename_pattern): use enum pattern_type. (handler_type): New enum. (handler): Can be of two types: HANDLER_EXTERN, which handles external programs and is equivalent to the prior content of the structure, and HANDLER_SENTINEL, which is planned to be a built-in handler for configuring watchpoints for newly created directories. All uses changed. (dirwatcher) <refcnt>: Change type to size_t. (handler_alloc,handler_add_pattern) (handler_add_exact_filename): New protos. * src/hashtab.c: Provisions for safe adding and removing from the hashtable when iterating over it. (hashtab) <flags>: Removed. <itr_level, list_new, list_del>: New members. (hashtab_remove): When iterating, place pointer to the removed entry in list_del instead of actually removing it. (hashtab_lookup_or_install): When iterating, add a pointer to the newly created entry to the list_new list, instead of adding it immediately. (hashtab_foreach): Flush list_del and list_new at the end of the topmost iteration. * src/config.c (handler_alloc): Rename to handler_copy (handler_alloc): New function. (handler_free): Two types of handlers. (handler_add_pattern) (handler_add_exact_filename): New functions. (file_name_pattern): Takes struct handler * as its first argument. (cb_file_pattern): Change accordingly. * src/fnpat.c (filename_pattern_free): Handle PAT_EXACT. (filename_pattern_match): Likewise. * src/progman.c (run_handler): Two types of handlers. * src/watcher.c (dirwatcher_install): Restore missing gettext marker. Allocate handler_list. (dirwatcher_init): Convert non-directory watchpoints to directory ones.
-rw-r--r--src/config.c127
-rw-r--r--src/direvent.h58
-rw-r--r--src/fnpat.c4
-rw-r--r--src/hashtab.c124
-rw-r--r--src/progman.c74
-rw-r--r--src/watcher.c89
6 files changed, 378 insertions, 98 deletions
diff --git a/src/config.c b/src/config.c
index e98dc0f..3a4878c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -146,8 +146,17 @@ static struct grecs_keyword syslog_kw[] = {
146 { NULL }, 146 { NULL },
147}; 147};
148 148
149struct handler *
150handler_alloc(enum handler_type type)
151{
152 struct handler *hp = ecalloc(1, sizeof(*hp));
153 hp->type = type;
154 hp->refcnt = 0;
155 return hp;
156}
157
149static struct handler * 158static struct handler *
150handler_alloc(struct handler *orig) 159handler_copy(struct handler *orig)
151{ 160{
152 struct handler *hp = emalloc(sizeof(*hp)); 161 struct handler *hp = emalloc(sizeof(*hp));
153 *hp = *orig; 162 *hp = *orig;
@@ -183,15 +192,15 @@ handler_envrealloc(struct handler *hp, size_t count)
183{ 192{
184 size_t i; 193 size_t i;
185 194
186 if (!hp->env) { 195 if (!hp->prog_env) {
187 hp->env = ecalloc(count + 1, sizeof(hp->env[0])); 196 hp->prog_env = ecalloc(count + 1, sizeof(hp->prog_env[0]));
188 i = 0; 197 i = 0;
189 } else { 198 } else {
190 for (i = 0; hp->env[i]; i++) 199 for (i = 0; hp->prog_env[i]; i++)
191 ; 200 ;
192 hp->env = erealloc(hp->env, 201 hp->prog_env = erealloc(hp->prog_env,
193 (i + count + 1) * sizeof(hp->env[0])); 202 (i + count + 1) * sizeof(hp->prog_env[0]));
194 memset(hp->env + i, 0, (count + 1) * sizeof(hp->env[0])); 203 memset(hp->prog_env + i, 0, (count + 1) * sizeof(hp->prog_env[0]));
195 } 204 }
196 return i; 205 return i;
197} 206}
@@ -200,9 +209,15 @@ static void
200handler_free(struct handler *hp) 209handler_free(struct handler *hp)
201{ 210{
202 grecs_list_free(hp->fnames); 211 grecs_list_free(hp->fnames);
203 free(hp->prog); 212 switch (hp->type) {
204 free(hp->gidv); 213 case HANDLER_EXTERN:
205 envfree(hp->env); 214 free(hp->prog_command);
215 free(hp->prog_gidv);
216 envfree(hp->prog_env);
217 break;
218 case HANDLER_SENTINEL:
219 dirwatcher_unref(hp->sentinel_watcher);
220 }
206} 221}
207 222
208static void 223static void
@@ -290,7 +305,6 @@ direvent_handler_list_append(direvent_handler_list_t hlist, struct handler *hp)
290 grecs_list_append(hlist->list, hp); 305 grecs_list_append(hlist->list, hp);
291} 306}
292 307
293
294struct eventconf { 308struct eventconf {
295 struct grecs_list *pathlist; 309 struct grecs_list *pathlist;
296 struct handler handler; 310 struct handler handler;
@@ -301,8 +315,9 @@ static struct eventconf eventconf;
301static void 315static void
302eventconf_init(void) 316eventconf_init(void)
303{ 317{
304 memset(&eventconf, 0, sizeof eventconf); 318 memset(&eventconf, 0, sizeof eventconf);
305 eventconf.handler.timeout = DEFAULT_TIMEOUT; 319 eventconf.handler.type = HANDLER_EXTERN;
320 eventconf.handler.prog_timeout = DEFAULT_TIMEOUT;
306} 321}
307 322
308static void 323static void
@@ -316,7 +331,7 @@ void
316eventconf_flush(grecs_locus_t *loc) 331eventconf_flush(grecs_locus_t *loc)
317{ 332{
318 struct grecs_list_entry *ep; 333 struct grecs_list_entry *ep;
319 struct handler *hp = handler_alloc(&eventconf.handler); 334 struct handler *hp = handler_copy(&eventconf.handler);
320 335
321 for (ep = eventconf.pathlist->head; ep; ep = ep->next) { 336 for (ep = eventconf.pathlist->head; ep; ep = ep->next) {
322 struct pathent *pe = ep->data; 337 struct pathent *pe = ep->data;
@@ -331,8 +346,6 @@ eventconf_flush(grecs_locus_t *loc)
331 _("%s: recursion depth does not match previous definition"), 346 _("%s: recursion depth does not match previous definition"),
332 pe->path); 347 pe->path);
333 dwp->depth = pe->depth; 348 dwp->depth = pe->depth;
334 if (!dwp->handler_list)
335 dwp->handler_list = direvent_handler_list_create();
336 direvent_handler_list_append(dwp->handler_list, hp); 349 direvent_handler_list_append(dwp->handler_list, hp);
337 } 350 }
338 grecs_list_free(eventconf.pathlist); 351 grecs_list_free(eventconf.pathlist);
@@ -354,7 +367,7 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node,
354 grecs_error(&node->locus, 0, _("no paths configured")); 367 grecs_error(&node->locus, 0, _("no paths configured"));
355 ++err; 368 ++err;
356 } 369 }
357 if (!eventconf.handler.prog) { 370 if (!eventconf.handler.prog_command) {
358 grecs_error(&node->locus, 0, 371 grecs_error(&node->locus, 0,
359 _("no command configured")); 372 _("no command configured"));
360 ++err; 373 ++err;
@@ -605,9 +618,9 @@ cb_user(enum grecs_callback_command cmd, grecs_node_t *node,
605 } else 618 } else
606 gid = pw->pw_gid; 619 gid = pw->pw_gid;
607 620
608 eventconf.handler.uid = pw->pw_uid; 621 eventconf.handler.prog_uid = pw->pw_uid;
609 get_user_groups(uv->v.string, gid, 622 get_user_groups(uv->v.string, gid,
610 &eventconf.handler.gidc, &eventconf.handler.gidv); 623 &eventconf.handler.prog_gidc, &eventconf.handler.prog_gidv);
611 624
612 return 0; 625 return 0;
613} 626}
@@ -630,15 +643,15 @@ cb_option(enum grecs_callback_command cmd, grecs_node_t *node,
630 GRECS_TYPE_STRING)) 643 GRECS_TYPE_STRING))
631 return 1; 644 return 1;
632 if (strcmp(vp->v.string, "nowait") == 0) 645 if (strcmp(vp->v.string, "nowait") == 0)
633 eventconf.handler.flags |= HF_NOWAIT; 646 eventconf.handler.prog_flags |= HF_NOWAIT;
634 else if (strcmp(vp->v.string, "wait") == 0) 647 else if (strcmp(vp->v.string, "wait") == 0)
635 eventconf.handler.flags &= ~HF_NOWAIT; 648 eventconf.handler.prog_flags &= ~HF_NOWAIT;
636 else if (strcmp(vp->v.string, "stdout") == 0) 649 else if (strcmp(vp->v.string, "stdout") == 0)
637 eventconf.handler.flags |= HF_STDOUT; 650 eventconf.handler.prog_flags |= HF_STDOUT;
638 else if (strcmp(vp->v.string, "stderr") == 0) 651 else if (strcmp(vp->v.string, "stderr") == 0)
639 eventconf.handler.flags |= HF_STDERR; 652 eventconf.handler.prog_flags |= HF_STDERR;
640 else if (strcmp(vp->v.string, "shell") == 0) 653 else if (strcmp(vp->v.string, "shell") == 0)
641 eventconf.handler.flags |= HF_SHELL; 654 eventconf.handler.prog_flags |= HF_SHELL;
642 else 655 else
643 grecs_error(&vp->locus, 0, _("unrecognized option")); 656 grecs_error(&vp->locus, 0, _("unrecognized option"));
644 } 657 }
@@ -661,8 +674,8 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node,
661 GRECS_TYPE_STRING)) 674 GRECS_TYPE_STRING))
662 return 1; 675 return 1;
663 i = handler_envrealloc(&eventconf.handler, 1); 676 i = handler_envrealloc(&eventconf.handler, 1);
664 eventconf.handler.env[i] = estrdup(val->v.string); 677 eventconf.handler.prog_env[i] = estrdup(val->v.string);
665 eventconf.handler.env[i+1] = NULL; 678 eventconf.handler.prog_env[i+1] = NULL;
666 break; 679 break;
667 680
668 case GRECS_TYPE_ARRAY: 681 case GRECS_TYPE_ARRAY:
@@ -672,9 +685,9 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node,
672 val->v.arg.v[i], 685 val->v.arg.v[i],
673 GRECS_TYPE_STRING)) 686 GRECS_TYPE_STRING))
674 return 1; 687 return 1;
675 eventconf.handler.env[j] = estrdup(val->v.arg.v[i]->v.string); 688 eventconf.handler.prog_env[j] = estrdup(val->v.arg.v[i]->v.string);
676 } 689 }
677 eventconf.handler.env[j] = NULL; 690 eventconf.handler.prog_env[j] = NULL;
678 break; 691 break;
679 692
680 case GRECS_TYPE_LIST: 693 case GRECS_TYPE_LIST:
@@ -684,15 +697,42 @@ cb_environ(enum grecs_callback_command cmd, grecs_node_t *node,
684 if (assert_grecs_value_type(&vp->locus, vp, 697 if (assert_grecs_value_type(&vp->locus, vp,
685 GRECS_TYPE_STRING)) 698 GRECS_TYPE_STRING))
686 return 1; 699 return 1;
687 eventconf.handler.env[j] = estrdup(vp->v.string); 700 eventconf.handler.prog_env[j] = estrdup(vp->v.string);
688 } 701 }
689 eventconf.handler.env[j] = NULL; 702 eventconf.handler.prog_env[j] = NULL;
690 } 703 }
691 return 0; 704 return 0;
692} 705}
693 706
707void
708handler_add_pattern(struct handler *hp, struct filename_pattern *pat)
709{
710 if (!hp->fnames) {
711 hp->fnames = grecs_list_create();
712 hp->fnames->free_entry = filename_pattern_free;
713 }
714 grecs_list_append(hp->fnames, pat);
715}
716