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_DELETE (int fd, short event, void* ptr)
321 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
327 rxpd_file_delete (self->file);
328 rxpd_buffer_printf (&self->out, "#OK:\n");
330 rxpd_connection_delete (self);
335 rxpd_connection_cmd_FETCH (int fd, short event, void* ptr)
338 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
339 struct rxpd_base* base = self->socket->base;
341 if (event == EV_READ)
344 line = rxpd_buffer_readline (&self->in, 0);
347 rxpd_file_rules_delete (self->file);
349 char* list = strrchr (line, '/');
350 // TODO error handling
352 rxpd_die ("syntax error");
357 char* port = strrchr (line, ':');
358 // TODO error handling / unix domain sockets
360 rxpd_die ("syntax error");
365 struct addrinfo* addrs = NULL;
368 aierr = getaddrinfo (line, port, NULL, &addrs);
370 rxpd_log (base, LOG_INFO, "fetching list '%s' from '%s(%s)' at port '%s' to '%s'\n",
373 inet_ntoa (((struct sockaddr_in*)addrs->ai_addr)->sin_addr),
375 self->file->node.key);
378 rxpd_die ("resolv error %s\n", gai_strerror (aierr));
382 // add recieving event
384 freeaddrinfo (addrs);
387 else if (!self->file)
389 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
390 rxpd_connection_delete (self);
394 if (!event && rxpd_buffer_state (&self->in) == RXPD_OK)
395 rxpd_connection_schedule (self);
399 rxpd_connection_cmd_DUMP (int fd, short event, void* ptr)
402 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
404 if (!event && !self->file)
406 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
407 rxpd_connection_delete (self);
411 if (llist_is_empty (&self->file->rules))
412 rxpd_buffer_printf (&self->out, "#OK:\n");
415 LLIST_FOREACH (&self->file->rules, n)
417 struct rxpd_rule* rule = (struct rxpd_rule*)n;
418 if (rule->atime != (time_t)-1)
419 rxpd_buffer_printf (&self->out, "%ld:%s\n", rule->atime, rule->string);
420 else if (*rule->string != '#')
421 rxpd_buffer_printf (&self->out, ":%s\n", rule->string);
423 rxpd_buffer_printf (&self->out, "%s\n", rule->string);
427 rxpd_connection_delete (self);
431 static psplay_delete_t
432 walk_LIST (PSplay node, const enum psplay_order_e which, int level, void* data)
435 struct rxpd_file* file = (struct rxpd_file*) node;
436 struct rxpd_connection* conn = (struct rxpd_connection*) data;
438 if (which == PSPLAY_INORDER)
439 rxpd_buffer_printf (&conn->out, "%s\n", file->node.key);
446 rxpd_connection_cmd_LIST (int fd, short event, void* ptr)
450 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
451 struct rxpd_base* base = self->socket->base;
453 if (psplay_isempty_root (&base->files))
454 rxpd_buffer_printf (&self->out, "#OK:\n");
456 psplay_walk (&base->files, NULL, walk_LIST, 0, ptr);
458 rxpd_connection_delete (self);
462 rxpd_connection_cmd_SHUTDOWN (int fd, short event, void* ptr)
466 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
467 struct rxpd_base* base = self->socket->base;
468 // destroy all sockets
469 LLIST_WHILE_HEAD (&base->sockets, n)
471 struct rxpd_socket* socket = (struct rxpd_socket*)n;
472 rxpd_socket_delete (socket);
474 rxpd_buffer_printf (&self->out, "#OK:\n");
475 rxpd_connection_delete (self);
480 rxpd_connection_cmd_VERSION (int fd, short event, void* ptr)
484 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
485 rxpd_buffer_printf (&self->out, PACKAGE_STRING "\n#\n"
487 "# 2007, Christian Thaeter <ct@pipapo.org>\n#\n"
488 "# This is free software. You may redistribute copies of it under the terms of\n"
489 "# the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
490 "# There is NO WARRANTY, to the extent permitted by law.\n#\n"
491 "# http://www.pipapo.org/pipawiki/RegexPolicyDaemon\n");
492 rxpd_connection_delete (self);
496 rxpd_connection_cmd_HELP (int fd, short event, void* ptr)
500 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
501 //struct rxpd_base* base = self->socket->base;
502 rxpd_buffer_printf (&self->out, "# Available commands:\n#\n");
503 #define RXPD_CMD(cmd, help) rxpd_buffer_printf (&self->out, "# %s %s.\n", #cmd, help);
506 rxpd_buffer_printf (&self->out, "#\n# general syntax is: 'COMMAND:listname\\n..data..'\n");
507 rxpd_connection_delete (self);
511 rxpd_connection_cmd_EXPIRE (int fd, short event, void* ptr)
514 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
515 struct rxpd_base* base = self->socket->base;
517 if (event == EV_READ)
521 while ((line = rxpd_buffer_readline (&self->in, ++again)))
525 time_t since = time (NULL) - atoi (line);
526 rxpd_log (base, LOG_INFO, "expire all entries in '%s' since %ld\n",
527 (const char*) self->file->node.key, since);
529 LLIST_FOREACH (&self->file->rules, n)
531 struct rxpd_rule* rule = (struct rxpd_rule*)n;
532 if (rule->atime != -1 && rule->atime < since)
535 rxpd_log (base, LOG_DEBUG, "expiring %ld:%s\n", rule->atime, rule->string);
536 rxpd_buffer_printf (&self->out, "#OK: expiring '%s'\n", rule->string);
537 rxpd_rule_delete (rule);
542 rxpd_buffer_printf (&self->out, "#OK:\n");
545 else if (!self->file)
547 rxpd_buffer_printf (&self->out, "#ERROR: no such file\n");
548 rxpd_connection_delete (self);
552 if (rxpd_buffer_state (&self->in) == RXPD_OK)
553 rxpd_connection_schedule (self);
556 if (rxpd_buffer_state (&self->in) == RXPD_ERROR)
557 rxpd_buffer_printf (&self->out, "#ERROR:\n");
558 rxpd_connection_delete (self);
564 rxpd_connection_cmd_ (int fd, short event, void* ptr)
568 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
569 struct rxpd_base* base = self->socket->base;
570 rxpd_die ("Unimplemented\n");