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

Contents of /imapfilter/imapfilter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.69 - (show annotations)
Sat Feb 14 22:48:04 2004 UTC (20 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.68: +3 -2 lines
File MIME type: text/plain
Added IMAP4 protocol support.

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <limits.h>
8 #include <fcntl.h>
9 #include <setjmp.h>
10 #include <locale.h>
11
12 #include "config.h"
13 #include "imapfilter.h"
14 #include "version.h"
15 #include "account.h"
16 #include "filter.h"
17 #include "buffer.h"
18
19 #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS || defined CRAM_MD5
20 #include <openssl/opensslv.h>
21 #include <openssl/crypto.h>
22 #endif
23
24
25 extern account_t *accounts;
26 extern filter_t *filters;
27 extern buffer_t ibuf, obuf;
28
29 options_t opts; /* Program options. */
30 unsigned int flags = 0; /* Program flags. */
31
32 connection_t connpri, connaux; /* Primary and auxiliary IMAP connection. */
33
34 char *home = NULL; /* User's home directory. */
35
36 jmp_buf acctloop; /* Non-local exit in case of network error. */
37
38
39 void imapfilter(void);
40 void daemonize(void);
41 void usage(void);
42 void version(void);
43
44
45 /*
46 * IMAPFilter: an IMAP mail filtering utility.
47 */
48 int
49 main(int argc, char *argv[])
50 {
51 int c;
52 char *cf;
53
54 setlocale(LC_ALL, "");
55
56 opts.debug = 0;
57 opts.verbosity = 0;
58 opts.timeout = -1;
59 opts.daemon = 0;
60 opts.headers = 0;
61 opts.errors = 0;
62 opts.namespace = 1;
63 opts.expunge = 0;
64 opts.subscribe = 0;
65 opts.peek = 1;
66 opts.passwd_editor = 0;
67 opts.charset[0] = '\0';
68 opts.logfile[0] = '\0';
69
70 home = getenv("HOME");
71 cf = NULL;
72 connpri.sock = connaux.sock = -1;
73
74 while ((c = getopt(argc, argv, "DVc:d:kl:"
75 #ifdef ENCRYPTED_PASSWORDS
76 "p"
77 #endif
78 "qv")) != -1) {
79 switch (c) {
80 case 'D':
81 if (opts.debug < 2)
82 opts.debug++;
83 break;
84 case 'V':
85 version();
86 /* NOTREACHED */
87 case 'c':
88 cf = optarg;
89 break;
90 case 'd':
91 errno = 0;
92 opts.daemon = strtoul(optarg, NULL, 10);
93 if (errno)
94 opts.daemon = 0;
95 break;
96 case 'k':
97 kill_imapfilter();
98 break;
99 case 'l':
100 strncat(opts.logfile, optarg, PATH_MAX - 1);
101 break;
102 #ifdef ENCRYPTED_PASSWORDS
103 case 'p':
104 opts.passwd_editor = 1;
105 break;
106 #endif
107 case 'q':
108 if (opts.verbosity > -2)
109 opts.verbosity--;
110 break;
111 case 'v':
112 if (opts.verbosity < 2)
113 opts.verbosity++;
114 break;
115 case '?':
116 default:
117 usage();
118 /* NOTREACHED */
119 }
120 }
121
122 debug_start();
123
124 create_homedir();
125
126 lockfile_check();
127 lockfile_create();
128
129 if (!opts.debug)
130 corefile_disable();
131
132 tty_store();
133
134 catch_signals();
135
136 read_config(cf);
137
138 #ifdef ENCRYPTED_PASSWORDS
139 read_passwords();
140
141 if (opts.passwd_editor) {
142 password_editor();
143
144 secmem_clear();
145 lockfile_remove();
146
147 exit(0);
148 }
149 #endif
150
151 log_start();
152
153 buffer_init(&ibuf);
154 buffer_init(&obuf);
155
156 if (opts.daemon)
157 opts.verbosity = -2;
158
159 do {
160 imapfilter();
161
162 if (opts.daemon && !(flags & FLAG_DAEMON))
163 daemonize();
164 if (opts.daemon && flags & FLAG_SIGUSR1) {
165 reread_config(cf);
166 continue;
167 }
168 if (opts.daemon > 0)
169 sleep(opts.daemon);
170 } while (opts.daemon);
171
172 log_stop();
173
174 secmem_clear();
175
176 lockfile_remove();
177
178 debug_stop();
179
180 exit(0);
181 }
182
183
184 /*
185 * Go through all accounts and apply filters to mailboxes as defined.
186 */
187 void
188 imapfilter(void)
189 {
190 int r;
191 account_t *ca;
192 mbox_t *cm;
193
194 for (ca = accounts; ca != NULL; ca = ca->next) {
195
196 if (setjmp(acctloop))
197 continue;
198
199 if (init_connection(&connpri, ca->server, ca->port, ca->ssl))
200 continue;
201
202 r = response_greeting(&connpri);
203
204 if (opts.debug)
205 test(&connpri);
206
207 if (check_capabilities(&connpri))
208 continue;
209
210 #ifdef SSL_TLS
211 if (ca->ssl == SSL_DISABLED &&
212 connpri.caps & CAPABILITY_STARTTLS)
213 if (negotiate_tls(&connpri) == RESPONSE_OK)
214 check_capabilities(&connpri);
215 #endif
216
217 log_info(LOG_ACCOUNT, ca->key);
218
219 if (r != RESPONSE_PREAUTH) {
220 if (ca->pass_attr == PASS_ATTR_NONE) {
221 printf("Enter password for %s@%s: ",
222 ca->user, ca->server);
223 get_password(ca->pass, PASS_LEN);
224 ca->pass_attr = PASS_ATTR_PLAIN;
225 }
226 #ifdef CRAM_MD5
227 if (connpri.caps & CAPABILITY_CRAMMD5)
228 r = auth_cram_md5(&connpri, ca->user, ca->pass);
229 else
230 #endif
231 r = login(&connpri, ca->user, ca->pass);
232
233 if (r == RESPONSE_NO) {
234 error("username %s or password rejected "
235 "at %s\n", ca->user, ca->server);
236 continue;
237 }
238 }
239 check_namespace(&connpri);
240
241 for (cm = ca->mboxes; cm != NULL; cm = cm->next)
242 if (*cm->filters == NULL)
243 mailbox_status(&connpri, cm->name);
244 else if (!select_mailbox(&connpri, cm->name)) {
245 apply_filters(cm->name, cm->filters);
246 close_mailbox(&connpri);
247 }
248 logout(&connpri);
249
250 close_connection(&connpri);
251 }
252 }
253
254
255 /*
256 * Fork if in daemon mode.
257 */
258 void
259 daemonize(void)
260 {
261
262 switch (fork()) {
263 case -1:
264 fatal(ERROR_FORK, "forking; %s\n", strerror(errno));
265 break;
266 case 0:
267 break;
268 default:
269 log_stop();
270 secmem_clear();
271 debug_stop();
272 exit(0);
273 break;
274 }
275
276 if (setsid() == -1)
277 fatal(ERROR_FORK, "creating session; %s\n", strerror(errno));
278
279 switch (fork()) {
280 case -1:
281 fatal(ERROR_FORK, "forking; %s\n", strerror(errno));
282 break;
283 case 0:
284 break;
285 default:
286 log_stop();
287 secmem_clear();
288 debug_stop();
289 exit(0);
290 break;
291 }
292
293 close(STDIN_FILENO);
294 close(STDOUT_FILENO);
295 close(STDERR_FILENO);
296 if (open("/dev/null", O_RDWR) != -1) {
297 dup(STDIN_FILENO);
298 dup(STDIN_FILENO);
299 }
300 lockfile_create();
301 corefile_disable();
302
303 flags |= FLAG_DAEMON;
304 }
305
306
307 /*
308 * Print a very brief usage message.
309 */
310 void
311 usage(void)
312 {
313
314 fprintf(stderr,
315 "usage: imapfilter [-DVbk"
316 #ifdef ENCRYPTED_PASSWORDS
317 "p"
318 #endif
319 "qv] [-c configfile] [-d interval] [-l logfile]\n");
320
321 exit(ERROR_UNDEFINED);
322 }
323
324
325 /*
326 * Print program's version, and if it is built in, OpenSSL's version number.
327 */
328 void
329 version(void)
330 {
331
332 fprintf(stderr, "IMAPFilter %s"
333 #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS || defined CRAM_MD5
334 ", OpenSSL 0x%8.8lx"
335 #endif
336 "\n", IMAPFILTER_VERSION
337 #if defined SSL_TLS || defined ENCRYPTED_PASSWORDS || defined CRAM_MD5
338 ,SSLeay()
339 #endif
340 );
341
342 exit(ERROR_UNDEFINED);
343 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26