Blame


1 941e1713 2006-02-15 devnull /*
2 941e1713 2006-02-15 devnull * Mail file system.
3 941e1713 2006-02-15 devnull *
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.
10 941e1713 2006-02-15 devnull
11 941e1713 2006-02-15 devnull TO DO:
12 941e1713 2006-02-15 devnull
13 941e1713 2006-02-15 devnull decode subject, etc.
14 941e1713 2006-02-15 devnull decode body
15 941e1713 2006-02-15 devnull
16 941e1713 2006-02-15 devnull digest
17 941e1713 2006-02-15 devnull disposition
18 941e1713 2006-02-15 devnull filename
19 941e1713 2006-02-15 devnull
20 941e1713 2006-02-15 devnull ctl messages
21 941e1713 2006-02-15 devnull
22 941e1713 2006-02-15 devnull fetch mail on demand
23 941e1713 2006-02-15 devnull
24 941e1713 2006-02-15 devnull */
25 941e1713 2006-02-15 devnull
26 941e1713 2006-02-15 devnull #include "a.h"
27 941e1713 2006-02-15 devnull
28 941e1713 2006-02-15 devnull enum
29 941e1713 2006-02-15 devnull {
30 941e1713 2006-02-15 devnull /* directories */
31 941e1713 2006-02-15 devnull Qroot,
32 941e1713 2006-02-15 devnull Qbox,
33 941e1713 2006-02-15 devnull Qmsg,
34 941e1713 2006-02-15 devnull
35 941e1713 2006-02-15 devnull /* control files */
36 941e1713 2006-02-15 devnull Qctl,
37 941e1713 2006-02-15 devnull Qboxctl,
38 941e1713 2006-02-15 devnull Qsearch,
39 941e1713 2006-02-15 devnull
40 941e1713 2006-02-15 devnull /* message header - same order as struct Hdr */
41 941e1713 2006-02-15 devnull Qdate,
42 941e1713 2006-02-15 devnull Qsubject,
43 941e1713 2006-02-15 devnull Qfrom,
44 941e1713 2006-02-15 devnull Qsender,
45 941e1713 2006-02-15 devnull Qreplyto,
46 941e1713 2006-02-15 devnull Qto,
47 941e1713 2006-02-15 devnull Qcc,
48 941e1713 2006-02-15 devnull Qbcc,
49 941e1713 2006-02-15 devnull Qinreplyto,
50 941e1713 2006-02-15 devnull Qmessageid,
51 941e1713 2006-02-15 devnull
52 941e1713 2006-02-15 devnull /* part data - same order as stuct Part */
53 941e1713 2006-02-15 devnull Qtype,
54 941e1713 2006-02-15 devnull Qidstr,
55 941e1713 2006-02-15 devnull Qdesc,
56 941e1713 2006-02-15 devnull Qencoding, /* only here temporarily! */
57 941e1713 2006-02-15 devnull Qcharset,
58 bb70a84b 2007-06-23 devnull Qfilename,
59 941e1713 2006-02-15 devnull Qraw,
60 941e1713 2006-02-15 devnull Qrawheader,
61 941e1713 2006-02-15 devnull Qrawbody,
62 941e1713 2006-02-15 devnull Qmimeheader,
63 941e1713 2006-02-15 devnull
64 941e1713 2006-02-15 devnull /* part numbers - same order as struct Part */
65 941e1713 2006-02-15 devnull Qsize,
66 941e1713 2006-02-15 devnull Qlines,
67 941e1713 2006-02-15 devnull
68 941e1713 2006-02-15 devnull /* other message files */
69 941e1713 2006-02-15 devnull Qbody,
70 941e1713 2006-02-15 devnull Qheader,
71 941e1713 2006-02-15 devnull Qdigest,
72 941e1713 2006-02-15 devnull Qdisposition,
73 941e1713 2006-02-15 devnull Qflags,
74 941e1713 2006-02-15 devnull Qinfo,
75 941e1713 2006-02-15 devnull Qrawunix,
76 941e1713 2006-02-15 devnull Qunixdate,
77 941e1713 2006-02-15 devnull Qunixheader,
78 941e1713 2006-02-15 devnull
79 941e1713 2006-02-15 devnull Qfile0 = Qbody,
80 cbeb0b26 2006-04-01 devnull Qnfile = Qunixheader+1-Qfile0
81 941e1713 2006-02-15 devnull };
82 941e1713 2006-02-15 devnull
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";
90 941e1713 2006-02-15 devnull
91 941e1713 2006-02-15 devnull Channel *fsreqchan;
92 941e1713 2006-02-15 devnull Srv fs;
93 941e1713 2006-02-15 devnull Qid rootqid;
94 941e1713 2006-02-15 devnull ulong t0;
95 941e1713 2006-02-15 devnull
96 941e1713 2006-02-15 devnull void
97 941e1713 2006-02-15 devnull responderror(Req *r)
98 941e1713 2006-02-15 devnull {
99 941e1713 2006-02-15 devnull char e[ERRMAX];
100 941e1713 2006-02-15 devnull
101 941e1713 2006-02-15 devnull rerrstr(e, sizeof e);
102 941e1713 2006-02-15 devnull respond(r, e);
103 941e1713 2006-02-15 devnull }
104 941e1713 2006-02-15 devnull
105 941e1713 2006-02-15 devnull int
106 941e1713 2006-02-15 devnull qtype(Qid q)
107 941e1713 2006-02-15 devnull {
108 941e1713 2006-02-15 devnull return q.path&0x3F;
109 941e1713 2006-02-15 devnull }
110 941e1713 2006-02-15 devnull
111 941e1713 2006-02-15 devnull int
112 941e1713 2006-02-15 devnull qboxid(Qid q)
113 941e1713 2006-02-15 devnull {
114 941e1713 2006-02-15 devnull return (q.path>>40)&0xFFFF;
115 941e1713 2006-02-15 devnull }
116 941e1713 2006-02-15 devnull
117 941e1713 2006-02-15 devnull int
118 941e1713 2006-02-15 devnull qmsgid(Qid q)
119 941e1713 2006-02-15 devnull {
120 941e1713 2006-02-15 devnull return ((q.path>>32)&0xFF000000) | ((q.path>>16)&0xFFFFFF);
121 941e1713 2006-02-15 devnull }
122 941e1713 2006-02-15 devnull
123 941e1713 2006-02-15 devnull int
124 941e1713 2006-02-15 devnull qpartid(Qid q)
125 941e1713 2006-02-15 devnull {
126 941e1713 2006-02-15 devnull return ((q.path>>6)&0x3FF);
127 941e1713 2006-02-15 devnull }
128 941e1713 2006-02-15 devnull
129 941e1713 2006-02-15 devnull Qid
130 941e1713 2006-02-15 devnull qid(int ctl, Box *box, Msg *msg, Part *part)
131 941e1713 2006-02-15 devnull {
132 941e1713 2006-02-15 devnull Qid q;
133 941e1713 2006-02-15 devnull
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;
144 941e1713 2006-02-15 devnull }
145 941e1713 2006-02-15 devnull
146 941e1713 2006-02-15 devnull int
147 941e1713 2006-02-15 devnull parseqid(Qid q, Box **box, Msg **msg, Part **part)
148 941e1713 2006-02-15 devnull {
149 941e1713 2006-02-15 devnull *msg = nil;
150 941e1713 2006-02-15 devnull *part = nil;
151 941e1713 2006-02-15 devnull
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));
155 941e1713 2006-02-15 devnull }
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);
159 941e1713 2006-02-15 devnull }
160 941e1713 2006-02-15 devnull
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"
193 941e1713 2006-02-15 devnull };
194 941e1713 2006-02-15 devnull
195 941e1713 2006-02-15 devnull char*
196 941e1713 2006-02-15 devnull nameoftype(int t)
197 941e1713 2006-02-15 devnull {
198 941e1713 2006-02-15 devnull int i;
199 941e1713 2006-02-15 devnull
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 "???";
204 941e1713 2006-02-15 devnull }
205 941e1713 2006-02-15 devnull
206 941e1713 2006-02-15 devnull int
207 941e1713 2006-02-15 devnull typeofname(char *name)
208 941e1713 2006-02-15 devnull {
209 941e1713 2006-02-15 devnull int i;
210 941e1713 2006-02-15 devnull
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;
215 941e1713 2006-02-15 devnull }
216 941e1713 2006-02-15 devnull
217 941e1713 2006-02-15 devnull static void
218 941e1713 2006-02-15 devnull fsattach(Req *r)
219 941e1713 2006-02-15 devnull {
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);
223 941e1713 2006-02-15 devnull }
224 941e1713 2006-02-15 devnull
225 c7722328 2006-02-28 devnull static int
226 941e1713 2006-02-15 devnull isnumber(char *s)
227 941e1713 2006-02-15 devnull {
228 941e1713 2006-02-15 devnull int n;
229 941e1713 2006-02-15 devnull
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;
236 941e1713 2006-02-15 devnull }
237 941e1713 2006-02-15 devnull
238 941e1713 2006-02-15 devnull static char*
239 941e1713 2006-02-15 devnull fswalk1(Fid *fid, char *name, void *arg)
240 941e1713 2006-02-15 devnull {
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;
245 941e1713 2006-02-15 devnull
246 941e1713 2006-02-15 devnull USED(arg);
247 941e1713 2006-02-15 devnull
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;
255 941e1713 2006-02-15 devnull }
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;
259 941e1713 2006-02-15 devnull }
260 941e1713 2006-02-15 devnull break;
261 941e1713 2006-02-15 devnull
262 941e1713 2006-02-15 devnull case Qbox:
263 941e1713 2006-02-15 devnull /*
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.
266 941e1713 2006-02-15 devnull */
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;
273 941e1713 2006-02-15 devnull }
274 941e1713 2006-02-15 devnull fid->qid = qid(Qbox, box, nil, nil);
275 941e1713 2006-02-15 devnull return nil;
276 941e1713 2006-02-15 devnull }
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;
280 941e1713 2006-02-15 devnull }
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;
284 941e1713 2006-02-15 devnull }
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;
288 941e1713 2006-02-15 devnull }
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;
292 941e1713 2006-02-15 devnull }
293 941e1713 2006-02-15 devnull fid->qid = qid(Qmsg, box, msg, nil);
294 941e1713 2006-02-15 devnull return nil;
295 941e1713 2006-02-15 devnull }
296 941e1713 2006-02-15 devnull break;
297 941e1713 2006-02-15 devnull
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;
303 941e1713 2006-02-15 devnull }
304 941e1713 2006-02-15 devnull fid->qid = qid(Qmsg, box, msg, part->parent);
305 941e1713 2006-02-15 devnull return nil;
306 941e1713 2006-02-15 devnull }
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;
311 941e1713 2006-02-15 devnull }
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;
316 941e1713 2006-02-15 devnull }
317 941e1713 2006-02-15 devnull }
318 941e1713 2006-02-15 devnull break;
319 941e1713 2006-02-15 devnull }
320 941e1713 2006-02-15 devnull return "not found";
321 941e1713 2006-02-15 devnull }
322 941e1713 2006-02-15 devnull
323 941e1713 2006-02-15 devnull static void
324 941e1713 2006-02-15 devnull fswalk(Req *r)
325 941e1713 2006-02-15 devnull {
326 941e1713 2006-02-15 devnull walkandclone(r, fswalk1, nil, nil);
327 941e1713 2006-02-15 devnull }
328 941e1713 2006-02-15 devnull
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"
340 941e1713 2006-02-15 devnull };
341 941e1713 2006-02-15 devnull
342 941e1713 2006-02-15 devnull static void
343 941e1713 2006-02-15 devnull addaddrs(Fmt *fmt, char *prefix, char *addrs)
344 941e1713 2006-02-15 devnull {
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;
348 941e1713 2006-02-15 devnull
349 941e1713 2006-02-15 devnull if(addrs == nil)
350 941e1713 2006-02-15 devnull return;
351 941e1713 2006-02-15 devnull addrs = estrdup(addrs);
352 941e1713 2006-02-15 devnull nf = 0;
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)
356 941e1713 2006-02-15 devnull nf++;
357 941e1713 2006-02-15 devnull if(*p == '\'')
358 941e1713 2006-02-15 devnull inquote = !inquote;
359 941e1713 2006-02-15 devnull }
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]);
368 941e1713 2006-02-15 devnull else
369 941e1713 2006-02-15 devnull fmtprint(fmt, "%s%s", sep, f[i+1]);
370 941e1713 2006-02-15 devnull sep = ", ";
371 941e1713 2006-02-15 devnull }
372 941e1713 2006-02-15 devnull fmtprint(fmt, "\n");
373 941e1713 2006-02-15 devnull free(addrs);
374 941e1713 2006-02-15 devnull }
375 941e1713 2006-02-15 devnull
376 941e1713 2006-02-15 devnull static void
377 941e1713 2006-02-15 devnull mkbody(Part *p, Qid q)
378 941e1713 2006-02-15 devnull {
379 941e1713 2006-02-15 devnull char *t;
380 941e1713 2006-02-15 devnull int len;
381 941e1713 2006-02-15 devnull
382 941e1713 2006-02-15 devnull if(p->msg->part[0] == p)
383 941e1713 2006-02-15 devnull t = p->rawbody;
384 941e1713 2006-02-15 devnull else
385 941e1713 2006-02-15 devnull t = p->raw;
386 941e1713 2006-02-15 devnull if(t == nil)
387 941e1713 2006-02-15 devnull return;
388 941e1713 2006-02-15 devnull
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);
394 941e1713 2006-02-15 devnull else
395 941e1713 2006-02-15 devnull t = estrdup(t);
396 941e1713 2006-02-15 devnull
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;
400 941e1713 2006-02-15 devnull }
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);
404 941e1713 2006-02-15 devnull else
405 941e1713 2006-02-15 devnull p->nbody = len;
406 941e1713 2006-02-15 devnull }
407 941e1713 2006-02-15 devnull
408 941e1713 2006-02-15 devnull static Qid ZQ;
409 941e1713 2006-02-15 devnull
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)
412 941e1713 2006-02-15 devnull {
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;
417 941e1713 2006-02-15 devnull
418 941e1713 2006-02-15 devnull *pp = nil;
419 941e1713 2006-02-15 devnull *freeme = 0;
420 941e1713 2006-02-15 devnull if(len)
421 941e1713 2006-02-15 devnull *len = -1;
422 941e1713 2006-02-15 devnull
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;
426 941e1713 2006-02-15 devnull }
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;
441 941e1713 2006-02-15 devnull }
442 941e1713 2006-02-15 devnull *pp = ((char**)&part->hdr->date)[type-Qdate];
443 941e1713 2006-02-15 devnull return 0;
444 941e1713 2006-02-15 devnull
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;
449 941e1713 2006-02-15 devnull
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;
454 941e1713 2006-02-15 devnull }
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 = "???";
458 941e1713 2006-02-15 devnull else{
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 == ' '){
464 941e1713 2006-02-15 devnull from++;
465 941e1713 2006-02-15 devnull break;
466 941e1713 2006-02-15 devnull }
467 941e1713 2006-02-15 devnull }
468 941e1713 2006-02-15 devnull if(*from == 0)
469 941e1713 2006-02-15 devnull from = part->hdr->from;
470 941e1713 2006-02-15 devnull }
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;
475 941e1713 2006-02-15 devnull }
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);
479 941e1713 2006-02-15 devnull if(s){
480 941e1713 2006-02-15 devnull *pp = s;
481 941e1713 2006-02-15 devnull *freeme = 1;
482 941e1713 2006-02-15 devnull }else
483 941e1713 2006-02-15 devnull *pp = buf;
484 941e1713 2006-02-15 devnull return 0;
485 941e1713 2006-02-15 devnull
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);
501 941e1713 2006-02-15 devnull break;
502 941e1713 2006-02-15 devnull case Qrawheader:
503 941e1713 2006-02-15 devnull imapfetchrawheader(imap, part);
504 941e1713 2006-02-15 devnull break;
505 941e1713 2006-02-15 devnull case Qrawbody:
506 941e1713 2006-02-15 devnull imapfetchrawbody(imap, part);
507 941e1713 2006-02-15 devnull break;
508 941e1713 2006-02-15 devnull case Qmimeheader:
509 941e1713 2006-02-15 devnull imapfetchrawmime(imap, part);
510 941e1713 2006-02-15 devnull break;
511 941e1713 2006-02-15 devnull default:
512 941e1713 2006-02-15 devnull return 0;
513 941e1713 2006-02-15 devnull }
514 941e1713 2006-02-15 devnull /*
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.
517 941e1713 2006-02-15 devnull */
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];
522 941e1713 2006-02-15 devnull }
523 941e1713 2006-02-15 devnull return 0;
524 941e1713 2006-02-15 devnull
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;
528 941e1713 2006-02-15 devnull if(len)
529 941e1713 2006-02-15 devnull *len = part->nbody;
530 941e1713 2006-02-15 devnull return 0;
531 941e1713 2006-02-15 devnull }
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);
537 941e1713 2006-02-15 devnull else
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;
542 941e1713 2006-02-15 devnull }
543 941e1713 2006-02-15 devnull mkbody(part, q);
544 941e1713 2006-02-15 devnull *pp = part->body;
545 941e1713 2006-02-15 devnull if(len)
546 941e1713 2006-02-15 devnull *len = part->nbody;
547 941e1713 2006-02-15 devnull return 0;
548 941e1713 2006-02-15 devnull
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;
555 941e1713 2006-02-15 devnull
556 941e1713 2006-02-15 devnull case Qflags:
557 941e1713 2006-02-15 devnull s = buf;
558 941e1713 2006-02-15 devnull *s = 0;
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);
565 941e1713 2006-02-15 devnull }
566 941e1713 2006-02-15 devnull }
567 941e1713 2006-02-15 devnull *pp = buf;
568 941e1713 2006-02-15 devnull return 0;
569 941e1713 2006-02-15 devnull
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);
578 941e1713 2006-02-15 devnull }
579 941e1713 2006-02-15 devnull }
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);
603 941e1713 2006-02-15 devnull }
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;
616 941e1713 2006-02-15 devnull
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));
623 941e1713 2006-02-15 devnull else
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;
640 941e1713 2006-02-15 devnull
641 941e1713 2006-02-15 devnull default:
642 941e1713 2006-02-15 devnull werrstr(Egreg);
643 941e1713 2006-02-15 devnull return -1;
644 941e1713 2006-02-15 devnull }
645 941e1713 2006-02-15 devnull }
646 941e1713 2006-02-15 devnull
647 941e1713 2006-02-15 devnull int
648 941e1713 2006-02-15 devnull filldir(Dir *d, int type, Box *box, Msg *msg, Part *part)
649 941e1713 2006-02-15 devnull {
650 941e1713 2006-02-15 devnull int freeme, len;
651 941e1713 2006-02-15 devnull char *s;
652 941e1713 2006-02-15 devnull
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;
657 941e1713 2006-02-15 devnull }else{
658 941e1713 2006-02-15 devnull d->atime = t0;
659 941e1713 2006-02-15 devnull d->mtime = t0;
660 941e1713 2006-02-15 devnull }
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);
665 941e1713 2006-02-15 devnull
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;
673 941e1713 2006-02-15 devnull break;
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;
677 941e1713 2006-02-15 devnull break;
678 941e1713 2006-02-15 devnull case Qsearch:
679 941e1713 2006-02-15 devnull d->mode = 0666;
680 941e1713 2006-02-15 devnull break;
681 941e1713 2006-02-15 devnull
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){
689 941e1713 2006-02-15 devnull if(s){
690 941e1713 2006-02-15 devnull if(len == -1)
691 941e1713 2006-02-15 devnull d->length = strlen(s);
692 941e1713 2006-02-15 devnull else
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);
696 941e1713 2006-02-15 devnull }
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;
699 941e1713 2006-02-15 devnull break;
700 941e1713 2006-02-15 devnull }
701 941e1713 2006-02-15 devnull
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("/");
705 941e1713 2006-02-15 devnull break;
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;
710 941e1713 2006-02-15 devnull }
711 941e1713 2006-02-15 devnull d->name = estrdup9p(box->elem);
712 941e1713 2006-02-15 devnull break;
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;
717 941e1713 2006-02-15 devnull }
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);
720 941e1713 2006-02-15 devnull else
721 941e1713 2006-02-15 devnull d->name = esmprint("%d", part->pix+1);
722 941e1713 2006-02-15 devnull break;
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");
726 941e1713 2006-02-15 devnull break;
727 941e1713 2006-02-15 devnull case Qsearch:
728 941e1713 2006-02-15 devnull d->name = estrdup9p("search");
729 941e1713 2006-02-15 devnull break;
730 941e1713 2006-02-15 devnull default:
731 941e1713 2006-02-15 devnull d->name = estrdup9p(nameoftype(type));
732 941e1713 2006-02-15 devnull break;
733 941e1713 2006-02-15 devnull }
734 941e1713 2006-02-15 devnull return 0;
735 941e1713 2006-02-15 devnull }
736 941e1713 2006-02-15 devnull
737 941e1713 2006-02-15 devnull static void
738 941e1713 2006-02-15 devnull fsstat(Req *r)
739 941e1713 2006-02-15 devnull {
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;
744 941e1713 2006-02-15 devnull
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);
748 941e1713 2006-02-15 devnull else
749 941e1713 2006-02-15 devnull respond(r, nil);
750 941e1713 2006-02-15 devnull }
751 941e1713 2006-02-15 devnull
752 941e1713 2006-02-15 devnull int
753 941e1713 2006-02-15 devnull rootgen(int i, Dir *d, void *aux)
754 941e1713 2006-02-15 devnull {
755 941e1713 2006-02-15 devnull USED(aux);
756 941e1713 2006-02-15 devnull
757 941e1713 2006-02-15 devnull if(i == 0)
758 941e1713 2006-02-15 devnull return filldir(d, Qctl, nil, nil, nil);
759 941e1713 2006-02-15 devnull i--;
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;
763 941e1713 2006-02-15 devnull }
764 941e1713 2006-02-15 devnull
765 941e1713 2006-02-15 devnull int
766 941e1713 2006-02-15 devnull boxgen(int i, Dir *d, void *aux)
767 941e1713 2006-02-15 devnull {
768 941e1713 2006-02-15 devnull Box *box;
769 941e1713 2006-02-15 devnull
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);
773 941e1713 2006-02-15 devnull i--;
774 941e1713 2006-02-15 devnull if(i == 0)
775 941e1713 2006-02-15 devnull return filldir(d, Qsearch, box, nil, nil);
776 bb70a84b 2007-06-23 devnull i--;
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;
783 941e1713 2006-02-15 devnull }
784 941e1713 2006-02-15 devnull
785 941e1713 2006-02-15 devnull static int msgdir[] = {
786 941e1713 2006-02-15 devnull Qtype,
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
792 941e1713 2006-02-15 devnull };
793 941e1713 2006-02-15 devnull static int mimemsgdir[] = {
794 941e1713 2006-02-15 devnull Qtype,
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
799 941e1713 2006-02-15 devnull };
800 941e1713 2006-02-15 devnull static int mimedir[] = {
801 941e1713 2006-02-15 devnull Qtype,
802 941e1713 2006-02-15 devnull Qbody,
803 bb70a84b 2007-06-23 devnull Qfilename,
804 bb70a84b 2007-06-23 devnull Qcharset,
805 941e1713 2006-02-15 devnull Qmimeheader,
806 cbeb0b26 2006-04-01 devnull Qraw
807 941e1713 2006-02-15 devnull };
808 941e1713 2006-02-15 devnull
809 941e1713 2006-02-15 devnull int
810 941e1713 2006-02-15 devnull msggen(int i, Dir *d, void *aux)
811 941e1713 2006-02-15 devnull {
812 941e1713 2006-02-15 devnull Box *box;
813 941e1713 2006-02-15 devnull Msg *msg;
814 941e1713 2006-02-15 devnull Part *part;
815 941e1713 2006-02-15 devnull
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);
827 941e1713 2006-02-15 devnull }else{
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);
831 941e1713 2006-02-15 devnull }
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;
835 941e1713 2006-02-15 devnull }
836 941e1713 2006-02-15 devnull
837 941e1713 2006-02-15 devnull enum
838 941e1713 2006-02-15 devnull {
839 cbeb0b26 2006-04-01 devnull CMhangup
840 941e1713 2006-02-15 devnull };
841 941e1713 2006-02-15 devnull static Cmdtab ctltab[] =
842 941e1713 2006-02-15 devnull {
843 cbeb0b26 2006-04-01 devnull CMhangup, "hangup", 2
844 941e1713 2006-02-15 devnull };
845 941e1713 2006-02-15 devnull
846 941e1713 2006-02-15 devnull enum
847 941e1713 2006-02-15 devnull {
848 941e1713 2006-02-15 devnull CMdelete,
849 941e1713 2006-02-15 devnull CMrefresh,
850 941e1713 2006-02-15 devnull CMreplied,
851 941e1713 2006-02-15 devnull CMread,
852 941e1713 2006-02-15 devnull CMsave,
853 941e1713 2006-02-15 devnull CMjunk,
854 cbeb0b26 2006-04-01 devnull CMnonjunk
855 941e1713 2006-02-15 devnull };
856 941e1713 2006-02-15 devnull static Cmdtab boxctltab[] =
857 941e1713 2006-02-15 devnull {
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
865 941e1713 2006-02-15 devnull };
866 941e1713 2006-02-15 devnull
867 941e1713 2006-02-15 devnull static void
868 941e1713 2006-02-15 devnull fsread(Req *r)
869 941e1713 2006-02-15 devnull {
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;
875 941e1713 2006-02-15 devnull
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);
880 941e1713 2006-02-15 devnull return;
881 941e1713 2006-02-15 devnull
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);
885 941e1713 2006-02-15 devnull return;
886 941e1713 2006-02-15 devnull }
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);
892 941e1713 2006-02-15 devnull return;
893 941e1713 2006-02-15 devnull }
894 941e1713 2006-02-15 devnull dirread9p(r, boxgen, box);
895 941e1713 2006-02-15 devnull respond(r, nil);
896 941e1713 2006-02-15 devnull return;
897 941e1713 2006-02-15 devnull
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);
901 941e1713 2006-02-15 devnull return;
902 941e1713 2006-02-15 devnull }
903 941e1713 2006-02-15 devnull dirread9p(r, msggen, part);
904 941e1713 2006-02-15 devnull respond(r, nil);
905 941e1713 2006-02-15 devnull return;
906 941e1713 2006-02-15 devnull
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);
910 941e1713 2006-02-15 devnull return;
911 941e1713 2006-02-15 devnull
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);
915 941e1713 2006-02-15 devnull return;
916 941e1713 2006-02-15 devnull
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);
920 941e1713 2006-02-15 devnull return;
921 941e1713 2006-02-15 devnull }
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);
928 941e1713 2006-02-15 devnull return;
929 941e1713 2006-02-15 devnull }
930 941e1713 2006-02-15 devnull }
931 941e1713 2006-02-15 devnull
932 941e1713 2006-02-15 devnull int
933 941e1713 2006-02-15 devnull mkmsglist(Box *box, char **f, int nf, Msg ***mm)
934 941e1713 2006-02-15 devnull {
935 941e1713 2006-02-15 devnull int i, nm;
936 941e1713 2006-02-15 devnull Msg **m;
937 941e1713 2006-02-15 devnull
938 941e1713 2006-02-15 devnull m = emalloc(nf*sizeof m[0]);
939 941e1713 2006-02-15 devnull nm = 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)
942 941e1713 2006-02-15 devnull nm++;
943 941e1713 2006-02-15 devnull *mm = m;
944 941e1713 2006-02-15 devnull return nm;
945 941e1713 2006-02-15 devnull }
946 941e1713 2006-02-15 devnull
947 941e1713 2006-02-15 devnull static void
948 941e1713 2006-02-15 devnull fswrite(Req *r)
949 941e1713 2006-02-15 devnull {
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;
957 941e1713 2006-02-15 devnull int nm;
958 941e1713 2006-02-15 devnull Fmt fmt;
959 941e1713 2006-02-15 devnull
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);
964 941e1713 2006-02-15 devnull break;
965 941e1713 2006-02-15 devnull
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);
971 941e1713 2006-02-15 devnull return;
972 941e1713 2006-02-15 devnull }
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);
978 941e1713 2006-02-15 devnull break;
979 941e1713 2006-02-15 devnull default:
980 941e1713 2006-02-15 devnull respond(r, Egreg);
981 941e1713 2006-02-15 devnull break;
982 941e1713 2006-02-15 devnull }
983 941e1713 2006-02-15 devnull free(cb);
984 941e1713 2006-02-15 devnull return;
985 941e1713 2006-02-15 devnull
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);
991 941e1713 2006-02-15 devnull return;
992 941e1713 2006-02-15 devnull }
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);
998 941e1713 2006-02-15 devnull break;
999 941e1713 2006-02-15 devnull }
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);
1004 941e1713 2006-02-15 devnull break;
1005 941e1713 2006-02-15 devnull }
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);
1008 941e1713 2006-02-15 devnull else
1009 941e1713 2006-02-15 devnull respond(r, nil);
1010 941e1713 2006-02-15 devnull free(m);
1011 941e1713 2006-02-15 devnull break;
1012 941e1713 2006-02-15 devnull
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);
1027 941e1713 2006-02-15 devnull break;
1028 941e1713 2006-02-15 devnull }
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);
1033 941e1713 2006-02-15 devnull break;
1034 941e1713 2006-02-15 devnull }
1035 941e1713 2006-02-15 devnull if(nm > 0 && imapflaglist(imap, +1, flag, m, nm) < 0)
1036 941e1713 2006-02-15 devnull responderror(r);
1037 941e1713 2006-02-15 devnull else
1038 941e1713 2006-02-15 devnull respond(r, nil);
1039 941e1713 2006-02-15 devnull free(m);
1040 941e1713 2006-02-15 devnull break;
1041 941e1713 2006-02-15 devnull
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);
1045 941e1713 2006-02-15 devnull break;
1046 941e1713 2006-02-15 devnull
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);
1050 941e1713 2006-02-15 devnull break;
1051 941e1713 2006-02-15 devnull }
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);
1055 941e1713 2006-02-15 devnull else
1056 941e1713 2006-02-15 devnull respond(r, nil);
1057 941e1713 2006-02-15 devnull free(m);
1058 941e1713 2006-02-15 devnull break;
1059 941e1713 2006-02-15 devnull
1060 941e1713 2006-02-15 devnull default:
1061 941e1713 2006-02-15 devnull respond(r, Egreg);
1062 941e1713 2006-02-15 devnull break;
1063 941e1713 2006-02-15 devnull }
1064 941e1713 2006-02-15 devnull free(cb);
1065 941e1713 2006-02-15 devnull return;
1066 941e1713 2006-02-15 devnull
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;
1071 941e1713 2006-02-15 devnull }
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++){
1078 941e1713 2006-02-15 devnull f = 0;
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;
1085 941e1713 2006-02-15 devnull break;
1086 941e1713 2006-02-15 devnull }
1087 941e1713 2006-02-15 devnull }
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;
1092 941e1713 2006-02-15 devnull }
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;
1097 941e1713 2006-02-15 devnull else
1098 941e1713 2006-02-15 devnull flagset |= f;
1099 941e1713 2006-02-15 devnull }
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;
1104 941e1713 2006-02-15 devnull }
1105 941e1713 2006-02-15 devnull if(flag)
1106 941e1713 2006-02-15 devnull i = 1;
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;
1110 941e1713 2006-02-15 devnull }else{
1111 941e1713 2006-02-15 devnull i = 0;
1112 941e1713 2006-02-15 devnull flag = flagset;
1113 941e1713 2006-02-15 devnull }
1114 941e1713 2006-02-15 devnull if(imapflaglist(imap, i, flag, &msg, 1) < 0)
1115 941e1713 2006-02-15 devnull responderror(r);
1116 941e1713 2006-02-15 devnull else
1117 941e1713 2006-02-15 devnull respond(r, nil);
1118 941e1713 2006-02-15 devnull return;
1119 941e1713 2006-02-15 devnull
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;
1124 941e1713 2006-02-15 devnull }
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);
1131 941e1713 2006-02-15 devnull }
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;
1136 941e1713 2006-02-15 devnull }
1137 941e1713 2006-02-15 devnull }
1138 941e1713 2006-02-15 devnull
1139 941e1713 2006-02-15 devnull static void
1140 941e1713 2006-02-15 devnull fsopen(Req *r)
1141 941e1713 2006-02-15 devnull {
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;
1148 941e1713 2006-02-15 devnull }
1149 941e1713 2006-02-15 devnull respond(r, nil);
1150 941e1713 2006-02-15 devnull return;
1151 941e1713 2006-02-15 devnull
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;
1157 941e1713 2006-02-15 devnull }
1158 941e1713 2006-02-15 devnull respond(r, nil);
1159 941e1713 2006-02-15 devnull return;
1160 941e1713 2006-02-15 devnull
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;
1165 941e1713 2006-02-15 devnull }
1166 941e1713 2006-02-15 devnull respond(r, nil);
1167 941e1713 2006-02-15 devnull return;
1168 941e1713 2006-02-15 devnull }
1169 941e1713 2006-02-15 devnull }
1170 941e1713 2006-02-15 devnull
1171 941e1713 2006-02-15 devnull static void
1172 941e1713 2006-02-15 devnull fsflush(Req *r)
1173 941e1713 2006-02-15 devnull {
1174 941e1713 2006-02-15 devnull /*
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.
1179 941e1713 2006-02-15 devnull */
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);
1183 941e1713 2006-02-15 devnull }
1184 941e1713 2006-02-15 devnull
1185 941e1713 2006-02-15 devnull static void
1186 941e1713 2006-02-15 devnull fsthread(void *v)
1187 941e1713 2006-02-15 devnull {
1188 941e1713 2006-02-15 devnull Req *r;
1189 941e1713 2006-02-15 devnull
1190 941e1713 2006-02-15 devnull r = v;
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);
1194 941e1713 2006-02-15 devnull break;
1195 941e1713 2006-02-15 devnull case Twrite:
1196 941e1713 2006-02-15 devnull fswrite(r);
1197 941e1713 2006-02-15 devnull break;
1198 941e1713 2006-02-15 devnull }
1199 941e1713 2006-02-15 devnull }
1200 941e1713 2006-02-15 devnull
1201 941e1713 2006-02-15 devnull static void
1202 941e1713 2006-02-15 devnull fsrecv(void *v)
1203 941e1713 2006-02-15 devnull {
1204 941e1713 2006-02-15 devnull Req *r;
1205 941e1713 2006-02-15 devnull
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);
1210 941e1713 2006-02-15 devnull break;
1211 941e1713 2006-02-15 devnull case Tflush:
1212 941e1713 2006-02-15 devnull fsflush(r);
1213 941e1713 2006-02-15 devnull break;
1214 941e1713 2006-02-15 devnull case Topen:
1215 941e1713 2006-02-15 devnull fsopen(r);
1216 941e1713 2006-02-15 devnull break;
1217 941e1713 2006-02-15 devnull case Twalk:
1218 941e1713 2006-02-15 devnull fswalk(r);
1219 941e1713 2006-02-15 devnull break;
1220 941e1713 2006-02-15 devnull case Tstat:
1221 941e1713 2006-02-15 devnull fsstat(r);
1222 941e1713 2006-02-15 devnull break;
1223 941e1713 2006-02-15 devnull default:
1224 941e1713 2006-02-15 devnull threadcreate(fsthread, r, STACK);
1225 941e1713 2006-02-15 devnull break;
1226 941e1713 2006-02-15 devnull }
1227 941e1713 2006-02-15 devnull }
1228 941e1713 2006-02-15 devnull }
1229 941e1713 2006-02-15 devnull
1230 941e1713 2006-02-15 devnull static void
1231 941e1713 2006-02-15 devnull fssend(Req *r)
1232 941e1713 2006-02-15 devnull {
1233 941e1713 2006-02-15 devnull sendp(fsreqchan, r);
1234 941e1713 2006-02-15 devnull }
1235 941e1713 2006-02-15 devnull
1236 941e1713 2006-02-15 devnull static void
1237 941e1713 2006-02-15 devnull fsdestroyfid(Fid *f)
1238 941e1713 2006-02-15 devnull {
1239 941e1713 2006-02-15 devnull free(f->aux);
1240 941e1713 2006-02-15 devnull }
1241 941e1713 2006-02-15 devnull
1242 941e1713 2006-02-15 devnull void
1243 941e1713 2006-02-15 devnull fsinit0(void) /* bad planning - clash with lib9pclient */
1244 941e1713 2006-02-15 devnull {
1245 941e1713 2006-02-15 devnull t0 = time(0);
1246 941e1713 2006-02-15 devnull
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;
1255 941e1713 2006-02-15 devnull
1256 941e1713 2006-02-15 devnull rootqid = qid(Qroot, nil, nil, nil);
1257 941e1713 2006-02-15 devnull
1258 941e1713 2006-02-15 devnull fsreqchan = chancreate(sizeof(void*), 0);
1259 941e1713 2006-02-15 devnull mailthread(fsrecv, nil);
1260 941e1713 2006-02-15 devnull }
1261 941e1713 2006-02-15 devnull