inc.c - rohrpost - A commandline mail client to change the world as we see it.
(HTM) git clone git://r-36.net/rohrpost
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
inc.c (6325B)
---
1 /*
2 * Copy me if you can.
3 * by 20h
4 */
5
6 #include <unistd.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <strings.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13
14 #include "ind.h"
15 #include "arg.h"
16 #include "cfg.h"
17 #include "llist.h"
18 #include "imap.h"
19 #include "mark.h"
20 #include "inc.h"
21 #include "path.h"
22
23 inc_t *
24 inc_init(char *cfgn)
25 {
26 inc_t *incs;
27 char *path;
28
29 if (cfgn == NULL)
30 cfgn = "default";
31
32 path = path_mkincfile(cfgn);
33 incs = inc_read(path);
34 if (incs == NULL)
35 incs = inc_new();
36 incs->path = memdups(path);
37 free(path);
38
39 incs->name = memdups(cfgn);
40
41 return incs;
42 }
43
44 void
45 inc_stop(inc_t *incs)
46 {
47 char *path;
48
49 if (incs->changed) {
50 path = path_mkincfile(incs->name);
51 if (inc_write(incs, path) == NULL)
52 edie("inc_write");
53 free(path);
54 }
55
56 inc_free(incs);
57 }
58
59 llist_t *
60 inc_getstatus(inc_t *incs, char *mailbox)
61 {
62 llistelem_t *statuse;
63
64 statuse = inc_get(incs, mailbox);
65 if (statuse == NULL || statuse->data == NULL) {
66 return NULL;
67 }
68
69 return llist_splitstr((char *)statuse->data, "\t");
70 }
71
72 char *
73 inc_getstatuselem(inc_t *incs, char *mailbox, char *elem)
74 {
75 llist_t *status;
76 llistelem_t *relem;
77 char *rstr;
78
79 status = inc_getstatus(incs, mailbox);
80 if (status == NULL)
81 return NULL;
82
83 if (!strcasecmp(elem, "messages")) {
84 relem = llist_getn(status, 0);
85 } else if (!strcasecmp(elem, "unseen")) {
86 relem = llist_getn(status, 1);
87 } else if (!strcasecmp(elem, "recent")) {
88 relem = llist_getn(status, 2);
89 } else {
90 llist_efree(status);
91 return NULL;
92 }
93 if (relem == NULL || relem->key == NULL) {
94 llist_efree(status);
95 return NULL;
96 }
97 rstr = memdups(relem->key);
98 llist_efree(status);
99
100 return rstr;
101 }
102
103 char *
104 inc_getstr(char *cfgn, char *mailbox, char *elem)
105 {
106 inc_t *incs;
107 char *ret;
108
109 incs = inc_init(cfgn);
110 if (incs == NULL)
111 return NULL;
112 ret = inc_getstatuselem(incs, mailbox, elem);
113 inc_free(incs);
114
115 return ret;
116 }
117
118 void
119 inc_setstatus(inc_t *incs, char *mailbox, char *msgs, char *unseen,
120 char *recent)
121 {
122 char *statuss;
123
124 statuss = smprintf("%s\t%s\t%s", msgs, unseen, recent);
125 inc_set(incs, mailbox, statuss);
126 free(statuss);
127 }
128
129 int
130 inc_updatefolder(imap_t *imap, char *folder, inc_t *gincs)
131 {
132 llist_t *statusl;
133 llistelem_t *elem;
134 char *msgs, *unseen, *recent;
135 inc_t *incs;
136
137 if (gincs == NULL) {
138 incs = inc_new();
139 } else {
140 incs = gincs;
141 }
142
143 statusl = imap_status(imap, folder);
144 if (statusl == NULL)
145 return 1;
146
147 msgs = "";
148 recent = "";
149 unseen = "";
150 elem = llist_ciget(statusl, "messages");
151 if (elem != NULL)
152 msgs = (char *)elem->data;
153 elem = llist_ciget(statusl, "recent");
154 if (elem != NULL)
155 recent = (char *)elem->data;
156 elem = llist_ciget(statusl, "unseen");
157 if (elem != NULL)
158 unseen = (char *)elem->data;
159 inc_setstatus(incs, folder, msgs, unseen, recent);
160
161 if (gincs == NULL)
162 inc_stop(incs);
163 llist_free(statusl);
164
165 return 0;
166 }
167
168 void
169 inc_mkunseen(imap_t *imap, char *cfgn, char *folder)
170 {
171 llist_t *results;
172 mark_t *marks;
173 char *str;
174
175 marks = mark_init(cfgn, folder);
176 if (marks == NULL)
177 die("Could not initialize marks for '%s'.\n", folder);
178
179 if (imap_select(imap, folder))
180 imap_die(imap, "imap_select");
181 results = imap_search(imap, "UNSEEN");
182 if (results != NULL) {
183 str = llist_joinstr(results, " ");
184 llist_free(results);
185 if (str != NULL) {
186 mark_set(marks, "u", str);
187 free(str);
188 }
189 mark_stop(marks);
190 }
191 }
192
193 void
194 inc_print(char *folder, char *msgs, char *unseen, char *recent)
195 {
196 printf("%s\t%s\t%s\t%s\n", folder, msgs, unseen, recent);
197 }
198
199 void
200 incusage(char *argv0)
201 {
202 die("usage: %s [-auqnh] [-c cfg] [[-r|] folder]\n", argv0);
203 }
204
205 int
206 incmain(int argc, char *argv[])
207 {
208 config_t *cfg;
209 imap_t *imap;
210 inc_t *incs;
211 int status;
212 char *user, *pass, *netspec, *msgs, *recent, *unseen, *ncmd, *cfgn, *argv0;
213 llist_t *folders, *ffolders;
214 llistelem_t *folder;
215
216 enum {
217 BEQUIET = 0x01,
218 RUNNOTIFY = 0x02,
219 GENUNSEEN = 0x04,
220 SHOWALL = 0x08,
221 DOREGEXP = 0x10,
222
223 NOARGS = 0x20
224 };
225
226 status = 0;
227 cfgn = NULL;
228
229 ARGBEGIN(argv0) {
230 case 'a':
231 status |= SHOWALL;
232 break;
233 case 'c':
234 cfgn = EARGF(incusage(argv0));
235 break;
236 case 'n':
237 status |= RUNNOTIFY;
238 break;
239 case 'q':
240 status |= BEQUIET;
241 break;
242 case 'r':
243 status |= DOREGEXP;
244 break;
245 case 'u':
246 status |= GENUNSEEN;
247 break;
248 default:
249 incusage(argv0);
250 } ARGEND;
251
252 cfg = config_init(cfgn);
253 user = config_checkgetstr(cfg, "imapuser");
254 pass = config_checkgetstr(cfg, "imappass");
255 netspec = config_checkgetstr(cfg, "imapnet");
256 ncmd = config_getstr(cfg, "runnotify");
257 config_free(cfg);
258
259 imap = imap_new(netspec, user, pass);
260 free(user);
261 free(pass);
262 free(netspec);
263
264 if (imap_init(imap))
265 imap_die(imap, "imap_init");
266 if (argc > 0) {
267 folders = imap_listfolders(imap);
268 if (folders == NULL)
269 imap_die(imap, "imap_subscribed");
270
271 if (status & DOREGEXP) {
272 ffolders = llist_find(folders, argv[0]);
273 } else {
274 folder = llist_get(folders, argv[0]);
275 if (folder != NULL) {
276 ffolders = llist_new();
277 llist_add(ffolders, folder->key, folder->data,
278 folder->datalen);
279 }
280 }
281 if (ffolders == NULL)
282 die("Could not find any mailbox '%s'.\n", argv[0]);
283 status |= SHOWALL;
284 } else {
285 folders = imap_subscribed(imap);
286 if (folders == NULL)
287 imap_die(imap, "imap_subscribed");
288
289 ffolders = folders;
290 }
291 llist_sort(ffolders);
292
293 if (!(status & BEQUIET))
294 inc_print("Folder", "Msgs", "Unseen", "Recent");
295 incs = inc_init(cfgn);
296 forllist(ffolders, folder) {
297 if (folder->key == NULL)
298 continue;
299
300 if (inc_updatefolder(imap, folder->key, incs))
301 continue;
302
303 msgs = inc_getstatuselem(incs, folder->key, "messages");
304 recent = inc_getstatuselem(incs, folder->key, "recent");
305 unseen = inc_getstatuselem(incs, folder->key, "unseen");
306
307 if (status & SHOWALL || (recent != NULL && atoi(recent) > 0) \
308 || (unseen != NULL && atoi(unseen) > 0)) {
309 if (!(status & BEQUIET))
310 inc_print(folder->key, msgs, unseen, recent);
311
312 if (status & GENUNSEEN)
313 inc_mkunseen(imap, cfgn, folder->key);
314 if (status & RUNNOTIFY && ncmd) {
315 runcmd(ncmd, NULL, NULL, NULL, 0);
316 wait(NULL);
317 }
318 }
319 if (msgs != NULL)
320 free(msgs);
321 if (recent != NULL)
322 free(recent);
323 if (unseen != NULL)
324 free(unseen);
325 }
326 inc_stop(incs);
327
328 if (argc > 0)
329 llist_free(ffolders);
330 if (ncmd != NULL)
331 free(ncmd);
332 llist_free(folders);
333
334 imap_close(imap);
335 imap_free(imap);
336 return 0;
337 }
338