2 rxpd_connection_cmd.c - regex policy daemon
5 2007, Christian Thaeter <ct@pipapo.org>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 rxpd_connection_cmd_CHECK (int fd, short event, void* ptr)
28 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
34 while ((line = rxpd_buffer_readline (&self->in, ++again)))
38 rxpd_buffer_printf (&self->out, "#OK:\n");
42 LLIST_FOREACH (&self->file->rules, n)
44 struct rxpd_rule* rule = (struct rxpd_rule*)n;
45 if (rule->string[0] != '#')
47 if (regexec (&rule->rx, line, 0, NULL, 0) == 0)
49 if (rule->atime != (time_t) -1)
52 rxpd_buffer_printf (&self->out, "%s\n", rule->string);
62 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
63 rxpd_connection_delete (self);
67 if (rxpd_buffer_state (&self->in) == RXPD_OK)
68 rxpd_connection_schedule (self);
71 if (rxpd_buffer_state (&self->in) == RXPD_ERROR)
72 rxpd_buffer_printf (&self->out, "#ERROR:\n");
73 rxpd_connection_delete (self);
80 rxpd_connection_APPEND_PREPEND_helper (short event, void* ptr, int do_append)
82 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
89 while ((line = rxpd_buffer_readline (&self->in, ++again)))
93 struct rxpd_rule* rule;
94 rule = rxpd_rule_new (line);
98 llist_insert_tail (&self->tmp_list, &rule->node);
100 else goto finish; /* move along, look elsewhere! This goto is not harmful and saves some code. */
103 else if (!event && !self->file)
105 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
106 rxpd_connection_delete (self);
110 if (rxpd_buffer_state (&self->in) == RXPD_OK)
111 rxpd_connection_schedule (self);
114 // TODO should also print error when any rule compilation failed, use tmp_str to save case?
115 if (rxpd_buffer_state (&self->in) == RXPD_ERROR)
116 rxpd_buffer_printf (&self->out, "#ERROR:\n");
120 rxpd_buffer_printf (&self->out, "#OK:\n");
124 llist_insertlist_prev (&self->file->rules, &self->tmp_list);
126 llist_insertlist_next (&self->file->rules, &self->tmp_list);
127 rxpd_connection_delete (self);
132 rxpd_connection_cmd_APPEND (int fd, short event, void* ptr)
135 rxpd_connection_APPEND_PREPEND_helper (event, ptr, 1);
139 rxpd_connection_cmd_PREPEND (int fd, short event, void* ptr)
142 rxpd_connection_APPEND_PREPEND_helper (event, ptr, 0);
147 rxpd_connection_cmd_REMOVE (int fd, short event, void* ptr)
150 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
152 if (event == EV_READ)
156 while ((line = rxpd_buffer_readline (&self->in, ++again)))
158 LLIST_FOREACH (&self->file->rules, n)
160 struct rxpd_rule* rule = (struct rxpd_rule*)n;
161 if (strcmp (rule->string, line) == 0)
163 LList tmp = llist_prev (n);
164 rxpd_rule_delete (rule);
166 rxpd_buffer_printf (&self->out, "#OK:\n");
170 rxpd_buffer_printf (&self->out, "#ERROR: line not found\n");
175 else if (!self->file)
177 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
178 rxpd_connection_delete (self);
182 if (rxpd_buffer_state (&self->in) == RXPD_OK)
183 rxpd_connection_schedule (self);
186 if (rxpd_buffer_state (&self->in) == RXPD_ERROR)
187 rxpd_buffer_printf (&self->out, "#ERROR:\n");
188 rxpd_connection_delete (self);
194 rxpd_connection_do_REPLACE (struct rxpd_connection* self)
196 struct rxpd_rule* rule;
198 LLIST_FOREACH (&self->file->rules, n)
200 rule = (struct rxpd_rule*)n;
201 if (strcmp (rule->string, self->tmp_str) == 0)
206 llist_insertlist_next (&rule->node, &self->tmp_list);
207 rxpd_rule_delete (rule);
208 free (self->tmp_str);
209 self->tmp_str = NULL;
214 rxpd_connection_cmd_REPLACE (int fd, short event, void* ptr)
217 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
219 if (event == EV_READ)
223 while ((line = rxpd_buffer_readline (&self->in, ++again)))
229 struct rxpd_rule* rule;
230 rule = rxpd_rule_new (line);
234 llist_insert_tail (&self->tmp_list, &rule->node);
236 /* TODO handle empty lines? */
239 self->tmp_str = rxpd_strdup (line);
242 else if (!self->file)
244 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
245 rxpd_connection_delete (self);
249 if (rxpd_buffer_state (&self->in) == RXPD_OK)
250 rxpd_connection_schedule (self);
253 if (rxpd_buffer_state (&self->in) == RXPD_ERROR)
254 rxpd_buffer_printf (&self->out, "#ERROR:\n");
257 if (rxpd_connection_do_REPLACE (self))
258 rxpd_buffer_printf (&self->out, "#OK:\n");
260 rxpd_buffer_printf (&self->out, "#ERROR: rule matching '%s'\n", self->tmp_str);
263 rxpd_connection_delete (self);
268 rxpd_connection_cmd_LOAD (int fd, short event, void* ptr)
271 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
277 if (rxpd_file_load (self->file))
279 rxpd_buffer_printf (&self->out, "#OK:\n");
283 rxpd_buffer_printf (&self->out, "#ERROR: loading file '%s'\n", (const char*)self->file->node.key);
287 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
288 rxpd_connection_delete (self);
293 rxpd_connection_cmd_SAVE (int fd, short event, void* ptr)
296 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
302 if (rxpd_file_save (self->file))
304 rxpd_buffer_printf (&self->out, "#OK:\n");
308 rxpd_buffer_printf (&self->out, "#ERROR: saving file '%s'\n", (const char*)self->file->node.key);
312 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
313 rxpd_connection_delete (self);
318 rxpd_connection_cmd_DUMP (int fd, short event, void* ptr)
321 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
323 if (!event && !self->file)
325 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
326 rxpd_connection_delete (self);
330 if (llist_is_empty (&self->file->rules))
331 rxpd_buffer_printf (&self->out, "#OK:\n");
334 LLIST_FOREACH (&self->file->rules, n)
336 struct rxpd_rule* rule = (struct rxpd_rule*)n;
337 if (rule->atime != (time_t)-1)
338 rxpd_buffer_printf (&self->out, "%ld:%s\n", rule->atime, rule->string);
339 else if (*rule->string != '#')
340 rxpd_buffer_printf (&self->out, ":%s\n", rule->string);
342 rxpd_buffer_printf (&self->out, "%s\n", rule->string);
346 rxpd_connection_delete (self);
350 static psplay_delete_t
351 walk_LIST (PSplay node, const enum psplay_order_e which, int level, void* data)
354 struct rxpd_file* file = (struct rxpd_file*) node;
355 struct rxpd_connection* conn = (struct rxpd_connection*) data;
357 if (which == PSPLAY_INORDER)
358 rxpd_buffer_printf (&conn->out, "%s\n", file->node.key);
365 rxpd_connection_cmd_LIST (int fd, short event, void* ptr)
369 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
370 struct rxpd_base* base = self->socket->base;
372 if (psplay_isempty_root (&base->files))
373 rxpd_buffer_printf (&self->out, "#OK:\n");
375 psplay_walk (&base->files, NULL, walk_LIST, 0, ptr);
377 rxpd_connection_delete (self);
381 rxpd_connection_cmd_SHUTDOWN (int fd, short event, void* ptr)
385 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
386 struct rxpd_base* base = self->socket->base;
387 // destroy all sockets
388 LLIST_WHILE_HEAD (&base->sockets, n)
390 struct rxpd_socket* socket = (struct rxpd_socket*)n;
391 rxpd_socket_delete (socket);
393 rxpd_buffer_printf (&self->out, "#OK:\n");
394 rxpd_connection_delete (self);
399 rxpd_connection_cmd_VERSION (int fd, short event, void* ptr)
403 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
404 rxpd_buffer_printf (&self->out, PACKAGE_STRING "\n#\n"
406 "# 2007, Christian Thaeter <ct@pipapo.org>\n#\n"
407 "# This is free software. You may redistribute copies of it under the terms of\n"
408 "# the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
409 "# There is NO WARRANTY, to the extent permitted by law.\n#\n"
410 "# http://www.pipapo.org/pipawiki/RegexPolicyDaemon\n");
411 rxpd_connection_delete (self);
415 rxpd_connection_cmd_HELP (int fd, short event, void* ptr)
419 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
420 //struct rxpd_base* base = self->socket->base;
421 rxpd_buffer_printf (&self->out, "# Available commands:\n#\n");
422 #define RXPD_CMD(cmd, help) rxpd_buffer_printf (&self->out, "# %s %s.\n", #cmd, help);
425 rxpd_buffer_printf (&self->out, "#\n# general syntax is: 'COMMAND:listname\\n..data..'\n");
426 rxpd_connection_delete (self);
430 rxpd_connection_cmd_EXPIRE (int fd, short event, void* ptr)
433 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
434 struct rxpd_base* base = self->socket->base;
436 if (event == EV_READ)
440 while ((line = rxpd_buffer_readline (&self->in, ++again)))
444 time_t since = time (NULL) - atoi (line);
445 rxpd_log (base, LOG_INFO, "expire all entries in '%s' since %ld\n",
446 (const char*) self->file->node.key, since);
448 LLIST_FOREACH (&self->file->rules, n)
450 struct rxpd_rule* rule = (struct rxpd_rule*)n;
451 if (rule->atime != -1 && rule->atime < since)
454 rxpd_log (base, LOG_DEBUG, "expiring %ld:%s\n", rule->atime, rule->string);
455 rxpd_buffer_printf (&self->out, "#OK: expiring '%s'\n", rule->string);
456 rxpd_rule_delete (rule);
461 rxpd_buffer_printf (&self->out, "#OK:\n");
464 else if (!self->file)
466 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
467 rxpd_connection_delete (self);
471 if (rxpd_buffer_state (&self->in) == RXPD_OK)
472 rxpd_connection_schedule (self);
475 if (rxpd_buffer_state (&self->in) == RXPD_ERROR)
476 rxpd_buffer_printf (&self->out, "#ERROR:\n");
477 rxpd_connection_delete (self);
483 rxpd_connection_cmd_ (int fd, short event, void* ptr)
487 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
488 struct rxpd_base* base = self->socket->base;
489 rxpd_die ("Unimplemented\n");