17dd7cddfSDavid du Colombier #include "common.h"
27dd7cddfSDavid du Colombier #include <auth.h>
37dd7cddfSDavid du Colombier #include <fcall.h>
47dd7cddfSDavid du Colombier #include <libsec.h>
5816336a7SDavid du Colombier #include <ctype.h>
67dd7cddfSDavid du Colombier #include "dat.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier enum
97dd7cddfSDavid du Colombier {
107dd7cddfSDavid du Colombier OPERM = 0x3, // mask of all permission types in open mode
117dd7cddfSDavid du Colombier };
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier typedef struct Fid Fid;
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier struct Fid
167dd7cddfSDavid du Colombier {
177dd7cddfSDavid du Colombier Qid qid;
187dd7cddfSDavid du Colombier short busy;
197dd7cddfSDavid du Colombier short open;
207dd7cddfSDavid du Colombier int fid;
217dd7cddfSDavid du Colombier Fid *next;
227dd7cddfSDavid du Colombier Mailbox *mb;
237dd7cddfSDavid du Colombier Message *m;
247dd7cddfSDavid du Colombier Message *mtop; // top level message
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier //finger pointers to speed up reads of large directories
277dd7cddfSDavid du Colombier long foff; // offset/DIRLEN of finger
287dd7cddfSDavid du Colombier Message *fptr; // pointer to message at off
297dd7cddfSDavid du Colombier int fvers; // mailbox version when finger was saved
307dd7cddfSDavid du Colombier };
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier ulong path; // incremented for each new file
337dd7cddfSDavid du Colombier Fid *fids;
347dd7cddfSDavid du Colombier int mfd[2];
359a747e4fSDavid du Colombier char user[Elemlen];
36*901d8e21SDavid du Colombier int messagesize = 4*1024+IOHDRSZ;
37*901d8e21SDavid du Colombier uchar mdata[8*1024+IOHDRSZ];
38*901d8e21SDavid du Colombier uchar mbuf[8*1024+IOHDRSZ];
397dd7cddfSDavid du Colombier Fcall thdr;
409a747e4fSDavid du Colombier Fcall rhdr;
417dd7cddfSDavid du Colombier int fflg;
427dd7cddfSDavid du Colombier char *mntpt;
437dd7cddfSDavid du Colombier int biffing;
447dd7cddfSDavid du Colombier int plumbing = 1;
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier QLock mbllock;
477dd7cddfSDavid du Colombier Mailbox *mbl;
487dd7cddfSDavid du Colombier
497dd7cddfSDavid du Colombier Fid *newfid(int);
507dd7cddfSDavid du Colombier void error(char*);
517dd7cddfSDavid du Colombier void io(void);
527dd7cddfSDavid du Colombier void *erealloc(void*, ulong);
537dd7cddfSDavid du Colombier void *emalloc(ulong);
547dd7cddfSDavid du Colombier void usage(void);
557dd7cddfSDavid du Colombier void reader(void);
567dd7cddfSDavid du Colombier int readheader(Message*, char*, int, int);
577dd7cddfSDavid du Colombier int cistrncmp(char*, char*, int);
587dd7cddfSDavid du Colombier int tokenconvert(String*, char*, int);
595d459b5aSDavid du Colombier String* stringconvert(String*, char*, int);
6080ee5cbfSDavid du Colombier void post(char*, char*, int);
617dd7cddfSDavid du Colombier
629a747e4fSDavid du Colombier char *rflush(Fid*), *rauth(Fid*),
639a747e4fSDavid du Colombier *rattach(Fid*), *rwalk(Fid*),
649a747e4fSDavid du Colombier *ropen(Fid*), *rcreate(Fid*),
657dd7cddfSDavid du Colombier *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
669a747e4fSDavid du Colombier *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*),
679a747e4fSDavid du Colombier *rversion(Fid*);
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier char *(*fcalls[])(Fid*) = {
707dd7cddfSDavid du Colombier [Tflush] rflush,
719a747e4fSDavid du Colombier [Tversion] rversion,
729a747e4fSDavid du Colombier [Tauth] rauth,
737dd7cddfSDavid du Colombier [Tattach] rattach,
747dd7cddfSDavid du Colombier [Twalk] rwalk,
757dd7cddfSDavid du Colombier [Topen] ropen,
767dd7cddfSDavid du Colombier [Tcreate] rcreate,
777dd7cddfSDavid du Colombier [Tread] rread,
787dd7cddfSDavid du Colombier [Twrite] rwrite,
797dd7cddfSDavid du Colombier [Tclunk] rclunk,
807dd7cddfSDavid du Colombier [Tremove] rremove,
817dd7cddfSDavid du Colombier [Tstat] rstat,
827dd7cddfSDavid du Colombier [Twstat] rwstat,
837dd7cddfSDavid du Colombier };
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier char Eperm[] = "permission denied";
867dd7cddfSDavid du Colombier char Enotdir[] = "not a directory";
873ff48bf5SDavid du Colombier char Enoauth[] = "upas/fs: authentication not required";
887dd7cddfSDavid du Colombier char Enotexist[] = "file does not exist";
897dd7cddfSDavid du Colombier char Einuse[] = "file in use";
907dd7cddfSDavid du Colombier char Eexist[] = "file exists";
917dd7cddfSDavid du Colombier char Enotowner[] = "not owner";
927dd7cddfSDavid du Colombier char Eisopen[] = "file already open for I/O";
937dd7cddfSDavid du Colombier char Excl[] = "exclusive use file already open";
947dd7cddfSDavid du Colombier char Ename[] = "illegal name";
957dd7cddfSDavid du Colombier char Ebadctl[] = "unknown control message";
967dd7cddfSDavid du Colombier
977dd7cddfSDavid du Colombier char *dirtab[] =
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier [Qdir] ".",
1007dd7cddfSDavid du Colombier [Qbody] "body",
1017dd7cddfSDavid du Colombier [Qbcc] "bcc",
1027dd7cddfSDavid du Colombier [Qcc] "cc",
1037dd7cddfSDavid du Colombier [Qdate] "date",
1047dd7cddfSDavid du Colombier [Qdigest] "digest",
1057dd7cddfSDavid du Colombier [Qdisposition] "disposition",
1067dd7cddfSDavid du Colombier [Qfilename] "filename",
1077dd7cddfSDavid du Colombier [Qfrom] "from",
1087dd7cddfSDavid du Colombier [Qheader] "header",
1097dd7cddfSDavid du Colombier [Qinfo] "info",
1107dd7cddfSDavid du Colombier [Qinreplyto] "inreplyto",
1117dd7cddfSDavid du Colombier [Qlines] "lines",
1127dd7cddfSDavid du Colombier [Qmimeheader] "mimeheader",
1137dd7cddfSDavid du Colombier [Qmessageid] "messageid",
1147dd7cddfSDavid du Colombier [Qraw] "raw",
1156b6b9ac8SDavid du Colombier [Qrawunix] "rawunix",
1167dd7cddfSDavid du Colombier [Qrawbody] "rawbody",
1177dd7cddfSDavid du Colombier [Qrawheader] "rawheader",
1187dd7cddfSDavid du Colombier [Qreplyto] "replyto",
1197dd7cddfSDavid du Colombier [Qsender] "sender",
1207dd7cddfSDavid du Colombier [Qsubject] "subject",
1217dd7cddfSDavid du Colombier [Qto] "to",
1227dd7cddfSDavid du Colombier [Qtype] "type",
1239a747e4fSDavid du Colombier [Qunixdate] "unixdate",
1247dd7cddfSDavid du Colombier [Qunixheader] "unixheader",
1257dd7cddfSDavid du Colombier [Qctl] "ctl",
12680ee5cbfSDavid du Colombier [Qmboxctl] "ctl",
1277dd7cddfSDavid du Colombier };
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier enum
1307dd7cddfSDavid du Colombier {
1317dd7cddfSDavid du Colombier Hsize= 1277,
1327dd7cddfSDavid du Colombier };
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier Hash *htab[Hsize];
1357dd7cddfSDavid du Colombier
1367dd7cddfSDavid du Colombier int debug;
1377dd7cddfSDavid du Colombier int fflag;
13859cc4ca5SDavid du Colombier int logging;
1397dd7cddfSDavid du Colombier
1407dd7cddfSDavid du Colombier void
usage(void)1417dd7cddfSDavid du Colombier usage(void)
1427dd7cddfSDavid du Colombier {
143816336a7SDavid du Colombier fprint(2, "usage: upas/fs [-bdlnps] [-f mboxfile] [-m mountpoint]\n");
1447dd7cddfSDavid du Colombier exits("usage");
1457dd7cddfSDavid du Colombier }
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier void
notifyf(void * a,char * s)1487dd7cddfSDavid du Colombier notifyf(void *a, char *s)
1497dd7cddfSDavid du Colombier {
1507dd7cddfSDavid du Colombier USED(a);
1517dd7cddfSDavid du Colombier if(strncmp(s, "interrupt", 9) == 0)
1527dd7cddfSDavid du Colombier noted(NCONT);
1537dd7cddfSDavid du Colombier noted(NDFLT);
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier
1567dd7cddfSDavid du Colombier void
main(int argc,char * argv[])1577dd7cddfSDavid du Colombier main(int argc, char *argv[])
1587dd7cddfSDavid du Colombier {
15959cc4ca5SDavid du Colombier int p[2], std, nodflt;
1607dd7cddfSDavid du Colombier char maildir[128];
1617dd7cddfSDavid du Colombier char mbox[128];
1627dd7cddfSDavid du Colombier char *mboxfile, *err;
16380ee5cbfSDavid du Colombier char srvfile[64];
16480ee5cbfSDavid du Colombier int srvpost;
1657dd7cddfSDavid du Colombier
1665d459b5aSDavid du Colombier rfork(RFNOTEG);
1677dd7cddfSDavid du Colombier mntpt = nil;
1687dd7cddfSDavid du Colombier fflag = 0;
1697dd7cddfSDavid du Colombier mboxfile = nil;
1707dd7cddfSDavid du Colombier std = 0;
17159cc4ca5SDavid du Colombier nodflt = 0;
17280ee5cbfSDavid du Colombier srvpost = 0;
1737dd7cddfSDavid du Colombier
1747dd7cddfSDavid du Colombier ARGBEGIN{
1757dd7cddfSDavid du Colombier case 'b':
1767dd7cddfSDavid du Colombier biffing = 1;
1777dd7cddfSDavid du Colombier break;
1787dd7cddfSDavid du Colombier case 'f':
1797dd7cddfSDavid du Colombier fflag = 1;
180816336a7SDavid du Colombier mboxfile = EARGF(usage());
1817dd7cddfSDavid du Colombier break;
1827dd7cddfSDavid du Colombier case 'm':
183816336a7SDavid du Colombier mntpt = EARGF(usage());
1847dd7cddfSDavid du Colombier break;
1857dd7cddfSDavid du Colombier case 'd':
1867dd7cddfSDavid du Colombier debug = 1;
1877dd7cddfSDavid du Colombier break;
1887dd7cddfSDavid du Colombier case 'p':
1897dd7cddfSDavid du Colombier plumbing = 0;
1907dd7cddfSDavid du Colombier break;
19180ee5cbfSDavid du Colombier case 's':
19280ee5cbfSDavid du Colombier srvpost = 1;
19380ee5cbfSDavid du Colombier break;
19459cc4ca5SDavid du Colombier case 'l':
19559cc4ca5SDavid du Colombier logging = 1;
19659cc4ca5SDavid du Colombier break;
19759cc4ca5SDavid du Colombier case 'n':
19859cc4ca5SDavid du Colombier nodflt = 1;
19959cc4ca5SDavid du Colombier break;
2007dd7cddfSDavid du Colombier default:
2017dd7cddfSDavid du Colombier usage();
2027dd7cddfSDavid du Colombier }ARGEND
2037dd7cddfSDavid du Colombier
204816336a7SDavid du Colombier if(argc)
205816336a7SDavid du Colombier usage();
2067dd7cddfSDavid du Colombier if(pipe(p) < 0)
2077dd7cddfSDavid du Colombier error("pipe failed");
2087dd7cddfSDavid du Colombier mfd[0] = p[0];
2097dd7cddfSDavid du Colombier mfd[1] = p[0];
2107dd7cddfSDavid du Colombier
2117dd7cddfSDavid du Colombier notify(notifyf);
2127dd7cddfSDavid du Colombier strcpy(user, getuser());
2137dd7cddfSDavid du Colombier if(mntpt == nil){
2147dd7cddfSDavid du Colombier snprint(maildir, sizeof(maildir), "/mail/fs");
2157dd7cddfSDavid du Colombier mntpt = maildir;
2167dd7cddfSDavid du Colombier }
21759cc4ca5SDavid du Colombier if(mboxfile == nil && !nodflt){
2187dd7cddfSDavid du Colombier snprint(mbox, sizeof(mbox), "/mail/box/%s/mbox", user);
2197dd7cddfSDavid du Colombier mboxfile = mbox;
2207dd7cddfSDavid du Colombier std = 1;
2217dd7cddfSDavid du Colombier }
2227dd7cddfSDavid du Colombier
2237dd7cddfSDavid du Colombier if(debug)
2249a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
2257dd7cddfSDavid du Colombier
22659cc4ca5SDavid du Colombier if(mboxfile != nil){
2277dd7cddfSDavid du Colombier err = newmbox(mboxfile, "mbox", std);
2287dd7cddfSDavid du Colombier if(err != nil)
2293e748dfcSDavid du Colombier sysfatal("opening %s: %s", mboxfile, err);
23059cc4ca5SDavid du Colombier }
2317dd7cddfSDavid du Colombier
23259cc4ca5SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG|RFREND)){
2337dd7cddfSDavid du Colombier case -1:
2347dd7cddfSDavid du Colombier error("fork");
2357dd7cddfSDavid du Colombier case 0:
2369a747e4fSDavid du Colombier henter(PATH(0, Qtop), dirtab[Qctl],
2379a747e4fSDavid du Colombier (Qid){PATH(0, Qctl), 0, QTFILE}, nil, nil);
2387dd7cddfSDavid du Colombier close(p[1]);
2397dd7cddfSDavid du Colombier io();
2407dd7cddfSDavid du Colombier postnote(PNGROUP, getpid(), "die yankee pig dog");
2417dd7cddfSDavid du Colombier break;
2427dd7cddfSDavid du Colombier default:
2437dd7cddfSDavid du Colombier close(p[0]); /* don't deadlock if child fails */
24480ee5cbfSDavid du Colombier if(srvpost){
24580ee5cbfSDavid du Colombier sprint(srvfile, "/srv/upasfs.%s", user);
24680ee5cbfSDavid du Colombier post(srvfile, "upasfs", p[1]);
24780ee5cbfSDavid du Colombier } else {
2489a747e4fSDavid du Colombier if(mount(p[1], -1, mntpt, MREPL, "") < 0)
2497dd7cddfSDavid du Colombier error("mount failed");
2507dd7cddfSDavid du Colombier }
25180ee5cbfSDavid du Colombier }
2527dd7cddfSDavid du Colombier exits(0);
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier static int
fileinfo(Message * m,int t,char ** pp)2567dd7cddfSDavid du Colombier fileinfo(Message *m, int t, char **pp)
2577dd7cddfSDavid du Colombier {
2587dd7cddfSDavid du Colombier char *p;
2597dd7cddfSDavid du Colombier int len;
2607dd7cddfSDavid du Colombier
2617dd7cddfSDavid du Colombier p = "";
2627dd7cddfSDavid du Colombier len = 0;
2637dd7cddfSDavid du Colombier switch(t){
2647dd7cddfSDavid du Colombier case Qbody:
2657dd7cddfSDavid du Colombier p = m->body;
2667dd7cddfSDavid du Colombier len = m->bend - m->body;
2677dd7cddfSDavid du Colombier break;
2687dd7cddfSDavid du Colombier case Qbcc:
2697dd7cddfSDavid du Colombier if(m->bcc822){
2707dd7cddfSDavid du Colombier p = s_to_c(m->bcc822);
2717dd7cddfSDavid du Colombier len = strlen(p);
2727dd7cddfSDavid du Colombier }
2737dd7cddfSDavid du Colombier break;
2747dd7cddfSDavid du Colombier case Qcc:
2757dd7cddfSDavid du Colombier if(m->cc822){
2767dd7cddfSDavid du Colombier p = s_to_c(m->cc822);
2777dd7cddfSDavid du Colombier len = strlen(p);
2787dd7cddfSDavid du Colombier }
2797dd7cddfSDavid du Colombier break;
2807dd7cddfSDavid du Colombier case Qdisposition:
2817dd7cddfSDavid du Colombier switch(m->disposition){
2827dd7cddfSDavid du Colombier case Dinline:
2837dd7cddfSDavid du Colombier p = "inline";
2847dd7cddfSDavid du Colombier break;
2857dd7cddfSDavid du Colombier case Dfile:
2867dd7cddfSDavid du Colombier p = "file";
2877dd7cddfSDavid du Colombier break;
2887dd7cddfSDavid du Colombier }
2897dd7cddfSDavid du Colombier len = strlen(p);
2907dd7cddfSDavid du Colombier break;
2917dd7cddfSDavid du Colombier case Qdate:
2927dd7cddfSDavid du Colombier if(m->date822){
2937dd7cddfSDavid du Colombier p = s_to_c(m->date822);
2947dd7cddfSDavid du Colombier len = strlen(p);
2957dd7cddfSDavid du Colombier } else if(m->unixdate != nil){
2967dd7cddfSDavid du Colombier p = s_to_c(m->unixdate);
2977dd7cddfSDavid du Colombier len = strlen(p);
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier break;
3007dd7cddfSDavid du Colombier case Qfilename:
3017dd7cddfSDavid du Colombier if(m->filename){
3027dd7cddfSDavid du Colombier p = s_to_c(m->filename);
3037dd7cddfSDavid du Colombier len = strlen(p);
3047dd7cddfSDavid du Colombier }
3057dd7cddfSDavid du Colombier break;
3067dd7cddfSDavid du Colombier case Qinreplyto:
3077dd7cddfSDavid du Colombier if(m->inreplyto822){
3087dd7cddfSDavid du Colombier p = s_to_c(m->inreplyto822);
3097dd7cddfSDavid du Colombier len = strlen(p);
3107dd7cddfSDavid du Colombier }
3117dd7cddfSDavid du Colombier break;
3127dd7cddfSDavid du Colombier case Qmessageid:
3137dd7cddfSDavid du Colombier if(m->messageid822){
3147dd7cddfSDavid du Colombier p = s_to_c(m->messageid822);
3157dd7cddfSDavid du Colombier len = strlen(p);
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier break;
3187dd7cddfSDavid du Colombier case Qfrom:
3197dd7cddfSDavid du Colombier if(m->from822){
3207dd7cddfSDavid du Colombier p = s_to_c(m->from822);
3217dd7cddfSDavid du Colombier len = strlen(p);
3227dd7cddfSDavid du Colombier } else if(m->unixfrom != nil){
3237dd7cddfSDavid du Colombier p = s_to_c(m->unixfrom);
3247dd7cddfSDavid du Colombier len = strlen(p);
3257dd7cddfSDavid du Colombier }
3267dd7cddfSDavid du Colombier break;
3277dd7cddfSDavid du Colombier case Qheader:
3287dd7cddfSDavid du Colombier p = m->header;
3297dd7cddfSDavid du Colombier len = headerlen(m);
3307dd7cddfSDavid du Colombier break;
3317dd7cddfSDavid du Colombier case Qlines:
3327dd7cddfSDavid du Colombier p = m->lines;
3337dd7cddfSDavid du Colombier if(*p == 0)
3347dd7cddfSDavid du Colombier countlines(m);
3357dd7cddfSDavid du Colombier len = strlen(m->lines);
3367dd7cddfSDavid du Colombier break;
3377dd7cddfSDavid du Colombier case Qraw:
3387dd7cddfSDavid du Colombier p = m->start;
3397dd7cddfSDavid du Colombier if(strncmp(m->start, "From ", 5) == 0){
3407dd7cddfSDavid du Colombier p = strchr(p, '\n');
3417dd7cddfSDavid du Colombier if(p == nil)
3427dd7cddfSDavid du Colombier p = m->start;
3437dd7cddfSDavid du Colombier else
3447dd7cddfSDavid du Colombier p++;
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier len = m->end - p;
3477dd7cddfSDavid du Colombier break;
3486b6b9ac8SDavid du Colombier case Qrawunix:
3496b6b9ac8SDavid du Colombier p = m->start;
3506b6b9ac8SDavid du Colombier len = m->end - p;
3516b6b9ac8SDavid du Colombier break;
3527dd7cddfSDavid du Colombier case Qrawbody:
3537dd7cddfSDavid du Colombier p = m->rbody;
3547dd7cddfSDavid du Colombier len = m->rbend - p;
3557dd7cddfSDavid du Colombier break;
3567dd7cddfSDavid du Colombier case Qrawheader:
3577dd7cddfSDavid du Colombier p = m->header;
3587dd7cddfSDavid du Colombier len = m->hend - p;
3597dd7cddfSDavid du Colombier break;
3607dd7cddfSDavid du Colombier case Qmimeheader:
3617dd7cddfSDavid du Colombier p = m->mheader;
3627dd7cddfSDavid du Colombier len = m->mhend - p;
3637dd7cddfSDavid du Colombier break;
3647dd7cddfSDavid du Colombier case Qreplyto:
3657dd7cddfSDavid du Colombier p = nil;
3667dd7cddfSDavid du Colombier if(m->replyto822 != nil){
3677dd7cddfSDavid du Colombier p = s_to_c(m->replyto822);
3687dd7cddfSDavid du Colombier len = strlen(p);
3697dd7cddfSDavid du Colombier } else if(m->from822 != nil){
3707dd7cddfSDavid du Colombier p = s_to_c(m->from822);
3717dd7cddfSDavid du Colombier len = strlen(p);
3727dd7cddfSDavid du Colombier } else if(m->sender822 != nil){
3737dd7cddfSDavid du Colombier p = s_to_c(m->sender822);
3747dd7cddfSDavid du Colombier len = strlen(p);
3757dd7cddfSDavid du Colombier } else if(m->unixfrom != nil){
3767dd7cddfSDavid du Colombier p = s_to_c(m->unixfrom);
3777dd7cddfSDavid du Colombier len = strlen(p);
3787dd7cddfSDavid du Colombier }
3797dd7cddfSDavid du Colombier break;
3807dd7cddfSDavid du Colombier case Qsender:
3817dd7cddfSDavid du Colombier if(m->sender822){
3827dd7cddfSDavid du Colombier p = s_to_c(m->sender822);
3837dd7cddfSDavid du Colombier len = strlen(p);
3847dd7cddfSDavid du Colombier }
3857dd7cddfSDavid du Colombier break;
3867dd7cddfSDavid du Colombier case Qsubject:
3877dd7cddfSDavid du Colombier p = nil;
3887dd7cddfSDavid du Colombier if(m->subject822){
3897dd7cddfSDavid du Colombier p = s_to_c(m->subject822);
3907dd7cddfSDavid du Colombier len = strlen(p);
3917dd7cddfSDavid du Colombier }
3927dd7cddfSDavid du Colombier break;
3937dd7cddfSDavid du Colombier case Qto:
3947dd7cddfSDavid du Colombier if(m->to822){
3957dd7cddfSDavid du Colombier p = s_to_c(m->to822);
3967dd7cddfSDavid du Colombier len = strlen(p);
3977dd7cddfSDavid du Colombier }
3987dd7cddfSDavid du Colombier break;
3997dd7cddfSDavid du Colombier case Qtype:
4007dd7cddfSDavid du Colombier if(m->type){
4017dd7cddfSDavid du Colombier p = s_to_c(m->type);
4027dd7cddfSDavid du Colombier len = strlen(p);
4037dd7cddfSDavid du Colombier }
4047dd7cddfSDavid du Colombier break;
4057dd7cddfSDavid du Colombier case Qunixdate:
4067dd7cddfSDavid du Colombier if(m->unixdate){
4077dd7cddfSDavid du Colombier p = s_to_c(m->unixdate);
4087dd7cddfSDavid du Colombier len = strlen(p);
4097dd7cddfSDavid du Colombier }
4107dd7cddfSDavid du Colombier break;
4117dd7cddfSDavid du Colombier case Qunixheader:
41280ee5cbfSDavid du Colombier if(m->unixheader){
41380ee5cbfSDavid du Colombier p = s_to_c(m->unixheader);
41480ee5cbfSDavid du Colombier len = s_len(m->unixheader);
41580ee5cbfSDavid du Colombier }
4167dd7cddfSDavid du Colombier break;
4177dd7cddfSDavid du Colombier case Qdigest:
4187dd7cddfSDavid du Colombier if(m->sdigest){
4197dd7cddfSDavid du Colombier p = s_to_c(m->sdigest);
4207dd7cddfSDavid du Colombier len = strlen(p);
4217dd7cddfSDavid du Colombier }
4227dd7cddfSDavid du Colombier break;
4237dd7cddfSDavid du Colombier }
4247dd7cddfSDavid du Colombier *pp = p;
4257dd7cddfSDavid du Colombier return len;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier
4287dd7cddfSDavid du Colombier int infofields[] = {
4297dd7cddfSDavid du Colombier Qfrom,
4307dd7cddfSDavid du Colombier Qto,
4317dd7cddfSDavid du Colombier Qcc,
4327dd7cddfSDavid du Colombier Qreplyto,
4337dd7cddfSDavid du Colombier Qunixdate,
4347dd7cddfSDavid du Colombier Qsubject,
4357dd7cddfSDavid du Colombier Qtype,
4367dd7cddfSDavid du Colombier Qdisposition,
4377dd7cddfSDavid du Colombier Qfilename,
4387dd7cddfSDavid du Colombier Qdigest,
4397dd7cddfSDavid du Colombier Qbcc,
4407dd7cddfSDavid du Colombier Qinreplyto,
4417dd7cddfSDavid du Colombier Qdate,
4427dd7cddfSDavid du Colombier Qsender,
4437dd7cddfSDavid du Colombier Qmessageid,
4447dd7cddfSDavid du Colombier Qlines,
4457dd7cddfSDavid du Colombier -1,
4467dd7cddfSDavid du Colombier };
4477dd7cddfSDavid du Colombier
4487dd7cddfSDavid du Colombier static int
readinfo(Message * m,char * buf,long off,int count)4497dd7cddfSDavid du Colombier readinfo(Message *m, char *buf, long off, int count)
4507dd7cddfSDavid du Colombier {
4517dd7cddfSDavid du Colombier char *p;
4527dd7cddfSDavid du Colombier int len, i, n;
4537dd7cddfSDavid du Colombier String *s;
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier s = s_new();
4567dd7cddfSDavid du Colombier len = 0;
4577dd7cddfSDavid du Colombier for(i = 0; len < count && infofields[i] >= 0; i++){
4587dd7cddfSDavid du Colombier n = fileinfo(m, infofields[i], &p);
4595d459b5aSDavid du Colombier s = stringconvert(s, p, n);
4609a747e4fSDavid du Colombier s_append(s, "\n");
4617dd7cddfSDavid du Colombier p = s_to_c(s);
4627dd7cddfSDavid du Colombier n = strlen(p);
4637dd7cddfSDavid du Colombier if(off > 0){
4649a747e4fSDavid du Colombier if(off >= n){
4659a747e4fSDavid du Colombier off -= n;
4667dd7cddfSDavid du Colombier continue;
4677dd7cddfSDavid du Colombier }
4687dd7cddfSDavid du Colombier p += off;
4697dd7cddfSDavid du Colombier n -= off;
4707dd7cddfSDavid du Colombier off = 0;
4717dd7cddfSDavid du Colombier }
4727dd7cddfSDavid du Colombier if(n > count - len)
4737dd7cddfSDavid du Colombier n = count - len;
4747dd7cddfSDavid du Colombier if(buf)
4757dd7cddfSDavid du Colombier memmove(buf+len, p, n);
4767dd7cddfSDavid du Colombier len += n;
4777dd7cddfSDavid du Colombier }
4787dd7cddfSDavid du Colombier s_free(s);
4797dd7cddfSDavid du Colombier return len;
4807dd7cddfSDavid du Colombier }
4817dd7cddfSDavid du Colombier
4827dd7cddfSDavid du Colombier static void
mkstat(Dir * d,Mailbox * mb,Message * m,int t)4837dd7cddfSDavid du Colombier mkstat(Dir *d, Mailbox *mb, Message *m, int t)
4847dd7cddfSDavid du Colombier {
4857dd7cddfSDavid du Colombier char *p;
4867dd7cddfSDavid du Colombier
4879a747e4fSDavid du Colombier d->uid = user;
4889a747e4fSDavid du Colombier d->gid = user;
4899a747e4fSDavid du Colombier d->muid = user;
4907dd7cddfSDavid du Colombier d->mode = 0444;
4917dd7cddfSDavid du Colombier d->qid.vers = 0;
4929a747e4fSDavid du Colombier d->qid.type = QTFILE;
4937dd7cddfSDavid du Colombier d->type = 0;
4947dd7cddfSDavid du Colombier d->dev = 0;
4959a747e4fSDavid du Colombier if(mb != nil && mb->d != nil){
4969a747e4fSDavid du Colombier d->atime = mb->d->atime;
4979a747e4fSDavid du Colombier d->mtime = mb->d->mtime;
4989a747e4fSDavid du Colombier } else {
4999a747e4fSDavid du Colombier d->atime = time(0);
5009a747e4fSDavid du Colombier d->mtime = d->atime;
5019a747e4fSDavid du Colombier }
5027dd7cddfSDavid du Colombier
5037dd7cddfSDavid du Colombier switch(t){
5047dd7cddfSDavid du Colombier case Qtop:
5059a747e4fSDavid du Colombier d->name = ".";
5069a747e4fSDavid du Colombier d->mode = DMDIR|0555;
5077dd7cddfSDavid du Colombier d->atime = d->mtime = time(0);
5087dd7cddfSDavid du Colombier d->length = 0;
5099a747e4fSDavid du Colombier d->qid.path = PATH(0, Qtop);
5109a747e4fSDavid du Colombier d->qid.type = QTDIR;
5117dd7cddfSDavid du Colombier break;
5127dd7cddfSDavid du Colombier case Qmbox:
5139a747e4fSDavid du Colombier d->name = mb->name;
5149a747e4fSDavid du Colombier d->mode = DMDIR|0555;
5157dd7cddfSDavid du Colombier d->length = 0;
5169a747e4fSDavid du Colombier d->qid.path = PATH(mb->id, Qmbox);
5179a747e4fSDavid du Colombier d->qid.type = QTDIR;
5187dd7cddfSDavid du Colombier d->qid.vers = mb->vers;
5197dd7cddfSDavid du Colombier break;
5207dd7cddfSDavid du Colombier case Qdir:
5219a747e4fSDavid du Colombier d->name = m->name;
5229a747e4fSDavid du Colombier d->mode = DMDIR|0555;
5237dd7cddfSDavid du Colombier d->length = 0;
5249a747e4fSDavid du Colombier d->qid.path = PATH(m->id, Qdir);
5259a747e4fSDavid du Colombier d->qid.type = QTDIR;
5267dd7cddfSDavid du Colombier break;
5277dd7cddfSDavid du Colombier case Qctl:
5289a747e4fSDavid du Colombier d->name = dirtab[t];
5297dd7cddfSDavid du Colombier d->mode = 0666;
5307dd7cddfSDavid du Colombier d->atime = d->mtime = time(0);
5317dd7cddfSDavid du Colombier d->length = 0;
5327dd7cddfSDavid du Colombier d->qid.path = PATH(0, Qctl);
5337dd7cddfSDavid du Colombier break;
53480ee5cbfSDavid du Colombier case Qmboxctl:
5359a747e4fSDavid du Colombier d->name = dirtab[t];
53680ee5cbfSDavid du Colombier d->mode = 0222;
53780ee5cbfSDavid du Colombier d->atime = d->mtime = time(0);
53880ee5cbfSDavid du Colombier d->length = 0;
53980ee5cbfSDavid du Colombier d->qid.path = PATH(mb->id, Qmboxctl);
54080ee5cbfSDavid du Colombier break;
5417dd7cddfSDavid du Colombier case Qinfo:
5429a747e4fSDavid du Colombier d->name = dirtab[t];
5437dd7cddfSDavid du Colombier d->length = readinfo(m, nil, 0, 1<<30);
5447dd7cddfSDavid du Colombier d->qid.path = PATH(m->id, t);
5457dd7cddfSDavid du Colombier break;
5467dd7cddfSDavid du Colombier default:
5479a747e4fSDavid du Colombier d->name = dirtab[t];
5487dd7cddfSDavid du Colombier d->length = fileinfo(m, t, &p);
5497dd7cddfSDavid du Colombier d->qid.path = PATH(m->id, t);
5507dd7cddfSDavid du Colombier break;
5517dd7cddfSDavid du Colombier }
5527dd7cddfSDavid du Colombier }
5537dd7cddfSDavid du Colombier
5547dd7cddfSDavid du Colombier char*
rversion(Fid *)5559a747e4fSDavid du Colombier rversion(Fid*)
5567dd7cddfSDavid du Colombier {
5577dd7cddfSDavid du Colombier Fid *f;
5587dd7cddfSDavid du Colombier
5599a747e4fSDavid du Colombier if(thdr.msize < 256)
5609a747e4fSDavid du Colombier return "max messagesize too small";
5619a747e4fSDavid du Colombier if(thdr.msize < messagesize)
5629a747e4fSDavid du Colombier messagesize = thdr.msize;
5639a747e4fSDavid du Colombier rhdr.msize = messagesize;
5649a747e4fSDavid du Colombier if(strncmp(thdr.version, "9P2000", 6) != 0)
5659a747e4fSDavid du Colombier return "unknown 9P version";
5669a747e4fSDavid du Colombier else
5679a747e4fSDavid du Colombier rhdr.version = "9P2000";
5687dd7cddfSDavid du Colombier for(f = fids; f; f = f->next)
5697dd7cddfSDavid du Colombier if(f->busy)
5707dd7cddfSDavid du Colombier rclunk(f);
5719a747e4fSDavid du Colombier return nil;
5729a747e4fSDavid du Colombier }
5739a747e4fSDavid du Colombier
5749a747e4fSDavid du Colombier char*
rauth(Fid *)5759a747e4fSDavid du Colombier rauth(Fid*)
5769a747e4fSDavid du Colombier {
5773ff48bf5SDavid du Colombier return Enoauth;
5787dd7cddfSDavid du Colombier }
5797dd7cddfSDavid du Colombier
5807dd7cddfSDavid du Colombier char*
rflush(Fid * f)5817dd7cddfSDavid du Colombier rflush(Fid *f)
5827dd7cddfSDavid du Colombier {
5837dd7cddfSDavid du Colombier USED(f);
5847dd7cddfSDavid du Colombier return 0;
5857dd7cddfSDavid du Colombier }
5867dd7cddfSDavid du Colombier
5877dd7cddfSDavid du Colombier char*
rattach(Fid * f)5887dd7cddfSDavid du Colombier rattach(Fid *f)
5897dd7cddfSDavid du Colombier {
5907dd7cddfSDavid du Colombier f->busy = 1;
5917dd7cddfSDavid du Colombier f->m = nil;
5927dd7cddfSDavid du Colombier f->mb = nil;
5939a747e4fSDavid du Colombier f->qid.path = PATH(0, Qtop);
5949a747e4fSDavid du Colombier f->qid.type = QTDIR;
5957dd7cddfSDavid du Colombier f->qid.vers = 0;
5969a747e4fSDavid du Colombier rhdr.qid = f->qid;
5979a747e4fSDavid du Colombier if(strcmp(thdr.uname, user) != 0)
5987dd7cddfSDavid du Colombier return Eperm;
5997dd7cddfSDavid du Colombier return 0;
6007dd7cddfSDavid du Colombier }
6017dd7cddfSDavid du Colombier
6029a747e4fSDavid du Colombier static Fid*
doclone(Fid * f,int nfid)6039a747e4fSDavid du Colombier doclone(Fid *f, int nfid)
6047dd7cddfSDavid du Colombier {
6057dd7cddfSDavid du Colombier Fid *nf;
6067dd7cddfSDavid du Colombier
6079a747e4fSDavid du Colombier nf = newfid(nfid);
6089a747e4fSDavid du Colombier if(nf->busy)
6099a747e4fSDavid du Colombier return nil;
6107dd7cddfSDavid du Colombier nf->busy = 1;
6117dd7cddfSDavid du Colombier nf->open = 0;
6127dd7cddfSDavid du Colombier nf->m = f->m;
6137dd7cddfSDavid du Colombier nf->mtop = f->mtop;
6147dd7cddfSDavid du Colombier nf->mb = f->mb;
6157dd7cddfSDavid du Colombier if(f->mb != nil)
6167dd7cddfSDavid du Colombier mboxincref(f->mb);
6177dd7cddfSDavid du Colombier if(f->mtop != nil){
6187dd7cddfSDavid du Colombier qlock(f->mb);
6197dd7cddfSDavid du Colombier msgincref(f->mtop);
6207dd7cddfSDavid du Colombier qunlock(f->mb);
6217dd7cddfSDavid du Colombier }
6227dd7cddfSDavid du Colombier nf->qid = f->qid;
6239a747e4fSDavid du Colombier return nf;
6247dd7cddfSDavid du Colombier }
6257dd7cddfSDavid du Colombier
6267dd7cddfSDavid du Colombier char*
dowalk(Fid * f,char * name)6279a747e4fSDavid du Colombier dowalk(Fid *f, char *name)
6287dd7cddfSDavid du Colombier {
6297dd7cddfSDavid du Colombier int t;
6307dd7cddfSDavid du Colombier Mailbox *omb, *mb;
6317dd7cddfSDavid du Colombier char *rv, *p;
6327dd7cddfSDavid du Colombier Hash *h;
6337dd7cddfSDavid du Colombier
6347dd7cddfSDavid du Colombier t = FILE(f->qid.path);
6357dd7cddfSDavid du Colombier
6367dd7cddfSDavid du Colombier rv = Enotexist;
6377dd7cddfSDavid du Colombier
6387dd7cddfSDavid du Colombier omb = f->mb;
6397dd7cddfSDavid du Colombier if(omb)
6407dd7cddfSDavid du Colombier qlock(omb);
6417dd7cddfSDavid du Colombier else
6427dd7cddfSDavid du Colombier qlock(&mbllock);
6437dd7cddfSDavid du Colombier
6447dd7cddfSDavid du Colombier // this must catch everything except . and ..
6457dd7cddfSDavid du Colombier retry:
6467dd7cddfSDavid du Colombier h = hlook(f->qid.path, name);
6477dd7cddfSDavid du Colombier if(h != nil){
6487dd7cddfSDavid du Colombier f->mb = h->mb;
6497dd7cddfSDavid du Colombier f->m = h->m;
6507dd7cddfSDavid du Colombier switch(t){
6517dd7cddfSDavid du Colombier case Qtop:
6527dd7cddfSDavid du Colombier if(f->mb != nil)
6537dd7cddfSDavid du Colombier mboxincref(f->mb);
6547dd7cddfSDavid du Colombier break;
6557dd7cddfSDavid du Colombier case Qmbox:
65680ee5cbfSDavid du Colombier if(f->m){
6577dd7cddfSDavid du Colombier msgincref(f->m);
6587dd7cddfSDavid du Colombier f->mtop = f->m;
65980ee5cbfSDavid du Colombier }
6607dd7cddfSDavid du Colombier break;
6617dd7cddfSDavid du Colombier }
6627dd7cddfSDavid du Colombier f->qid = h->qid;
6637dd7cddfSDavid du Colombier rv = nil;
6647dd7cddfSDavid du Colombier } else if((p = strchr(name, '.')) != nil && *name != '.'){
6657dd7cddfSDavid du Colombier *p = 0;
6667dd7cddfSDavid du Colombier goto retry;
6677dd7cddfSDavid du Colombier }
6687dd7cddfSDavid du Colombier
6697dd7cddfSDavid du Colombier if(omb)
6707dd7cddfSDavid du Colombier qunlock(omb);
6717dd7cddfSDavid du Colombier else
6727dd7cddfSDavid du Colombier qunlock(&mbllock);
6737dd7cddfSDavid du Colombier if(rv == nil)
6747dd7cddfSDavid du Colombier return rv;
6757dd7cddfSDavid du Colombier
6769a747e4fSDavid du Colombier if(strcmp(name, ".") == 0)
6777dd7cddfSDavid du Colombier return nil;
6787dd7cddfSDavid du Colombier
6799a747e4fSDavid du Colombier if(f->qid.type != QTDIR)
6807dd7cddfSDavid du Colombier return Enotdir;
6817dd7cddfSDavid du Colombier
6827dd7cddfSDavid du Colombier if(strcmp(name, "..") == 0){
6837dd7cddfSDavid du Colombier switch(t){
6847dd7cddfSDavid du Colombier case Qtop:
6859a747e4fSDavid du Colombier f->qid.path = PATH(0, Qtop);
6869a747e4fSDavid du Colombier f->qid.type = QTDIR;
6877dd7cddfSDavid du Colombier f->qid.vers = 0;
6887dd7cddfSDavid du Colombier break;
6897dd7cddfSDavid du Colombier case Qmbox:
6909a747e4fSDavid du Colombier f->qid.path = PATH(0, Qtop);
6919a747e4fSDavid du Colombier f->qid.type = QTDIR;
6927dd7cddfSDavid du Colombier f->qid.vers = 0;
6937dd7cddfSDavid du Colombier qlock(&mbllock);
6947dd7cddfSDavid du Colombier mb = f->mb;
6957dd7cddfSDavid du Colombier f->mb = nil;
6967dd7cddfSDavid du Colombier mboxdecref(mb);
6977dd7cddfSDavid du Colombier qunlock(&mbllock);
6987dd7cddfSDavid du Colombier break;
6997dd7cddfSDavid du Colombier case Qdir:
7007dd7cddfSDavid du Colombier qlock(f->mb);
7017dd7cddfSDavid du Colombier if(f->m->whole == f->mb->root){
7029a747e4fSDavid du Colombier f->qid.path = PATH(f->mb->id, Qmbox);
7039a747e4fSDavid du Colombier f->qid.type = QTDIR;
7049a747e4fSDavid du Colombier f->qid.vers = f->mb->d->qid.vers;
7057dd7cddfSDavid du Colombier msgdecref(f->mb, f->mtop);
7067dd7cddfSDavid du Colombier f->m = f->mtop = nil;
7077dd7cddfSDavid du Colombier } else {
7087dd7cddfSDavid du Colombier f->m = f->m->whole;
7099a747e4fSDavid du Colombier f->qid.path = PATH(f->m->id, Qdir);
7109a747e4fSDavid du Colombier f->qid.type = QTDIR;
7117dd7cddfSDavid du Colombier }
7127dd7cddfSDavid du Colombier qunlock(f->mb);
7137dd7cddfSDavid du Colombier break;
7147dd7cddfSDavid du Colombier }
7157dd7cddfSDavid du Colombier rv = nil;
7167dd7cddfSDavid du Colombier }
7177dd7cddfSDavid du Colombier return rv;
7187dd7cddfSDavid du Colombier }
7197dd7cddfSDavid du Colombier
7207dd7cddfSDavid du Colombier char*
rwalk(Fid * f)7219a747e4fSDavid du Colombier rwalk(Fid *f)
7227dd7cddfSDavid du Colombier {
7237dd7cddfSDavid du Colombier Fid *nf;
7249a747e4fSDavid du Colombier char *rv;
7259a747e4fSDavid du Colombier int i;
7267dd7cddfSDavid du Colombier
7279a747e4fSDavid du Colombier if(f->open)
7289a747e4fSDavid du Colombier return Eisopen;
7299a747e4fSDavid du Colombier
7309a747e4fSDavid du Colombier rhdr.nwqid = 0;
7319a747e4fSDavid du Colombier nf = nil;
7329a747e4fSDavid du Colombier
7339a747e4fSDavid du Colombier /* clone if requested */
7349a747e4fSDavid du Colombier if(thdr.newfid != thdr.fid){
7359a747e4fSDavid du Colombier nf = doclone(f, thdr.newfid);
7369a747e4fSDavid du Colombier if(nf == nil)
7379a747e4fSDavid du Colombier return "new fid in use";
7389a747e4fSDavid du Colombier f = nf;
7397dd7cddfSDavid du Colombier }
7409a747e4fSDavid du Colombier
7419a747e4fSDavid du Colombier /* if it's just a clone, return */
7429a747e4fSDavid du Colombier if(thdr.nwname == 0 && nf != nil)
7439a747e4fSDavid du Colombier return nil;
7449a747e4fSDavid du Colombier
7459a747e4fSDavid du Colombier /* walk each element */
7469a747e4fSDavid du Colombier rv = nil;
7479a747e4fSDavid du Colombier for(i = 0; i < thdr.nwname; i++){
7489a747e4fSDavid du Colombier rv = dowalk(f, thdr.wname[i]);
7499a747e4fSDavid du Colombier if(rv != nil){
7509a747e4fSDavid du Colombier if(nf != nil)
7517dd7cddfSDavid du Colombier rclunk(nf);
7529a747e4fSDavid du Colombier break;
7539a747e4fSDavid du Colombier }
7549a747e4fSDavid du Colombier rhdr.wqid[i] = f->qid;
7559a747e4fSDavid du Colombier }
7569a747e4fSDavid du Colombier rhdr.nwqid = i;
7579a747e4fSDavid du Colombier
7589a747e4fSDavid du Colombier /* we only error out if no walk */
7599a747e4fSDavid du Colombier if(i > 0)
7609a747e4fSDavid du Colombier rv = nil;
7619a747e4fSDavid du Colombier
7629a747e4fSDavid du Colombier return rv;
7637dd7cddfSDavid du Colombier }
7647dd7cddfSDavid du Colombier
7657dd7cddfSDavid du Colombier char *
ropen(Fid * f)7667dd7cddfSDavid du Colombier ropen(Fid *f)
7677dd7cddfSDavid du Colombier {
76880ee5cbfSDavid du Colombier int file;
76980ee5cbfSDavid du Colombier
7707dd7cddfSDavid du Colombier if(f->open)
7717dd7cddfSDavid du Colombier return Eisopen;
7727dd7cddfSDavid du Colombier
77380ee5cbfSDavid du Colombier file = FILE(f->qid.path);
7749a747e4fSDavid du Colombier if(thdr.mode != OREAD)
77580ee5cbfSDavid du Colombier if(file != Qctl && file != Qmboxctl)
7767dd7cddfSDavid du Colombier return Eperm;
7777dd7cddfSDavid du Colombier
7787dd7cddfSDavid du Colombier // make sure we've decoded
77980ee5cbfSDavid du Colombier if(file == Qbody){
7807dd7cddfSDavid du Colombier if(f->m->decoded == 0)
7817dd7cddfSDavid du Colombier decode(f->m);
7827dd7cddfSDavid du Colombier if(f->m->converted == 0)
7837dd7cddfSDavid du Colombier convert(f->m);
7847dd7cddfSDavid du Colombier }
7857dd7cddfSDavid du Colombier
7869a747e4fSDavid du Colombier rhdr.iounit = 0;
7879a747e4fSDavid du Colombier rhdr.qid = f->qid;
7887dd7cddfSDavid du Colombier f->open = 1;
7897dd7cddfSDavid du Colombier return 0;
7907dd7cddfSDavid du Colombier }
7917dd7cddfSDavid du Colombier
7927dd7cddfSDavid du Colombier char *
rcreate(Fid *)7937dd7cddfSDavid du Colombier rcreate(Fid*)
7947dd7cddfSDavid du Colombier {
7957dd7cddfSDavid du Colombier return Eperm;
7967dd7cddfSDavid du Colombier }
7977dd7cddfSDavid du Colombier
7987dd7cddfSDavid du Colombier int
readtopdir(Fid *,uchar * buf,long off,int cnt,int blen)7999a747e4fSDavid du Colombier readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
8007dd7cddfSDavid du Colombier {
8017dd7cddfSDavid du Colombier Dir d;
8029a747e4fSDavid du Colombier int m, n;
8039a747e4fSDavid du Colombier long pos;
8047dd7cddfSDavid du Colombier Mailbox *mb;
8057dd7cddfSDavid du Colombier
8067dd7cddfSDavid du Colombier n = 0;
8079a747e4fSDavid du Colombier pos = 0;
8087dd7cddfSDavid du Colombier mkstat(&d, nil, nil, Qctl);
8099a747e4fSDavid du Colombier m = convD2M(&d, &buf[n], blen);
8109a747e4fSDavid du Colombier if(off <= pos){
8119a747e4fSDavid du Colombier if(m <= BIT16SZ || m > cnt)
8129a747e4fSDavid du Colombier return 0;
8139a747e4fSDavid du Colombier n += m;
8149a747e4fSDavid du Colombier cnt -= m;
8157dd7cddfSDavid du Colombier }
8169a747e4fSDavid du Colombier pos += m;
8179a747e4fSDavid du Colombier
8189a747e4fSDavid du Colombier for(mb = mbl; mb != nil; mb = mb->next){
8197dd7cddfSDavid du Colombier mkstat(&d, mb, nil, Qmbox);
8209a747e4fSDavid du Colombier m = convD2M(&d, &buf[n], blen-n);
8219a747e4fSDavid du Colombier if(off <= pos){
8229a747e4fSDavid du Colombier if(m <= BIT16SZ || m > cnt)
8239a747e4fSDavid du Colombier break;
8249a747e4fSDavid du Colombier n += m;
8259a747e4fSDavid du Colombier cnt -= m;
8269a747e4fSDavid du Colombier }
8279a747e4fSDavid du Colombier pos += m;
8287dd7cddfSDavid du Colombier }
8297dd7cddfSDavid du Colombier return n;
8307dd7cddfSDavid du Colombier }
8317dd7cddfSDavid du Colombier
8327dd7cddfSDavid du Colombier int
readmboxdir(Fid * f,uchar * buf,long off,int cnt,int blen)8339a747e4fSDavid du Colombier readmboxdir(Fid *f, uchar *buf, long off, int cnt, int blen)
8347dd7cddfSDavid du Colombier {
8357dd7cddfSDavid du Colombier Dir d;
8369a747e4fSDavid du Colombier int n, m;
8377dd7cddfSDavid du Colombier long pos;
8389a747e4fSDavid du Colombier Message *msg;
8397dd7cddfSDavid du Colombier
84080ee5cbfSDavid du Colombier n = 0;
84180ee5cbfSDavid du Colombier if(f->mb->ctl){
84280ee5cbfSDavid du Colombier mkstat(&d, f->mb, nil, Qmboxctl);
8439a747e4fSDavid du Colombier m = convD2M(&d, &buf[n], blen);
8449a747e4fSDavid du Colombier if(off == 0){
8459a747e4fSDavid du Colombier if(m <= BIT16SZ || m > cnt){
8469a747e4fSDavid du Colombier f->fptr = nil;
8479a747e4fSDavid du Colombier return 0;
8489a747e4fSDavid du Colombier }
8499a747e4fSDavid du Colombier n += m;
8509a747e4fSDavid du Colombier cnt -= m;
85180ee5cbfSDavid du Colombier } else
8529a747e4fSDavid du Colombier off -= m;
85380ee5cbfSDavid du Colombier }
85480ee5cbfSDavid du Colombier
8557dd7cddfSDavid du Colombier // to avoid n**2 reads of the directory, use a saved finger pointer
8569a747e4fSDavid du Colombier if(f->mb->vers == f->fvers && off >= f->foff && f->fptr != nil){
8579a747e4fSDavid du Colombier msg = f->fptr;
8587dd7cddfSDavid du Colombier pos = f->foff;
8597dd7cddfSDavid du Colombier } else {
8609a747e4fSDavid du Colombier msg = f->mb->root->part;
8617dd7cddfSDavid du Colombier pos = 0;
8627dd7cddfSDavid du Colombier }
8637dd7cddfSDavid du Colombier
8649a747e4fSDavid du Colombier for(; cnt > 0 && msg != nil; msg = msg->next){
8657dd7cddfSDavid du Colombier // act like deleted files aren't there
8669a747e4fSDavid du Colombier if(msg->deleted)
8677dd7cddfSDavid du Colombier continue;
8687dd7cddfSDavid du Colombier
8699a747e4fSDavid du Colombier mkstat(&d, f->mb, msg, Qdir);
8709a747e4fSDavid du Colombier m = convD2M(&d, &buf[n], blen-n);
8719a747e4fSDavid du Colombier if(off <= pos){
8729a747e4fSDavid du Colombier if(m <= BIT16SZ || m > cnt)
8739a747e4fSDavid du Colombier break;
8749a747e4fSDavid du Colombier n += m;
8759a747e4fSDavid du Colombier cnt -= m;
8767dd7cddfSDavid du Colombier }
8779a747e4fSDavid du Colombier pos += m;
8787dd7cddfSDavid du Colombier }
8797dd7cddfSDavid du Colombier
8807dd7cddfSDavid du Colombier // save a finger pointer for next read of the mbox directory
8817dd7cddfSDavid du Colombier f->foff = pos;
8829a747e4fSDavid du Colombier f->fptr = msg;
8837dd7cddfSDavid du Colombier f->fvers = f->mb->vers;
8847dd7cddfSDavid du Colombier
8857dd7cddfSDavid du Colombier return n;
8867dd7cddfSDavid du Colombier }
8877dd7cddfSDavid du Colombier
8887dd7cddfSDavid du Colombier int
readmsgdir(Fid * f,uchar * buf,long off,int cnt,int blen)8899a747e4fSDavid du Colombier readmsgdir(Fid *f, uchar *buf, long off, int cnt, int blen)
8907dd7cddfSDavid du Colombier {
8917dd7cddfSDavid du Colombier Dir d;
8929a747e4fSDavid du Colombier int i, n, m;
8939a747e4fSDavid du Colombier long pos;
8949a747e4fSDavid du Colombier Message *msg;
8957dd7cddfSDavid du Colombier
8967dd7cddfSDavid du Colombier n = 0;
8979a747e4fSDavid du Colombier pos = 0;
8989a747e4fSDavid du Colombier for(i = 0; i < Qmax; i++){
8997dd7cddfSDavid du Colombier mkstat(&d, f->mb, f->m, i);
9009a747e4fSDavid du Colombier m = convD2M(&d, &buf[n], blen-n);
9019a747e4fSDavid du Colombier if(off <= pos){
9029a747e4fSDavid du Colombier if(m <= BIT16SZ || m > cnt)
9039a747e4fSDavid du Colombier return n;
9049a747e4fSDavid du Colombier n += m;
9059a747e4fSDavid du Colombier cnt -= m;
9067dd7cddfSDavid du Colombier }
9079a747e4fSDavid du Colombier pos += m;
9087dd7cddfSDavid du Colombier }
9099a747e4fSDavid du Colombier for(msg = f->m->part; msg != nil; msg = msg->next){
9109a747e4fSDavid du Colombier mkstat(&d, f->mb, msg, Qdir);
9119a747e4fSDavid du Colombier m = convD2M(&d, &buf[n], blen-n);
9129a747e4fSDavid du Colombier if(off <= pos){
9139a747e4fSDavid du Colombier if(m <= BIT16SZ || m > cnt)
9149a747e4fSDavid du Colombier break;
9159a747e4fSDavid du Colombier n += m;
9169a747e4fSDavid du Colombier cnt -= m;
9179a747e4fSDavid du Colombier }
9189a747e4fSDavid du Colombier pos += m;
9197dd7cddfSDavid du Colombier }
9207dd7cddfSDavid du Colombier
9217dd7cddfSDavid du Colombier return n;
9227dd7cddfSDavid du Colombier }
9237dd7cddfSDavid du Colombier
9247dd7cddfSDavid du Colombier char*
rread(Fid * f)9257dd7cddfSDavid du Colombier rread(Fid *f)
9267dd7cddfSDavid du Colombier {
9277dd7cddfSDavid du Colombier long off;
9287dd7cddfSDavid du Colombier int t, i, n, cnt;
9297dd7cddfSDavid du Colombier char *p;
9307dd7cddfSDavid du Colombier
9319a747e4fSDavid du Colombier rhdr.count = 0;
9329a747e4fSDavid du Colombier off = thdr.offset;
9339a747e4fSDavid du Colombier cnt = thdr.count;
9349a747e4fSDavid du Colombier
9359a747e4fSDavid du Colombier if(cnt > messagesize - IOHDRSZ)
9369a747e4fSDavid du Colombier cnt = messagesize - IOHDRSZ;
9379a747e4fSDavid du Colombier
9389a747e4fSDavid du Colombier rhdr.data = (char*)mbuf;
9397dd7cddfSDavid du Colombier
9407dd7cddfSDavid du Colombier t = FILE(f->qid.path);
9419a747e4fSDavid du Colombier if(f->qid.type & QTDIR){
9427dd7cddfSDavid du Colombier if(t == Qtop) {
9437dd7cddfSDavid du Colombier qlock(&mbllock);
9449a747e4fSDavid du Colombier n = readtopdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
9457dd7cddfSDavid du Colombier qunlock(&mbllock);
9467dd7cddfSDavid du Colombier } else if(t == Qmbox) {
9477dd7cddfSDavid du Colombier qlock(f->mb);
9487dd7cddfSDavid du Colombier if(off == 0)
9497dd7cddfSDavid du Colombier syncmbox(f->mb, 1);
9509a747e4fSDavid du Colombier n = readmboxdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
9517dd7cddfSDavid du Colombier qunlock(f->mb);
95280ee5cbfSDavid du Colombier } else if(t == Qmboxctl) {
95380ee5cbfSDavid du Colombier n = 0;
9547dd7cddfSDavid du Colombier } else {
9559a747e4fSDavid du Colombier n = readmsgdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
9567dd7cddfSDavid du Colombier }
9577dd7cddfSDavid du Colombier
9589a747e4fSDavid du Colombier rhdr.count = n;
9597dd7cddfSDavid du Colombier return nil;
9607dd7cddfSDavid du Colombier }
9617dd7cddfSDavid du Colombier
9627dd7cddfSDavid du Colombier if(FILE(f->qid.path) == Qheader){
9639a747e4fSDavid du Colombier rhdr.count = readheader(f->m, (char*)mbuf, off, cnt);
9647dd7cddfSDavid du Colombier return nil;
9657dd7cddfSDavid du Colombier }
9667dd7cddfSDavid du Colombier
9677dd7cddfSDavid du Colombier if(FILE(f->qid.path) == Qinfo){
9689a747e4fSDavid du Colombier rhdr.count = readinfo(f->m, (char*)mbuf, off, cnt);
9697dd7cddfSDavid du Colombier return nil;
9707dd7cddfSDavid du Colombier }
9717dd7cddfSDavid du Colombier
9727dd7cddfSDavid du Colombier i = fileinfo(f->m, FILE(f->qid.path), &p);
9737dd7cddfSDavid du Colombier if(off < i){
9747dd7cddfSDavid du Colombier if((off + cnt) > i)
9757dd7cddfSDavid du Colombier cnt = i - off;
9769a747e4fSDavid du Colombier memmove(mbuf, p + off, cnt);
9779a747e4fSDavid du Colombier rhdr.count = cnt;
9787dd7cddfSDavid du Colombier }
9797dd7cddfSDavid du Colombier return nil;
9807dd7cddfSDavid du Colombier }
9817dd7cddfSDavid du Colombier
9827dd7cddfSDavid du Colombier char*
rwrite(Fid * f)9837dd7cddfSDavid du Colombier rwrite(Fid *f)
9847dd7cddfSDavid du Colombier {
9857dd7cddfSDavid du Colombier char *err;
9867dd7cddfSDavid du Colombier char *token[1024];
9877dd7cddfSDavid du Colombier int t, n;
9887dd7cddfSDavid du Colombier String *file;
9897dd7cddfSDavid du Colombier
9907dd7cddfSDavid du Colombier t = FILE(f->qid.path);
9919a747e4fSDavid du Colombier rhdr.count = thdr.count;
9927dd7cddfSDavid du Colombier switch(t){
9937dd7cddfSDavid du Colombier case Qctl:
9949a747e4fSDavid du Colombier if(thdr.count == 0)
9957dd7cddfSDavid du Colombier return Ebadctl;
9969a747e4fSDavid du Colombier if(thdr.data[thdr.count-1] == '\n')
9979a747e4fSDavid du Colombier thdr.data[thdr.count-1] = 0;
9987dd7cddfSDavid du Colombier else
9999a747e4fSDavid du Colombier thdr.data[thdr.count] = 0;
10009a747e4fSDavid du Colombier n = tokenize(thdr.data, token, nelem(token));
10017dd7cddfSDavid du Colombier if(n == 0)
10027dd7cddfSDavid du Colombier return Ebadctl;
10037dd7cddfSDavid du Colombier if(strcmp(token[0], "open") == 0){
10047dd7cddfSDavid du Colombier file = s_new();
10057dd7cddfSDavid du Colombier switch(n){
10067dd7cddfSDavid du Colombier case 1:
10077dd7cddfSDavid du Colombier err = Ebadctl;
10087dd7cddfSDavid du Colombier break;
10097dd7cddfSDavid du Colombier case 2:
10107dd7cddfSDavid du Colombier mboxpath(token[1], getlog(), file, 0);
10117dd7cddfSDavid du Colombier err = newmbox(s_to_c(file), nil, 0);
10127dd7cddfSDavid du Colombier break;
10137dd7cddfSDavid du Colombier default:
10147dd7cddfSDavid du Colombier mboxpath(token[1], getlog(), file, 0);
101580ee5cbfSDavid du Colombier if(strchr(token[2], '/') != nil)
101680ee5cbfSDavid du Colombier err = "/ not allowed in mailbox name";
101780ee5cbfSDavid du Colombier else
10187dd7cddfSDavid du Colombier err = newmbox(s_to_c(file), token[2], 0);
10197dd7cddfSDavid du Colombier break;
10207dd7cddfSDavid du Colombier }
10217dd7cddfSDavid du Colombier s_free(file);
10227dd7cddfSDavid du Colombier return err;
10237dd7cddfSDavid du Colombier }
10247dd7cddfSDavid du Colombier if(strcmp(token[0], "close") == 0){
10257dd7cddfSDavid du Colombier if(n < 2)
10267dd7cddfSDavid du Colombier return nil;
10277dd7cddfSDavid du Colombier freembox(token[1]);
10287dd7cddfSDavid du Colombier return nil;
10297dd7cddfSDavid du Colombier }
10307dd7cddfSDavid du Colombier if(strcmp(token[0], "delete") == 0){
10317dd7cddfSDavid du Colombier if(n < 3)
10327dd7cddfSDavid du Colombier return nil;
10337dd7cddfSDavid du Colombier delmessages(n-1, &token[1]);
10347dd7cddfSDavid du Colombier return nil;
10357dd7cddfSDavid du Colombier }
10367dd7cddfSDavid du Colombier return Ebadctl;
103780ee5cbfSDavid du Colombier case Qmboxctl:
103880ee5cbfSDavid du Colombier if(f->mb && f->mb->ctl){
10399a747e4fSDavid du Colombier if(thdr.count == 0)
104080ee5cbfSDavid du Colombier return Ebadctl;
10419a747e4fSDavid du Colombier if(thdr.data[thdr.count-1] == '\n')
10429a747e4fSDavid du Colombier thdr.data[thdr.count-1] = 0;
104380ee5cbfSDavid du Colombier else
10449a747e4fSDavid du Colombier thdr.data[thdr.count] = 0;
10459a747e4fSDavid du Colombier n = tokenize(thdr.data, token, nelem(token));
104680ee5cbfSDavid du Colombier if(n == 0)
104780ee5cbfSDavid du Colombier return Ebadctl;
104880ee5cbfSDavid du Colombier return (*f->mb->ctl)(f->mb, n, token);
104980ee5cbfSDavid du Colombier }
10507dd7cddfSDavid du Colombier }
10517dd7cddfSDavid du Colombier return Eperm;
10527dd7cddfSDavid du Colombier }
10537dd7cddfSDavid du Colombier
10547dd7cddfSDavid du Colombier char *
rclunk(Fid * f)10557dd7cddfSDavid du Colombier rclunk(Fid *f)
10567dd7cddfSDavid du Colombier {
10577dd7cddfSDavid du Colombier Mailbox *mb;
10587dd7cddfSDavid du Colombier
10597dd7cddfSDavid du Colombier f->busy = 0;
10607dd7cddfSDavid du Colombier f->open = 0;
10617dd7cddfSDavid du Colombier if(f->mtop != nil){
10627dd7cddfSDavid du Colombier qlock(f->mb);
10637dd7cddfSDavid du Colombier msgdecref(f->mb, f->mtop);
10647dd7cddfSDavid du Colombier qunlock(f->mb);
10657dd7cddfSDavid du Colombier }
10667dd7cddfSDavid du Colombier f->m = f->mtop = nil;
10677dd7cddfSDavid du Colombier mb = f->mb;
10687dd7cddfSDavid du Colombier if(mb != nil){
10697dd7cddfSDavid du Colombier f->mb = nil;
10709a747e4fSDavid du Colombier assert(mb->refs > 0);
10717dd7cddfSDavid du Colombier qlock(&mbllock);
10727dd7cddfSDavid du Colombier mboxdecref(mb);
10737dd7cddfSDavid du Colombier qunlock(&mbllock);
10747dd7cddfSDavid du Colombier }
10755d459b5aSDavid du Colombier f->fid = -1;
10767dd7cddfSDavid du Colombier return 0;
10777dd7cddfSDavid du Colombier }
10787dd7cddfSDavid du Colombier
10797dd7cddfSDavid du Colombier char *
rremove(Fid * f)10807dd7cddfSDavid du Colombier rremove(Fid *f)
10817dd7cddfSDavid du Colombier {
10829a747e4fSDavid du Colombier if(f->m != nil){
10837dd7cddfSDavid du Colombier if(f->m->deleted == 0)
10847dd7cddfSDavid du Colombier mailplumb(f->mb, f->m, 1);
10857dd7cddfSDavid du Colombier f->m->deleted = 1;
10869a747e4fSDavid du Colombier }
10877dd7cddfSDavid du Colombier return rclunk(f);
10887dd7cddfSDavid du Colombier }
10897dd7cddfSDavid du Colombier
10907dd7cddfSDavid du Colombier char *
rstat(Fid * f)10917dd7cddfSDavid du Colombier rstat(Fid *f)
10927dd7cddfSDavid du Colombier {
10937dd7cddfSDavid du Colombier Dir d;
10947dd7cddfSDavid du Colombier
10957dd7cddfSDavid du Colombier if(FILE(f->qid.path) == Qmbox){
10967dd7cddfSDavid du Colombier qlock(f->mb);
10977dd7cddfSDavid du Colombier syncmbox(f->mb, 1);
10987dd7cddfSDavid du Colombier qunlock(f->mb);
10997dd7cddfSDavid du Colombier }
11007dd7cddfSDavid du Colombier mkstat(&d, f->mb, f->m, FILE(f->qid.path));
11019a747e4fSDavid du Colombier rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ);
11029a747e4fSDavid du Colombier rhdr.stat = mbuf;
11037dd7cddfSDavid du Colombier return 0;
11047dd7cddfSDavid du Colombier }
11057dd7cddfSDavid du Colombier
11067dd7cddfSDavid du Colombier char *
rwstat(Fid *)11077dd7cddfSDavid du Colombier rwstat(Fid*)
11087dd7cddfSDavid du Colombier {
11097dd7cddfSDavid du Colombier return Eperm;
11107dd7cddfSDavid du Colombier }
11117dd7cddfSDavid du Colombier
11127dd7cddfSDavid du Colombier Fid *
newfid(int fid)11137dd7cddfSDavid du Colombier newfid(int fid)
11147dd7cddfSDavid du Colombier {
11157dd7cddfSDavid du Colombier Fid *f, *ff;
11167dd7cddfSDavid du Colombier
11177dd7cddfSDavid du Colombier ff = 0;
11187dd7cddfSDavid du Colombier for(f = fids; f; f = f->next)
11197dd7cddfSDavid du Colombier if(f->fid == fid)
11207dd7cddfSDavid du Colombier return f;
11217dd7cddfSDavid du Colombier else if(!ff && !f->busy)
11227dd7cddfSDavid du Colombier ff = f;
11237dd7cddfSDavid du Colombier if(ff){
11247dd7cddfSDavid du Colombier ff->fid = fid;
11259a747e4fSDavid du Colombier ff->fptr = nil;
11267dd7cddfSDavid du Colombier return ff;
11277dd7cddfSDavid du Colombier }
11287dd7cddfSDavid du Colombier f = emalloc(sizeof *f);
11297dd7cddfSDavid du Colombier f->fid = fid;
11309a747e4fSDavid du Colombier f->fptr = nil;
11317dd7cddfSDavid du Colombier f->next = fids;
11327dd7cddfSDavid du Colombier fids = f;
11337dd7cddfSDavid du Colombier return f;
11347dd7cddfSDavid du Colombier }
11357dd7cddfSDavid du Colombier
11367dd7cddfSDavid du Colombier int
fidmboxrefs(Mailbox * mb)11377dd7cddfSDavid du Colombier fidmboxrefs(Mailbox *mb)
11387dd7cddfSDavid du Colombier {
11397dd7cddfSDavid du Colombier Fid *f;
11407dd7cddfSDavid du Colombier int refs = 0;
11417dd7cddfSDavid du Colombier
11427dd7cddfSDavid du Colombier for(f = fids; f; f = f->next){
11437dd7cddfSDavid du Colombier if(f->mb == mb)
11447dd7cddfSDavid du Colombier refs++;
11457dd7cddfSDavid du Colombier }
11467dd7cddfSDavid du Colombier return refs;
11477dd7cddfSDavid du Colombier }
11487dd7cddfSDavid du Colombier
11497dd7cddfSDavid du Colombier void
io(void)11507dd7cddfSDavid du Colombier io(void)
11517dd7cddfSDavid du Colombier {
11527dd7cddfSDavid du Colombier char *err;
11537dd7cddfSDavid du Colombier int n;
11547dd7cddfSDavid du Colombier
11559a747e4fSDavid du Colombier /* start a process to watch the mailboxes*/
115659cc4ca5SDavid du Colombier if(plumbing){
11577dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFMEM)){
11587dd7cddfSDavid du Colombier case -1:
11597dd7cddfSDavid du Colombier /* oh well */
11607dd7cddfSDavid du Colombier break;
11617dd7cddfSDavid du Colombier case 0:
11627dd7cddfSDavid du Colombier reader();
11637dd7cddfSDavid du Colombier exits(nil);
11647dd7cddfSDavid du Colombier default:
11657dd7cddfSDavid du Colombier break;
11667dd7cddfSDavid du Colombier }
116759cc4ca5SDavid du Colombier }
11687dd7cddfSDavid du Colombier
11697dd7cddfSDavid du Colombier for(;;){
11707dd7cddfSDavid du Colombier /*
11717dd7cddfSDavid du Colombier * reading from a pipe or a network device
11727dd7cddfSDavid du Colombier * will give an error after a few eof reads
11737dd7cddfSDavid du Colombier * however, we cannot tell the difference
11747dd7cddfSDavid du Colombier * between a zero-length read and an interrupt
11757dd7cddfSDavid du Colombier * on the processes writing to us,
11767dd7cddfSDavid du Colombier * so we wait for the error
11777dd7cddfSDavid du Colombier */
11785d459b5aSDavid du Colombier checkmboxrefs();
11799a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, messagesize);
11807dd7cddfSDavid du Colombier if(n == 0)
11817dd7cddfSDavid du Colombier continue;
11827dd7cddfSDavid du Colombier if(n < 0)
11837dd7cddfSDavid du Colombier return;
11849a747e4fSDavid du Colombier if(convM2S(mdata, n, &thdr) == 0)
11857dd7cddfSDavid du Colombier continue;
11867dd7cddfSDavid du Colombier
11877dd7cddfSDavid du Colombier if(debug)
11889a747e4fSDavid du Colombier fprint(2, "%s:<-%F\n", argv0, &thdr);
11897dd7cddfSDavid du Colombier
11909a747e4fSDavid du Colombier rhdr.data = (char*)mdata + messagesize;
11919a747e4fSDavid du Colombier if(!fcalls[thdr.type])
11927dd7cddfSDavid du Colombier err = "bad fcall type";
11937dd7cddfSDavid du Colombier else
11949a747e4fSDavid du Colombier err = (*fcalls[thdr.type])(newfid(thdr.fid));
11957dd7cddfSDavid du Colombier if(err){
11969a747e4fSDavid du Colombier rhdr.type = Rerror;
11979a747e4fSDavid du Colombier rhdr.ename = err;
11987dd7cddfSDavid du Colombier }else{
11999a747e4fSDavid du Colombier rhdr.type = thdr.type + 1;
12009a747e4fSDavid du Colombier rhdr.fid = thdr.fid;
12017dd7cddfSDavid du Colombier }
12029a747e4fSDavid du Colombier rhdr.tag = thdr.tag;
12037dd7cddfSDavid du Colombier if(debug)
12049a747e4fSDavid du Colombier fprint(2, "%s:->%F\n", argv0, &rhdr);/**/
12059a747e4fSDavid du Colombier n = convS2M(&rhdr, mdata, messagesize);
12067dd7cddfSDavid du Colombier if(write(mfd[1], mdata, n) != n)
12077dd7cddfSDavid du Colombier error("mount write");
12087dd7cddfSDavid du Colombier }
12097dd7cddfSDavid du Colombier }
12107dd7cddfSDavid du Colombier
12117dd7cddfSDavid du Colombier void
reader(void)12127dd7cddfSDavid du Colombier reader(void)
12137dd7cddfSDavid du Colombier {
121480ee5cbfSDavid du Colombier ulong t;
12159a747e4fSDavid du Colombier Dir *d;
12167dd7cddfSDavid du Colombier Mailbox *mb;
12177dd7cddfSDavid du Colombier
12187dd7cddfSDavid du Colombier sleep(15*1000);
12197dd7cddfSDavid du Colombier for(;;){
122080ee5cbfSDavid du Colombier t = time(0);
12217dd7cddfSDavid du Colombier qlock(&mbllock);
12227dd7cddfSDavid du Colombier for(mb = mbl; mb != nil; mb = mb->next){
12239a747e4fSDavid du Colombier assert(mb->refs > 0);
122480ee5cbfSDavid du Colombier if(mb->waketime != 0 && t > mb->waketime){
122580ee5cbfSDavid du Colombier qlock(mb);
122680ee5cbfSDavid du Colombier mb->waketime = 0;
122780ee5cbfSDavid du Colombier break;
122880ee5cbfSDavid du Colombier }
122980ee5cbfSDavid du Colombier
12309a747e4fSDavid du Colombier d = dirstat(mb->path);
12319a747e4fSDavid du Colombier if(d == nil)
12327dd7cddfSDavid du Colombier continue;
12337dd7cddfSDavid du Colombier
12343ff48bf5SDavid du Colombier qlock(mb);
12350fb3f58eSDavid du Colombier if(mb->d)
12369a747e4fSDavid du Colombier if(d->qid.path != mb->d->qid.path
12370fb3f58eSDavid du Colombier || d->qid.vers != mb->d->qid.vers){
12389a747e4fSDavid du Colombier free(d);
12397dd7cddfSDavid du Colombier break;
12407dd7cddfSDavid du Colombier }
12413ff48bf5SDavid du Colombier qunlock(mb);
12429a747e4fSDavid du Colombier free(d);
12437dd7cddfSDavid du Colombier }
12447dd7cddfSDavid du Colombier qunlock(&mbllock);
12457dd7cddfSDavid du Colombier if(mb != nil){
12467dd7cddfSDavid du Colombier syncmbox(mb, 1);
12477dd7cddfSDavid du Colombier qunlock(mb);
12487dd7cddfSDavid du Colombier } else
12497dd7cddfSDavid du Colombier sleep(15*1000);
12507dd7cddfSDavid du Colombier }
12517dd7cddfSDavid du Colombier }
12527dd7cddfSDavid du Colombier
12537dd7cddfSDavid du Colombier int
newid(void)12547dd7cddfSDavid du Colombier newid(void)
12557dd7cddfSDavid du Colombier {
12567dd7cddfSDavid du Colombier int rv;
12577dd7cddfSDavid du Colombier static int id;
12587dd7cddfSDavid du Colombier static Lock idlock;
12597dd7cddfSDavid du Colombier
12607dd7cddfSDavid du Colombier lock(&idlock);
12617dd7cddfSDavid du Colombier rv = ++id;
12627dd7cddfSDavid du Colombier unlock(&idlock);
12637dd7cddfSDavid du Colombier
12647dd7cddfSDavid du Colombier return rv;
12657dd7cddfSDavid du Colombier }
12667dd7cddfSDavid du Colombier
12677dd7cddfSDavid du Colombier void
error(char * s)12687dd7cddfSDavid du Colombier error(char *s)
12697dd7cddfSDavid du Colombier {
12707dd7cddfSDavid du Colombier postnote(PNGROUP, getpid(), "die yankee pig dog");
12717dd7cddfSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, s);
12727dd7cddfSDavid du Colombier exits(s);
12737dd7cddfSDavid du Colombier }
12747dd7cddfSDavid du Colombier
12757dd7cddfSDavid du Colombier
12767dd7cddfSDavid du Colombier typedef struct Ignorance Ignorance;
12777dd7cddfSDavid du Colombier struct Ignorance
12787dd7cddfSDavid du Colombier {
12797dd7cddfSDavid du Colombier Ignorance *next;
12807dd7cddfSDavid du Colombier char *str; /* string */
12817dd7cddfSDavid du Colombier int partial; /* true if not exact match */
12827dd7cddfSDavid du Colombier };
12837dd7cddfSDavid du Colombier Ignorance *ignorance;
12847dd7cddfSDavid du Colombier
12857dd7cddfSDavid du Colombier /*
12867dd7cddfSDavid du Colombier * read the file of headers to ignore
12877dd7cddfSDavid du Colombier */
12887dd7cddfSDavid du Colombier void
readignore(void)12897dd7cddfSDavid du Colombier readignore(void)
12907dd7cddfSDavid du Colombier {
12917dd7cddfSDavid du Colombier char *p;
12927dd7cddfSDavid du Colombier Ignorance *i;
12937dd7cddfSDavid du Colombier Biobuf *b;
12947dd7cddfSDavid du Colombier
12957dd7cddfSDavid du Colombier if(ignorance != nil)
12967dd7cddfSDavid du Colombier return;
12977dd7cddfSDavid du Colombier
12987dd7cddfSDavid du Colombier b = Bopen("/mail/lib/ignore", OREAD);
12997dd7cddfSDavid du Colombier if(b == 0)
13007dd7cddfSDavid du Colombier return;
13017dd7cddfSDavid du Colombier while(p = Brdline(b, '\n')){
13027dd7cddfSDavid du Colombier p[Blinelen(b)-1] = 0;
13037dd7cddfSDavid du Colombier while(*p && (*p == ' ' || *p == '\t'))
13047dd7cddfSDavid du Colombier p++;
13057dd7cddfSDavid du Colombier if(*p == '#')
13067dd7cddfSDavid du Colombier continue;
13077dd7cddfSDavid du Colombier i = malloc(sizeof(Ignorance));
13087dd7cddfSDavid du Colombier if(i == 0)
13097dd7cddfSDavid du Colombier break;
13107dd7cddfSDavid du Colombier i->partial = strlen(p);
13117dd7cddfSDavid du Colombier i->str = strdup(p);
13127dd7cddfSDavid du Colombier if(i->str == 0){
13137dd7cddfSDavid du Colombier free(i);
13147dd7cddfSDavid du Colombier break;
13157dd7cddfSDavid du Colombier }
13167dd7cddfSDavid du Colombier i->next = ignorance;
13177dd7cddfSDavid du Colombier ignorance = i;
13187dd7cddfSDavid du Colombier }
13197dd7cddfSDavid du Colombier Bterm(b);
13207dd7cddfSDavid du Colombier }
13217dd7cddfSDavid du Colombier
13227dd7cddfSDavid du Colombier int
ignore(char * p)13237dd7cddfSDavid du Colombier ignore(char *p)
13247dd7cddfSDavid du Colombier {
13257dd7cddfSDavid du Colombier Ignorance *i;
13267dd7cddfSDavid du Colombier
13277dd7cddfSDavid du Colombier readignore();
13287dd7cddfSDavid du Colombier for(i = ignorance; i != nil; i = i->next)
13297dd7cddfSDavid du Colombier if(cistrncmp(i->str, p, i->partial) == 0)
13307dd7cddfSDavid du Colombier return 1;
13317dd7cddfSDavid du Colombier return 0;
13327dd7cddfSDavid du Colombier }
13337dd7cddfSDavid du Colombier
13347dd7cddfSDavid du Colombier int
hdrlen(char * p,char * e)13357dd7cddfSDavid du Colombier hdrlen(char *p, char *e)
13367dd7cddfSDavid du Colombier {
13377dd7cddfSDavid du Colombier char *ep;
13387dd7cddfSDavid du Colombier
13397dd7cddfSDavid du Colombier ep = p;
13407dd7cddfSDavid du Colombier do {
13417dd7cddfSDavid du Colombier ep = strchr(ep, '\n');
13427dd7cddfSDavid du Colombier if(ep == nil){
13437dd7cddfSDavid du Colombier ep = e;
13447dd7cddfSDavid du Colombier break;
13457dd7cddfSDavid du Colombier }
13467dd7cddfSDavid du Colombier ep++;
13477dd7cddfSDavid du Colombier if(ep >= e){
13487dd7cddfSDavid du Colombier ep = e;
13497dd7cddfSDavid du Colombier break;
13507dd7cddfSDavid du Colombier }
13517dd7cddfSDavid du Colombier } while(*ep == ' ' || *ep == '\t');
13527dd7cddfSDavid du Colombier return ep - p;
13537dd7cddfSDavid du Colombier }
13547dd7cddfSDavid du Colombier
1355816336a7SDavid du Colombier // rfc2047 non-ascii: =?charset?q?encoded-text?=
13567dd7cddfSDavid du Colombier int
rfc2047convert(String * s,char * token,int len)13575d459b5aSDavid du Colombier rfc2047convert(String *s, char *token, int len)
13587dd7cddfSDavid du Colombier {
1359816336a7SDavid du Colombier char charset[100], decoded[1024], *e, *x;
1360816336a7SDavid du Colombier int l;
13617dd7cddfSDavid du Colombier
13627dd7cddfSDavid du Colombier if(len == 0)
13637dd7cddfSDavid du Colombier return -1;
13647dd7cddfSDavid du Colombier
13657dd7cddfSDavid du Colombier e = token+len-2;
13667dd7cddfSDavid du Colombier token += 2;
13677dd7cddfSDavid du Colombier
1368816336a7SDavid du Colombier x = memchr(token, '?', e-token);
1369816336a7SDavid du Colombier if(x == nil || (l=x-token) >= sizeof charset)
13707dd7cddfSDavid du Colombier return -1;
1371816336a7SDavid du Colombier memmove(charset, token, l);
1372816336a7SDavid du Colombier charset[l] = 0;
1373816336a7SDavid du Colombier
1374816336a7SDavid du Colombier token = x+1;
13757dd7cddfSDavid du Colombier
13767dd7cddfSDavid du Colombier // bail if it doesn't fit
13773ff48bf5SDavid du Colombier if(e-token > sizeof(decoded)-1)
13787dd7cddfSDavid du Colombier return -1;
13797dd7cddfSDavid du Colombier
13807dd7cddfSDavid du Colombier // bail if we don't understand the encoding
13817dd7cddfSDavid du Colombier if(cistrncmp(token, "b?", 2) == 0){
13827dd7cddfSDavid du Colombier token += 2;
13837dd7cddfSDavid du Colombier len = dec64((uchar*)decoded, sizeof(decoded), token, e-token);
13847dd7cddfSDavid du Colombier decoded[len] = 0;
13857dd7cddfSDavid du Colombier } else if(cistrncmp(token, "q?", 2) == 0){
13867dd7cddfSDavid du Colombier token += 2;
138717dd33a2SDavid du Colombier len = decquoted(decoded, token, e, 1);
13887dd7cddfSDavid du Colombier if(len > 0 && decoded[len-1] == '\n')
13897dd7cddfSDavid du Colombier len--;
13907dd7cddfSDavid du Colombier decoded[len] = 0;
13917dd7cddfSDavid du Colombier } else
13927dd7cddfSDavid du Colombier return -1;
13937dd7cddfSDavid du Colombier
1394816336a7SDavid du Colombier if(xtoutf(charset, &x, decoded, decoded+len) <= 0)
13957dd7cddfSDavid du Colombier s_append(s, decoded);
1396816336a7SDavid du Colombier else {
13977dd7cddfSDavid du Colombier s_append(s, x);
13987dd7cddfSDavid du Colombier free(x);
13997dd7cddfSDavid du Colombier }
14007dd7cddfSDavid du Colombier return 0;
14017dd7cddfSDavid du Colombier }
14027dd7cddfSDavid du Colombier
14035d459b5aSDavid du Colombier char*
rfc2047start(char * start,char * end)14045d459b5aSDavid du Colombier rfc2047start(char *start, char *end)
14057dd7cddfSDavid du Colombier {
14065d459b5aSDavid du Colombier int quests;
14077dd7cddfSDavid du Colombier
14085d459b5aSDavid du Colombier if(*--end != '=')
14095d459b5aSDavid du Colombier return nil;
14105d459b5aSDavid du Colombier if(*--end != '?')
14115d459b5aSDavid du Colombier return nil;
14125d459b5aSDavid du Colombier
14135d459b5aSDavid du Colombier quests = 0;
14145d459b5aSDavid du Colombier for(end--; end >= start; end--){
14155d459b5aSDavid du Colombier switch(*end){
14165d459b5aSDavid du Colombier case '=':
14175d459b5aSDavid du Colombier if(quests == 3 && *(end+1) == '?')
14185d459b5aSDavid du Colombier return end;
14195d459b5aSDavid du Colombier break;
14205d459b5aSDavid du Colombier case '?':
14215d459b5aSDavid du Colombier ++quests;
14225d459b5aSDavid du Colombier break;
14237dd7cddfSDavid du Colombier case ' ':
14247dd7cddfSDavid du Colombier case '\t':
14257dd7cddfSDavid du Colombier case '\n':
14265d459b5aSDavid du Colombier case '\r':
14275d459b5aSDavid du Colombier /* can't have white space in a token */
14285d459b5aSDavid du Colombier return nil;
14297dd7cddfSDavid du Colombier }
14305d459b5aSDavid du Colombier }
14315d459b5aSDavid du Colombier return nil;
14325d459b5aSDavid du Colombier }
14337dd7cddfSDavid du Colombier
14345d459b5aSDavid du Colombier // convert a header line
14355d459b5aSDavid du Colombier String*
stringconvert(String * s,char * uneaten,int len)14365d459b5aSDavid du Colombier stringconvert(String *s, char *uneaten, int len)
14375d459b5aSDavid du Colombier {
1438816336a7SDavid du Colombier char *token, *p, *e;
14395d459b5aSDavid du Colombier
14405d459b5aSDavid du Colombier s = s_reset(s);
14415d459b5aSDavid du Colombier p = uneaten;
1442816336a7SDavid du Colombier for(e = p+len; p < e; ){
1443816336a7SDavid du Colombier while(*p++ == '=' && (token = rfc2047start(uneaten, p))){
14445d459b5aSDavid du Colombier s_nappend(s, uneaten, token-uneaten);
14455d459b5aSDavid du Colombier if(rfc2047convert(s, token, p - token) < 0)
14465d459b5aSDavid du Colombier s_nappend(s, token, p - token);
14475d459b5aSDavid du Colombier uneaten = p;
1448816336a7SDavid du Colombier for(; p<e && isspace(*p);)
1449816336a7SDavid du Colombier p++;
1450816336a7SDavid du Colombier if(p+2 < e && p[0] == '=' && p[1] == '?')
1451816336a7SDavid du Colombier uneaten = p; // paste
14527dd7cddfSDavid du Colombier }
14535d459b5aSDavid du Colombier }
14545d459b5aSDavid du Colombier if(p > uneaten)
14555d459b5aSDavid du Colombier s_nappend(s, uneaten, p-uneaten);
14567dd7cddfSDavid du Colombier return s;
14577dd7cddfSDavid du Colombier }
14587dd7cddfSDavid du Colombier
14597dd7cddfSDavid du Colombier int
readheader(Message * m,char * buf,int off,int cnt)14607dd7cddfSDavid du Colombier readheader(Message *m, char *buf, int off, int cnt)
14617dd7cddfSDavid du Colombier {
14627dd7cddfSDavid du Colombier char *p, *e;
14637dd7cddfSDavid du Colombier int n, ns;
14647dd7cddfSDavid du Colombier char *to = buf;
14657dd7cddfSDavid du Colombier String *s;
14667dd7cddfSDavid du Colombier
14677dd7cddfSDavid du Colombier p = m->header;
14687dd7cddfSDavid du Colombier e = m->hend;
14697dd7cddfSDavid du Colombier s = nil;
14707dd7cddfSDavid du Colombier
14717dd7cddfSDavid du Colombier // copy in good headers
14727dd7cddfSDavid du Colombier while(cnt > 0 && p < e){
14737dd7cddfSDavid du Colombier n = hdrlen(p, e);
14747dd7cddfSDavid du Colombier if(ignore(p)){
14757dd7cddfSDavid du Colombier p += n;
14767dd7cddfSDavid du Colombier continue;
14777dd7cddfSDavid du Colombier }
14787dd7cddfSDavid du Colombier
14797dd7cddfSDavid du Colombier // rfc2047 processing
14805d459b5aSDavid du Colombier s = stringconvert(s, p, n);
14817dd7cddfSDavid du Colombier ns = s_len(s);
14827dd7cddfSDavid du Colombier if(off > 0){
14837dd7cddfSDavid du Colombier if(ns <= off){
14847dd7cddfSDavid du Colombier off -= ns;
14857dd7cddfSDavid du Colombier p += n;
14867dd7cddfSDavid du Colombier continue;
14877dd7cddfSDavid du Colombier }
14887dd7cddfSDavid du Colombier ns -= off;
14897dd7cddfSDavid du Colombier }
14907dd7cddfSDavid du Colombier if(ns > cnt)
14917dd7cddfSDavid du Colombier ns = cnt;
14927dd7cddfSDavid du Colombier memmove(to, s_to_c(s)+off, ns);
14937dd7cddfSDavid du Colombier to += ns;
14947dd7cddfSDavid du Colombier p += n;
14957dd7cddfSDavid du Colombier cnt -= ns;
14967dd7cddfSDavid du Colombier off = 0;
14977dd7cddfSDavid du Colombier }
14987dd7cddfSDavid du Colombier
14997dd7cddfSDavid du Colombier s_free(s);
15007dd7cddfSDavid du Colombier return to - buf;
15017dd7cddfSDavid du Colombier }
15027dd7cddfSDavid du Colombier
15037dd7cddfSDavid du Colombier int
headerlen(Message * m)15047dd7cddfSDavid du Colombier headerlen(Message *m)
15057dd7cddfSDavid du Colombier {
15067dd7cddfSDavid du Colombier char buf[1024];
15077dd7cddfSDavid du Colombier int i, n;
15087dd7cddfSDavid du Colombier
15097dd7cddfSDavid du Colombier if(m->hlen >= 0)
15107dd7cddfSDavid du Colombier return m->hlen;
15117dd7cddfSDavid du Colombier for(n = 0; ; n += i){
15127dd7cddfSDavid du Colombier i = readheader(m, buf, n, sizeof(buf));
15137dd7cddfSDavid du Colombier if(i <= 0)
15147dd7cddfSDavid du Colombier break;
15157dd7cddfSDavid du Colombier }
15167dd7cddfSDavid du Colombier m->hlen = n;
15177dd7cddfSDavid du Colombier return n;
15187dd7cddfSDavid du Colombier }
15197dd7cddfSDavid du Colombier
15207dd7cddfSDavid du Colombier QLock hashlock;
15217dd7cddfSDavid du Colombier
15227dd7cddfSDavid du Colombier uint
hash(ulong ppath,char * name)15237dd7cddfSDavid du Colombier hash(ulong ppath, char *name)
15247dd7cddfSDavid du Colombier {
15257dd7cddfSDavid du Colombier uchar *p;
15267dd7cddfSDavid du Colombier uint h;
15277dd7cddfSDavid du Colombier
15287dd7cddfSDavid du Colombier h = 0;
15297dd7cddfSDavid du Colombier for(p = (uchar*)name; *p; p++)
15307dd7cddfSDavid du Colombier h = h*7 + *p;
15317dd7cddfSDavid du Colombier h += ppath;
15327dd7cddfSDavid du Colombier
15337dd7cddfSDavid du Colombier return h % Hsize;
15347dd7cddfSDavid du Colombier }
15357dd7cddfSDavid du Colombier
15367dd7cddfSDavid du Colombier Hash*
hlook(ulong ppath,char * name)15377dd7cddfSDavid du Colombier hlook(ulong ppath, char *name)
15387dd7cddfSDavid du Colombier {
15397dd7cddfSDavid du Colombier int h;
15407dd7cddfSDavid du Colombier Hash *hp;
15417dd7cddfSDavid du Colombier
15427dd7cddfSDavid du Colombier qlock(&hashlock);
15437dd7cddfSDavid du Colombier h = hash(ppath, name);
15447dd7cddfSDavid du Colombier for(hp = htab[h]; hp != nil; hp = hp->next)
15457dd7cddfSDavid du Colombier if(ppath == hp->ppath && strcmp(name, hp->name) == 0){
15467dd7cddfSDavid du Colombier qunlock(&hashlock);
15477dd7cddfSDavid du Colombier return hp;
15487dd7cddfSDavid du Colombier }
15497dd7cddfSDavid du Colombier qunlock(&hashlock);
15507dd7cddfSDavid du Colombier return nil;
15517dd7cddfSDavid du Colombier }
15527dd7cddfSDavid du Colombier
15537dd7cddfSDavid du Colombier void
henter(ulong ppath,char * name,Qid qid,Message * m,Mailbox * mb)15547dd7cddfSDavid du Colombier henter(ulong ppath, char *name, Qid qid, Message *m, Mailbox *mb)
15557dd7cddfSDavid du Colombier {
15567dd7cddfSDavid du Colombier int h;
15577dd7cddfSDavid du Colombier Hash *hp, **l;
15587dd7cddfSDavid du Colombier
15597dd7cddfSDavid du Colombier qlock(&hashlock);
15607dd7cddfSDavid du Colombier h = hash(ppath, name);
15617dd7cddfSDavid du Colombier for(l = &htab[h]; *l != nil; l = &(*l)->next){
15627dd7cddfSDavid du Colombier hp = *l;
15637dd7cddfSDavid du Colombier if(ppath == hp->ppath && strcmp(name, hp->name) == 0){
15647dd7cddfSDavid du Colombier hp->m = m;
15657dd7cddfSDavid du Colombier hp->mb = mb;
15667dd7cddfSDavid du Colombier hp->qid = qid;
15677dd7cddfSDavid du Colombier qunlock(&hashlock);
15687dd7cddfSDavid du Colombier return;
15697dd7cddfSDavid du Colombier }
15707dd7cddfSDavid du Colombier }
15717dd7cddfSDavid du Colombier
15727dd7cddfSDavid du Colombier *l = hp = emalloc(sizeof(*hp));
15737dd7cddfSDavid du Colombier hp->m = m;
15747dd7cddfSDavid du Colombier hp->mb = mb;
15757dd7cddfSDavid du Colombier hp->qid = qid;
15767dd7cddfSDavid du Colombier hp->name = name;
15777dd7cddfSDavid du Colombier hp->ppath = ppath;
15787dd7cddfSDavid du Colombier qunlock(&hashlock);
15797dd7cddfSDavid du Colombier }
15807dd7cddfSDavid du Colombier
15817dd7cddfSDavid du Colombier void
hfree(ulong ppath,char * name)15827dd7cddfSDavid du Colombier hfree(ulong ppath, char *name)
15837dd7cddfSDavid du Colombier {
15847dd7cddfSDavid du Colombier int h;
15857dd7cddfSDavid du Colombier Hash *hp, **l;
15867dd7cddfSDavid du Colombier
15877dd7cddfSDavid du Colombier qlock(&hashlock);
15887dd7cddfSDavid du Colombier h = hash(ppath, name);
15897dd7cddfSDavid du Colombier for(l = &htab[h]; *l != nil; l = &(*l)->next){
15907dd7cddfSDavid du Colombier hp = *l;
15917dd7cddfSDavid du Colombier if(ppath == hp->ppath && strcmp(name, hp->name) == 0){
15925d459b5aSDavid du Colombier hp->mb = nil;
15937dd7cddfSDavid du Colombier *l = hp->next;
15947dd7cddfSDavid du Colombier free(hp);
15957dd7cddfSDavid du Colombier break;
15967dd7cddfSDavid du Colombier }
15977dd7cddfSDavid du Colombier }
15987dd7cddfSDavid du Colombier qunlock(&hashlock);
15997dd7cddfSDavid du Colombier }
16007dd7cddfSDavid du Colombier
16017dd7cddfSDavid du Colombier int
hashmboxrefs(Mailbox * mb)16027dd7cddfSDavid du Colombier hashmboxrefs(Mailbox *mb)
16037dd7cddfSDavid du Colombier {
16047dd7cddfSDavid du Colombier int h;
16057dd7cddfSDavid du Colombier Hash *hp;
16067dd7cddfSDavid du Colombier int refs = 0;
16077dd7cddfSDavid du Colombier
16087dd7cddfSDavid du Colombier qlock(&hashlock);
16097dd7cddfSDavid du Colombier for(h = 0; h < Hsize; h++){
16107dd7cddfSDavid du Colombier for(hp = htab[h]; hp != nil; hp = hp->next)
16117dd7cddfSDavid du Colombier if(hp->mb == mb)
16127dd7cddfSDavid du Colombier refs++;
16137dd7cddfSDavid du Colombier }
16147dd7cddfSDavid du Colombier qunlock(&hashlock);
16157dd7cddfSDavid du Colombier return refs;
16167dd7cddfSDavid du Colombier }
161780ee5cbfSDavid du Colombier
161880ee5cbfSDavid du Colombier void
checkmboxrefs(void)16195d459b5aSDavid du Colombier checkmboxrefs(void)
16205d459b5aSDavid du Colombier {
16215d459b5aSDavid du Colombier int f, refs;
16225d459b5aSDavid du Colombier Mailbox *mb;
16235d459b5aSDavid du Colombier
16245d459b5aSDavid du Colombier qlock(&mbllock);
16255d459b5aSDavid du Colombier for(mb=mbl; mb; mb=mb->next){
16265d459b5aSDavid du Colombier qlock(mb);
16275d459b5aSDavid du Colombier refs = (f=fidmboxrefs(mb))+1;
16285d459b5aSDavid du Colombier if(refs != mb->refs){
16295d459b5aSDavid du Colombier fprint(2, "mbox %s %s ref mismatch actual %d (%d+1) expected %d\n", mb->name, mb->path, refs, f, mb->refs);
16305d459b5aSDavid du Colombier abort();
16315d459b5aSDavid du Colombier }
16325d459b5aSDavid du Colombier qunlock(mb);
16335d459b5aSDavid du Colombier }
16345d459b5aSDavid du Colombier qunlock(&mbllock);
16355d459b5aSDavid du Colombier }
16365d459b5aSDavid du Colombier
16375d459b5aSDavid du Colombier void
post(char * name,char * envname,int srvfd)163880ee5cbfSDavid du Colombier post(char *name, char *envname, int srvfd)
163980ee5cbfSDavid du Colombier {
164080ee5cbfSDavid du Colombier int fd;
164180ee5cbfSDavid du Colombier char buf[32];
164280ee5cbfSDavid du Colombier
164380ee5cbfSDavid du Colombier fd = create(name, OWRITE, 0600);
164480ee5cbfSDavid du Colombier if(fd < 0)
164567031067SDavid du Colombier error("post failed");
164680ee5cbfSDavid du Colombier sprint(buf, "%d",srvfd);
164780ee5cbfSDavid du Colombier if(write(fd, buf, strlen(buf)) != strlen(buf))
164880ee5cbfSDavid du Colombier error("srv write");
164980ee5cbfSDavid du Colombier close(fd);
165080ee5cbfSDavid du Colombier putenv(envname, name);
165180ee5cbfSDavid du Colombier }
1652