Blob


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"
11 static CFid* showfd;
12 static CFid* seefd;
14 char **maildirs;
15 int nmaildirs;
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 }
26 void
27 addmaildir(char *dir)
28 {
29 maildirs = erealloc(maildirs, (nmaildirs+1)*sizeof(char*));
30 maildirs[nmaildirs++] = dir;
31 }
33 char*
34 attr(Face *f)
35 {
36 static char buf[128];
38 if(f->str[Sdigest]){
39 snprint(buf, sizeof buf, "digest=%s", f->str[Sdigest]);
40 return buf;
41 }
42 return nil;
43 }
45 void
46 showmail(Face *f)
47 {
48 char buf[256];
49 Plumbmsg pm;
50 Plumbattr a;
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 }
68 char*
69 value(Plumbattr *attr, char *key, char *def)
70 {
71 char *v;
73 v = plumblookup(attr, key);
74 if(v)
75 return v;
76 return def;
77 }
79 void
80 setname(Face *f, char *sender)
81 {
82 char *at, *bang;
83 char *p;
84 char *fld[3];
85 int nf;
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);
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;
105 bang = strchr(sender, '!');
106 if(bang){
107 *bang++ = '\0';
108 f->str[Suser] = estrdup(bang);
109 f->str[Sdomain] = sender;
110 return;
114 static char* months[] = {
115 "jan", "feb", "mar", "apr",
116 "may", "jun", "jul", "aug",
117 "sep", "oct", "nov", "dec"
118 };
120 static int
121 getmon(char *s)
123 int i;
125 for(i=0; i<nelem(months); i++)
126 if(cistrcmp(months[i], s) == 0)
127 return i;
128 return -1;
131 /* Fri Jul 23 14:05:14 EDT 1999 */
132 ulong
133 parsedatev(char **a)
135 char *p;
136 Tm tm;
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);
167 ulong
168 parsedate(char *s)
170 char *f[10];
171 int nf;
173 nf = getfields(s, f, nelem(f), 1, " ");
174 if(nf < 6)
175 return time(0);
176 return parsedatev(f);
180 char*
181 tweakdate(char *d)
183 char e[8];
185 /* d, date = "Mon Aug 2 23:46:55 EDT 1999" */
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);
196 Face*
197 nextface(void)
199 int i;
200 Face *f;
201 Plumbmsg *m;
202 char *t, *data, *showmailp, *digestp;
203 ulong xtime;
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;
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;
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;
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;
245 return nil;
248 char*
249 iline(char *data, char **pp)
251 char *p;
253 if(*data == 0)
254 return nil;
255 for(p=data; *p!='\0' && *p!='\n'; p++)
257 if(*p == '\n')
258 *p++ = '\0';
259 *pp = p;
260 return data;
263 Face*
264 dirface(char *dir, char *num)
266 Face *f;
267 char buf[1024], *info, *p, *t, *s;
268 int n;
269 ulong len;
270 CFid *fid;
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;
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);
297 else if(strcmp(s, "from") == 0)
298 setname(f, t);
299 else if(strcmp(s, "digest") == 0)
300 f->str[Sdigest] = estrdup(t);
302 sprint(buf, "%s/%s", dir, num);
303 f->str[Sshow] = estrdup(buf);
304 free(info);
305 return f;