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

Contents of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show 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 #include <stdio.h>
2 #include <errno.h>
3 #include <sys/types.h>
4 #include <regex.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <limits.h>
8 #include <sys/stat.h>
9
10 #include "config.h"
11 #include "imapfilter.h"
12 #include "file.h"
13 #include "log.h"
14
15
16 extern char logfile[PATH_MAX];
17 extern unsigned int options;
18
19 account_t *accounts = NULL; /* All accounts. */
20
21 filter_t *dfilters = NULL; /* Filters of DENY type. */
22 filter_t *afilters = NULL; /* Filters of ALLOW type. */
23
24 unsigned int dlimit = 0;
25 unsigned int alimit = 0; /* DENY and ALLOW message size limits. */
26
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
41 home = getenv("HOME");
42
43 snprintf(cfg, PATH_MAX, "%s/%s", home, ".imapfilterrc");
44 }
45 #ifdef DEBUG
46 printf("debug: configuration file: '%s'\n", cfg);
47 #endif
48 #ifdef PERMISSIONS
49 check_perms(cfg);
50 #endif
51 fp = fopen(cfg, "r");
52
53 if (!fp) {
54 error("imapfilter: opening config file %s; %s\n",
55 cfg, strerror(errno));
56 return 1;
57 }
58
59 r = parse_config(fp);
60
61 fclose(fp);
62
63 #ifdef DEBUG
64 printf("debug: options: %0#10x\n", options);
65 #endif
66
67 return r;
68 }
69
70
71 #ifdef PERMISSIONS
72 /*
73 * Checks the permissions of the configuration file.
74 */
75 int check_perms(char *cfg)
76 {
77 struct stat fs;
78
79 if (stat(cfg, &fs)) {
80 error("imapfilter: getting file %s status; %s\n", cfg,
81 strerror(errno));
82 return 1;
83 }
84
85 if (!S_ISREG(fs.st_mode)) {
86 error("imapfilter: file %s not a regular file\n", cfg);
87 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 #endif
101
102 /*
103 * 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 regex_t creg[7];
111 regmatch_t match[4];
112 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 };
121
122 for (i = 0; i < 7; i++)
123 regcomp(&creg[i], reg[i], REG_EXTENDED);
124
125 while (fgets(line, LINE_MAX - 1, fp)) {
126 row++;
127 if (!regexec(&creg[0], line, 3, match, 0)) {
128 if (set_account(line, match))
129 return 1;
130 continue;
131 } else if (!regexec(&creg[1], line, 4, match, 0)) {
132 if (standard_filter(line, match))
133 return 1;
134 continue;
135 } else if (!regexec(&creg[2], line, 4, match, 0)) {
136 if (custom_filter(line, match))
137 return 1;
138 continue;
139 } else if (!regexec(&creg[3], line, 3, match, 0)) {
140 set_limits(line, match);
141 continue;
142 } else if (!regexec(&creg[4], line, 3, match, 0) ||
143 !regexec(&creg[5], line, 3, match, 0)) {
144 set_options(line, match);
145 continue;
146 } 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 return 1;
152 }
153 }
154
155 /* Fail if no accounts were defined. */
156 if (!accounts) {
157 fprintf(stderr,
158 "imapfilter: no accounts defined in config file\n");
159 return 1;
160 }
161
162 /* Fail if no filters were defined. */
163 if (!dfilters && !afilters) {
164 error("imapfilter: no filters defined in config file\n");
165 return 1;
166 }
167
168 for (i = 0; i < 7; i++)
169 regfree(&creg[i]);
170
171 return 0;
172 }
173
174
175 /*
176 * Allocates memory for accounts, builds linked list, and NULL terminates
177 * account settings.
178 */
179 account_t *prepare_account(void)
180 {
181 static account_t *ca; /* Current account. */
182
183 if (!accounts) {
184 accounts = (account_t *) malloc(sizeof(account_t));
185 if (!accounts) {
186 error("imapfilter: allocating memory; %s\n", strerror(errno));
187 return NULL;
188 }
189 ca = accounts;
190 } else {
191 ca->next = (account_t *) malloc(sizeof(account_t));
192 if (!ca->next) {
193 error("imapfilter: allocating memory; %s\n", strerror(errno));
194 return NULL;
195 }
196 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
206 return ca;
207 }
208
209
210 /*
211 * An account setting was found from parse_config(), changes the
212 * apropriate variable.
213 */
214 int set_account(char *line, regmatch_t * match)
215 {
216 int s;
217 char p[6];
218 static account_t *ca;
219
220 if (!strncmp(line + match[1].rm_so, "SERVER", 6)) {
221 if (!(ca = prepare_account()))
222 return 1;
223 s = min((match[2].rm_eo - match[2].rm_so), SERVER_MAX - 1);
224 strncpy(ca->server, line + match[2].rm_so, s);
225 ca->server[s] = 0;
226 #ifdef DEBUG
227 printf("debug: account setting SERVER: '%s'\n", ca->server);
228 #endif
229 } else if (accounts) {
230 if (!strncmp(line + match[1].rm_so, "PORT", 4)) {
231 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 #ifdef DEBUG
236 printf("debug: account setting PORT: %d\n", ca->port);
237 #endif
238 } else if (!strncmp(line + match[1].rm_so, "USERNAME", 8)) {
239 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 #ifdef DEBUG
243 printf("debug: account setting USERNAME: '%s'\n", ca->userid);
244 #endif
245 } else if (!strncmp(line + match[1].rm_so, "PASSWORD", 8)) {
246 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 #ifdef DEBUG
250 printf("debug: account setting PASSWORD: '%s'\n", ca->passwd);
251 #endif
252 }
253 }
254
255 return 0;
256 }
257
258
259 /*
260 * A filter entry was found from parse_config() processes it and saves it.
261 */
262 int set_filters(char *line, regmatch_t * match, int csm)
263 {
264 int s;
265 static filter_t *cdf, *caf;
266 filter_t **cf;
267 filter_t **fl;
268
269 if (!(strncmp(line + match[1].rm_so, "DENY", 4))) {
270 #ifdef DEBUG
271 printf("debug: filter entry DENY:");
272 #endif
273 cf = &cdf;
274 fl = &dfilters;
275 } else {
276 #ifdef DEBUG
277 printf("debug: filter entry ALLOW:");
278 #endif
279 cf = &caf;
280 fl = &afilters;
281 }
282
283 /*
284 * Allocate memory for filter entry and build linked list.
285 */
286
287 if (!(*fl)) {
288 *fl = (filter_t *) malloc(sizeof(filter_t));
289 if (!(*fl)) {
290 error("imapfilter: allocating memory; %s\n", strerror(errno));
291 return 1;
292 }
293 *cf = *fl;
294 } else {
295 (*cf)->next = (filter_t *) malloc(sizeof(filter_t));
296 if (!((*cf)->next)) {
297 error("imapfilter: allocating memory; %s\n", strerror(errno));
298 return 1;
299 }
300 *cf = (*cf)->next;
301 }
302
303 (*cf)->next = NULL;
304
305 (*cf)->custom = csm;
306
307 s = min((match[2].rm_eo - match[2].rm_so), FIELD_NAME_MAX - 1);
308 strncpy((*cf)->name, line + match[2].rm_so, s);
309 (*cf)->name[s] = 0;
310
311 s = min((match[3].rm_eo - match[3].rm_so), FIELD_BODY_MAX - 1);
312 strncpy((*cf)->body, line + match[3].rm_so, s);
313 (*cf)->body[s] = 0;
314
315 #ifdef DEBUG
316 printf(" '%s' '%s'\n", (*cf)->name, (*cf)->body);
317 #endif
318 return 0;
319 }
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 char lim[10];
329
330 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
334 if (!strncmp(line + match[1].rm_so, "DENY_LIMIT", 10)) {
335 dlimit = strtoul(lim, NULL, 0);
336 #ifdef DEBUG
337 printf("debug: size filter DENY_LIMIT: %d\n", dlimit);
338 #endif
339 } else {
340 alimit = strtoul(lim, NULL, 0);
341 #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 }
376 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26