further on basic implementation
[rxpd] / rxpd.c
1 /*
2     rxpd.c - regex policy daemon
3
4   Copyright (C)
5     2007,               Christian Thaeter <ct@pipapo.org>
6
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.
11
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.
16
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.
20 */
21
22 #include "rxpd.h"
23
24 #include <string.h>
25 #include <stdlib.h>
26
27 static struct rxpd_base global_base = {NULL};
28
29 struct rxpd_base*
30 rxpd_init (char* rulesdir)
31 {
32   if (global_base.rulesdir)
33     return NULL;
34
35   global_base.rulesdir = strdup (rulesdir);
36   if (!global_base.rulesdir) abort();
37
38   psplay_init_root (&global_base.files, rxpd_file_cmp, rxpd_file_delete);
39   return &global_base;
40 }
41
42 void
43 rxpd_destroy (void)
44 {
45   if (global_base.rulesdir)
46     {
47       free (global_base.rulesdir);
48       psplay_destroy_root (&global_base.files);
49     }
50 }
51
52
53 //
54 struct rxpd_rule*
55 rxpd_rule_new (const char* buf)
56 {
57   struct rxpd_rule* self = malloc (sizeof (struct rxpd_rule));
58   if (self)
59     {
60       llist_init (&self->node);
61
62       if (*buf != '#')
63         {
64           int err;
65           char* rxstart = strchr (buf, ':') + 1;
66
67           err = regcomp (&self->rx, rxstart, REG_EXTENDED|REG_ICASE|REG_NOSUB);
68
69           if (!err)
70             {
71               self->string = strdup (buf);
72               if (!self->string) abort();
73             }
74           else
75             {
76               regfree (&self->rx);
77               char ebuf[256];
78               ebuf[0] = '#';
79               size_t len = regerror (err, NULL, ebuf+1, 255);
80               self->string = malloc(len + strlen(buf) + 2);
81               if (!self->string) abort();
82               strcpy (self->string, ebuf);
83               strcat (self->string, ": ");
84               strcat (self->string, buf);
85             }
86         }
87     }
88   return self;
89 }
90
91 void
92 rxpd_rule_delete (struct rxpd_rule* rule)
93 {
94   if (rule)
95     {
96       llist_unlink (&rule->node);
97       if (rule->string[0] != '#')
98         regfree (&rule->rx);
99       free (rule->string);
100       free(rule);
101     }
102 }
103
104 //
105
106
107 int
108 rxpd_file_load (struct rxpd_base* base, const char* filename)
109 {
110   char buf[2048];
111
112   // TODO better filenname validation / error handling
113   if (!filename ||
114       strchr (filename, '/') ||
115       strlen (filename) + strlen (base->rulesdir) > 2047)
116     abort();
117
118   strcpy (buf, base->rulesdir);
119   strcat (buf, filename);
120   filename = strdup (buf);
121
122   struct rxpd_file* file = malloc (sizeof (struct rxpd_file));
123   if (!file || !filename) abort();
124
125   psplay_init (&file->node, filename);
126   llist_init (&file->rules);
127   
128   FILE* f = fopen (filename, "r");
129   // TODO error handling
130   if (!f) abort();
131
132   while (fgets (buf, 2048, f))
133     {
134       struct rxpd_rule* rule;
135       rule = rxpd_rule_new (buf);
136       if (!rule)
137         abort();
138
139       llist_insert_tail (&file->rules, &rule->node);
140     }
141
142   fclose (f);
143
144   psplay_insert (&base->files, &file->node);
145
146   return 0;
147 }
148
149 void
150 rxpd_file_delete (PSplay f)
151 {
152   if (f)
153     {
154       struct rxpd_file* file = (struct rxpd_file*)f;
155       LLIST_WHILE_HEAD (&file->rules, n)
156         {
157           struct rxpd_rule* node = (struct rxpd_rule*)n;
158           rxpd_rule_delete (node);
159         }
160       free ((void*)file->node.key);
161       free (f);
162     }
163 }
164
165 int
166 rxpd_file_cmp (const void* A, const void* B)
167 {
168   return strcmp (A, B);
169 }