]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/faces/plumb.c
faces: remove log support
[plan9front.git] / sys / src / cmd / faces / plumb.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <plumb.h>
5 #include <regexp.h>
6 #include <bio.h>
7 #include "faces.h"
8
9 static int      showfd = -1;
10 static int      seefd = -1;
11 static char     *user;
12
13 char            **maildirs;
14 int             nmaildirs;
15
16 void
17 initplumb(void)
18 {
19         if((showfd = plumbopen("send", OWRITE)) == -1)
20                 sysfatal("plumbopen send: %r");
21         if((seefd = plumbopen("seemail", OREAD)) == -1)
22                 sysfatal("plumbopen seemail: %r");
23 }
24
25 void
26 addmaildir(char *dir)
27 {
28         maildirs = erealloc(maildirs, (nmaildirs+1)*sizeof(char*));
29         maildirs[nmaildirs++] = dir;
30 }
31
32 char*
33 attr(Face *f)
34 {
35         static char buf[128];
36
37         if(f->str[Sdigest]){
38                 snprint(buf, sizeof buf, "digest=%s", f->str[Sdigest]);
39                 return buf;
40         }
41         return nil;
42 }
43
44 void
45 showmail(Face *f)
46 {
47         char *s;
48         int n;
49
50         if(showfd<0 || f->str[Sshow]==nil || f->str[Sshow][0]=='\0')
51                 return;
52         s = emalloc(128+strlen(f->str[Sshow])+1);
53         n = sprint(s, "faces\nshowmail\n/mail/fs/\ntext\n%s\n%ld\n%s", attr(f), strlen(f->str[Sshow]), f->str[Sshow]);
54         write(showfd, s, n);
55         free(s);
56 }
57
58 char*
59 value(Plumbattr *attr, char *key, char *def)
60 {
61         char *v;
62
63         v = plumblookup(attr, key);
64         if(v)
65                 return v;
66         return def;
67 }
68
69 void
70 setname(Face *f, char *sender)
71 {
72         char *at, *bang;
73         char *p;
74
75         /* works with UTF-8, although it's written as ASCII */
76         for(p=sender; *p!='\0'; p++)
77                 *p = tolower(*p);
78         f->str[Suser] = sender;
79         at = strchr(sender, '@');
80         if(at){
81                 *at++ = '\0';
82                 f->str[Sdomain] = estrdup(at);
83                 return;
84         }
85         bang = strchr(sender, '!');
86         if(bang){
87                 *bang++ = '\0';
88                 f->str[Suser] = estrdup(bang);
89                 f->str[Sdomain] = sender;
90                 return;
91         }
92 }
93
94 ulong
95 parsedate(char *s)
96 {
97         char **f, *fmt[] = {
98                 "WW MMM DD hh:mm:ss ?Z YYYY",
99                 "?WW ?DD ?MMM ?YYYY hh:mm:ss ?Z",
100                 "?WW ?DD ?MMM ?YYYY hh:mm:ss",
101                 "?WW, DD-?MM-YY",
102                 "?DD ?MMM ?YYYY hh:mm:ss ?Z",
103                 "?DD ?MMM ?YYYY hh:mm:ss",
104                 "?DD-?MM-YY hh:mm:ss ?Z",
105                 "?DD-?MM-YY hh:mm:ss",
106                 "?DD-?MM-YY",
107                 "?MMM/?DD/?YYYY hh:mm:ss ?Z",
108                 "?MMM/?DD/?YYYY hh:mm:ss",
109                 "?MMM/?DD/?YYYY",
110                 nil,
111         };
112         Tzone *tz;
113         Tm tm;
114
115         if((tz = tzload("local")) == nil)
116                 sysfatal("tzload: %r");
117         for(f = fmt; *f; f++)
118                 if(tmparse(&tm, *f, s, tz, nil) != nil)
119                         return tmnorm(&tm);
120         return time(0);
121 }
122
123 Face*
124 nextface(void)
125 {
126         int i;
127         Face *f;
128         Plumbmsg *m;
129         char *t, *senderp, *showmailp, *digestp;
130         ulong xtime;
131
132         f = emalloc(sizeof(Face));
133         for(;;){
134                 m = plumbrecv(seefd);
135                 if(m == nil)
136                         killall("error on seemail plumb port");
137                 t = value(m->attr, "mailtype", "");
138                 if(strcmp(t, "modify") == 0)
139                         goto Ignore;
140                 else if(strcmp(t, "delete") == 0)
141                         delete(m->data, value(m->attr, "digest", nil));
142                 else if(strcmp(t, "new") == 0)
143                         for(i=0; i<nmaildirs; i++){
144                                 if(strncmp(m->data, maildirs[i], strlen(maildirs[i])) == 0)
145                                         goto Found;
146                         }
147                 else
148                         fprint(2, "faces: unknown plumb message type %s\n", t);
149         Ignore:
150                 plumbfree(m);
151                 continue;
152
153         Found:
154                 xtime = parsedate(value(m->attr, "date", date));
155                 digestp = value(m->attr, "digest", nil);
156                 if(alreadyseen(digestp)){
157                         /* duplicate upas/fs can send duplicate messages */
158                         plumbfree(m);
159                         continue;
160                 }
161                 senderp = estrdup(value(m->attr, "sender", "???"));
162                 showmailp = estrdup(m->data);
163                 if(digestp)
164                         digestp = estrdup(digestp);
165                 plumbfree(m);
166                 setname(f, senderp);
167                 f->time = xtime;
168                 f->tm = *localtime(xtime);
169                 f->str[Sshow] = showmailp;
170                 f->str[Sdigest] = digestp;
171                 return f;
172         }
173 }
174
175 char*
176 iline(char *data, char **pp)
177 {
178         char *p;
179
180         for(p=data; *p!='\0' && *p!='\n'; p++)
181                 ;
182         if(*p == '\n')
183                 *p++ = '\0';
184         *pp = p;
185         return data;
186 }
187
188 Face*
189 dirface(char *dir, char *num)
190 {
191         Face *f;
192         char *from, *date;
193         char buf[1024], pwd[1024], *info, *p, *digest;
194         int n, fd;
195         ulong len;
196
197         /*
198          * loadmbox leaves us in maildir, so we needn't
199          * walk /mail/fs/mbox for each face; this makes startup
200          * a fair bit quicker.
201          */
202         if(getwd(pwd, sizeof pwd) != nil && strcmp(pwd, dir) == 0)
203                 sprint(buf, "%s/info", num);
204         else
205                 sprint(buf, "%s/%s/info", dir, num);
206         len = dirlen(buf);
207         if(len <= 0)
208                 return nil;
209         fd = open(buf, OREAD);
210         if(fd < 0)
211                 return nil;
212         info = emalloc(len+1);
213         n = readn(fd, info, len);
214         close(fd);
215         if(n < 0){
216                 free(info);
217                 return nil;
218         }
219         info[n] = '\0';
220         f = emalloc(sizeof(Face));
221         from = iline(info, &p); /* from */
222         iline(p, &p);   /* to */
223         iline(p, &p);   /* cc */
224         iline(p, &p);   /* replyto */
225         date = iline(p, &p);    /* date */
226         setname(f, estrdup(from));
227         f->time = parsedate(date);
228         f->tm = *localtime(f->time);
229         sprint(buf, "%s/%s", dir, num);
230         f->str[Sshow] = estrdup(buf);
231         iline(p, &p);   /* subject */
232         iline(p, &p);   /* mime content type */
233         iline(p, &p);   /* mime disposition */
234         iline(p, &p);   /* filename */
235         digest = iline(p, &p);  /* digest */
236         f->str[Sdigest] = estrdup(digest);
237         free(info);
238         return f;
239 }