2 941e1713 2006-02-15 devnull * Mail file system.
4 941e1713 2006-02-15 devnull * Serve the bulk of requests out of memory, so they can
5 fa325e9b 2020-01-10 cross * be in the main loop (will never see their flushes).
6 941e1713 2006-02-15 devnull * Some requests do block and they get handled in
7 941e1713 2006-02-15 devnull * separate threads. They're all okay to give up on
8 941e1713 2006-02-15 devnull * early, though, so we just respond saying interrupted
9 941e1713 2006-02-15 devnull * and then when they finish, silently discard the request.
13 941e1713 2006-02-15 devnull decode subject, etc.
14 941e1713 2006-02-15 devnull decode body
17 941e1713 2006-02-15 devnull disposition
20 941e1713 2006-02-15 devnull ctl messages
22 941e1713 2006-02-15 devnull fetch mail on demand
26 941e1713 2006-02-15 devnull #include "a.h"
30 941e1713 2006-02-15 devnull /* directories */
35 941e1713 2006-02-15 devnull /* control files */
40 941e1713 2006-02-15 devnull /* message header - same order as struct Hdr */
42 941e1713 2006-02-15 devnull Qsubject,
45 941e1713 2006-02-15 devnull Qreplyto,
49 941e1713 2006-02-15 devnull Qinreplyto,
50 941e1713 2006-02-15 devnull Qmessageid,
52 941e1713 2006-02-15 devnull /* part data - same order as stuct Part */
56 941e1713 2006-02-15 devnull Qencoding, /* only here temporarily! */
57 941e1713 2006-02-15 devnull Qcharset,
58 bb70a84b 2007-06-23 devnull Qfilename,
60 941e1713 2006-02-15 devnull Qrawheader,
61 941e1713 2006-02-15 devnull Qrawbody,
62 941e1713 2006-02-15 devnull Qmimeheader,
64 941e1713 2006-02-15 devnull /* part numbers - same order as struct Part */
68 941e1713 2006-02-15 devnull /* other message files */
72 941e1713 2006-02-15 devnull Qdisposition,
75 941e1713 2006-02-15 devnull Qrawunix,
76 941e1713 2006-02-15 devnull Qunixdate,
77 941e1713 2006-02-15 devnull Qunixheader,
79 941e1713 2006-02-15 devnull Qfile0 = Qbody,
80 cbeb0b26 2006-04-01 devnull Qnfile = Qunixheader+1-Qfile0
83 941e1713 2006-02-15 devnull static char Egreg[] = "gone postal";
84 941e1713 2006-02-15 devnull static char Enobox[] = "no such mailbox";
85 941e1713 2006-02-15 devnull static char Enomsg[] = "no such message";
86 941e1713 2006-02-15 devnull static char Eboxgone[] = "mailbox not available";
87 941e1713 2006-02-15 devnull static char Emsggone[] = "message not available";
88 941e1713 2006-02-15 devnull static char Eperm[] = "permission denied";
89 941e1713 2006-02-15 devnull static char Ebadctl[] = "bad control message";
91 941e1713 2006-02-15 devnull Channel *fsreqchan;
93 941e1713 2006-02-15 devnull Qid rootqid;
94 941e1713 2006-02-15 devnull ulong t0;
96 2fc68b6d 2011-11-22 rsc #ifdef PLAN9PORT
98 941e1713 2006-02-15 devnull responderror(Req *r)
100 941e1713 2006-02-15 devnull char e[ERRMAX];
102 941e1713 2006-02-15 devnull rerrstr(e, sizeof e);
103 941e1713 2006-02-15 devnull respond(r, e);
108 941e1713 2006-02-15 devnull qtype(Qid q)
110 941e1713 2006-02-15 devnull return q.path&0x3F;
114 941e1713 2006-02-15 devnull qboxid(Qid q)
116 941e1713 2006-02-15 devnull return (q.path>>40)&0xFFFF;
120 941e1713 2006-02-15 devnull qmsgid(Qid q)
122 941e1713 2006-02-15 devnull return ((q.path>>32)&0xFF000000) | ((q.path>>16)&0xFFFFFF);
126 941e1713 2006-02-15 devnull qpartid(Qid q)
128 941e1713 2006-02-15 devnull return ((q.path>>6)&0x3FF);
132 941e1713 2006-02-15 devnull qid(int ctl, Box *box, Msg *msg, Part *part)
136 941e1713 2006-02-15 devnull q.type = 0;
137 941e1713 2006-02-15 devnull if(ctl == Qroot || ctl == Qbox || ctl == Qmsg)
138 941e1713 2006-02-15 devnull q.type = QTDIR;
139 941e1713 2006-02-15 devnull q.path = (vlong)((msg ? msg->id : 0)&0xFF000000)<<32;
140 941e1713 2006-02-15 devnull q.path |= (vlong)((msg ? msg->id : 0)&0xFFFFFF)<<16;
141 941e1713 2006-02-15 devnull q.path |= (vlong)((box ? box->id : 0)&0xFFFF)<<40;
142 941e1713 2006-02-15 devnull q.path |= ((part ? part->ix : 0)&0x3FF)<<6;
143 941e1713 2006-02-15 devnull q.path |= ctl&0x3F;
144 941e1713 2006-02-15 devnull q.vers = box ? box->validity : 0;
145 941e1713 2006-02-15 devnull return q;
149 941e1713 2006-02-15 devnull parseqid(Qid q, Box **box, Msg **msg, Part **part)
151 941e1713 2006-02-15 devnull *msg = nil;
152 941e1713 2006-02-15 devnull *part = nil;
154 941e1713 2006-02-15 devnull *box = boxbyid(qboxid(q));
155 941e1713 2006-02-15 devnull if(*box){
156 941e1713 2006-02-15 devnull *msg = msgbyid(*box, qmsgid(q));
158 941e1713 2006-02-15 devnull if(*msg)
159 941e1713 2006-02-15 devnull *part = partbyid(*msg, qpartid(q));
160 941e1713 2006-02-15 devnull return qtype(q);
163 941e1713 2006-02-15 devnull static struct {
164 941e1713 2006-02-15 devnull int type;
165 941e1713 2006-02-15 devnull char *name;
166 941e1713 2006-02-15 devnull } typenames[] = {
167 941e1713 2006-02-15 devnull Qbody, "body",
168 941e1713 2006-02-15 devnull Qbcc, "bcc",
169 941e1713 2006-02-15 devnull Qcc, "cc",
170 941e1713 2006-02-15 devnull Qdate, "date",
171 941e1713 2006-02-15 devnull Qfilename, "filename",
172 941e1713 2006-02-15 devnull Qflags, "flags",
173 941e1713 2006-02-15 devnull Qfrom, "from",
174 941e1713 2006-02-15 devnull Qheader, "header",
175 941e1713 2006-02-15 devnull Qinfo, "info",
176 941e1713 2006-02-15 devnull Qinreplyto, "inreplyto",
177 941e1713 2006-02-15 devnull Qlines, "lines",
178 941e1713 2006-02-15 devnull Qmimeheader, "mimeheader",
179 941e1713 2006-02-15 devnull Qmessageid, "messageid",
180 941e1713 2006-02-15 devnull Qraw, "raw",
181 941e1713 2006-02-15 devnull Qrawunix, "rawunix",
182 941e1713 2006-02-15 devnull Qrawbody, "rawbody",
183 941e1713 2006-02-15 devnull Qrawheader, "rawheader",
184 941e1713 2006-02-15 devnull Qreplyto, "replyto",
185 941e1713 2006-02-15 devnull Qsender, "sender",
186 941e1713 2006-02-15 devnull Qsubject, "subject",
187 941e1713 2006-02-15 devnull Qto, "to",
188 941e1713 2006-02-15 devnull Qtype, "type",
189 941e1713 2006-02-15 devnull Qunixdate, "unixdate",
190 941e1713 2006-02-15 devnull Qunixheader, "unixheader",
191 941e1713 2006-02-15 devnull Qidstr, "idstr",
192 941e1713 2006-02-15 devnull Qdesc, "desc",
193 941e1713 2006-02-15 devnull Qencoding, "encoding",
194 cbeb0b26 2006-04-01 devnull Qcharset, "charset"
198 941e1713 2006-02-15 devnull nameoftype(int t)
202 941e1713 2006-02-15 devnull for(i=0; i<nelem(typenames); i++)
203 941e1713 2006-02-15 devnull if(typenames[i].type == t)
204 941e1713 2006-02-15 devnull return typenames[i].name;
205 941e1713 2006-02-15 devnull return "???";
209 941e1713 2006-02-15 devnull typeofname(char *name)
213 941e1713 2006-02-15 devnull for(i=0; i<nelem(typenames); i++)
214 941e1713 2006-02-15 devnull if(strcmp(typenames[i].name, name) == 0)
215 941e1713 2006-02-15 devnull return typenames[i].type;
216 941e1713 2006-02-15 devnull return 0;
219 941e1713 2006-02-15 devnull static void
220 941e1713 2006-02-15 devnull fsattach(Req *r)
222 941e1713 2006-02-15 devnull r->fid->qid = rootqid;
223 941e1713 2006-02-15 devnull r->ofcall.qid = rootqid;
224 941e1713 2006-02-15 devnull respond(r, nil);
227 c7722328 2006-02-28 devnull static int
228 941e1713 2006-02-15 devnull isnumber(char *s)
232 941e1713 2006-02-15 devnull if(*s < '1' || *s > '9')
233 941e1713 2006-02-15 devnull return 0;
234 941e1713 2006-02-15 devnull n = strtol(s, &s, 10);
235 941e1713 2006-02-15 devnull if(*s != 0)
236 941e1713 2006-02-15 devnull return 0;
237 941e1713 2006-02-15 devnull return n;
240 941e1713 2006-02-15 devnull static char*
241 941e1713 2006-02-15 devnull fswalk1(Fid *fid, char *name, void *arg)
243 941e1713 2006-02-15 devnull int a, type;
244 941e1713 2006-02-15 devnull Box *b, *box;
245 941e1713 2006-02-15 devnull Msg *msg;
246 941e1713 2006-02-15 devnull Part *p, *part;
248 941e1713 2006-02-15 devnull USED(arg);
250 941e1713 2006-02-15 devnull switch(type = parseqid(fid->qid, &box, &msg, &part)){
251 941e1713 2006-02-15 devnull case Qroot:
252 941e1713 2006-02-15 devnull if(strcmp(name, "..") == 0)
253 941e1713 2006-02-15 devnull return nil;
254 941e1713 2006-02-15 devnull if(strcmp(name, "ctl") == 0){
255 941e1713 2006-02-15 devnull fid->qid = qid(Qctl, nil, nil, nil);
256 941e1713 2006-02-15 devnull return nil;
258 941e1713 2006-02-15 devnull if((box = boxbyname(name)) != nil){
259 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, box, nil, nil);
260 941e1713 2006-02-15 devnull return nil;
264 941e1713 2006-02-15 devnull case Qbox:
266 941e1713 2006-02-15 devnull * Would be nice if .. could work even if the box is gone,
267 941e1713 2006-02-15 devnull * but we don't know how deep the directory was.
269 941e1713 2006-02-15 devnull if(box == nil)
270 941e1713 2006-02-15 devnull return Eboxgone;
271 941e1713 2006-02-15 devnull if(strcmp(name, "..") == 0){
272 941e1713 2006-02-15 devnull if((box = box->parent) == nil){
273 941e1713 2006-02-15 devnull fid->qid = rootqid;
274 941e1713 2006-02-15 devnull return nil;
276 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, box, nil, nil);
277 941e1713 2006-02-15 devnull return nil;
279 941e1713 2006-02-15 devnull if(strcmp(name, "ctl") == 0){
280 941e1713 2006-02-15 devnull fid->qid = qid(Qboxctl, box, nil, nil);
281 941e1713 2006-02-15 devnull return nil;
283 941e1713 2006-02-15 devnull if(strcmp(name, "search") == 0){
284 941e1713 2006-02-15 devnull fid->qid = qid(Qsearch, box, nil, nil);
285 941e1713 2006-02-15 devnull return nil;
287 941e1713 2006-02-15 devnull if((b = subbox(box, name)) != nil){
288 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, b, nil, nil);
289 941e1713 2006-02-15 devnull return nil;
291 941e1713 2006-02-15 devnull if((a = isnumber(name)) != 0){
292 941e1713 2006-02-15 devnull if((msg = msgbyid(box, a)) == nil){
293 941e1713 2006-02-15 devnull return Enomsg;
295 941e1713 2006-02-15 devnull fid->qid = qid(Qmsg, box, msg, nil);
296 941e1713 2006-02-15 devnull return nil;
300 941e1713 2006-02-15 devnull case Qmsg:
301 941e1713 2006-02-15 devnull if(strcmp(name, "..") == 0){
302 941e1713 2006-02-15 devnull if(part == msg->part[0]){
303 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, box, nil, nil);
304 941e1713 2006-02-15 devnull return nil;
306 941e1713 2006-02-15 devnull fid->qid = qid(Qmsg, box, msg, part->parent);
307 941e1713 2006-02-15 devnull return nil;
309 941e1713 2006-02-15 devnull if((type = typeofname(name)) > 0){
310 941e1713 2006-02-15 devnull /* XXX - should check that type makes sense (see msggen) */
311 941e1713 2006-02-15 devnull fid->qid = qid(type, box, msg, part);
312 941e1713 2006-02-15 devnull return nil;
314 941e1713 2006-02-15 devnull if((a = isnumber(name)) != 0){
315 941e1713 2006-02-15 devnull if((p = subpart(part, a-1)) != nil){
316 941e1713 2006-02-15 devnull fid->qid = qid(Qmsg, box, msg, p);
317 941e1713 2006-02-15 devnull return nil;
322 941e1713 2006-02-15 devnull return "not found";
325 941e1713 2006-02-15 devnull static void
326 941e1713 2006-02-15 devnull fswalk(Req *r)
328 941e1713 2006-02-15 devnull walkandclone(r, fswalk1, nil, nil);
331 941e1713 2006-02-15 devnull static struct {
332 941e1713 2006-02-15 devnull int flag;
333 941e1713 2006-02-15 devnull char *name;
334 941e1713 2006-02-15 devnull } flagtab[] = {
335 941e1713 2006-02-15 devnull FlagJunk, "junk",
336 941e1713 2006-02-15 devnull FlagNonJunk, "notjunk",
337 941e1713 2006-02-15 devnull FlagReplied, "replied",
338 941e1713 2006-02-15 devnull FlagFlagged, "flagged",
339 cbeb0b26 2006-04-01 devnull /* FlagDeleted, "deleted", */
340 941e1713 2006-02-15 devnull FlagDraft, "draft",
341 cbeb0b26 2006-04-01 devnull FlagSeen, "seen"
344 941e1713 2006-02-15 devnull static void
345 941e1713 2006-02-15 devnull addaddrs(Fmt *fmt, char *prefix, char *addrs)
347 941e1713 2006-02-15 devnull char **f;
348 941e1713 2006-02-15 devnull int i, nf, inquote;
349 941e1713 2006-02-15 devnull char *p, *sep;
351 941e1713 2006-02-15 devnull if(addrs == nil)
353 941e1713 2006-02-15 devnull addrs = estrdup(addrs);
355 941e1713 2006-02-15 devnull inquote = 0;
356 941e1713 2006-02-15 devnull for(p=addrs; *p; p++){
357 941e1713 2006-02-15 devnull if(*p == ' ' && !inquote)
359 941e1713 2006-02-15 devnull if(*p == '\'')
360 941e1713 2006-02-15 devnull inquote = !inquote;
362 941e1713 2006-02-15 devnull nf += 10;
363 941e1713 2006-02-15 devnull f = emalloc(nf*sizeof f[0]);
364 941e1713 2006-02-15 devnull nf = tokenize(addrs, f, nf);
365 941e1713 2006-02-15 devnull fmtprint(fmt, "%s:", prefix);
366 941e1713 2006-02-15 devnull sep = " ";
367 941e1713 2006-02-15 devnull for(i=0; i+1<nf; i+=2){
368 941e1713 2006-02-15 devnull if(f[i][0])
369 941e1713 2006-02-15 devnull fmtprint(fmt, "%s%s <%s>", sep, f[i], f[i+1]);
371 941e1713 2006-02-15 devnull fmtprint(fmt, "%s%s", sep, f[i+1]);
372 941e1713 2006-02-15 devnull sep = ", ";
374 941e1713 2006-02-15 devnull fmtprint(fmt, "\n");
375 941e1713 2006-02-15 devnull free(addrs);
378 941e1713 2006-02-15 devnull static void
379 941e1713 2006-02-15 devnull mkbody(Part *p, Qid q)
381 941e1713 2006-02-15 devnull char *t;
382 941e1713 2006-02-15 devnull int len;
385 941e1713 2006-02-15 devnull if(p->msg->part[0] == p)
386 941e1713 2006-02-15 devnull t = p->rawbody;
388 941e1713 2006-02-15 devnull t = p->raw;
389 941e1713 2006-02-15 devnull if(t == nil)
392 941e1713 2006-02-15 devnull len = -1;
393 941e1713 2006-02-15 devnull if(p->encoding && cistrcmp(p->encoding, "quoted-printable") == 0)
394 941e1713 2006-02-15 devnull t = decode(QuotedPrintable, t, &len);
395 941e1713 2006-02-15 devnull else if(p->encoding && cistrcmp(p->encoding, "base64") == 0)
396 941e1713 2006-02-15 devnull t = decode(Base64, t, &len);
398 941e1713 2006-02-15 devnull t = estrdup(t);
400 941e1713 2006-02-15 devnull if(p->charset){
401 941e1713 2006-02-15 devnull t = tcs(p->charset, t);
402 941e1713 2006-02-15 devnull len = -1;
404 941e1713 2006-02-15 devnull p->body = t;
405 941e1713 2006-02-15 devnull if(len == -1)
406 941e1713 2006-02-15 devnull p->nbody = strlen(t);
408 941e1713 2006-02-15 devnull p->nbody = len;
411 941e1713 2006-02-15 devnull static Qid ZQ;
413 941e1713 2006-02-15 devnull static int
414 941e1713 2006-02-15 devnull filedata(int type, Box *box, Msg *msg, Part *part, char **pp, int *len, int *freeme, int force, Qid q)
416 941e1713 2006-02-15 devnull int i, inquote, n, t;
417 941e1713 2006-02-15 devnull char *from, *s;
418 941e1713 2006-02-15 devnull static char buf[256];
419 941e1713 2006-02-15 devnull Fmt fmt;
421 941e1713 2006-02-15 devnull *pp = nil;
422 941e1713 2006-02-15 devnull *freeme = 0;
424 941e1713 2006-02-15 devnull *len = -1;
426 941e1713 2006-02-15 devnull if(msg == nil || part == nil){
427 941e1713 2006-02-15 devnull werrstr(Emsggone);
428 941e1713 2006-02-15 devnull return -1;
430 941e1713 2006-02-15 devnull switch(type){
431 941e1713 2006-02-15 devnull case Qdate:
432 941e1713 2006-02-15 devnull case Qsubject:
433 941e1713 2006-02-15 devnull case Qfrom:
434 941e1713 2006-02-15 devnull case Qsender:
435 941e1713 2006-02-15 devnull case Qreplyto:
436 941e1713 2006-02-15 devnull case Qto:
437 941e1713 2006-02-15 devnull case Qcc:
438 941e1713 2006-02-15 devnull case Qbcc:
439 941e1713 2006-02-15 devnull case Qinreplyto:
440 941e1713 2006-02-15 devnull case Qmessageid:
441 941e1713 2006-02-15 devnull if(part->hdr == nil){
442 941e1713 2006-02-15 devnull werrstr(Emsggone);
443 941e1713 2006-02-15 devnull return -1;
445 941e1713 2006-02-15 devnull *pp = ((char**)&part->hdr->date)[type-Qdate];
446 941e1713 2006-02-15 devnull return 0;
448 941e1713 2006-02-15 devnull case Qunixdate:
449 941e1713 2006-02-15 devnull strcpy(buf, ctime(msg->date));
450 941e1713 2006-02-15 devnull *pp = buf;
451 941e1713 2006-02-15 devnull return 0;
453 941e1713 2006-02-15 devnull case Qunixheader:
454 941e1713 2006-02-15 devnull if(part->hdr == nil){
455 941e1713 2006-02-15 devnull werrstr(Emsggone);
456 941e1713 2006-02-15 devnull return -1;
458 941e1713 2006-02-15 devnull from = part->hdr->from;
459 941e1713 2006-02-15 devnull if(from == nil)
460 941e1713 2006-02-15 devnull from = "???";
462 941e1713 2006-02-15 devnull inquote = 0;
463 941e1713 2006-02-15 devnull for(; *from; from++){
464 941e1713 2006-02-15 devnull if(*from == '\'')
465 941e1713 2006-02-15 devnull inquote = !inquote;
466 941e1713 2006-02-15 devnull if(!inquote && *from == ' '){
471 941e1713 2006-02-15 devnull if(*from == 0)
472 941e1713 2006-02-15 devnull from = part->hdr->from;
474 941e1713 2006-02-15 devnull n = snprint(buf, sizeof buf, "From %s %s", from, ctime(msg->date));
475 941e1713 2006-02-15 devnull if(n+1 < sizeof buf){
476 941e1713 2006-02-15 devnull *pp = buf;
477 941e1713 2006-02-15 devnull return 0;
479 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
480 941e1713 2006-02-15 devnull fmtprint(&fmt, "From %s %s", from, ctime(msg->date));
481 941e1713 2006-02-15 devnull s = fmtstrflush(&fmt);
483 941e1713 2006-02-15 devnull *pp = s;
484 941e1713 2006-02-15 devnull *freeme = 1;
486 941e1713 2006-02-15 devnull *pp = buf;
487 941e1713 2006-02-15 devnull return 0;
489 941e1713 2006-02-15 devnull case Qtype:
490 941e1713 2006-02-15 devnull case Qidstr:
491 941e1713 2006-02-15 devnull case Qdesc:
492 941e1713 2006-02-15 devnull case Qencoding:
493 941e1713 2006-02-15 devnull case Qcharset:
494 bb70a84b 2007-06-23 devnull case Qfilename:
495 941e1713 2006-02-15 devnull case Qraw:
496 941e1713 2006-02-15 devnull case Qrawheader:
497 941e1713 2006-02-15 devnull case Qrawbody:
498 941e1713 2006-02-15 devnull case Qmimeheader:
499 941e1713 2006-02-15 devnull *pp = ((char**)&part->type)[type-Qtype];
500 941e1713 2006-02-15 devnull if(*pp == nil && force){
501 941e1713 2006-02-15 devnull switch(type){
502 941e1713 2006-02-15 devnull case Qraw:
503 941e1713 2006-02-15 devnull imapfetchraw(imap, part);
505 941e1713 2006-02-15 devnull case Qrawheader:
506 941e1713 2006-02-15 devnull imapfetchrawheader(imap, part);
508 941e1713 2006-02-15 devnull case Qrawbody:
509 941e1713 2006-02-15 devnull imapfetchrawbody(imap, part);
511 941e1713 2006-02-15 devnull case Qmimeheader:
512 941e1713 2006-02-15 devnull imapfetchrawmime(imap, part);
514 941e1713 2006-02-15 devnull default:
515 941e1713 2006-02-15 devnull return 0;
518 941e1713 2006-02-15 devnull * We ran fetchsomething, which might have changed
519 941e1713 2006-02-15 devnull * the mailbox contents. Msg might even be gone.
521 941e1713 2006-02-15 devnull t = parseqid(q, &box, &msg, &part);
522 941e1713 2006-02-15 devnull if(t != type || msg == nil || part == nil)
523 941e1713 2006-02-15 devnull return 0;
524 941e1713 2006-02-15 devnull *pp = ((char**)&part->type)[type-Qtype];
526 941e1713 2006-02-15 devnull return 0;
528 941e1713 2006-02-15 devnull case Qbody:
529 941e1713 2006-02-15 devnull if(part->body){
530 941e1713 2006-02-15 devnull *pp = part->body;
532 941e1713 2006-02-15 devnull *len = part->nbody;
533 941e1713 2006-02-15 devnull return 0;
535 941e1713 2006-02-15 devnull if(!force)
536 941e1713 2006-02-15 devnull return 0;
537 941e1713 2006-02-15 devnull if(part->rawbody == nil){
538 941e1713 2006-02-15 devnull if(part->msg->part[0] == part)
539 941e1713 2006-02-15 devnull imapfetchrawbody(imap, part);
541 941e1713 2006-02-15 devnull imapfetchraw(imap, part);
542 941e1713 2006-02-15 devnull t = parseqid(q, &box, &msg, &part);
543 941e1713 2006-02-15 devnull if(t != type || msg == nil || part == nil)
544 941e1713 2006-02-15 devnull return 0;
546 941e1713 2006-02-15 devnull mkbody(part, q);
547 941e1713 2006-02-15 devnull *pp = part->body;
549 941e1713 2006-02-15 devnull *len = part->nbody;
550 941e1713 2006-02-15 devnull return 0;
552 941e1713 2006-02-15 devnull case Qsize:
553 941e1713 2006-02-15 devnull case Qlines:
554 941e1713 2006-02-15 devnull n = ((uint*)&part->size)[type-Qsize];
555 941e1713 2006-02-15 devnull snprint(buf, sizeof buf, "%d", n);
556 941e1713 2006-02-15 devnull *pp = buf;
557 941e1713 2006-02-15 devnull return 0;
559 941e1713 2006-02-15 devnull case Qflags:
560 941e1713 2006-02-15 devnull s = buf;
562 941e1713 2006-02-15 devnull for(i=0; i<nelem(flagtab); i++){
563 941e1713 2006-02-15 devnull if(msg->flags&flagtab[i].flag){
564 941e1713 2006-02-15 devnull if(s > buf)
565 941e1713 2006-02-15 devnull *s++ = ' ';
566 941e1713 2006-02-15 devnull strcpy(s, flagtab[i].name);
567 941e1713 2006-02-15 devnull s += strlen(s);
570 941e1713 2006-02-15 devnull *pp = buf;
571 941e1713 2006-02-15 devnull return 0;
573 941e1713 2006-02-15 devnull case Qinfo:
574 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
575 941e1713 2006-02-15 devnull if(part == msg->part[0]){
576 941e1713 2006-02-15 devnull if(msg->date)
577 2fc68b6d 2011-11-22 rsc fmtprint(&fmt, "unixdate %ud %s", msg->date, ctime(msg->date));
578 941e1713 2006-02-15 devnull if(msg->flags){
579 941e1713 2006-02-15 devnull filedata(Qflags, box, msg, part, pp, nil, freeme, 0, ZQ);
580 941e1713 2006-02-15 devnull fmtprint(&fmt, "flags %s\n", buf);
583 941e1713 2006-02-15 devnull if(part->hdr){
584 941e1713 2006-02-15 devnull if(part->hdr->digest)
585 941e1713 2006-02-15 devnull fmtprint(&fmt, "digest %s\n", part->hdr->digest);
586 941e1713 2006-02-15 devnull if(part->hdr->from)
587 941e1713 2006-02-15 devnull fmtprint(&fmt, "from %s\n", part->hdr->from);
588 941e1713 2006-02-15 devnull if(part->hdr->to)
589 941e1713 2006-02-15 devnull fmtprint(&fmt, "to %s\n", part->hdr->to);
590 941e1713 2006-02-15 devnull if(part->hdr->cc)
591 941e1713 2006-02-15 devnull fmtprint(&fmt, "cc %s\n", part->hdr->cc);
592 941e1713 2006-02-15 devnull if(part->hdr->replyto)
593 941e1713 2006-02-15 devnull fmtprint(&fmt, "replyto %s\n", part->hdr->replyto);
594 941e1713 2006-02-15 devnull if(part->hdr->bcc)
595 941e1713 2006-02-15 devnull fmtprint(&fmt, "bcc %s\n", part->hdr->bcc);
596 941e1713 2006-02-15 devnull if(part->hdr->inreplyto)
597 941e1713 2006-02-15 devnull fmtprint(&fmt, "inreplyto %s\n", part->hdr->inreplyto);
598 941e1713 2006-02-15 devnull if(part->hdr->date)
599 941e1713 2006-02-15 devnull fmtprint(&fmt, "date %s\n", part->hdr->date);
600 941e1713 2006-02-15 devnull if(part->hdr->sender)
601 941e1713 2006-02-15 devnull fmtprint(&fmt, "sender %s\n", part->hdr->sender);
602 941e1713 2006-02-15 devnull if(part->hdr->messageid)
603 941e1713 2006-02-15 devnull fmtprint(&fmt, "messageid %s\n", part->hdr->messageid);
604 941e1713 2006-02-15 devnull if(part->hdr->subject)
605 941e1713 2006-02-15 devnull fmtprint(&fmt, "subject %s\n", part->hdr->subject);
607 941e1713 2006-02-15 devnull if(part->type)
608 941e1713 2006-02-15 devnull fmtprint(&fmt, "type %s\n", part->type);
609 941e1713 2006-02-15 devnull if(part->lines)
610 941e1713 2006-02-15 devnull fmtprint(&fmt, "lines %d\n", part->lines);
611 141d6009 2006-06-30 devnull if(part->filename)
612 141d6009 2006-06-30 devnull fmtprint(&fmt, "filename %s\n", part->filename);
613 941e1713 2006-02-15 devnull s = fmtstrflush(&fmt);
614 941e1713 2006-02-15 devnull if(s == nil)
615 941e1713 2006-02-15 devnull s = estrdup("");
616 941e1713 2006-02-15 devnull *freeme = 1;
617 941e1713 2006-02-15 devnull *pp = s;
618 941e1713 2006-02-15 devnull return 0;
620 941e1713 2006-02-15 devnull case Qheader:
621 941e1713 2006-02-15 devnull if(part->hdr == nil)
622 941e1713 2006-02-15 devnull return 0;
623 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
624 941e1713 2006-02-15 devnull if(part == msg->part[0])
625 941e1713 2006-02-15 devnull fmtprint(&fmt, "Date: %s", ctime(msg->date));
627 941e1713 2006-02-15 devnull fmtprint(&fmt, "Date: %s\n", part->hdr->date);
628 941e1713 2006-02-15 devnull addaddrs(&fmt, "To", part->hdr->to);
629 941e1713 2006-02-15 devnull addaddrs(&fmt, "From", part->hdr->from);
630 941e1713 2006-02-15 devnull if(part->hdr->from==nil
631 941e1713 2006-02-15 devnull || (part->hdr->sender && strcmp(part->hdr->sender, part->hdr->from) != 0))
632 941e1713 2006-02-15 devnull addaddrs(&fmt, "Sender", part->hdr->sender);
633 fa325e9b 2020-01-10 cross if(part->hdr->from==nil
634 941e1713 2006-02-15 devnull || (part->hdr->replyto && strcmp(part->hdr->replyto, part->hdr->from) != 0))
635 941e1713 2006-02-15 devnull addaddrs(&fmt, "Reply-To", part->hdr->replyto);
636 eb44dca2 2007-06-25 devnull fmtprint(&fmt, "Subject: %s\n", part->hdr->subject);
637 941e1713 2006-02-15 devnull s = fmtstrflush(&fmt);
638 941e1713 2006-02-15 devnull if(s == nil)
639 941e1713 2006-02-15 devnull s = estrdup("");
640 941e1713 2006-02-15 devnull *freeme = 1;
641 941e1713 2006-02-15 devnull *pp = s;
642 941e1713 2006-02-15 devnull return 0;
644 941e1713 2006-02-15 devnull default:
645 941e1713 2006-02-15 devnull werrstr(Egreg);
646 941e1713 2006-02-15 devnull return -1;
651 941e1713 2006-02-15 devnull filldir(Dir *d, int type, Box *box, Msg *msg, Part *part)
653 941e1713 2006-02-15 devnull int freeme, len;
654 941e1713 2006-02-15 devnull char *s;
656 941e1713 2006-02-15 devnull memset(d, 0, sizeof *d);
657 941e1713 2006-02-15 devnull if(box){
658 941e1713 2006-02-15 devnull d->atime = box->time;
659 941e1713 2006-02-15 devnull d->mtime = box->time;
661 941e1713 2006-02-15 devnull d->atime = t0;
662 941e1713 2006-02-15 devnull d->mtime = t0;
664 941e1713 2006-02-15 devnull d->uid = estrdup9p("upas");
665 941e1713 2006-02-15 devnull d->gid = estrdup9p("upas");
666 941e1713 2006-02-15 devnull d->muid = estrdup9p("upas");
667 941e1713 2006-02-15 devnull d->qid = qid(type, box, msg, part);
669 941e1713 2006-02-15 devnull switch(type){
670 941e1713 2006-02-15 devnull case Qroot:
671 941e1713 2006-02-15 devnull case Qbox:
672 941e1713 2006-02-15 devnull case Qmsg:
673 941e1713 2006-02-15 devnull d->mode = 0555|DMDIR;
674 941e1713 2006-02-15 devnull if(box && !(box->flags&FlagNoInferiors))
675 941e1713 2006-02-15 devnull d->mode = 0775|DMDIR;
677 941e1713 2006-02-15 devnull case Qctl:
678 941e1713 2006-02-15 devnull case Qboxctl:
679 941e1713 2006-02-15 devnull d->mode = 0222;
681 941e1713 2006-02-15 devnull case Qsearch:
682 941e1713 2006-02-15 devnull d->mode = 0666;
685 941e1713 2006-02-15 devnull case Qflags:
686 941e1713 2006-02-15 devnull d->mode = 0666;
687 941e1713 2006-02-15 devnull goto msgfile;
688 941e1713 2006-02-15 devnull default:
689 941e1713 2006-02-15 devnull d->mode = 0444;
690 941e1713 2006-02-15 devnull msgfile:
691 941e1713 2006-02-15 devnull if(filedata(type, box, msg, part, &s, &len, &freeme, 0, ZQ) >= 0){
693 941e1713 2006-02-15 devnull if(len == -1)
694 941e1713 2006-02-15 devnull d->length = strlen(s);
696 941e1713 2006-02-15 devnull d->length = len;
697 941e1713 2006-02-15 devnull if(freeme)
698 941e1713 2006-02-15 devnull free(s);
700 941e1713 2006-02-15 devnull }else if(type == Qraw && msg && part == msg->part[0])
701 941e1713 2006-02-15 devnull d->length = msg->size;
705 941e1713 2006-02-15 devnull switch(type){
706 941e1713 2006-02-15 devnull case Qroot:
707 941e1713 2006-02-15 devnull d->name = estrdup9p("/");
709 941e1713 2006-02-15 devnull case Qbox:
710 941e1713 2006-02-15 devnull if(box == nil){
711 941e1713 2006-02-15 devnull werrstr(Enobox);
712 941e1713 2006-02-15 devnull return -1;
714 941e1713 2006-02-15 devnull d->name = estrdup9p(box->elem);
716 941e1713 2006-02-15 devnull case Qmsg:
717 941e1713 2006-02-15 devnull if(msg == nil){
718 941e1713 2006-02-15 devnull werrstr(Enomsg);
719 941e1713 2006-02-15 devnull return -1;
721 941e1713 2006-02-15 devnull if(part == nil || part == msg->part[0])
722 941e1713 2006-02-15 devnull d->name = esmprint("%d", msg->id);
724 941e1713 2006-02-15 devnull d->name = esmprint("%d", part->pix+1);
726 941e1713 2006-02-15 devnull case Qctl:
727 941e1713 2006-02-15 devnull case Qboxctl:
728 941e1713 2006-02-15 devnull d->name = estrdup9p("ctl");
730 941e1713 2006-02-15 devnull case Qsearch:
731 941e1713 2006-02-15 devnull d->name = estrdup9p("search");
733 941e1713 2006-02-15 devnull default:
734 941e1713 2006-02-15 devnull d->name = estrdup9p(nameoftype(type));
737 941e1713 2006-02-15 devnull return 0;
740 941e1713 2006-02-15 devnull static void
741 941e1713 2006-02-15 devnull fsstat(Req *r)
743 941e1713 2006-02-15 devnull int type;
744 941e1713 2006-02-15 devnull Box *box;
745 941e1713 2006-02-15 devnull Msg *msg;
746 941e1713 2006-02-15 devnull Part *part;
748 941e1713 2006-02-15 devnull type = parseqid(r->fid->qid, &box, &msg, &part);
749 941e1713 2006-02-15 devnull if(filldir(&r->d, type, box, msg, part) < 0)
750 941e1713 2006-02-15 devnull responderror(r);
752 941e1713 2006-02-15 devnull respond(r, nil);
756 941e1713 2006-02-15 devnull rootgen(int i, Dir *d, void *aux)
758 941e1713 2006-02-15 devnull USED(aux);
760 941e1713 2006-02-15 devnull if(i == 0)
761 941e1713 2006-02-15 devnull return filldir(d, Qctl, nil, nil, nil);
763 941e1713 2006-02-15 devnull if(i < rootbox->nsub)
764 941e1713 2006-02-15 devnull return filldir(d, Qbox, rootbox->sub[i], nil, nil);
765 941e1713 2006-02-15 devnull return -1;
769 941e1713 2006-02-15 devnull boxgen(int i, Dir *d, void *aux)
771 941e1713 2006-02-15 devnull Box *box;
773 941e1713 2006-02-15 devnull box = aux;
774 941e1713 2006-02-15 devnull if(i == 0)
775 941e1713 2006-02-15 devnull return filldir(d, Qboxctl, box, nil, nil);
777 941e1713 2006-02-15 devnull if(i == 0)
778 941e1713 2006-02-15 devnull return filldir(d, Qsearch, box, nil, nil);
780 941e1713 2006-02-15 devnull if(i < box->nsub)
781 941e1713 2006-02-15 devnull return filldir(d, Qbox, box->sub[i], nil, nil);
782 941e1713 2006-02-15 devnull i -= box->nsub;
783 941e1713 2006-02-15 devnull if(i < box->nmsg)
784 941e1713 2006-02-15 devnull return filldir(d, Qmsg, box, box->msg[i], nil);
785 941e1713 2006-02-15 devnull return -1;
788 941e1713 2006-02-15 devnull static int msgdir[] = {
790 fa325e9b 2020-01-10 cross Qbody, Qbcc, Qcc, Qdate, Qflags, Qfrom, Qheader, Qinfo,
791 fa325e9b 2020-01-10 cross Qinreplyto, Qlines, Qmimeheader, Qmessageid,
792 941e1713 2006-02-15 devnull Qraw, Qrawunix, Qrawbody, Qrawheader,
793 941e1713 2006-02-15 devnull Qreplyto, Qsender, Qsubject, Qto,
794 941e1713 2006-02-15 devnull Qunixdate, Qunixheader
796 941e1713 2006-02-15 devnull static int mimemsgdir[] = {
798 fa325e9b 2020-01-10 cross Qbody, Qbcc, Qcc, Qdate, Qfrom, Qheader, Qinfo,
799 fa325e9b 2020-01-10 cross Qinreplyto, Qlines, Qmimeheader, Qmessageid,
800 941e1713 2006-02-15 devnull Qraw, Qrawunix, Qrawbody, Qrawheader,
801 cbeb0b26 2006-04-01 devnull Qreplyto, Qsender, Qsubject, Qto
803 941e1713 2006-02-15 devnull static int mimedir[] = {
806 bb70a84b 2007-06-23 devnull Qfilename,
807 bb70a84b 2007-06-23 devnull Qcharset,
808 941e1713 2006-02-15 devnull Qmimeheader,
813 941e1713 2006-02-15 devnull msggen(int i, Dir *d, void *aux)
815 941e1713 2006-02-15 devnull Box *box;
816 941e1713 2006-02-15 devnull Msg *msg;
817 941e1713 2006-02-15 devnull Part *part;
819 941e1713 2006-02-15 devnull part = aux;
820 941e1713 2006-02-15 devnull msg = part->msg;
821 941e1713 2006-02-15 devnull box = msg->box;
822 941e1713 2006-02-15 devnull if(part->ix == 0){
823 941e1713 2006-02-15 devnull if(i < nelem(msgdir))
824 941e1713 2006-02-15 devnull return filldir(d, msgdir[i], box, msg, part);
825 941e1713 2006-02-15 devnull i -= nelem(msgdir);
826 941e1713 2006-02-15 devnull }else if(part->type && strcmp(part->type, "message/rfc822") == 0){
827 941e1713 2006-02-15 devnull if(i < nelem(mimemsgdir))
828 941e1713 2006-02-15 devnull return filldir(d, mimemsgdir[i], box, msg, part);
829 941e1713 2006-02-15 devnull i -= nelem(mimemsgdir);
831 941e1713 2006-02-15 devnull if(i < nelem(mimedir))
832 941e1713 2006-02-15 devnull return filldir(d, mimedir[i], box, msg, part);
833 941e1713 2006-02-15 devnull i -= nelem(mimedir);
835 941e1713 2006-02-15 devnull if(i < part->nsub)
836 941e1713 2006-02-15 devnull return filldir(d, Qmsg, box, msg, part->sub[i]);
837 941e1713 2006-02-15 devnull return -1;
842 cbeb0b26 2006-04-01 devnull CMhangup
844 941e1713 2006-02-15 devnull static Cmdtab ctltab[] =
846 cbeb0b26 2006-04-01 devnull CMhangup, "hangup", 2
851 941e1713 2006-02-15 devnull CMdelete,
852 941e1713 2006-02-15 devnull CMrefresh,
853 941e1713 2006-02-15 devnull CMreplied,
857 cbeb0b26 2006-04-01 devnull CMnonjunk
859 941e1713 2006-02-15 devnull static Cmdtab boxctltab[] =
861 941e1713 2006-02-15 devnull CMdelete, "delete", 0,
862 941e1713 2006-02-15 devnull CMrefresh, "refresh", 1,
863 941e1713 2006-02-15 devnull CMreplied, "replied", 0,
864 941e1713 2006-02-15 devnull CMread, "read", 0,
865 941e1713 2006-02-15 devnull CMsave, "save", 0,
866 941e1713 2006-02-15 devnull CMjunk, "junk", 0,
867 cbeb0b26 2006-04-01 devnull CMnonjunk, "nonjunk", 0
870 941e1713 2006-02-15 devnull static void
871 941e1713 2006-02-15 devnull fsread(Req *r)
873 941e1713 2006-02-15 devnull char *s;
874 941e1713 2006-02-15 devnull int type, len, freeme;
875 941e1713 2006-02-15 devnull Box *box;
876 941e1713 2006-02-15 devnull Msg *msg;
877 941e1713 2006-02-15 devnull Part *part;
879 941e1713 2006-02-15 devnull switch(type = parseqid(r->fid->qid, &box, &msg, &part)){
880 941e1713 2006-02-15 devnull case Qroot:
881 941e1713 2006-02-15 devnull dirread9p(r, rootgen, nil);
882 941e1713 2006-02-15 devnull respond(r, nil);
885 941e1713 2006-02-15 devnull case Qbox:
886 941e1713 2006-02-15 devnull if(box == nil){
887 941e1713 2006-02-15 devnull respond(r, Eboxgone);
890 941e1713 2006-02-15 devnull if(box->nmsg == 0)
891 941e1713 2006-02-15 devnull imapcheckbox(imap, box);
892 941e1713 2006-02-15 devnull parseqid(r->fid->qid, &box, &msg, &part);
893 941e1713 2006-02-15 devnull if(box == nil){
894 941e1713 2006-02-15 devnull respond(r, Eboxgone);
897 941e1713 2006-02-15 devnull dirread9p(r, boxgen, box);
898 941e1713 2006-02-15 devnull respond(r, nil);
901 941e1713 2006-02-15 devnull case Qmsg:
902 941e1713 2006-02-15 devnull if(msg == nil || part == nil){
903 941e1713 2006-02-15 devnull respond(r, Emsggone);
906 941e1713 2006-02-15 devnull dirread9p(r, msggen, part);
907 941e1713 2006-02-15 devnull respond(r, nil);
910 941e1713 2006-02-15 devnull case Qctl:
911 941e1713 2006-02-15 devnull case Qboxctl:
912 941e1713 2006-02-15 devnull respond(r, Egreg);
915 941e1713 2006-02-15 devnull case Qsearch:
916 941e1713 2006-02-15 devnull readstr(r, r->fid->aux);
917 941e1713 2006-02-15 devnull respond(r, nil);
920 941e1713 2006-02-15 devnull default:
921 941e1713 2006-02-15 devnull if(filedata(type, box, msg, part, &s, &len, &freeme, 1, r->fid->qid) < 0){
922 941e1713 2006-02-15 devnull responderror(r);
925 941e1713 2006-02-15 devnull if(s && len == -1)
926 941e1713 2006-02-15 devnull len = strlen(s);
927 941e1713 2006-02-15 devnull readbuf(r, s, len);
928 941e1713 2006-02-15 devnull if(freeme)
929 941e1713 2006-02-15 devnull free(s);
930 941e1713 2006-02-15 devnull respond(r, nil);
936 941e1713 2006-02-15 devnull mkmsglist(Box *box, char **f, int nf, Msg ***mm)
938 941e1713 2006-02-15 devnull int i, nm;
939 941e1713 2006-02-15 devnull Msg **m;
941 941e1713 2006-02-15 devnull m = emalloc(nf*sizeof m[0]);
943 941e1713 2006-02-15 devnull for(i=0; i<nf; i++)
944 941e1713 2006-02-15 devnull if((m[nm] = msgbyid(box, atoi(f[i]))) != nil)
946 941e1713 2006-02-15 devnull *mm = m;
947 941e1713 2006-02-15 devnull return nm;
950 941e1713 2006-02-15 devnull static void
951 941e1713 2006-02-15 devnull fswrite(Req *r)
953 a6a35288 2017-10-13 0intro int i, j, c, type, flag, unflag, flagset, f;
954 941e1713 2006-02-15 devnull Box *box;
955 941e1713 2006-02-15 devnull Msg *msg;
956 941e1713 2006-02-15 devnull Part *part;
957 941e1713 2006-02-15 devnull Cmdbuf *cb;
958 941e1713 2006-02-15 devnull Cmdtab *ct;
959 941e1713 2006-02-15 devnull Msg **m;
961 941e1713 2006-02-15 devnull Fmt fmt;
963 941e1713 2006-02-15 devnull r->ofcall.count = r->ifcall.count;
964 941e1713 2006-02-15 devnull switch(type = parseqid(r->fid->qid, &box, &msg, &part)){
965 941e1713 2006-02-15 devnull default:
966 941e1713 2006-02-15 devnull respond(r, Egreg);
969 941e1713 2006-02-15 devnull case Qctl:
970 941e1713 2006-02-15 devnull cb = parsecmd(r->ifcall.data, r->ifcall.count);
971 941e1713 2006-02-15 devnull if((ct = lookupcmd(cb, ctltab, nelem(ctltab))) == nil){
972 941e1713 2006-02-15 devnull respondcmderror(r, cb, "unknown message");
973 941e1713 2006-02-15 devnull free(cb);
976 941e1713 2006-02-15 devnull r->ofcall.count = r->ifcall.count;
977 941e1713 2006-02-15 devnull switch(ct->index){
978 941e1713 2006-02-15 devnull case CMhangup:
979 941e1713 2006-02-15 devnull imaphangup(imap, atoi(cb->f[1]));
980 941e1713 2006-02-15 devnull respond(r, nil);
982 941e1713 2006-02-15 devnull default:
983 941e1713 2006-02-15 devnull respond(r, Egreg);
986 941e1713 2006-02-15 devnull free(cb);
989 941e1713 2006-02-15 devnull case Qboxctl:
990 941e1713 2006-02-15 devnull cb = parsecmd(r->ifcall.data, r->ifcall.count);
991 941e1713 2006-02-15 devnull if((ct = lookupcmd(cb, boxctltab, nelem(boxctltab))) == nil){
992 941e1713 2006-02-15 devnull respondcmderror(r, cb, "bad message");
993 941e1713 2006-02-15 devnull free(cb);
996 941e1713 2006-02-15 devnull r->ofcall.count = r->ifcall.count;
997 941e1713 2006-02-15 devnull switch(ct->index){
998 941e1713 2006-02-15 devnull case CMsave:
999 941e1713 2006-02-15 devnull if(cb->nf <= 2){
1000 941e1713 2006-02-15 devnull respondcmderror(r, cb, Ebadctl);
1003 941e1713 2006-02-15 devnull nm = mkmsglist(box, cb->f+2, cb->nf-2, &m);
1004 941e1713 2006-02-15 devnull if(nm != cb->nf-2){
1005 cbeb0b26 2006-04-01 devnull /* free(m); */
1006 941e1713 2006-02-15 devnull respond(r, Enomsg);
1009 941e1713 2006-02-15 devnull if(nm > 0 && imapcopylist(imap, cb->f[1], m, nm) < 0)
1010 941e1713 2006-02-15 devnull responderror(r);
1012 941e1713 2006-02-15 devnull respond(r, nil);
1013 941e1713 2006-02-15 devnull free(m);
1016 941e1713 2006-02-15 devnull case CMjunk:
1017 941e1713 2006-02-15 devnull flag = FlagJunk;
1018 941e1713 2006-02-15 devnull goto flagit;
1019 941e1713 2006-02-15 devnull case CMnonjunk:
1020 941e1713 2006-02-15 devnull flag = FlagNonJunk;
1021 941e1713 2006-02-15 devnull goto flagit;
1022 941e1713 2006-02-15 devnull case CMreplied:
1023 941e1713 2006-02-15 devnull flag = FlagReplied;
1024 941e1713 2006-02-15 devnull goto flagit;
1025 941e1713 2006-02-15 devnull case CMread:
1026 941e1713 2006-02-15 devnull flag = FlagSeen;
1027 941e1713 2006-02-15 devnull flagit:
1028 941e1713 2006-02-15 devnull if(cb->nf <= 1){
1029 941e1713 2006-02-15 devnull respondcmderror(r, cb, Ebadctl);
1032 941e1713 2006-02-15 devnull nm = mkmsglist(box, cb->f+1, cb->nf-1, &m);
1033 941e1713 2006-02-15 devnull if(nm != cb->nf-1){
1034 941e1713 2006-02-15 devnull free(m);
1035 941e1713 2006-02-15 devnull respond(r, Enomsg);
1038 941e1713 2006-02-15 devnull if(nm > 0 && imapflaglist(imap, +1, flag, m, nm) < 0)
1039 941e1713 2006-02-15 devnull responderror(r);
1041 941e1713 2006-02-15 devnull respond(r, nil);
1042 941e1713 2006-02-15 devnull free(m);
1045 941e1713 2006-02-15 devnull case CMrefresh:
1046 941e1713 2006-02-15 devnull imapcheckbox(imap, box);
1047 941e1713 2006-02-15 devnull respond(r, nil);
1050 941e1713 2006-02-15 devnull case CMdelete:
1051 941e1713 2006-02-15 devnull if(cb->nf <= 1){
1052 941e1713 2006-02-15 devnull respondcmderror(r, cb, Ebadctl);
1055 941e1713 2006-02-15 devnull nm = mkmsglist(box, cb->f+1, cb->nf-1, &m);
1056 941e1713 2006-02-15 devnull if(nm > 0 && imapremovelist(imap, m, nm) < 0)
1057 941e1713 2006-02-15 devnull responderror(r);
1059 941e1713 2006-02-15 devnull respond(r, nil);
1060 941e1713 2006-02-15 devnull free(m);
1063 941e1713 2006-02-15 devnull default:
1064 941e1713 2006-02-15 devnull respond(r, Egreg);
1067 941e1713 2006-02-15 devnull free(cb);
1068 941e1713 2006-02-15 devnull return;
1070 941e1713 2006-02-15 devnull case Qflags:
1071 941e1713 2006-02-15 devnull if(msg == nil){
1072 941e1713 2006-02-15 devnull respond(r, Enomsg);
1073 941e1713 2006-02-15 devnull return;
1075 941e1713 2006-02-15 devnull cb = parsecmd(r->ifcall.data, r->ifcall.count);
1076 941e1713 2006-02-15 devnull flag = 0;
1077 941e1713 2006-02-15 devnull unflag = 0;
1078 941e1713 2006-02-15 devnull flagset = 0;
1079 941e1713 2006-02-15 devnull for(i=0; i<cb->nf; i++){
1081 941e1713 2006-02-15 devnull c = cb->f[i][0];
1082 941e1713 2006-02-15 devnull if(c == '+' || c == '-')
1083 941e1713 2006-02-15 devnull cb->f[i]++;
1084 941e1713 2006-02-15 devnull for(j=0; j<nelem(flagtab); j++){
1085 941e1713 2006-02-15 devnull if(strcmp(flagtab[j].name, cb->f[i]) == 0){
1086 941e1713 2006-02-15 devnull f = flagtab[j].flag;
1090 941e1713 2006-02-15 devnull if(f == 0){
1091 941e1713 2006-02-15 devnull respondcmderror(r, cb, "unknown flag %s", cb->f[i]);
1092 941e1713 2006-02-15 devnull free(cb);
1093 941e1713 2006-02-15 devnull return;
1095 941e1713 2006-02-15 devnull if(c == '+')
1096 941e1713 2006-02-15 devnull flag |= f;
1097 941e1713 2006-02-15 devnull else if(c == '-')
1098 941e1713 2006-02-15 devnull unflag |= f;
1100 941e1713 2006-02-15 devnull flagset |= f;
1102 941e1713 2006-02-15 devnull free(cb);
1103 941e1713 2006-02-15 devnull if((flagset!=0)+(unflag!=0)+(flag!=0) != 1){
1104 941e1713 2006-02-15 devnull respondcmderror(r, cb, Ebadctl);
1105 941e1713 2006-02-15 devnull return;
1107 941e1713 2006-02-15 devnull if(flag)
1109 941e1713 2006-02-15 devnull else if(unflag){
1110 941e1713 2006-02-15 devnull i = -1;
1111 941e1713 2006-02-15 devnull flag = unflag;
1114 941e1713 2006-02-15 devnull flag = flagset;
1116 941e1713 2006-02-15 devnull if(imapflaglist(imap, i, flag, &msg, 1) < 0)
1117 941e1713 2006-02-15 devnull responderror(r);
1119 941e1713 2006-02-15 devnull respond(r, nil);
1120 941e1713 2006-02-15 devnull return;
1122 941e1713 2006-02-15 devnull case Qsearch:
1123 941e1713 2006-02-15 devnull if(box == nil){
1124 941e1713 2006-02-15 devnull respond(r, Eboxgone);
1125 941e1713 2006-02-15 devnull return;
1127 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
1128 941e1713 2006-02-15 devnull nm = imapsearchbox(imap, box, r->ifcall.data, &m);
1129 941e1713 2006-02-15 devnull for(i=0; i<nm; i++){
1130 941e1713 2006-02-15 devnull if(i>0)
1131 941e1713 2006-02-15 devnull fmtrune(&fmt, ' ');
1132 941e1713 2006-02-15 devnull fmtprint(&fmt, "%d", m[i]->id);
1134 941e1713 2006-02-15 devnull free(r->fid->aux);
1135 941e1713 2006-02-15 devnull r->fid->aux = fmtstrflush(&fmt);
1136 941e1713 2006-02-15 devnull respond(r, nil);
1137 941e1713 2006-02-15 devnull return;
1141 941e1713 2006-02-15 devnull static void
1142 941e1713 2006-02-15 devnull fsopen(Req *r)
1144 941e1713 2006-02-15 devnull switch(qtype(r->fid->qid)){
1145 941e1713 2006-02-15 devnull case Qctl:
1146 941e1713 2006-02-15 devnull case Qboxctl:
1147 941e1713 2006-02-15 devnull if((r->ifcall.mode&~OTRUNC) != OWRITE){
1148 941e1713 2006-02-15 devnull respond(r, Eperm);
1149 941e1713 2006-02-15 devnull return;
1151 941e1713 2006-02-15 devnull respond(r, nil);
1152 941e1713 2006-02-15 devnull return;
1154 941e1713 2006-02-15 devnull case Qflags:
1155 941e1713 2006-02-15 devnull case Qsearch:
1156 941e1713 2006-02-15 devnull if((r->ifcall.mode&~OTRUNC) > ORDWR){
1157 941e1713 2006-02-15 devnull respond(r, Eperm);
1158 941e1713 2006-02-15 devnull return;
1160 941e1713 2006-02-15 devnull respond(r, nil);
1161 941e1713 2006-02-15 devnull return;
1163 941e1713 2006-02-15 devnull default:
1164 941e1713 2006-02-15 devnull if(r->ifcall.mode != OREAD){
1165 941e1713 2006-02-15 devnull respond(r, Eperm);
1166 941e1713 2006-02-15 devnull return;
1168 941e1713 2006-02-15 devnull respond(r, nil);
1169 941e1713 2006-02-15 devnull return;
1173 941e1713 2006-02-15 devnull static void
1174 941e1713 2006-02-15 devnull fsflush(Req *r)
1177 941e1713 2006-02-15 devnull * We only handle reads and writes outside the main loop,
1178 941e1713 2006-02-15 devnull * so we must be flushing one of those. In both cases it's
1179 941e1713 2006-02-15 devnull * okay to just ignore the results of the request, whenever
1180 941e1713 2006-02-15 devnull * they're ready.
1182 941e1713 2006-02-15 devnull incref(&r->oldreq->ref);
1183 941e1713 2006-02-15 devnull respond(r->oldreq, "interrupted");
1184 941e1713 2006-02-15 devnull respond(r, nil);
1187 941e1713 2006-02-15 devnull static void
1188 941e1713 2006-02-15 devnull fsthread(void *v)
1190 941e1713 2006-02-15 devnull Req *r;
1193 941e1713 2006-02-15 devnull switch(r->ifcall.type){
1194 941e1713 2006-02-15 devnull case Tread:
1195 941e1713 2006-02-15 devnull fsread(r);
1197 941e1713 2006-02-15 devnull case Twrite:
1198 941e1713 2006-02-15 devnull fswrite(r);
1203 941e1713 2006-02-15 devnull static void
1204 941e1713 2006-02-15 devnull fsrecv(void *v)
1206 941e1713 2006-02-15 devnull Req *r;
1209 941e1713 2006-02-15 devnull while((r = recvp(fsreqchan)) != nil){
1210 941e1713 2006-02-15 devnull switch(r->ifcall.type){
1211 941e1713 2006-02-15 devnull case Tattach:
1212 941e1713 2006-02-15 devnull fsattach(r);
1214 941e1713 2006-02-15 devnull case Tflush:
1215 941e1713 2006-02-15 devnull fsflush(r);
1217 941e1713 2006-02-15 devnull case Topen:
1218 941e1713 2006-02-15 devnull fsopen(r);
1220 941e1713 2006-02-15 devnull case Twalk:
1221 941e1713 2006-02-15 devnull fswalk(r);
1223 941e1713 2006-02-15 devnull case Tstat:
1224 941e1713 2006-02-15 devnull fsstat(r);
1226 941e1713 2006-02-15 devnull default:
1227 941e1713 2006-02-15 devnull threadcreate(fsthread, r, STACK);
1233 941e1713 2006-02-15 devnull static void
1234 941e1713 2006-02-15 devnull fssend(Req *r)
1236 941e1713 2006-02-15 devnull sendp(fsreqchan, r);
1239 941e1713 2006-02-15 devnull static void
1240 941e1713 2006-02-15 devnull fsdestroyfid(Fid *f)
1242 941e1713 2006-02-15 devnull free(f->aux);
1246 941e1713 2006-02-15 devnull fsinit0(void) /* bad planning - clash with lib9pclient */
1248 941e1713 2006-02-15 devnull t0 = time(0);
1250 941e1713 2006-02-15 devnull fs.attach = fssend;
1251 941e1713 2006-02-15 devnull fs.flush = fssend;
1252 941e1713 2006-02-15 devnull fs.open = fssend;
1253 941e1713 2006-02-15 devnull fs.walk = fssend;
1254 941e1713 2006-02-15 devnull fs.read = fssend;
1255 941e1713 2006-02-15 devnull fs.write = fssend;
1256 941e1713 2006-02-15 devnull fs.stat = fssend;
1257 941e1713 2006-02-15 devnull fs.destroyfid = fsdestroyfid;
1259 941e1713 2006-02-15 devnull rootqid = qid(Qroot, nil, nil, nil);
1261 941e1713 2006-02-15 devnull fsreqchan = chancreate(sizeof(void*), 0);
1262 941e1713 2006-02-15 devnull mailthread(fsrecv, nil);