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 }