rohrpost

A commandline mail client to change the world as we see it.
git clone git://r-36.net/rohrpost
Log | Files | Refs | LICENSE

inc.c (6307B)


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