rule_acticvate function to 'uncomment' rules
[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               char ebuf[256];
59               size_t len = regerror (err, NULL, ebuf, 256);
60               self->string = rxpd_malloc (len + strlen(namestart+1) + 14);
61               strcpy (self->string, "#ERROR: ");
62               strcat (self->string, ebuf);
63               strcat (self->string, " in '");
64               strcat (self->string, namestart+1);
65               strcat (self->string, "'");
66             }
67         }
68     }
69   else
70     self->string = rxpd_strdup (buf);
71
72   return self;
73 }
74
75 struct rxpd_rule*
76 rxpd_rule_copy (const struct rxpd_rule* src)
77 {
78   struct rxpd_rule* self = rxpd_malloc (sizeof (struct rxpd_rule));
79
80   llist_init (&self->node);
81   self->string = rxpd_strdup (src->string);
82   self->atime = src->atime;
83
84   if (*self->string != '#')
85     {
86       int err;
87       char* rxstart = strchr (self->string, ':');
88
89       // TODO regflags from base
90       err = regcomp (&self->rx, rxstart+1, REG_EXTENDED|REG_ICASE|REG_NOSUB);
91       if (err)
92         rxpd_die ("unexpected regcomp error\n");
93     }
94
95   return self;
96 }
97
98 struct rxpd_rule*
99 rxpd_rule_activate (struct rxpd_rule* self)
100 {
101   if (self)
102     {
103       char* buf;
104       if (self->string[0] == '#' && (buf = strstr (self->string, ": ")+2) && *buf)
105         {
106           if (*buf != '#')
107             {
108               char* namestart = strchr (buf, ':');
109               char* rxstart = namestart? strchr (namestart+1, ':') : NULL;
110
111               if (!rxstart)
112                 return NULL;
113
114               // TODO regflags from base
115               if (regcomp (&self->rx, rxstart+1, REG_EXTENDED|REG_ICASE|REG_NOSUB))
116                 return NULL;
117
118               free (self->string);
119               self->string = rxpd_strdup (namestart+1);
120
121               if (namestart != buf)
122                 {
123                   /* atime given */
124                   self->atime = atoi (buf);
125                   if (!self->atime)
126                     /* atime was zero or not set */
127                     self->atime = time (NULL)-1;
128                 }
129             }
130           else
131             self->string = rxpd_strdup (buf);
132         }
133       else
134         return NULL;
135     }
136   return self;
137 }
138
139 struct rxpd_rule*
140 rxpd_rule_comment (struct rxpd_rule* self, const char* comment)
141 {
142   if (self)
143     {
144       int len;
145       if (self->atime != -1)
146         len = snprintf (NULL, 0, "#%s: %ld:%s", comment, self->atime, self->string);
147       else if (self->string[0] != '#')
148         len = snprintf (NULL, 0, "#%s: :%s", comment, self->string);
149       else
150         len = snprintf (NULL, 0, "#%s: %s", comment, self->string);
151
152       if (len < 0)
153         return NULL;
154
155       char* dst = rxpd_malloc (len+1);
156
157       if (self->atime != -1)
158         snprintf (dst, len+1, "#%s: %ld:%s", comment, self->atime, self->string);
159       else if (self->string[0] != '#')
160         snprintf (dst, len+1, "#%s: :%s", comment, self->string);
161       else
162         snprintf (dst, len+1, "#%s: %s", comment, self->string);
163
164       if (self->string[0] != '#')
165         regfree (&self->rx);
166
167       self->atime = -1;
168
169       free (self->string);
170       self->string = dst;
171     }
172   return self;
173 }
174
175 void
176 rxpd_rule_delete (struct rxpd_rule* rule)
177 {
178   if (rule)
179     {
180       llist_unlink (&rule->node);
181       if (rule->string[0] != '#')
182         regfree (&rule->rx);
183       free (rule->string);
184       free(rule);
185     }
186 }
187
188