1 /* direvent - directory content watcher daemon
2    Copyright (C) 2012-2016 Sergey Poznyakoff
3 
4    Direvent is free software; you can redistribute it and/or modify it
5    under the terms of the GNU General Public License as published by the
6    Free Software Foundation; either version 3 of the License, or (at your
7    option) any later version.
8 
9    Direvent is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License along
15    with direvent. If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include "config.h"
18 #include <sys/types.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <syslog.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <signal.h>
26 #include <regex.h>
27 #include <grecs/list.h>
28 #include <grecs/symtab.h>
29 #include "gettext.h"
30 
31 #define _(s) gettext(s)
32 #define N_(s) s
33 
34 /* Generic (system-independent) event codes */
35 #define GENEV_CREATE  0x01
36 #define GENEV_WRITE   0x02
37 #define GENEV_ATTRIB  0x04
38 #define GENEV_DELETE  0x08
39 
40 /* Handler flags. */
41 #define HF_NOWAIT  0x01   /* Don't wait for termination */
42 #define HF_STDOUT  0x02   /* Capture stdout */
43 #define HF_STDERR  0x04   /* Capture stderr */
44 #define HF_SHELL   0x08   /* Call program via /bin/sh -c */
45 
46 #ifndef DEFAULT_TIMEOUT
47 # define DEFAULT_TIMEOUT 5
48 #endif
49 
50 typedef struct {
51 	int gen_mask;        /* Generic event mask */
52 	int sys_mask;        /* System event mask */
53 } event_mask;
54 
55 /* Event description */
56 struct transtab {
57 	char *name;
58 	int tok;
59 };
60 
61 enum pattern_type {
62 	PAT_EXACT,
63 	PAT_GLOB,
64 	PAT_REGEX
65 };
66 
67 struct filename_pattern {
68 	enum pattern_type type;
69 	int neg;
70 	union {
71 		regex_t re;
72 		char *glob;
73 	} v;
74 };
75 
76 typedef struct filpatlist *filpatlist_t;
77 
78 struct watchpoint;
79 
80 typedef int (*event_handler_fn) (struct watchpoint *wp,
81 				 event_mask *event,
82 				 const char *dir,
83 				 const char *file,
84 				 void *data);
85 typedef void (*handler_free_fn) (void *data);
86 
87 /* Handler structure */
88 struct handler {
89 	size_t refcnt;        /* Reference counter */
90 	event_mask ev_mask;   /* Event mask */
91 	filpatlist_t fnames;  /* File name patterns */
92 	event_handler_fn run;
93 	handler_free_fn free;
94 	void *data;
95 };
96 
97 typedef struct handler_list *handler_list_t;
98 typedef struct handler_iterator *handler_iterator_t;
99 
100 /* Watchpoint links the directory being monitored and a list of
101    handlers for various events: */
102 struct watchpoint {
103 	size_t refcnt;
104 	int wd;                              /* Watch descriptor */
105 	struct watchpoint *parent;           /* Points to the parent watcher.
106 					        NULL for top-level watchers */
107 	char *dirname;                       /* Pathname being watched */
108 	int isdir;                           /* Is it directory */
109 	handler_list_t handler_list;         /* List of handlers */
110 	int depth;                           /* Recursion depth */
111 	char *split_p;                       /* Points to the deleted directory
112 						separator in dirname (see
113 						split_pathname,
114 						unsplit_pathname */
115 #if USE_IFACE == IFACE_KQUEUE
116 	mode_t file_mode;
117 	time_t file_ctime;
118 #endif
119 };
120 
121 #define __cat2__(a,b) a ## b
122 #define handler_matches_event(h,m,f,n)		\
123 	(((h)->ev_mask.__cat2__(m,_mask) & (f)) &&	\
124 	 filpatlist_match((h)->fnames, n) == 0)
125 
126 struct handler *handler_alloc(event_mask ev_mask);
127 void handler_free(struct handler *hp);
128 
129 struct prog_handler {
130 	int flags;     /* Handler flags */
131 	char *command; /* Handler command (with eventual arguments) */
132 	uid_t uid;     /* Run as this user (unless 0) */
133 	gid_t *gidv;   /* Run with these groups' privileges */
134 	size_t gidc;   /* Number of elements in gidv */
135 	unsigned timeout; /* Handler timeout */
136 	char **env;    /* Environment */
137 };
138 
139 struct handler *prog_handler_alloc(event_mask ev_mask, filpatlist_t fpat,
140 				   struct prog_handler *p);
141 void prog_handler_free(struct prog_handler *);
142 size_t prog_handler_envrealloc(struct prog_handler *hp, size_t count);
143 
144 
145 extern int foreground;
146 extern int debug_level;
147 extern int facility;
148 extern char *tag;
149 extern int syslog_include_prio;
150 extern char *pidfile;
151 extern char *user;
152 extern unsigned opt_timeout;
153 extern unsigned opt_flags;
154 extern int signo;
155 extern int stop;
156 
157 extern pid_t self_test_pid;
158 extern int exit_code;
159 
160 
161 void *emalloc(size_t size);
162 void *ecalloc(size_t nmemb, size_t size);
163 void *erealloc(void *ptr, size_t size);
164 char *estrdup(const char *str);
165 
166 char *mkfilename(const char *dir, const char *file);
167 
168 void diag(int prio, const char *fmt, ...);
169 void debugprt(const char *fmt, ...);
170 
171 #define debug(l, c) do { if (debug_level>=(l)) debugprt c; } while(0)
172 
173 void signal_setup(void (*sf) (int));
174 int detach(void (*)(void));
175 
176 int sysev_filemask(struct watchpoint *dp);
177 void sysev_init(void);
178 int sysev_add_watch(struct watchpoint *dwp, event_mask mask);
179 void sysev_rm_watch(struct watchpoint *dwp);
180 int sysev_select(void);
181 int sysev_name_to_code(const char *name);
182 const char *sysev_code_to_name(int code);
183 
184 int defevt(const char *name, event_mask *mask, int line);
185 int getevt(const char *name, event_mask *mask);
186 int evtnullp(event_mask *mask);
187 event_mask *event_mask_init(event_mask *m, int fflags, event_mask const *);
188 void evtsetall(event_mask *m);
189 
190 /* Translate generic events to system ones and vice-versa */
191 extern event_mask genev_xlat[];
192 /* Translate generic event codes to symbolic names and vice-versa */
193 extern struct transtab genev_transtab[];
194 /* Translate system event codes to symbolic names and vice-versa */
195 extern struct transtab sysev_transtab[];
196 
197 int trans_strtotok(struct transtab *tab, const char *str, int *ret);
198 char *trans_toktostr(struct transtab *tab, int tok);
199 char *trans_tokfirst(struct transtab *tab, int tok, int *next);
200 char *trans_toknext(struct transtab *tab, int tok, int *next);
201 
202 struct pathent {
203 	long depth;
204 	size_t len;
205 	char path[1];
206 };
207 
208 void config_help(void);
209 void config_init(void);
210 void config_parse(const char *file);
211 
212 int get_facility(const char *arg);
213 int get_priority(const char *arg);
214 
215 int  watchpoint_init(struct watchpoint *dwp);
216 void watchpoint_ref(struct watchpoint *dw);
217 void watchpoint_unref(struct watchpoint *dw);
218 void watchpoint_gc(void);
219 
220 int watchpoint_pattern_match(struct watchpoint *dwp, const char *file_name);
221 
222 void watchpoint_run_handlers(struct watchpoint *wp, int evflags,
223 			      const char *dirname, const char *filename);
224 
225 
226 void setup_watchers(void);
227 void shutdown_watchers(void);
228 
229 struct watchpoint *watchpoint_lookup(const char *dirname);
230 int check_new_watcher(const char *dir, const char *name);
231 struct watchpoint *watchpoint_install(const char *path, int *pnew);
232 struct watchpoint *watchpoint_install_ptr(struct watchpoint *dw);
233 void watchpoint_suspend(struct watchpoint *dwp);
234 void watchpoint_destroy(struct watchpoint *dwp);
235 int watchpoint_install_sentinel(struct watchpoint *dwp);
236 
237 int watch_pathname(struct watchpoint *parent, const char *dirname, int isdir, int notify);
238 
239 char *split_pathname(struct watchpoint *dp, char **dirname);
240 void unsplit_pathname(struct watchpoint *dp);
241 
242 void ev_log(int flags, struct watchpoint *dp);
243 void deliver_ev_create(struct watchpoint *dp,
244 		       const char *dirname, const char *filename);
245 int subwatcher_create(struct watchpoint *parent, const char *dirname,
246 		      int notify);
247 
248 struct handler *handler_itr_first(struct watchpoint *dp,
249 				       handler_iterator_t *itr);
250 struct handler *handler_itr_next(handler_iterator_t *itr);
251 struct handler *handler_itr_current(handler_iterator_t itr);
252 
253 #define for_each_handler(d,i,h)				\
254 	for (h = handler_itr_first(d, &(i));	\
255 	     h;						\
256 	     h = handler_itr_next(&(i)))
257 
258 
259 handler_list_t handler_list_create(void);
260 handler_list_t handler_list_copy(handler_list_t);
261 void handler_list_unref(handler_list_t hlist);
262 void handler_list_append(handler_list_t hlist,
263 				  struct handler *hp);
264 size_t handler_list_remove(handler_list_t hlist, struct handler *hp);
265 size_t handler_list_size(handler_list_t hlist);
266 
267 struct process *process_lookup(pid_t pid);
268 void process_cleanup(int expect_term);
269 void process_timeouts(void);
270 char **environ_setup(char **hint, char **kve);
271 
272 #define NITEMS(a) ((sizeof(a)/sizeof((a)[0])))
273 struct sigtab {
274 	int signo;
275 	void (*sigfun)(int);
276 };
277 
278 int sigv_set_action(int sigc, int *sigv, struct sigaction *sa);
279 int sigv_set_all(void (*handler)(int), int sigc, int *sigv,
280 		 struct sigaction *retsa);
281 int sigv_set_tab(int sigc, struct sigtab *sigtab, struct sigaction *retsa);
282 int sigv_set_action_tab(int sigc, struct sigtab *sigtab, struct sigaction *sa);
283 
284 struct grecs_locus;
285 int filpatlist_add(filpatlist_t *fptr, char const *arg,
286 		   struct grecs_locus *loc);
287 void filpatlist_add_exact(filpatlist_t *fptr, char const *arg);
288 void filpatlist_destroy(filpatlist_t *fptr);
289 int filpatlist_match(filpatlist_t fp, const char *name);
290 int filpatlist_is_empty(filpatlist_t fp);
291 
292