-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmaildir.c
119 lines (97 loc) · 3.09 KB
/
maildir.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <syslog.h>
#include "channel.h"
#include "mbconfig.h"
#include "mbidled.h"
struct maildir_store {
struct channel *chan;
struct mbconfig_store *mb_store;
char *mailbox;
char cur_path[PATH_MAX];
char new_path[PATH_MAX];
ev_stat cur_watcher;
ev_stat new_watcher;
};
DEFINE_CHANNEL_STORE_LOGGER(maildir, "Maildir")
static void
maildir_notify_change(struct maildir_store *store)
{
maildir_log(store, LOG_DEBUG, "Changed");
channel_notify_change(store->chan, store->mb_store, store->mailbox);
}
static void
cur_stat_cb(EV_P_ ev_stat *w, int revents)
{
(void)revents;
struct maildir_store *store = container_of(w, struct maildir_store, cur_watcher);
maildir_notify_change(store);
}
static void
new_stat_cb(EV_P_ ev_stat *w, int revents)
{
(void)revents;
struct maildir_store *store = container_of(w, struct maildir_store, new_watcher);
maildir_notify_change(store);
}
static void
maildir_open_mailbox(
struct channel *chan, struct mbconfig_store *mb_store, char const *mailbox_path,
char const *mailbox
)
{
char tmp[PATH_MAX];
ASSERT_SNPRINTF(tmp, "%s/cur", mailbox_path);
if (access(tmp, X_OK)) {
channel_log(chan, LOG_DEBUG, "%s: Not a maildir", mailbox_path);
return;
}
if (!mbconfig_patterns_test(&chan->mb_chan->patterns, mailbox)) {
channel_log(chan, LOG_DEBUG, "Mailbox [%s] not matched", mailbox);
return;
}
struct maildir_store *store;
ASSERT(store = malloc(sizeof *store));
store->chan = chan;
store->mb_store = mb_store;
ASSERT(store->mailbox = strdup(mailbox));
maildir_log(store, LOG_INFO, "Watching path %s", mailbox_path);
int poll_interval = chan->mb_chan->mbidled.start_interval;
strcpy(store->cur_path, tmp);
ev_stat_init(&store->cur_watcher, cur_stat_cb, store->cur_path, poll_interval);
ev_stat_start(chan->loop, &store->cur_watcher);
ASSERT_SNPRINTF(store->new_path, "%s/new", mailbox_path);
ev_stat_init(&store->new_watcher, new_stat_cb, store->new_path, poll_interval);
ev_stat_start(chan->loop, &store->new_watcher);
/* Bring other side up-to-date. */
maildir_notify_change(store);
}
void
maildir_open_store(struct channel *chan, struct mbconfig_store *mb_store)
{
assert(mb_store->type == MBCONFIG_STORE_MAILDIR);
struct mbconfig_maildir_store *mb_maildir_store = mb_store->maildir_store;
if (mb_maildir_store->inbox)
maildir_open_mailbox(chan, mb_store, mb_maildir_store->inbox, "INBOX");
/* Path is a prefix in fact. Go to parent and scan all files. */
char maildir_path[PATH_MAX];
ASSERT_SNPRINTF(maildir_path, "%s", mb_maildir_store->path);
char *slash = strrchr(maildir_path, '/');
if (slash)
*slash = '\0';
DIR *dir = opendir(maildir_path);
if (!dir)
return;
for (struct dirent *dent; (dent = readdir(dir));) {
char mailbox_path[PATH_MAX];
ASSERT_SNPRINTF(mailbox_path, "%s/%s", maildir_path, dent->d_name);
/* Inbox requires special handling. */
if (mb_maildir_store->inbox && !strcmp(mb_maildir_store->inbox, mailbox_path))
continue;
maildir_open_mailbox(chan, mb_store, mailbox_path, dent->d_name);
}
ASSERT(!closedir(dir));
}