rohrpost

A commandline mail client to change the world as we see it.
git clone git://r-36.net/rohrpost
Log | Files | Refs | README | 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