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

Contents of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.28 - (show annotations)
Sat Dec 8 14:39:10 2001 UTC (22 years, 3 months ago) by lefcha
Branch: MAIN
Changes since 1.27: +140 -35 lines
File MIME type: text/plain
Added functions for creation and checking of dirs and files.

1 #include <stdio.h>
2 #include <unistd.h>
3 #include <errno.h>
4 #include <sys/types.h>
5 #include <regex.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <limits.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11
12 #include "config.h"
13 #include "imapfilter.h"
14 #include "data.h"
15
16
17 extern char logfile[PATH_MAX];
18 extern unsigned int options;
19 extern long timeout;
20
21
22 /*
23 * Create $HOME/.imapfilter directory.
24 */
25 int create_homedir(void)
26 {
27 char *hdname = ".imapfilter";
28 char *home = NULL;
29
30 home = getenv("HOME");
31
32 if (home)
33 if (chdir(home))
34 error("imapfilter: could not change directory; %s\n",
35 strerror(errno));
36
37 create_dir(hdname, S_IRUSR | S_IWUSR | S_IXUSR);
38
39 return 0;
40 }
41
42
43 /*
44 * Create a file.
45 */
46 int create_file(char *fname, mode_t mode)
47 {
48 int fd;
49 struct stat fs;
50
51 if (access(fname, F_OK)) {
52 fd = creat(fname, mode);
53 if (fd == -1) {
54 error("imapfilter: could not create file %s; %s\n", fname,
55 strerror(errno));
56 return ERROR_FILE_OPEN;
57 }
58 close(fd);
59 } else {
60 stat(fname, &fs);
61 if (!S_ISREG(fs.st_mode)) {
62 error("imapfilter: file %s not a regular file\n", fname);
63 return ERROR_FILE_OPEN;
64 }
65 }
66
67 return 0;
68 }
69
70
71 /*
72 * Create a directory.
73 */
74 int create_dir(char *dname, mode_t mode)
75 {
76 struct stat ds;
77
78 if (access(dname, F_OK)) {
79 if (mkdir(dname, mode))
80 error("imapfilter: could not create directory %s; %s\n", dname,
81 strerror(errno));
82 } else {
83 stat(dname, &ds);
84 if (!S_ISDIR(ds.st_mode))
85 error("imapfilter: file %s not a directory\n", dname);
86 }
87
88 return 0;
89 }
90
91
92 #ifdef CHECK_PERMISSIONS
93 /*
94 * Check the permissions of a file.
95 */
96 int check_file_perms(char *fname, mode_t mode)
97 {
98 struct stat fs;
99
100 if (stat(fname, &fs)) {
101 error("imapfilter: getting file %s status; %s\n", fname,
102 strerror(errno));
103 return ERROR_TRIVIAL;
104 }
105 if (!S_ISREG(fs.st_mode)) {
106 error("imapfilter: file %s not a regular file\n", fname);
107 return ERROR_TRIVIAL;
108 }
109 if ((fs.st_mode & 00777) != mode) {
110 error("imapfilter: warning: improper file %s permissions\n"
111 "imapfilter: warning: file's mode should be %o not %o\n",
112 fname, mode, fs.st_mode & 00777);
113 return ERROR_TRIVIAL;
114 }
115
116 return 0;
117 }
118
119
120 /*
121 * Check the permissions of a directory.
122 */
123 int check_dir_perms(char *dname, mode_t mode)
124 {
125 struct stat ds;
126
127 if(stat(dname, &ds)) {
128 error("imapfilter: getting file %s status; %s\n", dname,
129 strerror(errno));
130 return ERROR_TRIVIAL;
131 }
132 if (!S_ISDIR(ds.st_mode)) {
133 error("imapfilter: file %s not a directory\n", dname);
134 return ERROR_TRIVIAL;
135 }
136 if ((ds.st_mode & 00777) != mode) {
137 error("imapfilter: warning: improper dir %s permissions\n"
138 "imapfilter: warning: file's mode should be %o not %o\n",
139 dname, mode, ds.st_mode & 00777);
140 return ERROR_TRIVIAL;
141 }
142
143 return 0;
144 }
145 #endif
146
147
148 /*
149 * Find the path to configuration file, open it and call parse_config().
150 */
151 int read_config(char *cfg)
152 {
153 int r;
154 FILE *fp;
155 char *home = NULL;
156 char *c = NULL;
157
158 if (!cfg) {
159 cfg = c = (char *) xmalloc(PATH_MAX * sizeof(char));
160
161 home = getenv("HOME");
162
163 snprintf(cfg, PATH_MAX, "%s/%s", home, ".imapfilterrc");
164 }
165 #ifdef DEBUG
166 printf("debug: configuration file: '%s'\n", cfg);
167 #endif
168 #ifdef CHECK_PERMISSIONS
169 check_file_perms(cfg, S_IRUSR | S_IWUSR);
170 #endif
171 fp = fopen(cfg, "r");
172
173 if (!fp)
174 fatal(ERROR_FILE_OPEN, "imapfilter: opening config file %s; %s\n",
175 cfg, strerror(errno));
176
177 if (c)
178 free(c);
179
180 if ((r = parse_config(fp)))
181 fatal(ERROR_CONFIG_PARSE,
182 "imapfilter: parse error in config file at row %d\n", r);
183
184 fclose(fp);
185
186 #ifdef DEBUG
187 printf("debug: options: %0#10x\n", options);
188 #endif
189
190 return 0;
191 }
192
193
194 /*
195 * Parse configuration file.
196 */
197 int parse_config(FILE * fp)
198 {
199 int i, r = 0;
200 unsigned int row = 0;
201 char line[LINE_MAX];
202 regex_t creg[13];
203 regmatch_t match[8];
204 const char *reg[13] = {
205 "^([[:blank:]]*\n|#.*\n)$",
206 #ifndef SSL_TLS
207 "^[[:blank:]]*ACCOUNT[[:blank:]]+(([[:graph:]]+):([[:graph:]]*)|([[:graph:]]+))@([[:alnum:].-]+)(:[[:digit:]]+)?[[:blank:]]*\n$",
208 #else
209 "^[[:blank:]]*ACCOUNT[[:blank:]]+(([[:graph:]]+):([[:graph:]]*)|([[:graph:]]+))@([[:alnum:].-]+)(:[[:digit:]]+)?[[:blank:]]*([[:blank:]]SSL|[[:blank:]]SSL2|[[:blank:]]SSL3|[[:blank:]]TLS1)?[[:blank:]]*\n$",
210 #endif
211 "^[[:blank:]]*FOLDER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+([[:graph:]]+)[[:blank:]]*\n$",
212 "^[[:blank:]]*FILTER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]*([[:blank:]]OR|[[:blank:]]AND)?[[:blank:]]*\n$",
213 "^[[:blank:]]*ACTION[[:blank:]]+(DELETE|COPY[[:blank:]]+([[:graph:]]+)|MOVE[[:blank:]]+([[:graph:]]+)|LIST)[[:blank:]]*([[:graph:]]*)[[:blank:]]*\n$",
214 "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*(ANSWERED|DELETED|DRAFT|FLAGGED|NEW|OLD|RECENT|SEEN|UNANSWERED|UNDELETED|UNDRAFT|UNFLAGGED|UNSEEN)[[:blank:]]*\n$",
215 "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*(BCC|BODY|CC|FROM|SUBJECT|TEXT|TO)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]*\n$",
216 "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*(HEADER)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]*\n$",
217 "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*(LARGER|SMALLER|OLDER|NEWER)[[:blank:]]+([[:digit:]]+)[[:blank:]]*\n$",
218 "^[[:blank:]]*JOB[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]*\n$",
219 "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(LOGFILE)[[:blank:]]*=[[:blank:]]*([[:print:]]+)\n$",
220 "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(HEADERS|NAMESPACE)[[:blank:]]*=[[:blank:]]*(YES|NO)[[:blank:]]*\n$",
221 "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(TIMEOUT)[[:blank:]]*=[[:blank:]]*(-?[[:digit:]]+)\n$"
222 };
223
224 for (i = 0; i < 13; i++)
225 regcomp(&creg[i], reg[i], REG_EXTENDED | REG_ICASE);
226
227 while (fgets(line, LINE_MAX - 1, fp)) {
228 row++;
229 if (!regexec(&creg[0], line, 0, match, 0))
230 continue;
231 #ifndef SSL_TLS
232 else if (!regexec(&creg[1], line, 7, match, 0))
233 #else
234 else if (!regexec(&creg[1], line, 8, match, 0))
235 #endif
236 set_account(line, match);
237 else if (!regexec(&creg[2], line, 3, match, 0))
238 r = set_mboxgrp(line, match);
239 else if (!regexec(&creg[3], line, 3, match, 0))
240 r = set_filter(line, match);
241 else if (!regexec(&creg[4], line, 5, match, 0))
242 r = set_action(line, match);
243 else if (!regexec(&creg[5], line, 7, match, 0) ||
244 !regexec(&creg[6], line, 7, match, 0) ||
245 !regexec(&creg[7], line, 7, match, 0) ||
246 !regexec(&creg[8], line, 7, match, 0))
247 r = set_mask(line, match);
248 else if (!regexec(&creg[9], line, 3, match, 0))
249 r = set_job(line, match);
250 else if (!regexec(&creg[10], line, 4, match, 0) ||
251 !regexec(&creg[11], line, 4, match, 0) ||
252 !regexec(&creg[12], line, 4, match, 0))
253 set_options(line, match);
254 else
255 return row;
256
257 if (r == ERROR_CONFIG_PARSE)
258 return row;
259 }
260
261 for (i = 0; i < 13; i++)
262 regfree(&creg[i]);
263
264 destroy_data();
265
266 return 0;
267 }
268
269
270 /*
271 * Set other options found in config file.
272 */
273 void set_options(char *line, regmatch_t * match)
274 {
275 if (!strncasecmp(line + match[2].rm_so, "logfile", 7)) {
276 if (!*logfile)
277 strncat(logfile, line + match[3].rm_so,
278 min((match[3].rm_eo - match[3].rm_so), PATH_MAX - 1));
279 } else if (!strncasecmp(line + match[2].rm_so, "header", 6)) {
280 if (!strncasecmp(line + match[3].rm_so, "yes", 3))
281 options |= OPTION_HEADERS;
282 else
283 options &= ~(OPTION_HEADERS);
284 } else if (!strncasecmp(line + match[2].rm_so, "namespace", 9)) {
285 if (!strncasecmp(line + match[3].rm_so, "yes", 3))
286 options |= OPTION_NAMESPACE;
287 else
288 options &= ~(OPTION_NAMESPACE);
289 } else if (!strncasecmp(line + match[2].rm_so, "timeout", 7)) {
290 errno = 0;
291 timeout = strtol(line + match[3].rm_so, NULL, 10);
292 if (errno)
293 timeout = 0;
294 }
295 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26