/[imapfilter]/imapfilter/file.c
ViewVC logotype

Annotation of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (hide annotations)
Sun Aug 26 19:37:45 2001 UTC (22 years, 7 months ago) by lefcha
Branch: MAIN
Changes since 1.10: +73 -31 lines
File MIME type: text/plain
New options and a bug fix  related to parsing of config file.

1 lefcha 1.1 #include <stdio.h>
2     #include <errno.h>
3 lefcha 1.5 #include <sys/types.h>
4 lefcha 1.1 #include <regex.h>
5     #include <string.h>
6     #include <stdlib.h>
7     #include <limits.h>
8 lefcha 1.10 #include <sys/stat.h>
9 lefcha 1.1
10     #include "config.h"
11     #include "imapfilter.h"
12     #include "file.h"
13     #include "log.h"
14    
15    
16 lefcha 1.6 extern char logfile[PATH_MAX];
17 lefcha 1.11 extern unsigned int options;
18 lefcha 1.8
19     account_t *accounts = NULL; /* All accounts. */
20    
21 lefcha 1.11 filter_t *dfilters = NULL; /* Filters of DENY type. */
22     filter_t *afilters = NULL; /* Filters of ALLOW type. */
23 lefcha 1.8
24 lefcha 1.4 unsigned int dlimit = 0;
25     unsigned int alimit = 0; /* DENY and ALLOW message size limits. */
26 lefcha 1.1
27    
28     /*
29     * Finds path to configuration file, opens it and calls parse_config().
30     */
31     int read_config(char *cfg)
32     {
33     int r;
34     FILE *fp;
35     char *home = NULL;
36    
37     if (!cfg) {
38     cfg = (char *) malloc(PATH_MAX * sizeof(char));
39    
40 lefcha 1.8
41 lefcha 1.1 home = getenv("HOME");
42    
43     snprintf(cfg, PATH_MAX, "%s/%s", home, ".imapfilterrc");
44     }
45     #ifdef DEBUG
46 lefcha 1.11 printf("debug: configuration file: '%s'\n", cfg);
47 lefcha 1.1 #endif
48    
49 lefcha 1.10 check_permissions(cfg);
50    
51 lefcha 1.1 fp = fopen(cfg, "r");
52    
53     if (!fp) {
54 lefcha 1.11 error("imapfilter: opening config file %s; %s\n",
55     cfg, strerror(errno));
56 lefcha 1.8 return 1;
57 lefcha 1.1 }
58    
59     r = parse_config(fp);
60    
61     fclose(fp);
62    
63 lefcha 1.11 #ifdef DEBUG
64     printf("debug: options: %0#10x\n", options);
65     #endif
66    
67 lefcha 1.1 return r;
68     }
69    
70 lefcha 1.6
71 lefcha 1.1 /*
72 lefcha 1.10 * Checks the permissions of the configuration file.
73     */
74     int check_permissions(char *cfg)
75     {
76     struct stat fs;
77    
78     if (stat(cfg, &fs)) {
79 lefcha 1.11 error("imapfilter: getting file %s status; %s\n", cfg,
80     strerror(errno));
81 lefcha 1.10 return 1;
82     }
83    
84     if (!S_ISREG(fs.st_mode)) {
85 lefcha 1.11 error("imapfilter: file %s not a regular file\n", cfg);
86 lefcha 1.10 return 1;
87     }
88    
89     if ((fs.st_mode & 00777) != (S_IRUSR | S_IWUSR)) {
90     fprintf(stderr,
91     "imapfilter: warning: bad config file %s permissions\n"
92     "imapfilter: warning: file's mode should be 600 not %o\n",
93     cfg, fs.st_mode & 00777);
94     return 1;
95     }
96    
97     return 0;
98     }
99    
100    
101     /*
102 lefcha 1.1 * Parses configuration file.
103     */
104     int parse_config(FILE * fp)
105     {
106     int i;
107     unsigned int row = 0;
108     char line[LINE_MAX];
109 lefcha 1.11 regex_t creg[7];
110 lefcha 1.2 regmatch_t match[4];
111 lefcha 1.11 const char *reg[7] = {
112     "^[[:blank:]]*(SERVER|PORT|USERNAME|PASSWORD)[[:blank:]]*=[[:blank:]]*([[:graph:]]*)[[:blank:]]*\n$",
113     "^[[:blank:]]*(DENY|ALLOW)[[:blank:]]*=[[:blank:]]*(FROM|CC|BCC|SUBJECT|TO):? ([[:print:]]*)\n$",
114     "^[[:blank:]]*(DENY|ALLOW)[[:blank:]]*=[[:blank:]]*([[:graph:]]+):? ([[:print:]]*)\n$",
115     "^[[:blank:]]*(DENY_LIMIT|ALLOW_LIMIT)[[:blank:]]*=[[:blank:]]*([[:digit:]]*)[[:blank:]]*\n$",
116     "^[[:blank:]]*(LOGFILE)[[:blank:]]*=[[:blank:]]*([[:graph:]]*)[[:blank:]]*\n$",
117     "^[[:blank:]]*(TEST_MODE|SHOW_HEADERS|UNSEEN_ONLY)[[:blank:]]*=[[:blank:]]*(yes|no)[[:blank:]]*\n$",
118     "^([[:blank:]]*\n|#.*\n)$"
119 lefcha 1.1 };
120    
121 lefcha 1.11 for (i = 0; i < 7; i++)
122 lefcha 1.8 regcomp(&creg[i], reg[i], REG_EXTENDED);
123 lefcha 1.1
124     while (fgets(line, LINE_MAX - 1, fp)) {
125     row++;
126 lefcha 1.8 if (!regexec(&creg[0], line, 3, match, 0)) {
127 lefcha 1.9 if (set_account(line, match))
128     return 1;
129 lefcha 1.1 continue;
130 lefcha 1.8 } else if (!regexec(&creg[1], line, 4, match, 0)) {
131 lefcha 1.9 if (standard_filter(line, match))
132     return 1;
133 lefcha 1.1 continue;
134 lefcha 1.8 } else if (!regexec(&creg[2], line, 4, match, 0)) {
135 lefcha 1.9 if (custom_filter(line, match))
136     return 1;
137 lefcha 1.1 continue;
138 lefcha 1.8 } else if (!regexec(&creg[3], line, 3, match, 0)) {
139 lefcha 1.4 set_limits(line, match);
140     continue;
141 lefcha 1.11 } else if (!regexec(&creg[4], line, 3, match, 0) ||
142     !regexec(&creg[5], line, 3, match, 0)) {
143     set_options(line, match);
144 lefcha 1.1 continue;
145 lefcha 1.11 } else if (!regexec(&creg[6], line, 0, match, 0)) {
146     continue;
147     } else {
148     error("imapfilter: parse error in config file at row %d\n",
149     row);
150 lefcha 1.8 return 1;
151 lefcha 1.1 }
152     }
153 lefcha 1.3
154 lefcha 1.6 /* Fail if no accounts were defined. */
155 lefcha 1.8 if (!accounts) {
156 lefcha 1.6 fprintf(stderr,
157     "imapfilter: no accounts defined in config file\n");
158 lefcha 1.8 return 1;
159 lefcha 1.6 }
160    
161 lefcha 1.8 /* Fail if no filters were defined. */
162     if (!dfilters && !afilters) {
163 lefcha 1.11 error("imapfilter: no filters defined in config file\n");
164 lefcha 1.8 return 1;
165 lefcha 1.3 }
166 lefcha 1.6
167 lefcha 1.8 return 0;
168 lefcha 1.1 }
169    
170    
171     /*
172 lefcha 1.9 * Allocates memory for accounts, builds linked list, and NULL terminates
173 lefcha 1.8 * account settings.
174 lefcha 1.4 */
175 lefcha 1.8 account_t *prepare_account(void)
176 lefcha 1.4 {
177 lefcha 1.8 static account_t *ca; /* Current account. */
178    
179     if (!accounts) {
180     accounts = (account_t *) malloc(sizeof(account_t));
181 lefcha 1.9 if (!accounts) {
182     error("imapfilter: allocating memory; %s\n", strerror(errno));
183     return NULL;
184 lefcha 1.10 }
185 lefcha 1.8 ca = accounts;
186     } else {
187     ca->next = (account_t *) malloc(sizeof(account_t));
188 lefcha 1.9 if (!ca->next) {
189     error("imapfilter: allocating memory; %s\n", strerror(errno));
190     return NULL;
191     }
192 lefcha 1.8 ca = ca->next;
193     }
194    
195     ca->next = NULL;
196    
197     ca->server[0] = 0;
198     ca->port = 143;
199     ca->userid[0] = 0;
200     ca->passwd[0] = 0;
201 lefcha 1.6
202 lefcha 1.8 return ca;
203 lefcha 1.4 }
204    
205    
206     /*
207 lefcha 1.1 * An account setting was found from parse_config(), changes the
208     * apropriate variable.
209     */
210 lefcha 1.9 int set_account(char *line, regmatch_t * match)
211 lefcha 1.1 {
212     int s;
213 lefcha 1.8 char p[6];
214     static account_t *ca;
215 lefcha 1.1
216     if (!strncmp(line + match[1].rm_so, "SERVER", 6)) {
217 lefcha 1.9 if (!(ca = prepare_account()))
218     return 1;
219 lefcha 1.1 s = min((match[2].rm_eo - match[2].rm_so), SERVER_MAX - 1);
220 lefcha 1.8 strncpy(ca->server, line + match[2].rm_so, s);
221     ca->server[s] = 0;
222 lefcha 1.6 #ifdef DEBUG
223 lefcha 1.8 printf("debug: account setting SERVER: '%s'\n", ca->server);
224 lefcha 1.6 #endif
225 lefcha 1.8 } else if (accounts) {
226 lefcha 1.6 if (!strncmp(line + match[1].rm_so, "PORT", 4)) {
227 lefcha 1.8 s = min((match[2].rm_eo - match[2].rm_so), sizeof(p));
228     strncpy(p, line + match[2].rm_so, s);
229     p[s] = 0;
230     ca->port = strtoul(p, NULL, 0);
231 lefcha 1.6 #ifdef DEBUG
232 lefcha 1.11 printf("debug: account setting PORT: %d\n", ca->port);
233 lefcha 1.7 #endif
234 lefcha 1.6 } else if (!strncmp(line + match[1].rm_so, "USERNAME", 8)) {
235 lefcha 1.8 s = min((match[2].rm_eo - match[2].rm_so), USERID_MAX - 1);
236     strncpy(ca->userid, line + match[2].rm_so, s);
237     ca->userid[s] = 0;
238 lefcha 1.6 #ifdef DEBUG
239 lefcha 1.8 printf("debug: account setting USERNAME: '%s'\n", ca->userid);
240 lefcha 1.7 #endif
241 lefcha 1.6 } else if (!strncmp(line + match[1].rm_so, "PASSWORD", 8)) {
242 lefcha 1.8 s = min((match[2].rm_eo - match[2].rm_so), PASSWD_MAX - 1);
243     strncpy(ca->passwd, line + match[2].rm_so, s);
244     ca->passwd[s] = 0;
245 lefcha 1.6 #ifdef DEBUG
246 lefcha 1.8 printf("debug: account setting PASSWORD: '%s'\n", ca->passwd);
247 lefcha 1.6 #endif
248     }
249 lefcha 1.1 }
250 lefcha 1.10
251 lefcha 1.9 return 0;
252 lefcha 1.1 }
253    
254    
255     /*
256 lefcha 1.4 * A filter entry was found from parse_config() processes it and saves it.
257 lefcha 1.1 */
258 lefcha 1.9 int set_filters(char *line, regmatch_t * match, int csm)
259 lefcha 1.1 {
260     int s;
261 lefcha 1.8 static filter_t *cdf, *caf;
262     filter_t **cf;
263     filter_t **fl;
264 lefcha 1.2
265     if (!(strncmp(line + match[1].rm_so, "DENY", 4))) {
266     #ifdef DEBUG
267 lefcha 1.11 printf("debug: filter entry DENY:");
268 lefcha 1.2 #endif
269 lefcha 1.8 cf = &cdf;
270     fl = &dfilters;
271 lefcha 1.2 } else {
272     #ifdef DEBUG
273 lefcha 1.11 printf("debug: filter entry ALLOW:");
274 lefcha 1.2 #endif
275 lefcha 1.8 cf = &caf;
276     fl = &afilters;
277 lefcha 1.2 }
278 lefcha 1.1
279 lefcha 1.8 /*
280     * Allocate memory for filter entry and build linked list.
281     */
282    
283     if (!(*fl)) {
284     *fl = (filter_t *) malloc(sizeof(filter_t));
285 lefcha 1.9 if (!(*fl)) {
286     error("imapfilter: allocating memory; %s\n", strerror(errno));
287     return 1;
288 lefcha 1.10 }
289 lefcha 1.8 *cf = *fl;
290     } else {
291     (*cf)->next = (filter_t *) malloc(sizeof(filter_t));
292 lefcha 1.9 if (!((*cf)->next)) {
293     error("imapfilter: allocating memory; %s\n", strerror(errno));
294     return 1;
295     }
296 lefcha 1.8 *cf = (*cf)->next;
297     }
298 lefcha 1.2
299 lefcha 1.8 (*cf)->next = NULL;
300 lefcha 1.2
301 lefcha 1.8 (*cf)->custom = csm;
302 lefcha 1.2
303     s = min((match[2].rm_eo - match[2].rm_so), FIELD_NAME_MAX - 1);
304 lefcha 1.8 strncpy((*cf)->name, line + match[2].rm_so, s);
305     (*cf)->name[s] = 0;
306 lefcha 1.2
307     s = min((match[3].rm_eo - match[3].rm_so), FIELD_BODY_MAX - 1);
308 lefcha 1.8 strncpy((*cf)->body, line + match[3].rm_so, s);
309     (*cf)->body[s] = 0;
310 lefcha 1.1
311     #ifdef DEBUG
312 lefcha 1.11 printf(" '%s' '%s'\n", (*cf)->name, (*cf)->body);
313 lefcha 1.1 #endif
314 lefcha 1.9 return 0;
315 lefcha 1.4 }
316    
317    
318     /*
319     * Sets the DENY and ALLOW limits from the values found in config file.
320     */
321     void set_limits(char *line, regmatch_t * match)
322     {
323     int s;
324 lefcha 1.8 char lim[10];
325 lefcha 1.4
326 lefcha 1.8 s = min((match[2].rm_eo - match[2].rm_so), sizeof(lim));
327     strncpy(lim, line + match[2].rm_so, s);
328     lim[s] = 0;
329 lefcha 1.4
330     if (!strncmp(line + match[1].rm_so, "DENY_LIMIT", 10)) {
331 lefcha 1.8 dlimit = strtoul(lim, NULL, 0);
332 lefcha 1.11 #ifdef DEBUG
333     printf("debug: size filter DENY_LIMIT: %d\n", dlimit);
334     #endif
335 lefcha 1.4 } else {
336 lefcha 1.8 alimit = strtoul(lim, NULL, 0);
337 lefcha 1.11 #ifdef DEBUG
338     printf("debug: size filter ALLOW_LIMIT: %d\n", alimit);
339     #endif
340     }
341     }
342    
343    
344     /*
345     * Sets other options found in config file.
346     */
347     void set_options(char *line, regmatch_t * match)
348     {
349     int s;
350    
351     if (!logfile[0] && !strncmp(line + match[1].rm_so, "LOGFILE", 7)) {
352     s = min((match[2].rm_eo - match[2].rm_so), PATH_MAX - 1);
353     strncpy(logfile, line + match[2].rm_so, s);
354     logfile[s] = 0;
355     } else if (!strncmp(line + match[1].rm_so, "TEST_MODE", 9) &&
356     !(options & OPT_TEST_MODE_STICKY)) {
357     if (!strncmp(line + match[2].rm_so, "yes", 3))
358     options |= OPT_TEST_MODE;
359     else if (options & OPT_TEST_MODE)
360     options ^= OPT_TEST_MODE;
361     } else if (!strncmp(line + match[1].rm_so, "SHOW_HEADERS", 12)) {
362     if (!strncmp(line + match[2].rm_so, "yes", 3))
363     options |= OPT_SHOW_HEADERS;
364     else if (options & OPT_UNSEEN_ONLY)
365     options ^= OPT_SHOW_HEADERS;
366     } else if (!strncmp(line + match[1].rm_so, "UNSEEN_ONLY", 11)) {
367     if (!strncmp(line + match[2].rm_so, "yes", 3))
368     options |= OPT_UNSEEN_ONLY;
369     else if (options & OPT_UNSEEN_ONLY)
370     options ^= OPT_UNSEEN_ONLY;
371 lefcha 1.4 }
372 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26