3fc9d67ea024de54e76000ac8bd0a9f4b861475e
[rxpd] / src / rxpd_rule.c
1 /*
2     rxpd_rule.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 struct rxpd_rule*
25 rxpd_rule_new (const char* buf)
26 {
27   struct rxpd_rule* self = rxpd_malloc (sizeof (struct rxpd_rule));
28
29   llist_init (&self->node);
30   self->atime = (time_t)-1;
31
32   if (*buf != '#')
33     {
34       int err;
35       char* namestart = strchr (buf, ':');
36       char* rxstart = namestart? strchr (namestart+1, ':') : NULL;
37
38       if (!rxstart)
39           self->string = rxpd_strdup ("#ERROR: Syntax error, line was neither a comment nor a rule");
40       else
41         {
42           if (namestart != buf)
43             {
44               /* atime given */
45               self->atime = atoi (buf);
46               if (!self->atime)
47                 /* atime was zero or not set */
48                 self->atime = time (NULL)-1;
49             }
50
51           // TODO regflags from base
52           err = regcomp (&self->rx, rxstart+1, REG_EXTENDED|REG_ICASE|REG_NOSUB);
53
54           if (!err)
55             self->string = rxpd_strdup (namestart+1);
56           else
57             {
58               regfree (&self->rx);
59               char ebuf[256];
60               size_t len = regerror (err, NULL, ebuf, 256);
61               self->string = rxpd_malloc (len + strlen(namestart+1) + 14);
62               strcpy (self->string, "#ERROR: ");
63               strcat (self->string, ebuf);
64               strcat (self->string, " in '");
65               strcat (self->string, namestart+1);
66               strcat (self->string, "'");
67             }
68         }
69     }
70   else
71     self->string = rxpd_strdup (buf);
72
73   return self;
74 }
75
76 struct rxpd_rule*
77 rxpd_rule_copy (const struct rxpd_rule* src)
78 {
79   struct rxpd_rule* self = rxpd_malloc (sizeof (struct rxpd_rule));
80
81   llist_init (&self->node);
82   self->string = rxpd_strdup (src->string);
83   self->atime = src->atime;
84
85   if (*self->string != '#')
86     {
87       int err;
88       char* rxstart = strchr (self->string, ':');
89
90       // TODO regflags from base
91       err = regcomp (&self->rx, rxstart+1, REG_EXTENDED|REG_ICASE|REG_NOSUB);
92       if (err)
93         rxpd_die ("unexpected regcomp error\n");
94     }
95
96   return self;
97 }
98
99 struct rxpd_rule*
100 rxpd_rule_comment (struct rxpd_rule* self, const char* comment)
101 {
102   if (self)
103     {
104       int len;
105       if (self->atime != -1)
106         len = snprintf (NULL, 0, "#%s: %ld:%s", comment, self->atime, self->string);
107       else if (self->string[0] != '#')
108         len = snprintf (NULL, 0, "#%s: :%s", comment, self->string);
109       else
110         len = snprintf (NULL, 0, "#%s: %s", comment, self->string);
111
112       if (len < 0)
113         return NULL;
114
115       char* dst = rxpd_malloc (len+1);
116
117       if (self->atime != -1)
118         snprintf (dst, len+1, "#%s: %ld:%s", comment, self->atime, self->string);
119       else if (self->string[0] != '#')
120         snprintf (dst, len+1, "#%s: :%s", comment, self->string);
121       else
122         snprintf (dst, len+1, "#%s: %s", comment, self->string);
123
124       if (self->string[0] != '#')
125         regfree (&self->rx);
126
127       self->atime = -1;
128
129       free (self->string);
130       self->string = dst;
131     }
132   return self;
133 }
134
135 void
136 rxpd_rule_delete (struct rxpd_rule* rule)
137 {
138   if (rule)
139     {
140       llist_unlink (&rule->node);
141       if (rule->string[0] != '#')
142         regfree (&rule->rx);
143       free (rule->string);
144       free(rule);
145     }
146 }
147
148