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

Annotation of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (hide annotations)
Tue Aug 28 22:43:36 2001 UTC (22 years, 7 months ago) by lefcha
Branch: MAIN
Changes since 1.11: +9 -5 lines
File MIME type: text/plain
Minor changes.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26