Blame


1 b330c942 2005-10-31 devnull #include <u.h>
2 b330c942 2005-10-31 devnull #include <libc.h>
3 b330c942 2005-10-31 devnull #include <draw.h>
4 b330c942 2005-10-31 devnull #include <plumb.h>
5 b330c942 2005-10-31 devnull #include <regexp.h>
6 b330c942 2005-10-31 devnull #include <bio.h>
7 b330c942 2005-10-31 devnull #include <9pclient.h>
8 b330c942 2005-10-31 devnull #include "faces.h"
9 b330c942 2005-10-31 devnull
10 b330c942 2005-10-31 devnull static int showfd = -1;
11 b330c942 2005-10-31 devnull static int seefd = -1;
12 b330c942 2005-10-31 devnull static int logfd = -1;
13 b330c942 2005-10-31 devnull static char *user;
14 b330c942 2005-10-31 devnull static char *logtag;
15 b330c942 2005-10-31 devnull
16 b330c942 2005-10-31 devnull char **maildirs;
17 b330c942 2005-10-31 devnull int nmaildirs;
18 b330c942 2005-10-31 devnull
19 b330c942 2005-10-31 devnull void
20 b330c942 2005-10-31 devnull initplumb(void)
21 b330c942 2005-10-31 devnull {
22 b330c942 2005-10-31 devnull showfd = plumbopen("send", OWRITE);
23 b330c942 2005-10-31 devnull seefd = plumbopen("seemail", OREAD);
24 b330c942 2005-10-31 devnull
25 b330c942 2005-10-31 devnull if(seefd < 0){
26 b330c942 2005-10-31 devnull logfd = open(unsharp("#9/log/mail"), OREAD);
27 b330c942 2005-10-31 devnull seek(logfd, 0LL, 2);
28 b330c942 2005-10-31 devnull user = getenv("user");
29 b330c942 2005-10-31 devnull if(user == nil){
30 b330c942 2005-10-31 devnull fprint(2, "faces: can't find user name: %r\n");
31 b330c942 2005-10-31 devnull exits("$user");
32 b330c942 2005-10-31 devnull }
33 b330c942 2005-10-31 devnull logtag = emalloc(32+strlen(user)+1);
34 b330c942 2005-10-31 devnull sprint(logtag, " delivered %s From ", user);
35 b330c942 2005-10-31 devnull }
36 b330c942 2005-10-31 devnull }
37 b330c942 2005-10-31 devnull
38 b330c942 2005-10-31 devnull void
39 b330c942 2005-10-31 devnull addmaildir(char *dir)
40 b330c942 2005-10-31 devnull {
41 b330c942 2005-10-31 devnull maildirs = erealloc(maildirs, (nmaildirs+1)*sizeof(char*));
42 b330c942 2005-10-31 devnull maildirs[nmaildirs++] = dir;
43 b330c942 2005-10-31 devnull }
44 b330c942 2005-10-31 devnull
45 b330c942 2005-10-31 devnull char*
46 b330c942 2005-10-31 devnull attr(Face *f)
47 b330c942 2005-10-31 devnull {
48 b330c942 2005-10-31 devnull static char buf[128];
49 b330c942 2005-10-31 devnull
50 b330c942 2005-10-31 devnull if(f->str[Sdigest]){
51 b330c942 2005-10-31 devnull snprint(buf, sizeof buf, "digest=%s", f->str[Sdigest]);
52 b330c942 2005-10-31 devnull return buf;
53 b330c942 2005-10-31 devnull }
54 b330c942 2005-10-31 devnull return nil;
55 b330c942 2005-10-31 devnull }
56 b330c942 2005-10-31 devnull
57 b330c942 2005-10-31 devnull void
58 b330c942 2005-10-31 devnull showmail(Face *f)
59 b330c942 2005-10-31 devnull {
60 b330c942 2005-10-31 devnull Plumbmsg pm;
61 b330c942 2005-10-31 devnull Plumbattr a;
62 b330c942 2005-10-31 devnull char *s;
63 b330c942 2005-10-31 devnull
64 b330c942 2005-10-31 devnull if(showfd<0 || f->str[Sshow]==nil || f->str[Sshow][0]=='\0')
65 b330c942 2005-10-31 devnull return;
66 b330c942 2005-10-31 devnull s = emalloc(strlen("/mail/fs")+1+strlen(f->str[Sshow]));
67 b330c942 2005-10-31 devnull sprint(s,"/mail/fs/%s",f->str[Sshow]);
68 b330c942 2005-10-31 devnull pm.src = "faces";
69 b330c942 2005-10-31 devnull pm.dst = "showmail";
70 b330c942 2005-10-31 devnull pm.wdir = "/mail/fs";
71 b330c942 2005-10-31 devnull pm.type = "text";
72 b330c942 2005-10-31 devnull a.name = "digest";
73 b330c942 2005-10-31 devnull a.value = f->str[Sdigest];
74 b330c942 2005-10-31 devnull a.next = nil;
75 b330c942 2005-10-31 devnull pm.attr = &a;
76 b330c942 2005-10-31 devnull pm.ndata = strlen(s);
77 b330c942 2005-10-31 devnull pm.data = s;
78 b330c942 2005-10-31 devnull plumbsend(showfd,&pm);
79 b330c942 2005-10-31 devnull }
80 b330c942 2005-10-31 devnull
81 b330c942 2005-10-31 devnull char*
82 b330c942 2005-10-31 devnull value(Plumbattr *attr, char *key, char *def)
83 b330c942 2005-10-31 devnull {
84 b330c942 2005-10-31 devnull char *v;
85 b330c942 2005-10-31 devnull
86 b330c942 2005-10-31 devnull v = plumblookup(attr, key);
87 b330c942 2005-10-31 devnull if(v)
88 b330c942 2005-10-31 devnull return v;
89 b330c942 2005-10-31 devnull return def;
90 b330c942 2005-10-31 devnull }
91 b330c942 2005-10-31 devnull
92 b330c942 2005-10-31 devnull void
93 b330c942 2005-10-31 devnull setname(Face *f, char *sender)
94 b330c942 2005-10-31 devnull {
95 b330c942 2005-10-31 devnull char *at, *bang;
96 b330c942 2005-10-31 devnull char *p;
97 b330c942 2005-10-31 devnull
98 b330c942 2005-10-31 devnull /* works with UTF-8, although it's written as ASCII */
99 b330c942 2005-10-31 devnull for(p=sender; *p!='\0'; p++)
100 b330c942 2005-10-31 devnull *p = tolower(*p);
101 b330c942 2005-10-31 devnull f->str[Suser] = sender;
102 b330c942 2005-10-31 devnull at = strchr(sender, '@');
103 b330c942 2005-10-31 devnull if(at){
104 b330c942 2005-10-31 devnull *at++ = '\0';
105 b330c942 2005-10-31 devnull f->str[Sdomain] = estrdup(at);
106 b330c942 2005-10-31 devnull return;
107 b330c942 2005-10-31 devnull }
108 b330c942 2005-10-31 devnull bang = strchr(sender, '!');
109 b330c942 2005-10-31 devnull if(bang){
110 b330c942 2005-10-31 devnull *bang++ = '\0';
111 b330c942 2005-10-31 devnull f->str[Suser] = estrdup(bang);
112 b330c942 2005-10-31 devnull f->str[Sdomain] = sender;
113 b330c942 2005-10-31 devnull return;
114 b330c942 2005-10-31 devnull }
115 b330c942 2005-10-31 devnull }
116 b330c942 2005-10-31 devnull
117 b330c942 2005-10-31 devnull int
118 b330c942 2005-10-31 devnull getc(void)
119 b330c942 2005-10-31 devnull {
120 b330c942 2005-10-31 devnull static uchar buf[512];
121 b330c942 2005-10-31 devnull static int nbuf = 0;
122 b330c942 2005-10-31 devnull static int i = 0;
123 b330c942 2005-10-31 devnull
124 b330c942 2005-10-31 devnull while(i == nbuf){
125 b330c942 2005-10-31 devnull i = 0;
126 b330c942 2005-10-31 devnull nbuf = read(logfd, buf, sizeof buf);
127 b330c942 2005-10-31 devnull if(nbuf == 0){
128 b330c942 2005-10-31 devnull sleep(15000);
129 b330c942 2005-10-31 devnull continue;
130 b330c942 2005-10-31 devnull }
131 b330c942 2005-10-31 devnull if(nbuf < 0)
132 b330c942 2005-10-31 devnull return -1;
133 b330c942 2005-10-31 devnull }
134 b330c942 2005-10-31 devnull return buf[i++];
135 b330c942 2005-10-31 devnull }
136 b330c942 2005-10-31 devnull
137 b330c942 2005-10-31 devnull char*
138 b330c942 2005-10-31 devnull getline(char *buf, int n)
139 b330c942 2005-10-31 devnull {
140 b330c942 2005-10-31 devnull int i, c;
141 b330c942 2005-10-31 devnull
142 b330c942 2005-10-31 devnull for(i=0; i<n-1; i++){
143 b330c942 2005-10-31 devnull c = getc();
144 b330c942 2005-10-31 devnull if(c <= 0)
145 b330c942 2005-10-31 devnull return nil;
146 b330c942 2005-10-31 devnull if(c == '\n')
147 b330c942 2005-10-31 devnull break;
148 b330c942 2005-10-31 devnull buf[i] = c;
149 b330c942 2005-10-31 devnull }
150 b330c942 2005-10-31 devnull buf[i] = '\0';
151 b330c942 2005-10-31 devnull return buf;
152 b330c942 2005-10-31 devnull }
153 b330c942 2005-10-31 devnull
154 b330c942 2005-10-31 devnull static char* months[] = {
155 b330c942 2005-10-31 devnull "jan", "feb", "mar", "apr",
156 b330c942 2005-10-31 devnull "may", "jun", "jul", "aug",
157 b330c942 2005-10-31 devnull "sep", "oct", "nov", "dec"
158 b330c942 2005-10-31 devnull };
159 b330c942 2005-10-31 devnull
160 b330c942 2005-10-31 devnull static int
161 b330c942 2005-10-31 devnull getmon(char *s)
162 b330c942 2005-10-31 devnull {
163 b330c942 2005-10-31 devnull int i;
164 b330c942 2005-10-31 devnull
165 b330c942 2005-10-31 devnull for(i=0; i<nelem(months); i++)
166 b330c942 2005-10-31 devnull if(cistrcmp(months[i], s) == 0)
167 b330c942 2005-10-31 devnull return i;
168 b330c942 2005-10-31 devnull return -1;
169 b330c942 2005-10-31 devnull }
170 b330c942 2005-10-31 devnull
171 b330c942 2005-10-31 devnull /* Fri Jul 23 14:05:14 EDT 1999 */
172 b330c942 2005-10-31 devnull ulong
173 b330c942 2005-10-31 devnull parsedatev(char **a)
174 b330c942 2005-10-31 devnull {
175 b330c942 2005-10-31 devnull char *p;
176 b330c942 2005-10-31 devnull Tm tm;
177 b330c942 2005-10-31 devnull
178 b330c942 2005-10-31 devnull memset(&tm, 0, sizeof tm);
179 b330c942 2005-10-31 devnull if((tm.mon=getmon(a[1])) == -1)
180 b330c942 2005-10-31 devnull goto Err;
181 b330c942 2005-10-31 devnull tm.mday = strtol(a[2], &p, 10);
182 b330c942 2005-10-31 devnull if(*p != '\0')
183 b330c942 2005-10-31 devnull goto Err;
184 b330c942 2005-10-31 devnull tm.hour = strtol(a[3], &p, 10);
185 b330c942 2005-10-31 devnull if(*p != ':')
186 b330c942 2005-10-31 devnull goto Err;
187 b330c942 2005-10-31 devnull tm.min = strtol(p+1, &p, 10);
188 b330c942 2005-10-31 devnull if(*p != ':')
189 b330c942 2005-10-31 devnull goto Err;
190 b330c942 2005-10-31 devnull tm.sec = strtol(p+1, &p, 10);
191 b330c942 2005-10-31 devnull if(*p != '\0')
192 b330c942 2005-10-31 devnull goto Err;
193 b330c942 2005-10-31 devnull if(strlen(a[4]) != 3)
194 b330c942 2005-10-31 devnull goto Err;
195 b330c942 2005-10-31 devnull strcpy(tm.zone, a[4]);
196 b330c942 2005-10-31 devnull if(strlen(a[5]) != 4)
197 b330c942 2005-10-31 devnull goto Err;
198 b330c942 2005-10-31 devnull tm.year = strtol(a[5], &p, 10);
199 b330c942 2005-10-31 devnull if(*p != '\0')
200 b330c942 2005-10-31 devnull goto Err;
201 b330c942 2005-10-31 devnull tm.year -= 1900;
202 b330c942 2005-10-31 devnull return tm2sec(&tm);
203 b330c942 2005-10-31 devnull Err:
204 b330c942 2005-10-31 devnull return time(0);
205 b330c942 2005-10-31 devnull }
206 b330c942 2005-10-31 devnull
207 b330c942 2005-10-31 devnull ulong
208 b330c942 2005-10-31 devnull parsedate(char *s)
209 b330c942 2005-10-31 devnull {
210 b330c942 2005-10-31 devnull char *f[10];
211 b330c942 2005-10-31 devnull int nf;
212 b330c942 2005-10-31 devnull
213 b330c942 2005-10-31 devnull nf = getfields(s, f, nelem(f), 1, " ");
214 b330c942 2005-10-31 devnull if(nf < 6)
215 b330c942 2005-10-31 devnull return time(0);
216 b330c942 2005-10-31 devnull return parsedatev(f);
217 b330c942 2005-10-31 devnull }
218 b330c942 2005-10-31 devnull
219 b330c942 2005-10-31 devnull /* achille Jul 23 14:05:15 delivered jmk From ms.com!bub Fri Jul 23 14:05:14 EDT 1999 (plan9.bell-labs.com!jmk) 1352 */
220 b330c942 2005-10-31 devnull /* achille Oct 26 13:45:42 remote local!rsc From rsc Sat Oct 26 13:45:41 EDT 2002 (rsc) 170 */
221 b330c942 2005-10-31 devnull int
222 b330c942 2005-10-31 devnull parselog(char *s, char **sender, ulong *xtime)
223 b330c942 2005-10-31 devnull {
224 b330c942 2005-10-31 devnull char *f[20];
225 b330c942 2005-10-31 devnull int nf;
226 b330c942 2005-10-31 devnull
227 b330c942 2005-10-31 devnull nf = getfields(s, f, nelem(f), 1, " ");
228 b330c942 2005-10-31 devnull if(nf < 14)
229 b330c942 2005-10-31 devnull return 0;
230 b330c942 2005-10-31 devnull if(strcmp(f[4], "delivered") == 0 && strcmp(f[5], user) == 0)
231 b330c942 2005-10-31 devnull goto Found;
232 b330c942 2005-10-31 devnull if(strcmp(f[4], "remote") == 0 && strncmp(f[5], "local!", 6) == 0 && strcmp(f[5]+6, user) == 0)
233 b330c942 2005-10-31 devnull goto Found;
234 b330c942 2005-10-31 devnull return 0;
235 b330c942 2005-10-31 devnull
236 b330c942 2005-10-31 devnull Found:
237 b330c942 2005-10-31 devnull *sender = estrdup(f[7]);
238 b330c942 2005-10-31 devnull *xtime = parsedatev(&f[8]);
239 b330c942 2005-10-31 devnull return 1;
240 b330c942 2005-10-31 devnull }
241 b330c942 2005-10-31 devnull
242 b330c942 2005-10-31 devnull int
243 b330c942 2005-10-31 devnull logrecv(char **sender, ulong *xtime)
244 b330c942 2005-10-31 devnull {
245 b330c942 2005-10-31 devnull char buf[4096];
246 b330c942 2005-10-31 devnull
247 b330c942 2005-10-31 devnull for(;;){
248 b330c942 2005-10-31 devnull if(getline(buf, sizeof buf) == nil)
249 b330c942 2005-10-31 devnull return 0;
250 b330c942 2005-10-31 devnull if(parselog(buf, sender, xtime))
251 b330c942 2005-10-31 devnull return 1;
252 b330c942 2005-10-31 devnull }
253 b330c942 2005-10-31 devnull return -1;
254 b330c942 2005-10-31 devnull }
255 b330c942 2005-10-31 devnull
256 b330c942 2005-10-31 devnull char*
257 b330c942 2005-10-31 devnull tweakdate(char *d)
258 b330c942 2005-10-31 devnull {
259 b330c942 2005-10-31 devnull char e[8];
260 b330c942 2005-10-31 devnull
261 b330c942 2005-10-31 devnull /* d, date = "Mon Aug 2 23:46:55 EDT 1999" */
262 b330c942 2005-10-31 devnull
263 b330c942 2005-10-31 devnull if(strlen(d) < strlen("Mon Aug 2 23:46:55 EDT 1999"))
264 b330c942 2005-10-31 devnull return estrdup("");
265 b330c942 2005-10-31 devnull if(strncmp(date, d, 4+4+3) == 0)
266 b330c942 2005-10-31 devnull snprint(e, sizeof e, "%.5s", d+4+4+3); /* 23:46 */
267 b330c942 2005-10-31 devnull else
268 b330c942 2005-10-31 devnull snprint(e, sizeof e, "%.6s", d+4); /* Aug 2 */
269 b330c942 2005-10-31 devnull return estrdup(e);
270 b330c942 2005-10-31 devnull }
271 b330c942 2005-10-31 devnull
272 b330c942 2005-10-31 devnull Face*
273 b330c942 2005-10-31 devnull nextface(void)
274 b330c942 2005-10-31 devnull {
275 b330c942 2005-10-31 devnull int i;
276 b330c942 2005-10-31 devnull Face *f;
277 b330c942 2005-10-31 devnull Plumbmsg *m;
278 b330c942 2005-10-31 devnull char *t, *senderp, *showmailp, *digestp;
279 b330c942 2005-10-31 devnull ulong xtime;
280 b330c942 2005-10-31 devnull
281 b330c942 2005-10-31 devnull f = emalloc(sizeof(Face));
282 b330c942 2005-10-31 devnull for(;;){
283 b330c942 2005-10-31 devnull if(seefd >= 0){
284 b330c942 2005-10-31 devnull m = plumbrecv(seefd);
285 b330c942 2005-10-31 devnull if(m == nil)
286 b330c942 2005-10-31 devnull killall("error on seemail plumb port");
287 b330c942 2005-10-31 devnull t = value(m->attr, "mailtype", "");
288 b330c942 2005-10-31 devnull if(strcmp(t, "delete") == 0)
289 b330c942 2005-10-31 devnull delete(m->data, value(m->attr, "digest", nil));
290 b330c942 2005-10-31 devnull else if(strcmp(t, "new") != 0)
291 b330c942 2005-10-31 devnull fprint(2, "faces: unknown plumb message type %s\n", t);
292 b330c942 2005-10-31 devnull else for(i=0; i<nmaildirs; i++) {
293 b330c942 2005-10-31 devnull if(strncmp(m->data,"/mail/fs/",strlen("/mail/fs/")) == 0)
294 b330c942 2005-10-31 devnull m->data += strlen("/mail/fs/");
295 b330c942 2005-10-31 devnull if(strncmp(m->data, maildirs[i], strlen(maildirs[i])) == 0)
296 b330c942 2005-10-31 devnull goto Found;
297 b330c942 2005-10-31 devnull }
298 b330c942 2005-10-31 devnull plumbfree(m);
299 b330c942 2005-10-31 devnull continue;
300 b330c942 2005-10-31 devnull
301 b330c942 2005-10-31 devnull Found:
302 b330c942 2005-10-31 devnull xtime = parsedate(value(m->attr, "date", date));
303 b330c942 2005-10-31 devnull digestp = value(m->attr, "digest", nil);
304 b330c942 2005-10-31 devnull if(alreadyseen(digestp)){
305 b330c942 2005-10-31 devnull /* duplicate upas/fs can send duplicate messages */
306 b330c942 2005-10-31 devnull plumbfree(m);
307 b330c942 2005-10-31 devnull continue;
308 b330c942 2005-10-31 devnull }
309 b330c942 2005-10-31 devnull senderp = estrdup(value(m->attr, "sender", "???"));
310 b330c942 2005-10-31 devnull showmailp = estrdup(m->data);
311 b330c942 2005-10-31 devnull if(digestp)
312 b330c942 2005-10-31 devnull digestp = estrdup(digestp);
313 b330c942 2005-10-31 devnull plumbfree(m);
314 b330c942 2005-10-31 devnull }else{
315 b330c942 2005-10-31 devnull if(logrecv(&senderp, &xtime) <= 0)
316 b330c942 2005-10-31 devnull killall("error reading log file");
317 b330c942 2005-10-31 devnull showmailp = estrdup("");
318 b330c942 2005-10-31 devnull digestp = nil;
319 b330c942 2005-10-31 devnull }
320 b330c942 2005-10-31 devnull setname(f, senderp);
321 b330c942 2005-10-31 devnull f->time = xtime;
322 b330c942 2005-10-31 devnull f->tm = *localtime(xtime);
323 b330c942 2005-10-31 devnull f->str[Sshow] = showmailp;
324 b330c942 2005-10-31 devnull f->str[Sdigest] = digestp;
325 b330c942 2005-10-31 devnull return f;
326 b330c942 2005-10-31 devnull }
327 b330c942 2005-10-31 devnull return nil;
328 b330c942 2005-10-31 devnull }
329 b330c942 2005-10-31 devnull
330 b330c942 2005-10-31 devnull char*
331 b330c942 2005-10-31 devnull iline(char *data, char **pp)
332 b330c942 2005-10-31 devnull {
333 b330c942 2005-10-31 devnull char *p;
334 b330c942 2005-10-31 devnull
335 b330c942 2005-10-31 devnull for(p=data; *p!='\0' && *p!='\n'; p++)
336 b330c942 2005-10-31 devnull ;
337 b330c942 2005-10-31 devnull if(*p == '\n')
338 b330c942 2005-10-31 devnull *p++ = '\0';
339 b330c942 2005-10-31 devnull *pp = p;
340 b330c942 2005-10-31 devnull return data;
341 b330c942 2005-10-31 devnull }
342 b330c942 2005-10-31 devnull
343 b330c942 2005-10-31 devnull Face*
344 b330c942 2005-10-31 devnull dirface(char *dir, char *num)
345 b330c942 2005-10-31 devnull {
346 b330c942 2005-10-31 devnull Face *f;
347 b330c942 2005-10-31 devnull char *from, *date;
348 b330c942 2005-10-31 devnull char buf[1024], *info, *p, *digest;
349 b330c942 2005-10-31 devnull int n;
350 b330c942 2005-10-31 devnull ulong len;
351 b330c942 2005-10-31 devnull CFid *fid;
352 b330c942 2005-10-31 devnull
353 b330c942 2005-10-31 devnull #if 0
354 b330c942 2005-10-31 devnull /*
355 b330c942 2005-10-31 devnull * loadmbox leaves us in maildir, so we needn't
356 b330c942 2005-10-31 devnull * walk /mail/fs/mbox for each face; this makes startup
357 b330c942 2005-10-31 devnull * a fair bit quicker.
358 b330c942 2005-10-31 devnull */
359 b330c942 2005-10-31 devnull if(getwd(pwd, sizeof pwd) != nil && strcmp(pwd, dir) == 0)
360 b330c942 2005-10-31 devnull sprint(buf, "%s/info", num);
361 b330c942 2005-10-31 devnull else
362 b330c942 2005-10-31 devnull sprint(buf, "%s/%s/info", dir, num);
363 b330c942 2005-10-31 devnull #endif
364 b330c942 2005-10-31 devnull sprint(buf, "%s/%s/info", dir, num);
365 b330c942 2005-10-31 devnull len = fsdirlen(upasfs, buf);
366 b330c942 2005-10-31 devnull if(len <= 0)
367 b330c942 2005-10-31 devnull return nil;
368 b330c942 2005-10-31 devnull fid = fsopen(upasfs,buf, OREAD);
369 b330c942 2005-10-31 devnull if(fid == nil)
370 b330c942 2005-10-31 devnull return nil;
371 b330c942 2005-10-31 devnull info = emalloc(len+1);
372 b330c942 2005-10-31 devnull n = fsreadn(fid, info, len);
373 b330c942 2005-10-31 devnull fsclose(fid);
374 b330c942 2005-10-31 devnull if(n < 0){
375 b330c942 2005-10-31 devnull free(info);
376 b330c942 2005-10-31 devnull return nil;
377 b330c942 2005-10-31 devnull }
378 b330c942 2005-10-31 devnull info[n] = '\0';
379 b330c942 2005-10-31 devnull f = emalloc(sizeof(Face));
380 b330c942 2005-10-31 devnull from = iline(info, &p); /* from */
381 b330c942 2005-10-31 devnull iline(p, &p); /* to */
382 b330c942 2005-10-31 devnull iline(p, &p); /* cc */
383 b330c942 2005-10-31 devnull iline(p, &p); /* replyto */
384 b330c942 2005-10-31 devnull date = iline(p, &p); /* date */
385 b330c942 2005-10-31 devnull setname(f, estrdup(from));
386 b330c942 2005-10-31 devnull f->time = parsedate(date);
387 b330c942 2005-10-31 devnull f->tm = *localtime(f->time);
388 b330c942 2005-10-31 devnull sprint(buf, "%s/%s", dir, num);
389 b330c942 2005-10-31 devnull f->str[Sshow] = estrdup(buf);
390 b330c942 2005-10-31 devnull iline(p, &p); /* subject */
391 b330c942 2005-10-31 devnull iline(p, &p); /* mime content type */
392 b330c942 2005-10-31 devnull iline(p, &p); /* mime disposition */
393 b330c942 2005-10-31 devnull iline(p, &p); /* filename */
394 b330c942 2005-10-31 devnull digest = iline(p, &p); /* digest */
395 b330c942 2005-10-31 devnull f->str[Sdigest] = estrdup(digest);
396 b330c942 2005-10-31 devnull free(info);
397 b330c942 2005-10-31 devnull return f;
398 b330c942 2005-10-31 devnull }