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 941e1713 2006-02-15 devnull * 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;
97 941e1713 2006-02-15 devnull responderror(Req *r)
99 941e1713 2006-02-15 devnull char e[ERRMAX];
101 941e1713 2006-02-15 devnull rerrstr(e, sizeof e);
102 941e1713 2006-02-15 devnull respond(r, e);
106 941e1713 2006-02-15 devnull qtype(Qid q)
108 941e1713 2006-02-15 devnull return q.path&0x3F;
112 941e1713 2006-02-15 devnull qboxid(Qid q)
114 941e1713 2006-02-15 devnull return (q.path>>40)&0xFFFF;
118 941e1713 2006-02-15 devnull qmsgid(Qid q)
120 941e1713 2006-02-15 devnull return ((q.path>>32)&0xFF000000) | ((q.path>>16)&0xFFFFFF);
124 941e1713 2006-02-15 devnull qpartid(Qid q)
126 941e1713 2006-02-15 devnull return ((q.path>>6)&0x3FF);
130 941e1713 2006-02-15 devnull qid(int ctl, Box *box, Msg *msg, Part *part)
134 941e1713 2006-02-15 devnull q.type = 0;
135 941e1713 2006-02-15 devnull if(ctl == Qroot || ctl == Qbox || ctl == Qmsg)
136 941e1713 2006-02-15 devnull q.type = QTDIR;
137 941e1713 2006-02-15 devnull q.path = (vlong)((msg ? msg->id : 0)&0xFF000000)<<32;
138 941e1713 2006-02-15 devnull q.path |= (vlong)((msg ? msg->id : 0)&0xFFFFFF)<<16;
139 941e1713 2006-02-15 devnull q.path |= (vlong)((box ? box->id : 0)&0xFFFF)<<40;
140 941e1713 2006-02-15 devnull q.path |= ((part ? part->ix : 0)&0x3FF)<<6;
141 941e1713 2006-02-15 devnull q.path |= ctl&0x3F;
142 941e1713 2006-02-15 devnull q.vers = box ? box->validity : 0;
143 941e1713 2006-02-15 devnull return q;
147 941e1713 2006-02-15 devnull parseqid(Qid q, Box **box, Msg **msg, Part **part)
149 941e1713 2006-02-15 devnull *msg = nil;
150 941e1713 2006-02-15 devnull *part = nil;
152 941e1713 2006-02-15 devnull *box = boxbyid(qboxid(q));
153 941e1713 2006-02-15 devnull if(*box){
154 941e1713 2006-02-15 devnull *msg = msgbyid(*box, qmsgid(q));
156 941e1713 2006-02-15 devnull if(*msg)
157 941e1713 2006-02-15 devnull *part = partbyid(*msg, qpartid(q));
158 941e1713 2006-02-15 devnull return qtype(q);
161 941e1713 2006-02-15 devnull static struct {
162 941e1713 2006-02-15 devnull int type;
163 941e1713 2006-02-15 devnull char *name;
164 941e1713 2006-02-15 devnull } typenames[] = {
165 941e1713 2006-02-15 devnull Qbody, "body",
166 941e1713 2006-02-15 devnull Qbcc, "bcc",
167 941e1713 2006-02-15 devnull Qcc, "cc",
168 941e1713 2006-02-15 devnull Qdate, "date",
169 941e1713 2006-02-15 devnull Qfilename, "filename",
170 941e1713 2006-02-15 devnull Qflags, "flags",
171 941e1713 2006-02-15 devnull Qfrom, "from",
172 941e1713 2006-02-15 devnull Qheader, "header",
173 941e1713 2006-02-15 devnull Qinfo, "info",
174 941e1713 2006-02-15 devnull Qinreplyto, "inreplyto",
175 941e1713 2006-02-15 devnull Qlines, "lines",
176 941e1713 2006-02-15 devnull Qmimeheader, "mimeheader",
177 941e1713 2006-02-15 devnull Qmessageid, "messageid",
178 941e1713 2006-02-15 devnull Qraw, "raw",
179 941e1713 2006-02-15 devnull Qrawunix, "rawunix",
180 941e1713 2006-02-15 devnull Qrawbody, "rawbody",
181 941e1713 2006-02-15 devnull Qrawheader, "rawheader",
182 941e1713 2006-02-15 devnull Qreplyto, "replyto",
183 941e1713 2006-02-15 devnull Qsender, "sender",
184 941e1713 2006-02-15 devnull Qsubject, "subject",
185 941e1713 2006-02-15 devnull Qto, "to",
186 941e1713 2006-02-15 devnull Qtype, "type",
187 941e1713 2006-02-15 devnull Qunixdate, "unixdate",
188 941e1713 2006-02-15 devnull Qunixheader, "unixheader",
189 941e1713 2006-02-15 devnull Qidstr, "idstr",
190 941e1713 2006-02-15 devnull Qdesc, "desc",
191 941e1713 2006-02-15 devnull Qencoding, "encoding",
192 cbeb0b26 2006-04-01 devnull Qcharset, "charset"
196 941e1713 2006-02-15 devnull nameoftype(int t)
200 941e1713 2006-02-15 devnull for(i=0; i<nelem(typenames); i++)
201 941e1713 2006-02-15 devnull if(typenames[i].type == t)
202 941e1713 2006-02-15 devnull return typenames[i].name;
203 941e1713 2006-02-15 devnull return "???";
207 941e1713 2006-02-15 devnull typeofname(char *name)
211 941e1713 2006-02-15 devnull for(i=0; i<nelem(typenames); i++)
212 941e1713 2006-02-15 devnull if(strcmp(typenames[i].name, name) == 0)
213 941e1713 2006-02-15 devnull return typenames[i].type;
214 941e1713 2006-02-15 devnull return 0;
217 941e1713 2006-02-15 devnull static void
218 941e1713 2006-02-15 devnull fsattach(Req *r)
220 941e1713 2006-02-15 devnull r->fid->qid = rootqid;
221 941e1713 2006-02-15 devnull r->ofcall.qid = rootqid;
222 941e1713 2006-02-15 devnull respond(r, nil);
225 c7722328 2006-02-28 devnull static int
226 941e1713 2006-02-15 devnull isnumber(char *s)
230 941e1713 2006-02-15 devnull if(*s < '1' || *s > '9')
231 941e1713 2006-02-15 devnull return 0;
232 941e1713 2006-02-15 devnull n = strtol(s, &s, 10);
233 941e1713 2006-02-15 devnull if(*s != 0)
234 941e1713 2006-02-15 devnull return 0;
235 941e1713 2006-02-15 devnull return n;
238 941e1713 2006-02-15 devnull static char*
239 941e1713 2006-02-15 devnull fswalk1(Fid *fid, char *name, void *arg)
241 941e1713 2006-02-15 devnull int a, type;
242 941e1713 2006-02-15 devnull Box *b, *box;
243 941e1713 2006-02-15 devnull Msg *msg;
244 941e1713 2006-02-15 devnull Part *p, *part;
246 941e1713 2006-02-15 devnull USED(arg);
248 941e1713 2006-02-15 devnull switch(type = parseqid(fid->qid, &box, &msg, &part)){
249 941e1713 2006-02-15 devnull case Qroot:
250 941e1713 2006-02-15 devnull if(strcmp(name, "..") == 0)
251 941e1713 2006-02-15 devnull return nil;
252 941e1713 2006-02-15 devnull if(strcmp(name, "ctl") == 0){
253 941e1713 2006-02-15 devnull fid->qid = qid(Qctl, nil, nil, nil);
254 941e1713 2006-02-15 devnull return nil;
256 941e1713 2006-02-15 devnull if((box = boxbyname(name)) != nil){
257 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, box, nil, nil);
258 941e1713 2006-02-15 devnull return nil;
262 941e1713 2006-02-15 devnull case Qbox:
264 941e1713 2006-02-15 devnull * Would be nice if .. could work even if the box is gone,
265 941e1713 2006-02-15 devnull * but we don't know how deep the directory was.
267 941e1713 2006-02-15 devnull if(box == nil)
268 941e1713 2006-02-15 devnull return Eboxgone;
269 941e1713 2006-02-15 devnull if(strcmp(name, "..") == 0){
270 941e1713 2006-02-15 devnull if((box = box->parent) == nil){
271 941e1713 2006-02-15 devnull fid->qid = rootqid;
272 941e1713 2006-02-15 devnull return nil;
274 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, box, nil, nil);
275 941e1713 2006-02-15 devnull return nil;
277 941e1713 2006-02-15 devnull if(strcmp(name, "ctl") == 0){
278 941e1713 2006-02-15 devnull fid->qid = qid(Qboxctl, box, nil, nil);
279 941e1713 2006-02-15 devnull return nil;
281 941e1713 2006-02-15 devnull if(strcmp(name, "search") == 0){
282 941e1713 2006-02-15 devnull fid->qid = qid(Qsearch, box, nil, nil);
283 941e1713 2006-02-15 devnull return nil;
285 941e1713 2006-02-15 devnull if((b = subbox(box, name)) != nil){
286 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, b, nil, nil);
287 941e1713 2006-02-15 devnull return nil;
289 941e1713 2006-02-15 devnull if((a = isnumber(name)) != 0){
290 941e1713 2006-02-15 devnull if((msg = msgbyid(box, a)) == nil){
291 941e1713 2006-02-15 devnull return Enomsg;
293 941e1713 2006-02-15 devnull fid->qid = qid(Qmsg, box, msg, nil);
294 941e1713 2006-02-15 devnull return nil;
298 941e1713 2006-02-15 devnull case Qmsg:
299 941e1713 2006-02-15 devnull if(strcmp(name, "..") == 0){
300 941e1713 2006-02-15 devnull if(part == msg->part[0]){
301 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, box, nil, nil);
302 941e1713 2006-02-15 devnull return nil;
304 941e1713 2006-02-15 devnull fid->qid = qid(Qmsg, box, msg, part->parent);
305 941e1713 2006-02-15 devnull return nil;
307 941e1713 2006-02-15 devnull if((type = typeofname(name)) > 0){
308 941e1713 2006-02-15 devnull /* XXX - should check that type makes sense (see msggen) */
309 941e1713 2006-02-15 devnull fid->qid = qid(type, box, msg, part);
310 941e1713 2006-02-15 devnull return nil;
312 941e1713 2006-02-15 devnull if((a = isnumber(name)) != 0){
313 941e1713 2006-02-15 devnull if((p = subpart(part, a-1)) != nil){
314 941e1713 2006-02-15 devnull fid->qid = qid(Qmsg, box, msg, p);
315 941e1713 2006-02-15 devnull return nil;
320 941e1713 2006-02-15 devnull return "not found";
323 941e1713 2006-02-15 devnull static void
324 941e1713 2006-02-15 devnull fswalk(Req *r)
326 941e1713 2006-02-15 devnull walkandclone(r, fswalk1, nil, nil);
329 941e1713 2006-02-15 devnull static struct {
330 941e1713 2006-02-15 devnull int flag;
331 941e1713 2006-02-15 devnull char *name;
332 941e1713 2006-02-15 devnull } flagtab[] = {
333 941e1713 2006-02-15 devnull FlagJunk, "junk",
334 941e1713 2006-02-15 devnull FlagNonJunk, "notjunk",
335 941e1713 2006-02-15 devnull FlagReplied, "replied",
336 941e1713 2006-02-15 devnull FlagFlagged, "flagged",
337 cbeb0b26 2006-04-01 devnull /* FlagDeleted, "deleted", */
338 941e1713 2006-02-15 devnull FlagDraft, "draft",
339 cbeb0b26 2006-04-01 devnull FlagSeen, "seen"
342 941e1713 2006-02-15 devnull static void
343 941e1713 2006-02-15 devnull addaddrs(Fmt *fmt, char *prefix, char *addrs)
345 941e1713 2006-02-15 devnull char **f;
346 941e1713 2006-02-15 devnull int i, nf, inquote;
347 941e1713 2006-02-15 devnull char *p, *sep;
349 941e1713 2006-02-15 devnull if(addrs == nil)
351 941e1713 2006-02-15 devnull addrs = estrdup(addrs);
353 941e1713 2006-02-15 devnull inquote = 0;
354 941e1713 2006-02-15 devnull for(p=addrs; *p; p++){
355 941e1713 2006-02-15 devnull if(*p == ' ' && !inquote)
357 941e1713 2006-02-15 devnull if(*p == '\'')
358 941e1713 2006-02-15 devnull inquote = !inquote;
360 941e1713 2006-02-15 devnull nf += 10;
361 941e1713 2006-02-15 devnull f = emalloc(nf*sizeof f[0]);
362 941e1713 2006-02-15 devnull nf = tokenize(addrs, f, nf);
363 941e1713 2006-02-15 devnull fmtprint(fmt, "%s:", prefix);
364 941e1713 2006-02-15 devnull sep = " ";
365 941e1713 2006-02-15 devnull for(i=0; i+1<nf; i+=2){
366 941e1713 2006-02-15 devnull if(f[i][0])
367 941e1713 2006-02-15 devnull fmtprint(fmt, "%s%s <%s>", sep, f[i], f[i+1]);
369 941e1713 2006-02-15 devnull fmtprint(fmt, "%s%s", sep, f[i+1]);
370 941e1713 2006-02-15 devnull sep = ", ";
372 941e1713 2006-02-15 devnull fmtprint(fmt, "\n");
373 941e1713 2006-02-15 devnull free(addrs);
376 941e1713 2006-02-15 devnull static void
377 941e1713 2006-02-15 devnull mkbody(Part *p, Qid q)
379 941e1713 2006-02-15 devnull char *t;
380 941e1713 2006-02-15 devnull int len;
382 941e1713 2006-02-15 devnull if(p->msg->part[0] == p)
383 941e1713 2006-02-15 devnull t = p->rawbody;
385 941e1713 2006-02-15 devnull t = p->raw;
386 941e1713 2006-02-15 devnull if(t == nil)
389 941e1713 2006-02-15 devnull len = -1;
390 941e1713 2006-02-15 devnull if(p->encoding && cistrcmp(p->encoding, "quoted-printable") == 0)
391 941e1713 2006-02-15 devnull t = decode(QuotedPrintable, t, &len);
392 941e1713 2006-02-15 devnull else if(p->encoding && cistrcmp(p->encoding, "base64") == 0)
393 941e1713 2006-02-15 devnull t = decode(Base64, t, &len);
395 941e1713 2006-02-15 devnull t = estrdup(t);
397 941e1713 2006-02-15 devnull if(p->charset){
398 941e1713 2006-02-15 devnull t = tcs(p->charset, t);
399 941e1713 2006-02-15 devnull len = -1;
401 941e1713 2006-02-15 devnull p->body = t;
402 941e1713 2006-02-15 devnull if(len == -1)
403 941e1713 2006-02-15 devnull p->nbody = strlen(t);
405 941e1713 2006-02-15 devnull p->nbody = len;
408 941e1713 2006-02-15 devnull static Qid ZQ;
410 941e1713 2006-02-15 devnull static int
411 941e1713 2006-02-15 devnull filedata(int type, Box *box, Msg *msg, Part *part, char **pp, int *len, int *freeme, int force, Qid q)
413 941e1713 2006-02-15 devnull int i, inquote, n, t;
414 941e1713 2006-02-15 devnull char *from, *s;
415 941e1713 2006-02-15 devnull static char buf[256];
416 941e1713 2006-02-15 devnull Fmt fmt;
418 941e1713 2006-02-15 devnull *pp = nil;
419 941e1713 2006-02-15 devnull *freeme = 0;
421 941e1713 2006-02-15 devnull *len = -1;
423 941e1713 2006-02-15 devnull if(msg == nil || part == nil){
424 941e1713 2006-02-15 devnull werrstr(Emsggone);
425 941e1713 2006-02-15 devnull return -1;
427 941e1713 2006-02-15 devnull switch(type){
428 941e1713 2006-02-15 devnull case Qdate:
429 941e1713 2006-02-15 devnull case Qsubject:
430 941e1713 2006-02-15 devnull case Qfrom:
431 941e1713 2006-02-15 devnull case Qsender:
432 941e1713 2006-02-15 devnull case Qreplyto:
433 941e1713 2006-02-15 devnull case Qto:
434 941e1713 2006-02-15 devnull case Qcc:
435 941e1713 2006-02-15 devnull case Qbcc:
436 941e1713 2006-02-15 devnull case Qinreplyto:
437 941e1713 2006-02-15 devnull case Qmessageid:
438 941e1713 2006-02-15 devnull if(part->hdr == nil){
439 941e1713 2006-02-15 devnull werrstr(Emsggone);
440 941e1713 2006-02-15 devnull return -1;
442 941e1713 2006-02-15 devnull *pp = ((char**)&part->hdr->date)[type-Qdate];
443 941e1713 2006-02-15 devnull return 0;
445 941e1713 2006-02-15 devnull case Qunixdate:
446 941e1713 2006-02-15 devnull strcpy(buf, ctime(msg->date));
447 941e1713 2006-02-15 devnull *pp = buf;
448 941e1713 2006-02-15 devnull return 0;
450 941e1713 2006-02-15 devnull case Qunixheader:
451 941e1713 2006-02-15 devnull if(part->hdr == nil){
452 941e1713 2006-02-15 devnull werrstr(Emsggone);
453 941e1713 2006-02-15 devnull return -1;
455 941e1713 2006-02-15 devnull from = part->hdr->from;
456 941e1713 2006-02-15 devnull if(from == nil)
457 941e1713 2006-02-15 devnull from = "???";
459 941e1713 2006-02-15 devnull inquote = 0;
460 941e1713 2006-02-15 devnull for(; *from; from++){
461 941e1713 2006-02-15 devnull if(*from == '\'')
462 941e1713 2006-02-15 devnull inquote = !inquote;
463 941e1713 2006-02-15 devnull if(!inquote && *from == ' '){
468 941e1713 2006-02-15 devnull if(*from == 0)
469 941e1713 2006-02-15 devnull from = part->hdr->from;
471 941e1713 2006-02-15 devnull n = snprint(buf, sizeof buf, "From %s %s", from, ctime(msg->date));
472 941e1713 2006-02-15 devnull if(n+1 < sizeof buf){
473 941e1713 2006-02-15 devnull *pp = buf;
474 941e1713 2006-02-15 devnull return 0;
476 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
477 941e1713 2006-02-15 devnull fmtprint(&fmt, "From %s %s", from, ctime(msg->date));
478 941e1713 2006-02-15 devnull s = fmtstrflush(&fmt);
480 941e1713 2006-02-15 devnull *pp = s;
481 941e1713 2006-02-15 devnull *freeme = 1;
483 941e1713 2006-02-15 devnull *pp = buf;
484 941e1713 2006-02-15 devnull return 0;
486 941e1713 2006-02-15 devnull case Qtype:
487 941e1713 2006-02-15 devnull case Qidstr:
488 941e1713 2006-02-15 devnull case Qdesc:
489 941e1713 2006-02-15 devnull case Qencoding:
490 941e1713 2006-02-15 devnull case Qcharset:
491 bb70a84b 2007-06-23 devnull case Qfilename:
492 941e1713 2006-02-15 devnull case Qraw:
493 941e1713 2006-02-15 devnull case Qrawheader:
494 941e1713 2006-02-15 devnull case Qrawbody:
495 941e1713 2006-02-15 devnull case Qmimeheader:
496 941e1713 2006-02-15 devnull *pp = ((char**)&part->type)[type-Qtype];
497 941e1713 2006-02-15 devnull if(*pp == nil && force){
498 941e1713 2006-02-15 devnull switch(type){
499 941e1713 2006-02-15 devnull case Qraw:
500 941e1713 2006-02-15 devnull imapfetchraw(imap, part);
502 941e1713 2006-02-15 devnull case Qrawheader:
503 941e1713 2006-02-15 devnull imapfetchrawheader(imap, part);
505 941e1713 2006-02-15 devnull case Qrawbody:
506 941e1713 2006-02-15 devnull imapfetchrawbody(imap, part);
508 941e1713 2006-02-15 devnull case Qmimeheader:
509 941e1713 2006-02-15 devnull imapfetchrawmime(imap, part);
511 941e1713 2006-02-15 devnull default:
512 941e1713 2006-02-15 devnull return 0;
515 941e1713 2006-02-15 devnull * We ran fetchsomething, which might have changed
516 941e1713 2006-02-15 devnull * the mailbox contents. Msg might even be gone.
518 941e1713 2006-02-15 devnull t = parseqid(q, &box, &msg, &part);
519 941e1713 2006-02-15 devnull if(t != type || msg == nil || part == nil)
520 941e1713 2006-02-15 devnull return 0;
521 941e1713 2006-02-15 devnull *pp = ((char**)&part->type)[type-Qtype];
523 941e1713 2006-02-15 devnull return 0;
525 941e1713 2006-02-15 devnull case Qbody:
526 941e1713 2006-02-15 devnull if(part->body){
527 941e1713 2006-02-15 devnull *pp = part->body;
529 941e1713 2006-02-15 devnull *len = part->nbody;
530 941e1713 2006-02-15 devnull return 0;
532 941e1713 2006-02-15 devnull if(!force)
533 941e1713 2006-02-15 devnull return 0;
534 941e1713 2006-02-15 devnull if(part->rawbody == nil){
535 941e1713 2006-02-15 devnull if(part->msg->part[0] == part)
536 941e1713 2006-02-15 devnull imapfetchrawbody(imap, part);
538 941e1713 2006-02-15 devnull imapfetchraw(imap, part);
539 941e1713 2006-02-15 devnull t = parseqid(q, &box, &msg, &part);
540 941e1713 2006-02-15 devnull if(t != type || msg == nil || part == nil)
541 941e1713 2006-02-15 devnull return 0;
543 941e1713 2006-02-15 devnull mkbody(part, q);
544 941e1713 2006-02-15 devnull *pp = part->body;
546 941e1713 2006-02-15 devnull *len = part->nbody;
547 941e1713 2006-02-15 devnull return 0;
549 941e1713 2006-02-15 devnull case Qsize:
550 941e1713 2006-02-15 devnull case Qlines:
551 941e1713 2006-02-15 devnull n = ((uint*)&part->size)[type-Qsize];
552 941e1713 2006-02-15 devnull snprint(buf, sizeof buf, "%d", n);
553 941e1713 2006-02-15 devnull *pp = buf;
554 941e1713 2006-02-15 devnull return 0;
556 941e1713 2006-02-15 devnull case Qflags:
557 941e1713 2006-02-15 devnull s = buf;
559 941e1713 2006-02-15 devnull for(i=0; i<nelem(flagtab); i++){
560 941e1713 2006-02-15 devnull if(msg->flags&flagtab[i].flag){
561 941e1713 2006-02-15 devnull if(s > buf)
562 941e1713 2006-02-15 devnull *s++ = ' ';
563 941e1713 2006-02-15 devnull strcpy(s, flagtab[i].name);
564 941e1713 2006-02-15 devnull s += strlen(s);
567 941e1713 2006-02-15 devnull *pp = buf;
568 941e1713 2006-02-15 devnull return 0;
570 941e1713 2006-02-15 devnull case Qinfo:
571 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
572 941e1713 2006-02-15 devnull if(part == msg->part[0]){
573 941e1713 2006-02-15 devnull if(msg->date)
574 941e1713 2006-02-15 devnull fmtprint(&fmt, "unixdate %lud %s", msg->date, ctime(msg->date));
575 941e1713 2006-02-15 devnull if(msg->flags){
576 941e1713 2006-02-15 devnull filedata(Qflags, box, msg, part, pp, nil, freeme, 0, ZQ);
577 941e1713 2006-02-15 devnull fmtprint(&fmt, "flags %s\n", buf);
580 941e1713 2006-02-15 devnull if(part->hdr){
581 941e1713 2006-02-15 devnull if(part->hdr->digest)
582 941e1713 2006-02-15 devnull fmtprint(&fmt, "digest %s\n", part->hdr->digest);
583 941e1713 2006-02-15 devnull if(part->hdr->from)
584 941e1713 2006-02-15 devnull fmtprint(&fmt, "from %s\n", part->hdr->from);
585 941e1713 2006-02-15 devnull if(part->hdr->to)
586 941e1713 2006-02-15 devnull fmtprint(&fmt, "to %s\n", part->hdr->to);
587 941e1713 2006-02-15 devnull if(part->hdr->cc)
588 941e1713 2006-02-15 devnull fmtprint(&fmt, "cc %s\n", part->hdr->cc);
589 941e1713 2006-02-15 devnull if(part->hdr->replyto)
590 941e1713 2006-02-15 devnull fmtprint(&fmt, "replyto %s\n", part->hdr->replyto);
591 941e1713 2006-02-15 devnull if(part->hdr->bcc)
592 941e1713 2006-02-15 devnull fmtprint(&fmt, "bcc %s\n", part->hdr->bcc);
593 941e1713 2006-02-15 devnull if(part->hdr->inreplyto)
594 941e1713 2006-02-15 devnull fmtprint(&fmt, "inreplyto %s\n", part->hdr->inreplyto);
595 941e1713 2006-02-15 devnull if(part->hdr->date)
596 941e1713 2006-02-15 devnull fmtprint(&fmt, "date %s\n", part->hdr->date);
597 941e1713 2006-02-15 devnull if(part->hdr->sender)
598 941e1713 2006-02-15 devnull fmtprint(&fmt, "sender %s\n", part->hdr->sender);
599 941e1713 2006-02-15 devnull if(part->hdr->messageid)
600 941e1713 2006-02-15 devnull fmtprint(&fmt, "messageid %s\n", part->hdr->messageid);
601 941e1713 2006-02-15 devnull if(part->hdr->subject)
602 941e1713 2006-02-15 devnull fmtprint(&fmt, "subject %s\n", part->hdr->subject);
604 941e1713 2006-02-15 devnull if(part->type)
605 941e1713 2006-02-15 devnull fmtprint(&fmt, "type %s\n", part->type);
606 941e1713 2006-02-15 devnull if(part->lines)
607 941e1713 2006-02-15 devnull fmtprint(&fmt, "lines %d\n", part->lines);
608 141d6009 2006-06-30 devnull if(part->filename)
609 141d6009 2006-06-30 devnull fmtprint(&fmt, "filename %s\n", part->filename);
610 941e1713 2006-02-15 devnull s = fmtstrflush(&fmt);
611 941e1713 2006-02-15 devnull if(s == nil)
612 941e1713 2006-02-15 devnull s = estrdup("");
613 941e1713 2006-02-15 devnull *freeme = 1;
614 941e1713 2006-02-15 devnull *pp = s;
615 941e1713 2006-02-15 devnull return 0;
617 941e1713 2006-02-15 devnull case Qheader:
618 941e1713 2006-02-15 devnull if(part->hdr == nil)
619 941e1713 2006-02-15 devnull return 0;
620 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
621 941e1713 2006-02-15 devnull if(part == msg->part[0])
622 941e1713 2006-02-15 devnull fmtprint(&fmt, "Date: %s", ctime(msg->date));
624 941e1713 2006-02-15 devnull fmtprint(&fmt, "Date: %s\n", part->hdr->date);
625 941e1713 2006-02-15 devnull addaddrs(&fmt, "To", part->hdr->to);
626 941e1713 2006-02-15 devnull addaddrs(&fmt, "From", part->hdr->from);
627 941e1713 2006-02-15 devnull if(part->hdr->from==nil
628 941e1713 2006-02-15 devnull || (part->hdr->sender && strcmp(part->hdr->sender, part->hdr->from) != 0))
629 941e1713 2006-02-15 devnull addaddrs(&fmt, "Sender", part->hdr->sender);
630 941e1713 2006-02-15 devnull if(part->hdr->from==nil
631 941e1713 2006-02-15 devnull || (part->hdr->replyto && strcmp(part->hdr->replyto, part->hdr->from) != 0))
632 941e1713 2006-02-15 devnull addaddrs(&fmt, "Reply-To", part->hdr->replyto);
633 eb44dca2 2007-06-25 devnull fmtprint(&fmt, "Subject: %s\n", part->hdr->subject);
634 941e1713 2006-02-15 devnull s = fmtstrflush(&fmt);
635 941e1713 2006-02-15 devnull if(s == nil)
636 941e1713 2006-02-15 devnull s = estrdup("");
637 941e1713 2006-02-15 devnull *freeme = 1;
638 941e1713 2006-02-15 devnull *pp = s;
639 941e1713 2006-02-15 devnull return 0;
641 941e1713 2006-02-15 devnull default:
642 941e1713 2006-02-15 devnull werrstr(Egreg);
643 941e1713 2006-02-15 devnull return -1;
648 941e1713 2006-02-15 devnull filldir(Dir *d, int type, Box *box, Msg *msg, Part *part)
650 941e1713 2006-02-15 devnull int freeme, len;
651 941e1713 2006-02-15 devnull char *s;
653 941e1713 2006-02-15 devnull memset(d, 0, sizeof *d);
654 941e1713 2006-02-15 devnull if(box){
655 941e1713 2006-02-15 devnull d->atime = box->time;
656 941e1713 2006-02-15 devnull d->mtime = box->time;
658 941e1713 2006-02-15 devnull d->atime = t0;
659 941e1713 2006-02-15 devnull d->mtime = t0;
661 941e1713 2006-02-15 devnull d->uid = estrdup9p("upas");
662 941e1713 2006-02-15 devnull d->gid = estrdup9p("upas");
663 941e1713 2006-02-15 devnull d->muid = estrdup9p("upas");
664 941e1713 2006-02-15 devnull d->qid = qid(type, box, msg, part);
666 941e1713 2006-02-15 devnull switch(type){
667 941e1713 2006-02-15 devnull case Qroot:
668 941e1713 2006-02-15 devnull case Qbox:
669 941e1713 2006-02-15 devnull case Qmsg:
670 941e1713 2006-02-15 devnull d->mode = 0555|DMDIR;
671 941e1713 2006-02-15 devnull if(box && !(box->flags&FlagNoInferiors))
672 941e1713 2006-02-15 devnull d->mode = 0775|DMDIR;
674 941e1713 2006-02-15 devnull case Qctl:
675 941e1713 2006-02-15 devnull case Qboxctl:
676 941e1713 2006-02-15 devnull d->mode = 0222;
678 941e1713 2006-02-15 devnull case Qsearch:
679 941e1713 2006-02-15 devnull d->mode = 0666;
682 941e1713 2006-02-15 devnull case Qflags:
683 941e1713 2006-02-15 devnull d->mode = 0666;
684 941e1713 2006-02-15 devnull goto msgfile;
685 941e1713 2006-02-15 devnull default:
686 941e1713 2006-02-15 devnull d->mode = 0444;
687 941e1713 2006-02-15 devnull msgfile:
688 941e1713 2006-02-15 devnull if(filedata(type, box, msg, part, &s, &len, &freeme, 0, ZQ) >= 0){
690 941e1713 2006-02-15 devnull if(len == -1)
691 941e1713 2006-02-15 devnull d->length = strlen(s);
693 941e1713 2006-02-15 devnull d->length = len;
694 941e1713 2006-02-15 devnull if(freeme)
695 941e1713 2006-02-15 devnull free(s);
697 941e1713 2006-02-15 devnull }else if(type == Qraw && msg && part == msg->part[0])
698 941e1713 2006-02-15 devnull d->length = msg->size;
702 941e1713 2006-02-15 devnull switch(type){
703 941e1713 2006-02-15 devnull case Qroot:
704 941e1713 2006-02-15 devnull d->name = estrdup9p("/");
706 941e1713 2006-02-15 devnull case Qbox:
707 941e1713 2006-02-15 devnull if(box == nil){
708 941e1713 2006-02-15 devnull werrstr(Enobox);
709 941e1713 2006-02-15 devnull return -1;
711 941e1713 2006-02-15 devnull d->name = estrdup9p(box->elem);
713 941e1713 2006-02-15 devnull case Qmsg:
714 941e1713 2006-02-15 devnull if(msg == nil){
715 941e1713 2006-02-15 devnull werrstr(Enomsg);
716 941e1713 2006-02-15 devnull return -1;
718 941e1713 2006-02-15 devnull if(part == nil || part == msg->part[0])
719 941e1713 2006-02-15 devnull d->name = esmprint("%d", msg->id);
721 941e1713 2006-02-15 devnull d->name = esmprint("%d", part->pix+1);
723 941e1713 2006-02-15 devnull case Qctl:
724 941e1713 2006-02-15 devnull case Qboxctl:
725 941e1713 2006-02-15 devnull d->name = estrdup9p("ctl");
727 941e1713 2006-02-15 devnull case Qsearch:
728 941e1713 2006-02-15 devnull d->name = estrdup9p("search");
730 941e1713 2006-02-15 devnull default:
731 941e1713 2006-02-15 devnull d->name = estrdup9p(nameoftype(type));
734 941e1713 2006-02-15 devnull return 0;
737 941e1713 2006-02-15 devnull static void
738 941e1713 2006-02-15 devnull fsstat(Req *r)
740 941e1713 2006-02-15 devnull int type;
741 941e1713 2006-02-15 devnull Box *box;
742 941e1713 2006-02-15 devnull Msg *msg;
743 941e1713 2006-02-15 devnull Part *part;
745 941e1713 2006-02-15 devnull type = parseqid(r->fid->qid, &box, &msg, &part);
746 941e1713 2006-02-15 devnull if(filldir(&r->d, type, box, msg, part) < 0)
747 941e1713 2006-02-15 devnull responderror(r);
749 941e1713 2006-02-15 devnull respond(r, nil);
753 941e1713 2006-02-15 devnull rootgen(int i, Dir *d, void *aux)
755 941e1713 2006-02-15 devnull USED(aux);
757 941e1713 2006-02-15 devnull if(i == 0)
758 941e1713 2006-02-15 devnull return filldir(d, Qctl, nil, nil, nil);
760 941e1713 2006-02-15 devnull if(i < rootbox->nsub)
761 941e1713 2006-02-15 devnull return filldir(d, Qbox, rootbox->sub[i], nil, nil);
762 941e1713 2006-02-15 devnull return -1;
766 941e1713 2006-02-15 devnull boxgen(int i, Dir *d, void *aux)
768 941e1713 2006-02-15 devnull Box *box;
770 941e1713 2006-02-15 devnull box = aux;
771 941e1713 2006-02-15 devnull if(i == 0)
772 941e1713 2006-02-15 devnull return filldir(d, Qboxctl, box, nil, nil);
774 941e1713 2006-02-15 devnull if(i == 0)
775 941e1713 2006-02-15 devnull return filldir(d, Qsearch, box, nil, nil);
777 941e1713 2006-02-15 devnull if(i < box->nsub)
778 941e1713 2006-02-15 devnull return filldir(d, Qbox, box->sub[i], nil, nil);
779 941e1713 2006-02-15 devnull i -= box->nsub;
780 941e1713 2006-02-15 devnull if(i < box->nmsg)
781 941e1713 2006-02-15 devnull return filldir(d, Qmsg, box, box->msg[i], nil);
782 941e1713 2006-02-15 devnull return -1;
785 941e1713 2006-02-15 devnull static int msgdir[] = {
787 941e1713 2006-02-15 devnull Qbody, Qbcc, Qcc, Qdate, Qflags, Qfrom, Qheader, Qinfo,
788 941e1713 2006-02-15 devnull Qinreplyto, Qlines, Qmimeheader, Qmessageid,
789 941e1713 2006-02-15 devnull Qraw, Qrawunix, Qrawbody, Qrawheader,
790 941e1713 2006-02-15 devnull Qreplyto, Qsender, Qsubject, Qto,
791 941e1713 2006-02-15 devnull Qunixdate, Qunixheader
793 941e1713 2006-02-15 devnull static int mimemsgdir[] = {
795 941e1713 2006-02-15 devnull Qbody, Qbcc, Qcc, Qdate, Qfrom, Qheader, Qinfo,
796 941e1713 2006-02-15 devnull Qinreplyto, Qlines, Qmimeheader, Qmessageid,
797 941e1713 2006-02-15 devnull Qraw, Qrawunix, Qrawbody, Qrawheader,
798 cbeb0b26 2006-04-01 devnull Qreplyto, Qsender, Qsubject, Qto
800 941e1713 2006-02-15 devnull static int mimedir[] = {
803 bb70a84b 2007-06-23 devnull Qfilename,
804 bb70a84b 2007-06-23 devnull Qcharset,
805 941e1713 2006-02-15 devnull Qmimeheader,
810 941e1713 2006-02-15 devnull msggen(int i, Dir *d, void *aux)
812 941e1713 2006-02-15 devnull Box *box;
813 941e1713 2006-02-15 devnull Msg *msg;
814 941e1713 2006-02-15 devnull Part *part;
816 941e1713 2006-02-15 devnull part = aux;
817 941e1713 2006-02-15 devnull msg = part->msg;
818 941e1713 2006-02-15 devnull box = msg->box;
819 941e1713 2006-02-15 devnull if(part->ix == 0){
820 941e1713 2006-02-15 devnull if(i < nelem(msgdir))
821 941e1713 2006-02-15 devnull return filldir(d, msgdir[i], box, msg, part);
822 941e1713 2006-02-15 devnull i -= nelem(msgdir);
823 941e1713 2006-02-15 devnull }else if(part->type && strcmp(part->type, "message/rfc822") == 0){
824 941e1713 2006-02-15 devnull if(i < nelem(mimemsgdir))
825 941e1713 2006-02-15 devnull return filldir(d, mimemsgdir[i], box, msg, part);
826 941e1713 2006-02-15 devnull i -= nelem(mimemsgdir);
828 941e1713 2006-02-15 devnull if(i < nelem(mimedir))
829 941e1713 2006-02-15 devnull return filldir(d, mimedir[i], box, msg, part);
830 941e1713 2006-02-15 devnull i -= nelem(mimedir);
832 941e1713 2006-02-15 devnull if(i < part->nsub)
833 941e1713 2006-02-15 devnull return filldir(d, Qmsg, box, msg, part->sub[i]);
834 941e1713 2006-02-15 devnull return -1;
839 cbeb0b26 2006-04-01 devnull CMhangup
841 941e1713 2006-02-15 devnull static Cmdtab ctltab[] =
843 cbeb0b26 2006-04-01 devnull CMhangup, "hangup", 2
848 941e1713 2006-02-15 devnull CMdelete,
849 941e1713 2006-02-15 devnull CMrefresh,
850 941e1713 2006-02-15 devnull CMreplied,
854 cbeb0b26 2006-04-01 devnull CMnonjunk
856 941e1713 2006-02-15 devnull static Cmdtab boxctltab[] =
858 941e1713 2006-02-15 devnull CMdelete, "delete", 0,
859 941e1713 2006-02-15 devnull CMrefresh, "refresh", 1,
860 941e1713 2006-02-15 devnull CMreplied, "replied", 0,
861 941e1713 2006-02-15 devnull CMread, "read", 0,
862 941e1713 2006-02-15 devnull CMsave, "save", 0,
863 941e1713 2006-02-15 devnull CMjunk, "junk", 0,
864 cbeb0b26 2006-04-01 devnull CMnonjunk, "nonjunk", 0
867 941e1713 2006-02-15 devnull static void
868 941e1713 2006-02-15 devnull fsread(Req *r)
870 941e1713 2006-02-15 devnull char *s;
871 941e1713 2006-02-15 devnull int type, len, freeme;
872 941e1713 2006-02-15 devnull Box *box;
873 941e1713 2006-02-15 devnull Msg *msg;
874 941e1713 2006-02-15 devnull Part *part;
876 941e1713 2006-02-15 devnull switch(type = parseqid(r->fid->qid, &box, &msg, &part)){
877 941e1713 2006-02-15 devnull case Qroot:
878 941e1713 2006-02-15 devnull dirread9p(r, rootgen, nil);
879 941e1713 2006-02-15 devnull respond(r, nil);
882 941e1713 2006-02-15 devnull case Qbox:
883 941e1713 2006-02-15 devnull if(box == nil){
884 941e1713 2006-02-15 devnull respond(r, Eboxgone);
887 941e1713 2006-02-15 devnull if(box->nmsg == 0)
888 941e1713 2006-02-15 devnull imapcheckbox(imap, box);
889 941e1713 2006-02-15 devnull parseqid(r->fid->qid, &box, &msg, &part);
890 941e1713 2006-02-15 devnull if(box == nil){
891 941e1713 2006-02-15 devnull respond(r, Eboxgone);
894 941e1713 2006-02-15 devnull dirread9p(r, boxgen, box);
895 941e1713 2006-02-15 devnull respond(r, nil);
898 941e1713 2006-02-15 devnull case Qmsg:
899 941e1713 2006-02-15 devnull if(msg == nil || part == nil){
900 941e1713 2006-02-15 devnull respond(r, Emsggone);
903 941e1713 2006-02-15 devnull dirread9p(r, msggen, part);
904 941e1713 2006-02-15 devnull respond(r, nil);
907 941e1713 2006-02-15 devnull case Qctl:
908 941e1713 2006-02-15 devnull case Qboxctl:
909 941e1713 2006-02-15 devnull respond(r, Egreg);
912 941e1713 2006-02-15 devnull case Qsearch:
913 941e1713 2006-02-15 devnull readstr(r, r->fid->aux);
914 941e1713 2006-02-15 devnull respond(r, nil);
917 941e1713 2006-02-15 devnull default:
918 941e1713 2006-02-15 devnull if(filedata(type, box, msg, part, &s, &len, &freeme, 1, r->fid->qid) < 0){
919 941e1713 2006-02-15 devnull responderror(r);
922 941e1713 2006-02-15 devnull if(s && len == -1)
923 941e1713 2006-02-15 devnull len = strlen(s);
924 941e1713 2006-02-15 devnull readbuf(r, s, len);
925 941e1713 2006-02-15 devnull if(freeme)
926 941e1713 2006-02-15 devnull free(s);
927 941e1713 2006-02-15 devnull respond(r, nil);
933 941e1713 2006-02-15 devnull mkmsglist(Box *box, char **f, int nf, Msg ***mm)
935 941e1713 2006-02-15 devnull int i, nm;
936 941e1713 2006-02-15 devnull Msg **m;
938 941e1713 2006-02-15 devnull m = emalloc(nf*sizeof m[0]);
940 941e1713 2006-02-15 devnull for(i=0; i<nf; i++)
941 941e1713 2006-02-15 devnull if((m[nm] = msgbyid(box, atoi(f[i]))) != nil)
943 941e1713 2006-02-15 devnull *mm = m;
944 941e1713 2006-02-15 devnull return nm;
947 941e1713 2006-02-15 devnull static void
948 941e1713 2006-02-15 devnull fswrite(Req *r)
950 941e1713 2006-02-15 devnull int i, j, c, type, flag, unflag, flagset, f, reset;
951 941e1713 2006-02-15 devnull Box *box;
952 941e1713 2006-02-15 devnull Msg *msg;
953 941e1713 2006-02-15 devnull Part *part;
954 941e1713 2006-02-15 devnull Cmdbuf *cb;
955 941e1713 2006-02-15 devnull Cmdtab *ct;
956 941e1713 2006-02-15 devnull Msg **m;
958 941e1713 2006-02-15 devnull Fmt fmt;
960 941e1713 2006-02-15 devnull r->ofcall.count = r->ifcall.count;
961 941e1713 2006-02-15 devnull switch(type = parseqid(r->fid->qid, &box, &msg, &part)){
962 941e1713 2006-02-15 devnull default:
963 941e1713 2006-02-15 devnull respond(r, Egreg);
966 941e1713 2006-02-15 devnull case Qctl:
967 941e1713 2006-02-15 devnull cb = parsecmd(r->ifcall.data, r->ifcall.count);
968 941e1713 2006-02-15 devnull if((ct = lookupcmd(cb, ctltab, nelem(ctltab))) == nil){
969 941e1713 2006-02-15 devnull respondcmderror(r, cb, "unknown message");
970 941e1713 2006-02-15 devnull free(cb);
973 941e1713 2006-02-15 devnull r->ofcall.count = r->ifcall.count;
974 941e1713 2006-02-15 devnull switch(ct->index){
975 941e1713 2006-02-15 devnull case CMhangup:
976 941e1713 2006-02-15 devnull imaphangup(imap, atoi(cb->f[1]));
977 941e1713 2006-02-15 devnull respond(r, nil);
979 941e1713 2006-02-15 devnull default:
980 941e1713 2006-02-15 devnull respond(r, Egreg);
983 941e1713 2006-02-15 devnull free(cb);
986 941e1713 2006-02-15 devnull case Qboxctl:
987 941e1713 2006-02-15 devnull cb = parsecmd(r->ifcall.data, r->ifcall.count);
988 941e1713 2006-02-15 devnull if((ct = lookupcmd(cb, boxctltab, nelem(boxctltab))) == nil){
989 941e1713 2006-02-15 devnull respondcmderror(r, cb, "bad message");
990 941e1713 2006-02-15 devnull free(cb);
993 941e1713 2006-02-15 devnull r->ofcall.count = r->ifcall.count;
994 941e1713 2006-02-15 devnull switch(ct->index){
995 941e1713 2006-02-15 devnull case CMsave:
996 941e1713 2006-02-15 devnull if(cb->nf <= 2){
997 941e1713 2006-02-15 devnull respondcmderror(r, cb, Ebadctl);
1000 941e1713 2006-02-15 devnull nm = mkmsglist(box, cb->f+2, cb->nf-2, &m);
1001 941e1713 2006-02-15 devnull if(nm != cb->nf-2){
1002 cbeb0b26 2006-04-01 devnull /* free(m); */
1003 941e1713 2006-02-15 devnull respond(r, Enomsg);
1006 941e1713 2006-02-15 devnull if(nm > 0 && imapcopylist(imap, cb->f[1], m, nm) < 0)
1007 941e1713 2006-02-15 devnull responderror(r);
1009 941e1713 2006-02-15 devnull respond(r, nil);
1010 941e1713 2006-02-15 devnull free(m);
1013 941e1713 2006-02-15 devnull case CMjunk:
1014 941e1713 2006-02-15 devnull flag = FlagJunk;
1015 941e1713 2006-02-15 devnull goto flagit;
1016 941e1713 2006-02-15 devnull case CMnonjunk:
1017 941e1713 2006-02-15 devnull flag = FlagNonJunk;
1018 941e1713 2006-02-15 devnull goto flagit;
1019 941e1713 2006-02-15 devnull case CMreplied:
1020 941e1713 2006-02-15 devnull flag = FlagReplied;
1021 941e1713 2006-02-15 devnull goto flagit;
1022 941e1713 2006-02-15 devnull case CMread:
1023 941e1713 2006-02-15 devnull flag = FlagSeen;
1024 941e1713 2006-02-15 devnull flagit:
1025 941e1713 2006-02-15 devnull if(cb->nf <= 1){
1026 941e1713 2006-02-15 devnull respondcmderror(r, cb, Ebadctl);
1029 941e1713 2006-02-15 devnull nm = mkmsglist(box, cb->f+1, cb->nf-1, &m);
1030 941e1713 2006-02-15 devnull if(nm != cb->nf-1){
1031 941e1713 2006-02-15 devnull free(m);
1032 941e1713 2006-02-15 devnull respond(r, Enomsg);
1035 941e1713 2006-02-15 devnull if(nm > 0 && imapflaglist(imap, +1, flag, m, nm) < 0)
1036 941e1713 2006-02-15 devnull responderror(r);
1038 941e1713 2006-02-15 devnull respond(r, nil);
1039 941e1713 2006-02-15 devnull free(m);
1042 941e1713 2006-02-15 devnull case CMrefresh:
1043 941e1713 2006-02-15 devnull imapcheckbox(imap, box);
1044 941e1713 2006-02-15 devnull respond(r, nil);
1047 941e1713 2006-02-15 devnull case CMdelete:
1048 941e1713 2006-02-15 devnull if(cb->nf <= 1){
1049 941e1713 2006-02-15 devnull respondcmderror(r, cb, Ebadctl);
1052 941e1713 2006-02-15 devnull nm = mkmsglist(box, cb->f+1, cb->nf-1, &m);
1053 941e1713 2006-02-15 devnull if(nm > 0 && imapremovelist(imap, m, nm) < 0)
1054 941e1713 2006-02-15 devnull responderror(r);
1056 941e1713 2006-02-15 devnull respond(r, nil);
1057 941e1713 2006-02-15 devnull free(m);
1060 941e1713 2006-02-15 devnull default:
1061 941e1713 2006-02-15 devnull respond(r, Egreg);
1064 941e1713 2006-02-15 devnull free(cb);
1065 941e1713 2006-02-15 devnull return;
1067 941e1713 2006-02-15 devnull case Qflags:
1068 941e1713 2006-02-15 devnull if(msg == nil){
1069 941e1713 2006-02-15 devnull respond(r, Enomsg);
1070 941e1713 2006-02-15 devnull return;
1072 941e1713 2006-02-15 devnull cb = parsecmd(r->ifcall.data, r->ifcall.count);
1073 941e1713 2006-02-15 devnull flag = 0;
1074 941e1713 2006-02-15 devnull unflag = 0;
1075 941e1713 2006-02-15 devnull flagset = 0;
1076 941e1713 2006-02-15 devnull reset = 0;
1077 941e1713 2006-02-15 devnull for(i=0; i<cb->nf; i++){
1079 941e1713 2006-02-15 devnull c = cb->f[i][0];
1080 941e1713 2006-02-15 devnull if(c == '+' || c == '-')
1081 941e1713 2006-02-15 devnull cb->f[i]++;
1082 941e1713 2006-02-15 devnull for(j=0; j<nelem(flagtab); j++){
1083 941e1713 2006-02-15 devnull if(strcmp(flagtab[j].name, cb->f[i]) == 0){
1084 941e1713 2006-02-15 devnull f = flagtab[j].flag;
1088 941e1713 2006-02-15 devnull if(f == 0){
1089 941e1713 2006-02-15 devnull respondcmderror(r, cb, "unknown flag %s", cb->f[i]);
1090 941e1713 2006-02-15 devnull free(cb);
1091 941e1713 2006-02-15 devnull return;
1093 941e1713 2006-02-15 devnull if(c == '+')
1094 941e1713 2006-02-15 devnull flag |= f;
1095 941e1713 2006-02-15 devnull else if(c == '-')
1096 941e1713 2006-02-15 devnull unflag |= f;
1098 941e1713 2006-02-15 devnull flagset |= f;
1100 941e1713 2006-02-15 devnull free(cb);
1101 941e1713 2006-02-15 devnull if((flagset!=0)+(unflag!=0)+(flag!=0) != 1){
1102 941e1713 2006-02-15 devnull respondcmderror(r, cb, Ebadctl);
1103 941e1713 2006-02-15 devnull return;
1105 941e1713 2006-02-15 devnull if(flag)
1107 941e1713 2006-02-15 devnull else if(unflag){
1108 941e1713 2006-02-15 devnull i = -1;
1109 941e1713 2006-02-15 devnull flag = unflag;
1112 941e1713 2006-02-15 devnull flag = flagset;
1114 941e1713 2006-02-15 devnull if(imapflaglist(imap, i, flag, &msg, 1) < 0)
1115 941e1713 2006-02-15 devnull responderror(r);
1117 941e1713 2006-02-15 devnull respond(r, nil);
1118 941e1713 2006-02-15 devnull return;
1120 941e1713 2006-02-15 devnull case Qsearch:
1121 941e1713 2006-02-15 devnull if(box == nil){
1122 941e1713 2006-02-15 devnull respond(r, Eboxgone);
1123 941e1713 2006-02-15 devnull return;
1125 941e1713 2006-02-15 devnull fmtstrinit(&fmt);
1126 941e1713 2006-02-15 devnull nm = imapsearchbox(imap, box, r->ifcall.data, &m);
1127 941e1713 2006-02-15 devnull for(i=0; i<nm; i++){
1128 941e1713 2006-02-15 devnull if(i>0)
1129 941e1713 2006-02-15 devnull fmtrune(&fmt, ' ');
1130 941e1713 2006-02-15 devnull fmtprint(&fmt, "%d", m[i]->id);
1132 941e1713 2006-02-15 devnull free(r->fid->aux);
1133 941e1713 2006-02-15 devnull r->fid->aux = fmtstrflush(&fmt);
1134 941e1713 2006-02-15 devnull respond(r, nil);
1135 941e1713 2006-02-15 devnull return;
1139 941e1713 2006-02-15 devnull static void
1140 941e1713 2006-02-15 devnull fsopen(Req *r)
1142 941e1713 2006-02-15 devnull switch(qtype(r->fid->qid)){
1143 941e1713 2006-02-15 devnull case Qctl:
1144 941e1713 2006-02-15 devnull case Qboxctl:
1145 941e1713 2006-02-15 devnull if((r->ifcall.mode&~OTRUNC) != OWRITE){
1146 941e1713 2006-02-15 devnull respond(r, Eperm);
1147 941e1713 2006-02-15 devnull return;
1149 941e1713 2006-02-15 devnull respond(r, nil);
1150 941e1713 2006-02-15 devnull return;
1152 941e1713 2006-02-15 devnull case Qflags:
1153 941e1713 2006-02-15 devnull case Qsearch:
1154 941e1713 2006-02-15 devnull if((r->ifcall.mode&~OTRUNC) > ORDWR){
1155 941e1713 2006-02-15 devnull respond(r, Eperm);
1156 941e1713 2006-02-15 devnull return;
1158 941e1713 2006-02-15 devnull respond(r, nil);
1159 941e1713 2006-02-15 devnull return;
1161 941e1713 2006-02-15 devnull default:
1162 941e1713 2006-02-15 devnull if(r->ifcall.mode != OREAD){
1163 941e1713 2006-02-15 devnull respond(r, Eperm);
1164 941e1713 2006-02-15 devnull return;
1166 941e1713 2006-02-15 devnull respond(r, nil);
1167 941e1713 2006-02-15 devnull return;
1171 941e1713 2006-02-15 devnull static void
1172 941e1713 2006-02-15 devnull fsflush(Req *r)
1175 941e1713 2006-02-15 devnull * We only handle reads and writes outside the main loop,
1176 941e1713 2006-02-15 devnull * so we must be flushing one of those. In both cases it's
1177 941e1713 2006-02-15 devnull * okay to just ignore the results of the request, whenever
1178 941e1713 2006-02-15 devnull * they're ready.
1180 941e1713 2006-02-15 devnull incref(&r->oldreq->ref);
1181 941e1713 2006-02-15 devnull respond(r->oldreq, "interrupted");
1182 941e1713 2006-02-15 devnull respond(r, nil);
1185 941e1713 2006-02-15 devnull static void
1186 941e1713 2006-02-15 devnull fsthread(void *v)
1188 941e1713 2006-02-15 devnull Req *r;
1191 941e1713 2006-02-15 devnull switch(r->ifcall.type){
1192 941e1713 2006-02-15 devnull case Tread:
1193 941e1713 2006-02-15 devnull fsread(r);
1195 941e1713 2006-02-15 devnull case Twrite:
1196 941e1713 2006-02-15 devnull fswrite(r);
1201 941e1713 2006-02-15 devnull static void
1202 941e1713 2006-02-15 devnull fsrecv(void *v)
1204 941e1713 2006-02-15 devnull Req *r;
1206 941e1713 2006-02-15 devnull while((r = recvp(fsreqchan)) != nil){
1207 941e1713 2006-02-15 devnull switch(r->ifcall.type){
1208 941e1713 2006-02-15 devnull case Tattach:
1209 941e1713 2006-02-15 devnull fsattach(r);
1211 941e1713 2006-02-15 devnull case Tflush:
1212 941e1713 2006-02-15 devnull fsflush(r);
1214 941e1713 2006-02-15 devnull case Topen:
1215 941e1713 2006-02-15 devnull fsopen(r);
1217 941e1713 2006-02-15 devnull case Twalk:
1218 941e1713 2006-02-15 devnull fswalk(r);
1220 941e1713 2006-02-15 devnull case Tstat:
1221 941e1713 2006-02-15 devnull fsstat(r);
1223 941e1713 2006-02-15 devnull default:
1224 941e1713 2006-02-15 devnull threadcreate(fsthread, r, STACK);
1230 941e1713 2006-02-15 devnull static void
1231 941e1713 2006-02-15 devnull fssend(Req *r)
1233 941e1713 2006-02-15 devnull sendp(fsreqchan, r);
1236 941e1713 2006-02-15 devnull static void
1237 941e1713 2006-02-15 devnull fsdestroyfid(Fid *f)
1239 941e1713 2006-02-15 devnull free(f->aux);
1243 941e1713 2006-02-15 devnull fsinit0(void) /* bad planning - clash with lib9pclient */
1245 941e1713 2006-02-15 devnull t0 = time(0);
1247 941e1713 2006-02-15 devnull fs.attach = fssend;
1248 941e1713 2006-02-15 devnull fs.flush = fssend;
1249 941e1713 2006-02-15 devnull fs.open = fssend;
1250 941e1713 2006-02-15 devnull fs.walk = fssend;
1251 941e1713 2006-02-15 devnull fs.read = fssend;
1252 941e1713 2006-02-15 devnull fs.write = fssend;
1253 941e1713 2006-02-15 devnull fs.stat = fssend;
1254 941e1713 2006-02-15 devnull fs.destroyfid = fsdestroyfid;
1256 941e1713 2006-02-15 devnull rootqid = qid(Qroot, nil, nil, nil);
1258 941e1713 2006-02-15 devnull fsreqchan = chancreate(sizeof(void*), 0);
1259 941e1713 2006-02-15 devnull mailthread(fsrecv, nil);