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

Diff of /imapfilter/imapfilter.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1.22.2.2  
changed lines
  Added in v.1.70

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26