diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | Makefile | 44 | ||||
-rw-r--r-- | dircond.c | 1062 | ||||
-rw-r--r-- | dlist.c | 35 |
4 files changed, 1146 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef072ec --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,5 @@ | |||
1 | dircond | ||
2 | *~ | ||
3 | *.o | ||
4 | *.tar.* | ||
5 | .emacs* | ||
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5651d93 --- /dev/null +++ b/Makefile | |||
@@ -0,0 +1,44 @@ | |||
1 | CFLAGS=-ggdb -Wall | ||
2 | PREFIX=/usr/local | ||
3 | BINDIR=$(PREFIX)/bin | ||
4 | MANDIR=$(PREFIX)/share/man | ||
5 | PACKAGE=upev | ||
6 | VERSION=1.0 | ||
7 | DISTFILES=Makefile dircond.c dlist.c | ||
8 | |||
9 | dircond: dircond.c dlist.c | ||
10 | cc -odircond $(CFLAGS) dircond.c | ||
11 | |||
12 | install-bin: dircond | ||
13 | mkdir -p $(DESTDIR)$(BINDIR) | ||
14 | cp dircond $(DESTDIR)$(BINDIR) | ||
15 | |||
16 | install-man:; | ||
17 | #install-man: dircond.1 | ||
18 | # mkdir -p $(DESTDIR)$(MANDIR)/man1 | ||
19 | # cp dircond.1 $(DESTDIR)$(MANDIR)/man1 | ||
20 | |||
21 | install: install-bin install-man | ||
22 | |||
23 | distdir = $(PACKAGE)-$(VERSION) | ||
24 | |||
25 | distdir: | ||
26 | rm -rf $(distdir) | ||
27 | mkdir $(distdir) | ||
28 | cp $(DISTFILES) $(distdir) | ||
29 | |||
30 | dist: distdir | ||
31 | tar cfz $(distdir).tar.gz $(distdir) | ||
32 | rm -rf $(distdir) | ||
33 | |||
34 | distcheck: distdir | ||
35 | mkdir $(distdir)/_inst; \ | ||
36 | cd $(distdir) || exit 2;\ | ||
37 | make || exit 2; \ | ||
38 | make DESTDIR=`pwd`/_inst install || exit 2 | ||
39 | (cd $(distdir)/_inst; find . -type f)|sort|cut -c2- | \ | ||
40 | cmp - instlist | ||
41 | make dist | ||
42 | |||
43 | clean: | ||
44 | rm -f dircond | ||
diff --git a/dircond.c b/dircond.c new file mode 100644 index 0000000..682e1c3 --- /dev/null +++ b/dircond.c | |||
@@ -0,0 +1,1062 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <stdarg.h> | ||
4 | #include <fcntl.h> | ||
5 | #include <syslog.h> | ||
6 | #include <unistd.h> | ||
7 | #include <getopt.h> | ||
8 | #include <string.h> | ||
9 | #include <errno.h> | ||
10 | #include <pwd.h> | ||
11 | #include <signal.h> | ||
12 | #include <time.h> | ||
13 | #include <sys/inotify.h> | ||
14 | #include <sys/wait.h> | ||
15 | #include <sys/stat.h> | ||
16 | |||
17 | /* Configuration settings */ | ||
18 | const char *program_name; /* This program name */ | ||
19 | int foreground; /* Remain in the foreground */ | ||
20 | int facility = -1; /* Use this syslog facility for logging. | ||
21 | -1 means log to stderr */ | ||
22 | int debug_level; /* Debug verbosity level */ | ||
23 | unsigned handler_timeout = 5; /* Timeout for handler program (seconds) */ | ||
24 | int autowatch; /* Automatically add directories created | ||
25 | under watchpoints to the watcher. If set | ||
26 | to -1, nesting level is not limited. If | ||
27 | set to a positive value, this value limits | ||
28 | the nesting depth. */ | ||
29 | |||
30 | /* Event codes */ | ||
31 | enum { | ||
32 | evt_create, /* file has been created */ | ||
33 | evt_delete, /* file has been deleted */ | ||
34 | evt_close, /* file has been modified and closed */ | ||
35 | evt_max /* number of handled events */ | ||
36 | }; | ||
37 | |||
38 | /* Handler flags. */ | ||
39 | #define HF_NOWAIT 0x01 /* Don't wait for termination */ | ||
40 | #define HF_STDOUT 0x02 /* Capture stdout */ | ||
41 | #define HF_STDERR 0x04 /* Capture stderr */ | ||
42 | |||
43 | /* Handler structure */ | ||
44 | struct handler { | ||
45 | int flags; /* Handler flags */ | ||
46 | const char *prog; /* Handler program (no arguments allowed) */ | ||
47 | }; | ||
48 | |||
49 | /* Array of handlers for each event */ | ||
50 | struct handler handler[evt_max]; | ||
51 | |||
52 | /* Process list */ | ||
53 | |||
54 | /* Redirector codes */ | ||
55 | #define REDIR_OUT 0 | ||
56 | #define REDIR_ERR 1 | ||
57 | |||
58 | /* A running process is described by this structure */ | ||
59 | struct process { | ||
60 | struct process *next, *prev; | ||
61 | int master; /* Master process or redirector */ | ||
62 | pid_t pid; /* PID */ | ||
63 | time_t start; /* Time when the process started */ | ||
64 | pid_t redir[2]; /* If master==1, holds PIDs of redirector | ||
65 | processes (0 if no redirector) */ | ||
66 | }; | ||
67 | |||
68 | /* List of running processes */ | ||
69 | struct process *proc_list; | ||
70 | /* List of available process slots */ | ||
71 | struct process *proc_avail; | ||
72 | /* Declare functions for handling process lists */ | ||
73 | #define LIST process | ||
74 | #define LIST_PUSH proc_push | ||
75 | #define LIST_POP proc_pop | ||
76 | #define LIST_UNLINK proc_unlink | ||
77 | #include "dlist.c" | ||
78 | |||
79 | /* Diagnostic functions */ | ||
80 | const char * | ||
81 | severity(int prio) | ||
82 | { | ||
83 | switch (prio) { | ||
84 | case LOG_EMERG: | ||
85 | return "EMERG"; | ||
86 | case LOG_ALERT: | ||
87 | return "ALERT"; | ||
88 | case LOG_CRIT: | ||
89 | return "CRIT"; | ||
90 | case LOG_ERR: | ||
91 | return "ERROR"; | ||
92 | case LOG_WARNING: | ||
93 | return "WARNING"; | ||
94 | case LOG_NOTICE: | ||
95 | return "NOTICE"; | ||
96 | case LOG_INFO: | ||
97 | return "INFO"; | ||
98 | case LOG_DEBUG: | ||
99 | return "DEBUG"; | ||
100 | } | ||
101 | return NULL; | ||
102 | } | ||
103 | |||
104 | void | ||
105 | vdiag(int prio, const char *fmt, va_list ap) | ||
106 | { | ||
107 | const char *s; | ||
108 | |||
109 | if (facility <= 0) { | ||
110 | fprintf(stderr, "%s: ", program_name); | ||
111 | s = severity(prio); | ||
112 | if (s) | ||
113 | fprintf(stderr, "[%s] ", s); | ||
114 | vfprintf(stderr, fmt, ap); | ||
115 | fputc('\n', stderr); | ||
116 | } else { | ||
117 | vsyslog(prio, fmt, ap); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | void | ||
122 | diag(int prio, const char *fmt, ...) | ||
123 | { | ||
124 | va_list ap; | ||
125 | |||
126 | va_start(ap, fmt); | ||
127 | vdiag(prio, fmt, ap); | ||
128 | va_end(ap); | ||
129 | } | ||
130 | |||
131 | static void | ||
132 | debugprt(const char *fmt, ...) | ||
133 | { | ||
134 | va_list ap; | ||
135 | |||
136 | va_start(ap, fmt); | ||
137 | vdiag(LOG_DEBUG, fmt, ap); | ||
138 | va_end(ap); | ||
139 | } | ||
140 | |||
141 | #define debug(l, c) do { if (debug_level>=(l)) debugprt c; } while(0) | ||
142 | |||
143 | /* Command line processing and auxiliary functions */ | ||
144 | |||
145 | static void | ||
146 | set_program_name(const char *arg) | ||
147 | { | ||
148 | char *p = strrchr(arg, '/'); | ||
149 | if (p) | ||
150 | program_name = p + 1; | ||
151 | else | ||
152 | program_name = arg; | ||
153 | } | ||
154 | |||
155 | static int | ||
156 | read_facility(const char *arg) | ||
157 | { | ||
158 | static struct transtab { int f; char *s; } ftab[] = { | ||
159 | { LOG_AUTH, "auth" }, | ||
160 | { LOG_AUTHPRIV, "authpriv" }, | ||
161 | { LOG_CRON, "cron" }, | ||
162 | { LOG_DAEMON, "daemon" }, | ||
163 | { LOG_FTP, "ftp" }, | ||
164 | { LOG_LOCAL0, "local0" }, | ||
165 | { LOG_LOCAL1, "local1" }, | ||
166 | { LOG_LOCAL2, "local2" }, | ||
167 | { LOG_LOCAL3, "local3" }, | ||
168 | { LOG_LOCAL4, "local4" }, | ||
169 | { LOG_LOCAL5, "local5" }, | ||
170 | { LOG_LOCAL6, "local6" }, | ||
171 | { LOG_LOCAL7, "local7" }, | ||
172 | { LOG_LPR, "lpr" }, | ||
173 | { LOG_MAIL, "mail" }, | ||
174 | { LOG_NEWS, "news" }, | ||
175 | { LOG_USER, "user" }, | ||
176 | { LOG_UUCP, "uucp" }, | ||
177 | { 0, NULL } | ||
178 | }; | ||
179 | struct transtab *p; | ||
180 | char *s; | ||
181 | unsigned long n; | ||
182 | |||
183 | for (p = ftab; p->s; p++) { | ||
184 | if (strcmp(p->s, arg) == 0) | ||
185 | return p->f; | ||
186 | } | ||
187 | n = strtoul(arg, &s, 10); | ||
188 | if (*s) { | ||
189 | diag(LOG_CRIT, "unknown facility: %s", arg); | ||
190 | exit(1); | ||
191 | } | ||
192 | if (n > 256) { | ||
193 | diag(LOG_CRIT, "facility out of range: %s", arg); | ||
194 | exit(1); | ||
195 | } | ||
196 | return n; | ||
197 | } | ||
198 | |||
199 | void | ||