plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

plumb.c (5376B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <thread.h>
      4 #include <draw.h>
      5 #include <regexp.h>
      6 #include <bio.h>
      7 #include <9pclient.h>
      8 #include <plumb.h>
      9 #include "faces.h"
     10 
     11 static CFid*	showfd;
     12 static CFid*	seefd;
     13 
     14 char		**maildirs;
     15 int		nmaildirs;
     16 
     17 void
     18 initplumb(void)
     19 {
     20 	showfd = plumbopenfid("send", OWRITE);
     21 	seefd = plumbopenfid("seemail", OREAD);
     22 	if(showfd == nil || seefd == nil)
     23 		sysfatal("plumbopen: %r");
     24 }
     25 
     26 void
     27 addmaildir(char *dir)
     28 {
     29 	maildirs = erealloc(maildirs, (nmaildirs+1)*sizeof(char*));
     30 	maildirs[nmaildirs++] = dir;
     31 }
     32 
     33 char*
     34 attr(Face *f)
     35 {
     36 	static char buf[128];
     37 
     38 	if(f->str[Sdigest]){
     39 		snprint(buf, sizeof buf, "digest=%s", f->str[Sdigest]);
     40 		return buf;
     41 	}
     42 	return nil;
     43 }
     44 
     45 void
     46 showmail(Face *f)
     47 {
     48 	char buf[256];
     49 	Plumbmsg pm;
     50 	Plumbattr a;
     51 
     52 	if(showfd<0 || f->str[Sshow]==nil || f->str[Sshow][0]=='\0')
     53 		return;
     54 	snprint(buf, sizeof buf, "Mail/%s", f->str[Sshow]);
     55 	pm.src = "faces";
     56 	pm.dst = "showmail";
     57 	pm.wdir = "/";
     58 	pm.type = "text";
     59 	a.name = "digest";
     60 	a.value = f->str[Sdigest];
     61 	a.next = nil;
     62 	pm.attr = &a;
     63 	pm.ndata = strlen(buf);
     64 	pm.data = buf;
     65 	plumbsendtofid(showfd, &pm);
     66 }
     67 
     68 char*
     69 value(Plumbattr *attr, char *key, char *def)
     70 {
     71 	char *v;
     72 
     73 	v = plumblookup(attr, key);
     74 	if(v)
     75 		return v;
     76 	return def;
     77 }
     78 
     79 void
     80 setname(Face *f, char *sender)
     81 {
     82 	char *at, *bang;
     83 	char *p;
     84 	char *fld[3];
     85 	int nf;
     86 
     87 	p = estrdup(sender);
     88 	nf = tokenize(p, fld, 3);
     89 	if(nf <= 1)
     90 		sender = estrdup(fld[0]);
     91 	else
     92 		sender = estrdup(fld[1]);
     93 	free(p);
     94 
     95 	/* works with UTF-8, although it's written as ASCII */
     96 	for(p=sender; *p!='\0'; p++)
     97 		*p = tolower(*p);
     98 	f->str[Suser] = sender;
     99 	at = strchr(sender, '@');
    100 	if(at){
    101 		*at++ = '\0';
    102 		f->str[Sdomain] = estrdup(at);
    103 		return;
    104 	}
    105 	bang = strchr(sender, '!');
    106 	if(bang){
    107 		*bang++ = '\0';
    108 		f->str[Suser] = estrdup(bang);
    109 		f->str[Sdomain] = sender;
    110 		return;
    111 	}
    112 }
    113 
    114 static char* months[] = {
    115 	"jan", "feb", "mar", "apr",
    116 	"may", "jun", "jul", "aug",
    117 	"sep", "oct", "nov", "dec"
    118 };
    119 
    120 static int
    121 getmon(char *s)
    122 {
    123 	int i;
    124 
    125 	for(i=0; i<nelem(months); i++)
    126 		if(cistrcmp(months[i], s) == 0)
    127 			return i;
    128 	return -1;
    129 }
    130 
    131 /* Fri Jul 23 14:05:14 EDT 1999 */
    132 ulong
    133 parsedatev(char **a)
    134 {
    135 	char *p;
    136 	Tm tm;
    137 
    138 	memset(&tm, 0, sizeof tm);
    139 	if((tm.mon=getmon(a[1])) == -1)
    140 		goto Err;
    141 	tm.mday = strtol(a[2], &p, 10);
    142 	if(*p != '\0')
    143 		goto Err;
    144 	tm.hour = strtol(a[3], &p, 10);
    145 	if(*p != ':')
    146 		goto Err;
    147 	tm.min = strtol(p+1, &p, 10);
    148 	if(*p != ':')
    149 		goto Err;
    150 	tm.sec = strtol(p+1, &p, 10);
    151 	if(*p != '\0')
    152 		goto Err;
    153 	if(strlen(a[4]) != 3)
    154 		goto Err;
    155 	strcpy(tm.zone, a[4]);
    156 	if(strlen(a[5]) != 4)
    157 		goto Err;
    158 	tm.year = strtol(a[5], &p, 10);
    159 	if(*p != '\0')
    160 		goto Err;
    161 	tm.year -= 1900;
    162 	return tm2sec(&tm);
    163 Err:
    164 	return time(0);
    165 }
    166 
    167 ulong
    168 parsedate(char *s)
    169 {
    170 	char *f[10];
    171 	int nf;
    172 
    173 	nf = getfields(s, f, nelem(f), 1, " ");
    174 	if(nf < 6)
    175 		return time(0);
    176 	return parsedatev(f);
    177 }
    178 
    179 
    180 char*
    181 tweakdate(char *d)
    182 {
    183 	char e[8];
    184 
    185 	/* d, date = "Mon Aug  2 23:46:55 EDT 1999" */
    186 
    187 	if(strlen(d) < strlen("Mon Aug  2 23:46:55 EDT 1999"))
    188 		return estrdup("");
    189 	if(strncmp(date, d, 4+4+3) == 0)
    190 		snprint(e, sizeof e, "%.5s", d+4+4+3);	/* 23:46 */
    191 	else
    192 		snprint(e, sizeof e, "%.6s", d+4);	/* Aug  2 */
    193 	return estrdup(e);
    194 }
    195 
    196 Face*
    197 nextface(void)
    198 {
    199 	int i;
    200 	Face *f;
    201 	Plumbmsg *m;
    202 	char *t, *data, *showmailp, *digestp;
    203 	ulong xtime;
    204 
    205 	f = emalloc(sizeof(Face));
    206 	for(;;){
    207 		m = plumbrecvfid(seefd);
    208 		if(m == nil)
    209 			killall("error on seemail plumb port");
    210 		if(strncmp(m->data, "Mail/", 5) != 0){
    211 			plumbfree(m);
    212 			continue;
    213 		}
    214 		data = m->data+5;
    215 		t = value(m->attr, "mailtype", "");
    216 		if(strcmp(t, "delete") == 0)
    217 			delete(data, value(m->attr, "digest", nil));
    218 		else if(strcmp(t, "new") != 0)
    219 			fprint(2, "faces: unknown plumb message type %s\n", t);
    220 		else for(i=0; i<nmaildirs; i++)
    221 			if(strncmp(data, maildirs[i], strlen(maildirs[i])) == 0)
    222 				goto Found;
    223 		plumbfree(m);
    224 		continue;
    225 
    226 	Found:
    227 		xtime = parsedate(value(m->attr, "date", date));
    228 		digestp = value(m->attr, "digest", nil);
    229 		if(alreadyseen(digestp)){
    230 			/* duplicate upas/fs can send duplicate messages */
    231 			plumbfree(m);
    232 			continue;
    233 		}
    234 		showmailp = estrdup(data);
    235 		if(digestp)
    236 			digestp = estrdup(digestp);
    237 		setname(f, value(m->attr, "sender", "???"));
    238 		plumbfree(m);
    239 		f->time = xtime;
    240 		f->tm = *localtime(xtime);
    241 		f->str[Sshow] = showmailp;
    242 		f->str[Sdigest] = digestp;
    243 		return f;
    244 	}
    245 	return nil;
    246 }
    247 
    248 char*
    249 iline(char *data, char **pp)
    250 {
    251 	char *p;
    252 
    253 	if(*data == 0)
    254 		return nil;
    255 	for(p=data; *p!='\0' && *p!='\n'; p++)
    256 		;
    257 	if(*p == '\n')
    258 		*p++ = '\0';
    259 	*pp = p;
    260 	return data;
    261 }
    262 
    263 Face*
    264 dirface(char *dir, char *num)
    265 {
    266 	Face *f;
    267 	char buf[1024],  *info, *p, *t, *s;
    268 	int n;
    269 	ulong len;
    270 	CFid *fid;
    271 
    272 	sprint(buf, "%s/%s/info", dir, num);
    273 	len = fsdirlen(mailfs, buf);
    274 	if(len <= 0)
    275 		return nil;
    276 	fid = fsopen(mailfs, buf, OREAD);
    277 	if(fid == nil)
    278 		return nil;
    279 	info = emalloc(len+1);
    280 	n = fsreadn(fid, info, len);
    281 	fsclose(fid);
    282 	if(n < 0){
    283 		free(info);
    284 		return nil;
    285 	}
    286 	info[n] = '\0';
    287 	f = emalloc(sizeof(Face));
    288 	for(p=info; (s=iline(p, &p)) != nil; ){
    289 		t = strchr(s, ' ');
    290 		if(t == nil)
    291 			continue;
    292 		*t++ = 0;
    293 		if(strcmp(s, "unixdate") == 0){
    294 			f->time = atoi(t);
    295 			f->tm = *localtime(f->time);
    296 		}
    297 		else if(strcmp(s, "from") == 0)
    298 			setname(f, t);
    299 		else if(strcmp(s, "digest") == 0)
    300 			f->str[Sdigest] = estrdup(t);
    301 	}
    302 	sprint(buf, "%s/%s", dir, num);
    303 	f->str[Sshow] = estrdup(buf);
    304 	free(info);
    305 	return f;
    306 }