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