1*7dd7cddfSDavid du Colombier #include "common.h" 2*7dd7cddfSDavid du Colombier #include <auth.h> 3*7dd7cddfSDavid du Colombier #include <fcall.h> 4*7dd7cddfSDavid du Colombier #include <libsec.h> 5*7dd7cddfSDavid du Colombier #include "dat.h" 6*7dd7cddfSDavid du Colombier 7*7dd7cddfSDavid du Colombier enum 8*7dd7cddfSDavid du Colombier { 9*7dd7cddfSDavid du Colombier OPERM = 0x3, // mask of all permission types in open mode 10*7dd7cddfSDavid du Colombier }; 11*7dd7cddfSDavid du Colombier 12*7dd7cddfSDavid du Colombier typedef struct Fid Fid; 13*7dd7cddfSDavid du Colombier 14*7dd7cddfSDavid du Colombier struct Fid 15*7dd7cddfSDavid du Colombier { 16*7dd7cddfSDavid du Colombier Qid qid; 17*7dd7cddfSDavid du Colombier short busy; 18*7dd7cddfSDavid du Colombier short open; 19*7dd7cddfSDavid du Colombier int fid; 20*7dd7cddfSDavid du Colombier Fid *next; 21*7dd7cddfSDavid du Colombier Mailbox *mb; 22*7dd7cddfSDavid du Colombier Message *m; 23*7dd7cddfSDavid du Colombier Message *mtop; // top level message 24*7dd7cddfSDavid du Colombier 25*7dd7cddfSDavid du Colombier //finger pointers to speed up reads of large directories 26*7dd7cddfSDavid du Colombier long foff; // offset/DIRLEN of finger 27*7dd7cddfSDavid du Colombier Message *fptr; // pointer to message at off 28*7dd7cddfSDavid du Colombier int fvers; // mailbox version when finger was saved 29*7dd7cddfSDavid du Colombier }; 30*7dd7cddfSDavid du Colombier 31*7dd7cddfSDavid du Colombier ulong path; // incremented for each new file 32*7dd7cddfSDavid du Colombier Fid *fids; 33*7dd7cddfSDavid du Colombier int mfd[2]; 34*7dd7cddfSDavid du Colombier char user[NAMELEN]; 35*7dd7cddfSDavid du Colombier char mdata[MAXMSG+MAXFDATA]; 36*7dd7cddfSDavid du Colombier Fcall rhdr; 37*7dd7cddfSDavid du Colombier Fcall thdr; 38*7dd7cddfSDavid du Colombier int fflg; 39*7dd7cddfSDavid du Colombier char *mntpt; 40*7dd7cddfSDavid du Colombier int biffing; 41*7dd7cddfSDavid du Colombier int plumbing = 1; 42*7dd7cddfSDavid du Colombier 43*7dd7cddfSDavid du Colombier QLock mbllock; 44*7dd7cddfSDavid du Colombier Mailbox *mbl; 45*7dd7cddfSDavid du Colombier 46*7dd7cddfSDavid du Colombier Fid *newfid(int); 47*7dd7cddfSDavid du Colombier void error(char*); 48*7dd7cddfSDavid du Colombier void io(void); 49*7dd7cddfSDavid du Colombier void *erealloc(void*, ulong); 50*7dd7cddfSDavid du Colombier void *emalloc(ulong); 51*7dd7cddfSDavid du Colombier void usage(void); 52*7dd7cddfSDavid du Colombier void reader(void); 53*7dd7cddfSDavid du Colombier int readheader(Message*, char*, int, int); 54*7dd7cddfSDavid du Colombier int cistrncmp(char*, char*, int); 55*7dd7cddfSDavid du Colombier int tokenconvert(String*, char*, int); 56*7dd7cddfSDavid du Colombier 57*7dd7cddfSDavid du Colombier char *rflush(Fid*), *rnop(Fid*), *rsession(Fid*), 58*7dd7cddfSDavid du Colombier *rattach(Fid*), *rclone(Fid*), *rwalk(Fid*), 59*7dd7cddfSDavid du Colombier *rclwalk(Fid*), *ropen(Fid*), *rcreate(Fid*), 60*7dd7cddfSDavid du Colombier *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*), 61*7dd7cddfSDavid du Colombier *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*); 62*7dd7cddfSDavid du Colombier 63*7dd7cddfSDavid du Colombier char *(*fcalls[])(Fid*) = { 64*7dd7cddfSDavid du Colombier [Tflush] rflush, 65*7dd7cddfSDavid du Colombier [Tsession] rsession, 66*7dd7cddfSDavid du Colombier [Tnop] rnop, 67*7dd7cddfSDavid du Colombier [Tattach] rattach, 68*7dd7cddfSDavid du Colombier [Tclone] rclone, 69*7dd7cddfSDavid du Colombier [Twalk] rwalk, 70*7dd7cddfSDavid du Colombier [Tclwalk] rclwalk, 71*7dd7cddfSDavid du Colombier [Topen] ropen, 72*7dd7cddfSDavid du Colombier [Tcreate] rcreate, 73*7dd7cddfSDavid du Colombier [Tread] rread, 74*7dd7cddfSDavid du Colombier [Twrite] rwrite, 75*7dd7cddfSDavid du Colombier [Tclunk] rclunk, 76*7dd7cddfSDavid du Colombier [Tremove] rremove, 77*7dd7cddfSDavid du Colombier [Tstat] rstat, 78*7dd7cddfSDavid du Colombier [Twstat] rwstat, 79*7dd7cddfSDavid du Colombier }; 80*7dd7cddfSDavid du Colombier 81*7dd7cddfSDavid du Colombier char Eperm[] = "permission denied"; 82*7dd7cddfSDavid du Colombier char Enotdir[] = "not a directory"; 83*7dd7cddfSDavid du Colombier char Enoauth[] = "no authentication in ramfs"; 84*7dd7cddfSDavid du Colombier char Enotexist[] = "file does not exist"; 85*7dd7cddfSDavid du Colombier char Einuse[] = "file in use"; 86*7dd7cddfSDavid du Colombier char Eexist[] = "file exists"; 87*7dd7cddfSDavid du Colombier char Enotowner[] = "not owner"; 88*7dd7cddfSDavid du Colombier char Eisopen[] = "file already open for I/O"; 89*7dd7cddfSDavid du Colombier char Excl[] = "exclusive use file already open"; 90*7dd7cddfSDavid du Colombier char Ename[] = "illegal name"; 91*7dd7cddfSDavid du Colombier char Ebadctl[] = "unknown control message"; 92*7dd7cddfSDavid du Colombier 93*7dd7cddfSDavid du Colombier char *dirtab[] = 94*7dd7cddfSDavid du Colombier { 95*7dd7cddfSDavid du Colombier [Qdir] ".", 96*7dd7cddfSDavid du Colombier [Qbody] "body", 97*7dd7cddfSDavid du Colombier [Qbcc] "bcc", 98*7dd7cddfSDavid du Colombier [Qcc] "cc", 99*7dd7cddfSDavid du Colombier [Qdate] "date", 100*7dd7cddfSDavid du Colombier [Qdigest] "digest", 101*7dd7cddfSDavid du Colombier [Qdisposition] "disposition", 102*7dd7cddfSDavid du Colombier [Qfilename] "filename", 103*7dd7cddfSDavid du Colombier [Qfrom] "from", 104*7dd7cddfSDavid du Colombier [Qheader] "header", 105*7dd7cddfSDavid du Colombier [Qinfo] "info", 106*7dd7cddfSDavid du Colombier [Qinreplyto] "inreplyto", 107*7dd7cddfSDavid du Colombier [Qlines] "lines", 108*7dd7cddfSDavid du Colombier [Qmimeheader] "mimeheader", 109*7dd7cddfSDavid du Colombier [Qmessageid] "messageid", 110*7dd7cddfSDavid du Colombier [Qraw] "raw", 111*7dd7cddfSDavid du Colombier [Qrawbody] "rawbody", 112*7dd7cddfSDavid du Colombier [Qrawheader] "rawheader", 113*7dd7cddfSDavid du Colombier [Qreplyto] "replyto", 114*7dd7cddfSDavid du Colombier [Qsender] "sender", 115*7dd7cddfSDavid du Colombier [Qsubject] "subject", 116*7dd7cddfSDavid du Colombier [Qto] "to", 117*7dd7cddfSDavid du Colombier [Qtype] "type", 118*7dd7cddfSDavid du Colombier [Qunixheader] "unixheader", 119*7dd7cddfSDavid du Colombier [Qctl] "ctl", 120*7dd7cddfSDavid du Colombier }; 121*7dd7cddfSDavid du Colombier 122*7dd7cddfSDavid du Colombier enum 123*7dd7cddfSDavid du Colombier { 124*7dd7cddfSDavid du Colombier Hsize= 1277, 125*7dd7cddfSDavid du Colombier }; 126*7dd7cddfSDavid du Colombier 127*7dd7cddfSDavid du Colombier Hash *htab[Hsize]; 128*7dd7cddfSDavid du Colombier 129*7dd7cddfSDavid du Colombier int debug; 130*7dd7cddfSDavid du Colombier int fflag; 131*7dd7cddfSDavid du Colombier 132*7dd7cddfSDavid du Colombier void 133*7dd7cddfSDavid du Colombier usage(void) 134*7dd7cddfSDavid du Colombier { 135*7dd7cddfSDavid du Colombier fprint(2, "usage: %s [-b -m mountpoint]\n", argv0); 136*7dd7cddfSDavid du Colombier exits("usage"); 137*7dd7cddfSDavid du Colombier } 138*7dd7cddfSDavid du Colombier 139*7dd7cddfSDavid du Colombier void 140*7dd7cddfSDavid du Colombier notifyf(void *a, char *s) 141*7dd7cddfSDavid du Colombier { 142*7dd7cddfSDavid du Colombier USED(a); 143*7dd7cddfSDavid du Colombier if(strncmp(s, "interrupt", 9) == 0) 144*7dd7cddfSDavid du Colombier noted(NCONT); 145*7dd7cddfSDavid du Colombier noted(NDFLT); 146*7dd7cddfSDavid du Colombier } 147*7dd7cddfSDavid du Colombier 148*7dd7cddfSDavid du Colombier void 149*7dd7cddfSDavid du Colombier main(int argc, char *argv[]) 150*7dd7cddfSDavid du Colombier { 151*7dd7cddfSDavid du Colombier int p[2], std; 152*7dd7cddfSDavid du Colombier char maildir[128]; 153*7dd7cddfSDavid du Colombier char mbox[128]; 154*7dd7cddfSDavid du Colombier char *mboxfile, *err; 155*7dd7cddfSDavid du Colombier 156*7dd7cddfSDavid du Colombier mntpt = nil; 157*7dd7cddfSDavid du Colombier fflag = 0; 158*7dd7cddfSDavid du Colombier mboxfile = nil; 159*7dd7cddfSDavid du Colombier std = 0; 160*7dd7cddfSDavid du Colombier 161*7dd7cddfSDavid du Colombier ARGBEGIN{ 162*7dd7cddfSDavid du Colombier case 'b': 163*7dd7cddfSDavid du Colombier biffing = 1; 164*7dd7cddfSDavid du Colombier break; 165*7dd7cddfSDavid du Colombier case 'f': 166*7dd7cddfSDavid du Colombier fflag = 1; 167*7dd7cddfSDavid du Colombier mboxfile = ARGF(); 168*7dd7cddfSDavid du Colombier break; 169*7dd7cddfSDavid du Colombier case 'm': 170*7dd7cddfSDavid du Colombier mntpt = ARGF(); 171*7dd7cddfSDavid du Colombier break; 172*7dd7cddfSDavid du Colombier case 'd': 173*7dd7cddfSDavid du Colombier debug = 1; 174*7dd7cddfSDavid du Colombier break; 175*7dd7cddfSDavid du Colombier case 'p': 176*7dd7cddfSDavid du Colombier plumbing = 0; 177*7dd7cddfSDavid du Colombier break; 178*7dd7cddfSDavid du Colombier default: 179*7dd7cddfSDavid du Colombier usage(); 180*7dd7cddfSDavid du Colombier }ARGEND 181*7dd7cddfSDavid du Colombier 182*7dd7cddfSDavid du Colombier if(pipe(p) < 0) 183*7dd7cddfSDavid du Colombier error("pipe failed"); 184*7dd7cddfSDavid du Colombier mfd[0] = p[0]; 185*7dd7cddfSDavid du Colombier mfd[1] = p[0]; 186*7dd7cddfSDavid du Colombier 187*7dd7cddfSDavid du Colombier notify(notifyf); 188*7dd7cddfSDavid du Colombier strcpy(user, getuser()); 189*7dd7cddfSDavid du Colombier if(mntpt == nil){ 190*7dd7cddfSDavid du Colombier snprint(maildir, sizeof(maildir), "/mail/fs"); 191*7dd7cddfSDavid du Colombier mntpt = maildir; 192*7dd7cddfSDavid du Colombier } 193*7dd7cddfSDavid du Colombier if(mboxfile == nil){ 194*7dd7cddfSDavid du Colombier snprint(mbox, sizeof(mbox), "/mail/box/%s/mbox", user); 195*7dd7cddfSDavid du Colombier mboxfile = mbox; 196*7dd7cddfSDavid du Colombier std = 1; 197*7dd7cddfSDavid du Colombier } 198*7dd7cddfSDavid du Colombier 199*7dd7cddfSDavid du Colombier if(debug) 200*7dd7cddfSDavid du Colombier fmtinstall('F', fcallconv); 201*7dd7cddfSDavid du Colombier 202*7dd7cddfSDavid du Colombier err = newmbox(mboxfile, "mbox", std); 203*7dd7cddfSDavid du Colombier if(err != nil) 204*7dd7cddfSDavid du Colombier sysfatal("opening mailbox: %s", err); 205*7dd7cddfSDavid du Colombier 206*7dd7cddfSDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){ 207*7dd7cddfSDavid du Colombier case -1: 208*7dd7cddfSDavid du Colombier error("fork"); 209*7dd7cddfSDavid du Colombier case 0: 210*7dd7cddfSDavid du Colombier henter(CHDIR|PATH(0, Qtop), dirtab[Qctl], 211*7dd7cddfSDavid du Colombier (Qid){PATH(0, Qctl), 0}, nil, nil); 212*7dd7cddfSDavid du Colombier close(p[1]); 213*7dd7cddfSDavid du Colombier io(); 214*7dd7cddfSDavid du Colombier postnote(PNGROUP, getpid(), "die yankee pig dog"); 215*7dd7cddfSDavid du Colombier break; 216*7dd7cddfSDavid du Colombier default: 217*7dd7cddfSDavid du Colombier close(p[0]); /* don't deadlock if child fails */ 218*7dd7cddfSDavid du Colombier if(mount(p[1], mntpt, MREPL, "") < 0) 219*7dd7cddfSDavid du Colombier error("mount failed"); 220*7dd7cddfSDavid du Colombier } 221*7dd7cddfSDavid du Colombier exits(0); 222*7dd7cddfSDavid du Colombier } 223*7dd7cddfSDavid du Colombier 224*7dd7cddfSDavid du Colombier static int 225*7dd7cddfSDavid du Colombier fileinfo(Message *m, int t, char **pp) 226*7dd7cddfSDavid du Colombier { 227*7dd7cddfSDavid du Colombier char *p; 228*7dd7cddfSDavid du Colombier int len; 229*7dd7cddfSDavid du Colombier 230*7dd7cddfSDavid du Colombier p = ""; 231*7dd7cddfSDavid du Colombier len = 0; 232*7dd7cddfSDavid du Colombier switch(t){ 233*7dd7cddfSDavid du Colombier case Qbody: 234*7dd7cddfSDavid du Colombier p = m->body; 235*7dd7cddfSDavid du Colombier len = m->bend - m->body; 236*7dd7cddfSDavid du Colombier break; 237*7dd7cddfSDavid du Colombier case Qbcc: 238*7dd7cddfSDavid du Colombier if(m->bcc822){ 239*7dd7cddfSDavid du Colombier p = s_to_c(m->bcc822); 240*7dd7cddfSDavid du Colombier len = strlen(p); 241*7dd7cddfSDavid du Colombier } 242*7dd7cddfSDavid du Colombier break; 243*7dd7cddfSDavid du Colombier case Qcc: 244*7dd7cddfSDavid du Colombier if(m->cc822){ 245*7dd7cddfSDavid du Colombier p = s_to_c(m->cc822); 246*7dd7cddfSDavid du Colombier len = strlen(p); 247*7dd7cddfSDavid du Colombier } 248*7dd7cddfSDavid du Colombier break; 249*7dd7cddfSDavid du Colombier case Qdisposition: 250*7dd7cddfSDavid du Colombier switch(m->disposition){ 251*7dd7cddfSDavid du Colombier case Dinline: 252*7dd7cddfSDavid du Colombier p = "inline"; 253*7dd7cddfSDavid du Colombier break; 254*7dd7cddfSDavid du Colombier case Dfile: 255*7dd7cddfSDavid du Colombier p = "file"; 256*7dd7cddfSDavid du Colombier break; 257*7dd7cddfSDavid du Colombier } 258*7dd7cddfSDavid du Colombier len = strlen(p); 259*7dd7cddfSDavid du Colombier break; 260*7dd7cddfSDavid du Colombier case Qdate: 261*7dd7cddfSDavid du Colombier if(m->date822){ 262*7dd7cddfSDavid du Colombier p = s_to_c(m->date822); 263*7dd7cddfSDavid du Colombier len = strlen(p); 264*7dd7cddfSDavid du Colombier } else if(m->unixdate != nil){ 265*7dd7cddfSDavid du Colombier p = s_to_c(m->unixdate); 266*7dd7cddfSDavid du Colombier len = strlen(p); 267*7dd7cddfSDavid du Colombier } 268*7dd7cddfSDavid du Colombier break; 269*7dd7cddfSDavid du Colombier case Qfilename: 270*7dd7cddfSDavid du Colombier if(m->filename){ 271*7dd7cddfSDavid du Colombier p = s_to_c(m->filename); 272*7dd7cddfSDavid du Colombier len = strlen(p); 273*7dd7cddfSDavid du Colombier } 274*7dd7cddfSDavid du Colombier break; 275*7dd7cddfSDavid du Colombier case Qinreplyto: 276*7dd7cddfSDavid du Colombier if(m->inreplyto822){ 277*7dd7cddfSDavid du Colombier p = s_to_c(m->inreplyto822); 278*7dd7cddfSDavid du Colombier len = strlen(p); 279*7dd7cddfSDavid du Colombier } 280*7dd7cddfSDavid du Colombier break; 281*7dd7cddfSDavid du Colombier case Qmessageid: 282*7dd7cddfSDavid du Colombier if(m->messageid822){ 283*7dd7cddfSDavid du Colombier p = s_to_c(m->messageid822); 284*7dd7cddfSDavid du Colombier len = strlen(p); 285*7dd7cddfSDavid du Colombier } 286*7dd7cddfSDavid du Colombier break; 287*7dd7cddfSDavid du Colombier case Qfrom: 288*7dd7cddfSDavid du Colombier if(m->from822){ 289*7dd7cddfSDavid du Colombier p = s_to_c(m->from822); 290*7dd7cddfSDavid du Colombier len = strlen(p); 291*7dd7cddfSDavid du Colombier } else if(m->unixfrom != nil){ 292*7dd7cddfSDavid du Colombier p = s_to_c(m->unixfrom); 293*7dd7cddfSDavid du Colombier len = strlen(p); 294*7dd7cddfSDavid du Colombier } 295*7dd7cddfSDavid du Colombier break; 296*7dd7cddfSDavid du Colombier case Qheader: 297*7dd7cddfSDavid du Colombier p = m->header; 298*7dd7cddfSDavid du Colombier len = headerlen(m); 299*7dd7cddfSDavid du Colombier break; 300*7dd7cddfSDavid du Colombier case Qlines: 301*7dd7cddfSDavid du Colombier p = m->lines; 302*7dd7cddfSDavid du Colombier if(*p == 0) 303*7dd7cddfSDavid du Colombier countlines(m); 304*7dd7cddfSDavid du Colombier len = strlen(m->lines); 305*7dd7cddfSDavid du Colombier break; 306*7dd7cddfSDavid du Colombier case Qraw: 307*7dd7cddfSDavid du Colombier p = m->start; 308*7dd7cddfSDavid du Colombier if(strncmp(m->start, "From ", 5) == 0){ 309*7dd7cddfSDavid du Colombier p = strchr(p, '\n'); 310*7dd7cddfSDavid du Colombier if(p == nil) 311*7dd7cddfSDavid du Colombier p = m->start; 312*7dd7cddfSDavid du Colombier else 313*7dd7cddfSDavid du Colombier p++; 314*7dd7cddfSDavid du Colombier } 315*7dd7cddfSDavid du Colombier len = m->end - p; 316*7dd7cddfSDavid du Colombier break; 317*7dd7cddfSDavid du Colombier case Qrawbody: 318*7dd7cddfSDavid du Colombier p = m->rbody; 319*7dd7cddfSDavid du Colombier len = m->rbend - p; 320*7dd7cddfSDavid du Colombier break; 321*7dd7cddfSDavid du Colombier case Qrawheader: 322*7dd7cddfSDavid du Colombier p = m->header; 323*7dd7cddfSDavid du Colombier len = m->hend - p; 324*7dd7cddfSDavid du Colombier break; 325*7dd7cddfSDavid du Colombier case Qmimeheader: 326*7dd7cddfSDavid du Colombier p = m->mheader; 327*7dd7cddfSDavid du Colombier len = m->mhend - p; 328*7dd7cddfSDavid du Colombier break; 329*7dd7cddfSDavid du Colombier case Qreplyto: 330*7dd7cddfSDavid du Colombier p = nil; 331*7dd7cddfSDavid du Colombier if(m->replyto822 != nil){ 332*7dd7cddfSDavid du Colombier p = s_to_c(m->replyto822); 333*7dd7cddfSDavid du Colombier len = strlen(p); 334*7dd7cddfSDavid du Colombier } else if(m->from822 != nil){ 335*7dd7cddfSDavid du Colombier p = s_to_c(m->from822); 336*7dd7cddfSDavid du Colombier len = strlen(p); 337*7dd7cddfSDavid du Colombier } else if(m->sender822 != nil){ 338*7dd7cddfSDavid du Colombier p = s_to_c(m->sender822); 339*7dd7cddfSDavid du Colombier len = strlen(p); 340*7dd7cddfSDavid du Colombier } else if(m->unixfrom != nil){ 341*7dd7cddfSDavid du Colombier p = s_to_c(m->unixfrom); 342*7dd7cddfSDavid du Colombier len = strlen(p); 343*7dd7cddfSDavid du Colombier } 344*7dd7cddfSDavid du Colombier break; 345*7dd7cddfSDavid du Colombier case Qsender: 346*7dd7cddfSDavid du Colombier if(m->sender822){ 347*7dd7cddfSDavid du Colombier p = s_to_c(m->sender822); 348*7dd7cddfSDavid du Colombier len = strlen(p); 349*7dd7cddfSDavid du Colombier } 350*7dd7cddfSDavid du Colombier break; 351*7dd7cddfSDavid du Colombier case Qsubject: 352*7dd7cddfSDavid du Colombier p = nil; 353*7dd7cddfSDavid du Colombier if(m->subject822){ 354*7dd7cddfSDavid du Colombier p = s_to_c(m->subject822); 355*7dd7cddfSDavid du Colombier len = strlen(p); 356*7dd7cddfSDavid du Colombier } 357*7dd7cddfSDavid du Colombier break; 358*7dd7cddfSDavid du Colombier case Qto: 359*7dd7cddfSDavid du Colombier if(m->to822){ 360*7dd7cddfSDavid du Colombier p = s_to_c(m->to822); 361*7dd7cddfSDavid du Colombier len = strlen(p); 362*7dd7cddfSDavid du Colombier } 363*7dd7cddfSDavid du Colombier break; 364*7dd7cddfSDavid du Colombier case Qtype: 365*7dd7cddfSDavid du Colombier if(m->type){ 366*7dd7cddfSDavid du Colombier p = s_to_c(m->type); 367*7dd7cddfSDavid du Colombier len = strlen(p); 368*7dd7cddfSDavid du Colombier } 369*7dd7cddfSDavid du Colombier break; 370*7dd7cddfSDavid du Colombier case Qunixdate: 371*7dd7cddfSDavid du Colombier if(m->unixdate){ 372*7dd7cddfSDavid du Colombier p = s_to_c(m->unixdate); 373*7dd7cddfSDavid du Colombier len = strlen(p); 374*7dd7cddfSDavid du Colombier } 375*7dd7cddfSDavid du Colombier break; 376*7dd7cddfSDavid du Colombier case Qunixheader: 377*7dd7cddfSDavid du Colombier p = m->start; 378*7dd7cddfSDavid du Colombier len = m->header - m->start; 379*7dd7cddfSDavid du Colombier break; 380*7dd7cddfSDavid du Colombier case Qdigest: 381*7dd7cddfSDavid du Colombier if(m->sdigest){ 382*7dd7cddfSDavid du Colombier p = s_to_c(m->sdigest); 383*7dd7cddfSDavid du Colombier len = strlen(p); 384*7dd7cddfSDavid du Colombier } 385*7dd7cddfSDavid du Colombier break; 386*7dd7cddfSDavid du Colombier } 387*7dd7cddfSDavid du Colombier *pp = p; 388*7dd7cddfSDavid du Colombier return len; 389*7dd7cddfSDavid du Colombier } 390*7dd7cddfSDavid du Colombier 391*7dd7cddfSDavid du Colombier int infofields[] = { 392*7dd7cddfSDavid du Colombier Qfrom, 393*7dd7cddfSDavid du Colombier Qto, 394*7dd7cddfSDavid du Colombier Qcc, 395*7dd7cddfSDavid du Colombier Qreplyto, 396*7dd7cddfSDavid du Colombier Qunixdate, 397*7dd7cddfSDavid du Colombier Qsubject, 398*7dd7cddfSDavid du Colombier Qtype, 399*7dd7cddfSDavid du Colombier Qdisposition, 400*7dd7cddfSDavid du Colombier Qfilename, 401*7dd7cddfSDavid du Colombier Qdigest, 402*7dd7cddfSDavid du Colombier Qbcc, 403*7dd7cddfSDavid du Colombier Qinreplyto, 404*7dd7cddfSDavid du Colombier Qdate, 405*7dd7cddfSDavid du Colombier Qsender, 406*7dd7cddfSDavid du Colombier Qmessageid, 407*7dd7cddfSDavid du Colombier Qlines, 408*7dd7cddfSDavid du Colombier -1, 409*7dd7cddfSDavid du Colombier }; 410*7dd7cddfSDavid du Colombier 411*7dd7cddfSDavid du Colombier static int 412*7dd7cddfSDavid du Colombier readinfo(Message *m, char *buf, long off, int count) 413*7dd7cddfSDavid du Colombier { 414*7dd7cddfSDavid du Colombier char *p; 415*7dd7cddfSDavid du Colombier int len, i, n; 416*7dd7cddfSDavid du Colombier String *s; 417*7dd7cddfSDavid du Colombier 418*7dd7cddfSDavid du Colombier s = s_new(); 419*7dd7cddfSDavid du Colombier len = 0; 420*7dd7cddfSDavid du Colombier for(i = 0; len < count && infofields[i] >= 0; i++){ 421*7dd7cddfSDavid du Colombier n = fileinfo(m, infofields[i], &p); 422*7dd7cddfSDavid du Colombier s_reset(s); 423*7dd7cddfSDavid du Colombier if(tokenconvert(s, p, n) == 0){ 424*7dd7cddfSDavid du Colombier p = s_to_c(s); 425*7dd7cddfSDavid du Colombier n = strlen(p); 426*7dd7cddfSDavid du Colombier } 427*7dd7cddfSDavid du Colombier if(off > 0){ 428*7dd7cddfSDavid du Colombier if(off >= n+1){ 429*7dd7cddfSDavid du Colombier off -= n+1; 430*7dd7cddfSDavid du Colombier continue; 431*7dd7cddfSDavid du Colombier } 432*7dd7cddfSDavid du Colombier p += off; 433*7dd7cddfSDavid du Colombier n -= off; 434*7dd7cddfSDavid du Colombier off = 0; 435*7dd7cddfSDavid du Colombier } 436*7dd7cddfSDavid du Colombier if(n > count - len) 437*7dd7cddfSDavid du Colombier n = count - len; 438*7dd7cddfSDavid du Colombier if(buf) 439*7dd7cddfSDavid du Colombier memmove(buf+len, p, n); 440*7dd7cddfSDavid du Colombier len += n; 441*7dd7cddfSDavid du Colombier if(buf) 442*7dd7cddfSDavid du Colombier buf[len] = '\n'; 443*7dd7cddfSDavid du Colombier len++; 444*7dd7cddfSDavid du Colombier } 445*7dd7cddfSDavid du Colombier s_free(s); 446*7dd7cddfSDavid du Colombier return len; 447*7dd7cddfSDavid du Colombier } 448*7dd7cddfSDavid du Colombier 449*7dd7cddfSDavid du Colombier static void 450*7dd7cddfSDavid du Colombier mkstat(Dir *d, Mailbox *mb, Message *m, int t) 451*7dd7cddfSDavid du Colombier { 452*7dd7cddfSDavid du Colombier char *p; 453*7dd7cddfSDavid du Colombier 454*7dd7cddfSDavid du Colombier strncpy(d->uid, user, NAMELEN); 455*7dd7cddfSDavid du Colombier strncpy(d->gid, user, NAMELEN); 456*7dd7cddfSDavid du Colombier d->mode = 0444; 457*7dd7cddfSDavid du Colombier d->qid.vers = 0; 458*7dd7cddfSDavid du Colombier d->type = 0; 459*7dd7cddfSDavid du Colombier d->dev = 0; 460*7dd7cddfSDavid du Colombier 461*7dd7cddfSDavid du Colombier switch(t){ 462*7dd7cddfSDavid du Colombier case Qtop: 463*7dd7cddfSDavid du Colombier strcpy(d->name, "."); 464*7dd7cddfSDavid du Colombier d->mode = CHDIR|0555; 465*7dd7cddfSDavid du Colombier d->atime = d->mtime = time(0); 466*7dd7cddfSDavid du Colombier d->length = 0; 467*7dd7cddfSDavid du Colombier d->qid.path = CHDIR|PATH(0, Qtop); 468*7dd7cddfSDavid du Colombier break; 469*7dd7cddfSDavid du Colombier case Qmbox: 470*7dd7cddfSDavid du Colombier strcpy(d->name, mb->name); 471*7dd7cddfSDavid du Colombier d->mode = CHDIR|0555; 472*7dd7cddfSDavid du Colombier d->atime = mb->d.atime; 473*7dd7cddfSDavid du Colombier d->mtime = mb->d.mtime; 474*7dd7cddfSDavid du Colombier d->length = 0; 475*7dd7cddfSDavid du Colombier d->qid.path = CHDIR|PATH(mb->id, Qmbox); 476*7dd7cddfSDavid du Colombier d->qid.vers = mb->vers; 477*7dd7cddfSDavid du Colombier break; 478*7dd7cddfSDavid du Colombier case Qdir: 479*7dd7cddfSDavid du Colombier strcpy(d->name, m->name); 480*7dd7cddfSDavid du Colombier d->mode = CHDIR|0555; 481*7dd7cddfSDavid du Colombier d->atime = mb->d.atime; 482*7dd7cddfSDavid du Colombier d->mtime = mb->d.mtime; 483*7dd7cddfSDavid du Colombier d->length = 0; 484*7dd7cddfSDavid du Colombier d->qid.path = CHDIR|PATH(m->id, Qdir); 485*7dd7cddfSDavid du Colombier break; 486*7dd7cddfSDavid du Colombier case Qctl: 487*7dd7cddfSDavid du Colombier strncpy(d->name, dirtab[t], NAMELEN); 488*7dd7cddfSDavid du Colombier d->mode = 0666; 489*7dd7cddfSDavid du Colombier d->atime = d->mtime = time(0); 490*7dd7cddfSDavid du Colombier d->length = 0; 491*7dd7cddfSDavid du Colombier d->qid.path = PATH(0, Qctl); 492*7dd7cddfSDavid du Colombier break; 493*7dd7cddfSDavid du Colombier case Qinfo: 494*7dd7cddfSDavid du Colombier strncpy(d->name, dirtab[t], NAMELEN); 495*7dd7cddfSDavid du Colombier d->atime = mb->d.atime; 496*7dd7cddfSDavid du Colombier d->mtime = mb->d.mtime; 497*7dd7cddfSDavid du Colombier d->length = readinfo(m, nil, 0, 1<<30); 498*7dd7cddfSDavid du Colombier d->qid.path = PATH(m->id, t); 499*7dd7cddfSDavid du Colombier break; 500*7dd7cddfSDavid du Colombier default: 501*7dd7cddfSDavid du Colombier strncpy(d->name, dirtab[t], NAMELEN); 502*7dd7cddfSDavid du Colombier d->atime = mb->d.atime; 503*7dd7cddfSDavid du Colombier d->mtime = mb->d.mtime; 504*7dd7cddfSDavid du Colombier d->length = fileinfo(m, t, &p); 505*7dd7cddfSDavid du Colombier d->qid.path = PATH(m->id, t); 506*7dd7cddfSDavid du Colombier break; 507*7dd7cddfSDavid du Colombier } 508*7dd7cddfSDavid du Colombier } 509*7dd7cddfSDavid du Colombier 510*7dd7cddfSDavid du Colombier char* 511*7dd7cddfSDavid du Colombier rnop(Fid *f) 512*7dd7cddfSDavid du Colombier { 513*7dd7cddfSDavid du Colombier USED(f); 514*7dd7cddfSDavid du Colombier return 0; 515*7dd7cddfSDavid du Colombier } 516*7dd7cddfSDavid du Colombier 517*7dd7cddfSDavid du Colombier char* 518*7dd7cddfSDavid du Colombier rsession(Fid *unused) 519*7dd7cddfSDavid du Colombier { 520*7dd7cddfSDavid du Colombier Fid *f; 521*7dd7cddfSDavid du Colombier 522*7dd7cddfSDavid du Colombier USED(unused); 523*7dd7cddfSDavid du Colombier 524*7dd7cddfSDavid du Colombier for(f = fids; f; f = f->next) 525*7dd7cddfSDavid du Colombier if(f->busy) 526*7dd7cddfSDavid du Colombier rclunk(f); 527*7dd7cddfSDavid du Colombier memset(thdr.authid, 0, sizeof(thdr.authid)); 528*7dd7cddfSDavid du Colombier memset(thdr.authdom, 0, sizeof(thdr.authdom)); 529*7dd7cddfSDavid du Colombier memset(thdr.chal, 0, sizeof(thdr.chal)); 530*7dd7cddfSDavid du Colombier return 0; 531*7dd7cddfSDavid du Colombier } 532*7dd7cddfSDavid du Colombier 533*7dd7cddfSDavid du Colombier char* 534*7dd7cddfSDavid du Colombier rflush(Fid *f) 535*7dd7cddfSDavid du Colombier { 536*7dd7cddfSDavid du Colombier USED(f); 537*7dd7cddfSDavid du Colombier return 0; 538*7dd7cddfSDavid du Colombier } 539*7dd7cddfSDavid du Colombier 540*7dd7cddfSDavid du Colombier char* 541*7dd7cddfSDavid du Colombier rattach(Fid *f) 542*7dd7cddfSDavid du Colombier { 543*7dd7cddfSDavid du Colombier f->busy = 1; 544*7dd7cddfSDavid du Colombier f->m = nil; 545*7dd7cddfSDavid du Colombier f->mb = nil; 546*7dd7cddfSDavid du Colombier thdr.qid.path = f->qid.path = CHDIR|PATH(0, Qtop); 547*7dd7cddfSDavid du Colombier f->qid.vers = 0; 548*7dd7cddfSDavid du Colombier thdr.qid.vers = 0; 549*7dd7cddfSDavid du Colombier if(strcmp(rhdr.uname, user) != 0) 550*7dd7cddfSDavid du Colombier return Eperm; 551*7dd7cddfSDavid du Colombier return 0; 552*7dd7cddfSDavid du Colombier } 553*7dd7cddfSDavid du Colombier 554*7dd7cddfSDavid du Colombier char* 555*7dd7cddfSDavid du Colombier rclone(Fid *f) 556*7dd7cddfSDavid du Colombier { 557*7dd7cddfSDavid du Colombier Fid *nf; 558*7dd7cddfSDavid du Colombier 559*7dd7cddfSDavid du Colombier if(f->open) 560*7dd7cddfSDavid du Colombier return Eisopen; 561*7dd7cddfSDavid du Colombier nf = newfid(rhdr.newfid); 562*7dd7cddfSDavid du Colombier nf->busy = 1; 563*7dd7cddfSDavid du Colombier nf->open = 0; 564*7dd7cddfSDavid du Colombier nf->m = f->m; 565*7dd7cddfSDavid du Colombier nf->mtop = f->mtop; 566*7dd7cddfSDavid du Colombier nf->mb = f->mb; 567*7dd7cddfSDavid du Colombier if(f->mb != nil) 568*7dd7cddfSDavid du Colombier mboxincref(f->mb); 569*7dd7cddfSDavid du Colombier if(f->mtop != nil){ 570*7dd7cddfSDavid du Colombier qlock(f->mb); 571*7dd7cddfSDavid du Colombier msgincref(f->mtop); 572*7dd7cddfSDavid du Colombier qunlock(f->mb); 573*7dd7cddfSDavid du Colombier } 574*7dd7cddfSDavid du Colombier nf->qid = f->qid; 575*7dd7cddfSDavid du Colombier return 0; 576*7dd7cddfSDavid du Colombier } 577*7dd7cddfSDavid du Colombier 578*7dd7cddfSDavid du Colombier char* 579*7dd7cddfSDavid du Colombier rwalk(Fid *f) 580*7dd7cddfSDavid du Colombier { 581*7dd7cddfSDavid du Colombier char *name; 582*7dd7cddfSDavid du Colombier int t; 583*7dd7cddfSDavid du Colombier Mailbox *omb, *mb; 584*7dd7cddfSDavid du Colombier char *rv, *p; 585*7dd7cddfSDavid du Colombier Hash *h; 586*7dd7cddfSDavid du Colombier 587*7dd7cddfSDavid du Colombier name = rhdr.name; 588*7dd7cddfSDavid du Colombier t = FILE(f->qid.path); 589*7dd7cddfSDavid du Colombier 590*7dd7cddfSDavid du Colombier rv = Enotexist; 591*7dd7cddfSDavid du Colombier 592*7dd7cddfSDavid du Colombier omb = f->mb; 593*7dd7cddfSDavid du Colombier if(omb) 594*7dd7cddfSDavid du Colombier qlock(omb); 595*7dd7cddfSDavid du Colombier else 596*7dd7cddfSDavid du Colombier qlock(&mbllock); 597*7dd7cddfSDavid du Colombier 598*7dd7cddfSDavid du Colombier // this must catch everything except . and .. 599*7dd7cddfSDavid du Colombier retry: 600*7dd7cddfSDavid du Colombier h = hlook(f->qid.path, name); 601*7dd7cddfSDavid du Colombier if(h != nil){ 602*7dd7cddfSDavid du Colombier f->mb = h->mb; 603*7dd7cddfSDavid du Colombier f->m = h->m; 604*7dd7cddfSDavid du Colombier switch(t){ 605*7dd7cddfSDavid du Colombier case Qtop: 606*7dd7cddfSDavid du Colombier if(f->mb != nil) 607*7dd7cddfSDavid du Colombier mboxincref(f->mb); 608*7dd7cddfSDavid du Colombier break; 609*7dd7cddfSDavid du Colombier case Qmbox: 610*7dd7cddfSDavid du Colombier msgincref(f->m); 611*7dd7cddfSDavid du Colombier f->mtop = f->m; 612*7dd7cddfSDavid du Colombier break; 613*7dd7cddfSDavid du Colombier } 614*7dd7cddfSDavid du Colombier f->qid = h->qid; 615*7dd7cddfSDavid du Colombier thdr.qid = f->qid; 616*7dd7cddfSDavid du Colombier rv = nil; 617*7dd7cddfSDavid du Colombier } else if((p = strchr(name, '.')) != nil && *name != '.'){ 618*7dd7cddfSDavid du Colombier *p = 0; 619*7dd7cddfSDavid du Colombier goto retry; 620*7dd7cddfSDavid du Colombier } 621*7dd7cddfSDavid du Colombier 622*7dd7cddfSDavid du Colombier if(omb) 623*7dd7cddfSDavid du Colombier qunlock(omb); 624*7dd7cddfSDavid du Colombier else 625*7dd7cddfSDavid du Colombier qunlock(&mbllock); 626*7dd7cddfSDavid du Colombier if(rv == nil) 627*7dd7cddfSDavid du Colombier return rv; 628*7dd7cddfSDavid du Colombier 629*7dd7cddfSDavid du Colombier 630*7dd7cddfSDavid du Colombier if(strcmp(name, ".") == 0){ 631*7dd7cddfSDavid du Colombier thdr.qid = f->qid; 632*7dd7cddfSDavid du Colombier return nil; 633*7dd7cddfSDavid du Colombier } 634*7dd7cddfSDavid du Colombier 635*7dd7cddfSDavid du Colombier if((f->qid.path&CHDIR) != CHDIR) 636*7dd7cddfSDavid du Colombier return Enotdir; 637*7dd7cddfSDavid du Colombier 638*7dd7cddfSDavid du Colombier if(strcmp(name, "..") == 0){ 639*7dd7cddfSDavid du Colombier switch(t){ 640*7dd7cddfSDavid du Colombier case Qtop: 641*7dd7cddfSDavid du Colombier f->qid.path = CHDIR|PATH(0, Qtop); 642*7dd7cddfSDavid du Colombier f->qid.vers = 0; 643*7dd7cddfSDavid du Colombier break; 644*7dd7cddfSDavid du Colombier case Qmbox: 645*7dd7cddfSDavid du Colombier f->qid.path = CHDIR|PATH(0, Qtop); 646*7dd7cddfSDavid du Colombier f->qid.vers = 0; 647*7dd7cddfSDavid du Colombier qlock(&mbllock); 648*7dd7cddfSDavid du Colombier mb = f->mb; 649*7dd7cddfSDavid du Colombier f->mb = nil; 650*7dd7cddfSDavid du Colombier mboxdecref(mb); 651*7dd7cddfSDavid du Colombier qunlock(&mbllock); 652*7dd7cddfSDavid du Colombier break; 653*7dd7cddfSDavid du Colombier case Qdir: 654*7dd7cddfSDavid du Colombier qlock(f->mb); 655*7dd7cddfSDavid du Colombier if(f->m->whole == f->mb->root){ 656*7dd7cddfSDavid du Colombier f->qid.path = CHDIR|PATH(f->mb->id, Qmbox); 657*7dd7cddfSDavid du Colombier f->qid.vers = f->mb->d.qid.vers; 658*7dd7cddfSDavid du Colombier msgdecref(f->mb, f->mtop); 659*7dd7cddfSDavid du Colombier f->m = f->mtop = nil; 660*7dd7cddfSDavid du Colombier } else { 661*7dd7cddfSDavid du Colombier f->m = f->m->whole; 662*7dd7cddfSDavid du Colombier f->qid.path = CHDIR|PATH(f->m->id, Qdir); 663*7dd7cddfSDavid du Colombier } 664*7dd7cddfSDavid du Colombier qunlock(f->mb); 665*7dd7cddfSDavid du Colombier break; 666*7dd7cddfSDavid du Colombier } 667*7dd7cddfSDavid du Colombier thdr.qid = f->qid; 668*7dd7cddfSDavid du Colombier rv = nil; 669*7dd7cddfSDavid du Colombier } 670*7dd7cddfSDavid du Colombier 671*7dd7cddfSDavid du Colombier return rv; 672*7dd7cddfSDavid du Colombier } 673*7dd7cddfSDavid du Colombier 674*7dd7cddfSDavid du Colombier char * 675*7dd7cddfSDavid du Colombier rclwalk(Fid *f) 676*7dd7cddfSDavid du Colombier { 677*7dd7cddfSDavid du Colombier Fid *nf; 678*7dd7cddfSDavid du Colombier char *err; 679*7dd7cddfSDavid du Colombier 680*7dd7cddfSDavid du Colombier nf = newfid(rhdr.newfid); 681*7dd7cddfSDavid du Colombier nf->busy = 1; 682*7dd7cddfSDavid du Colombier nf->open = 0; 683*7dd7cddfSDavid du Colombier if(f->mb != nil) 684*7dd7cddfSDavid du Colombier mboxincref(f->mb); 685*7dd7cddfSDavid du Colombier if(f->mtop != nil){ 686*7dd7cddfSDavid du Colombier qlock(f->mb); 687*7dd7cddfSDavid du Colombier msgincref(f->m); 688*7dd7cddfSDavid du Colombier qunlock(f->mb); 689*7dd7cddfSDavid du Colombier } 690*7dd7cddfSDavid du Colombier nf->mtop = f->mtop; 691*7dd7cddfSDavid du Colombier nf->m = f->m; 692*7dd7cddfSDavid du Colombier nf->mb = f->mb; 693*7dd7cddfSDavid du Colombier if(err = rwalk(nf)) 694*7dd7cddfSDavid du Colombier rclunk(nf); 695*7dd7cddfSDavid du Colombier return err; 696*7dd7cddfSDavid du Colombier } 697*7dd7cddfSDavid du Colombier 698*7dd7cddfSDavid du Colombier char * 699*7dd7cddfSDavid du Colombier ropen(Fid *f) 700*7dd7cddfSDavid du Colombier { 701*7dd7cddfSDavid du Colombier if(f->open) 702*7dd7cddfSDavid du Colombier return Eisopen; 703*7dd7cddfSDavid du Colombier 704*7dd7cddfSDavid du Colombier if(rhdr.mode != OREAD) 705*7dd7cddfSDavid du Colombier if(FILE(f->qid.path) != Qctl) 706*7dd7cddfSDavid du Colombier return Eperm; 707*7dd7cddfSDavid du Colombier 708*7dd7cddfSDavid du Colombier // make sure we've decoded 709*7dd7cddfSDavid du Colombier if(FILE(f->qid.path) == Qbody){ 710*7dd7cddfSDavid du Colombier if(f->m->decoded == 0) 711*7dd7cddfSDavid du Colombier decode(f->m); 712*7dd7cddfSDavid du Colombier if(f->m->converted == 0) 713*7dd7cddfSDavid du Colombier convert(f->m); 714*7dd7cddfSDavid du Colombier } 715*7dd7cddfSDavid du Colombier 716*7dd7cddfSDavid du Colombier thdr.qid = f->qid; 717*7dd7cddfSDavid du Colombier f->open = 1; 718*7dd7cddfSDavid du Colombier return 0; 719*7dd7cddfSDavid du Colombier } 720*7dd7cddfSDavid du Colombier 721*7dd7cddfSDavid du Colombier char * 722*7dd7cddfSDavid du Colombier rcreate(Fid*) 723*7dd7cddfSDavid du Colombier { 724*7dd7cddfSDavid du Colombier return Eperm; 725*7dd7cddfSDavid du Colombier } 726*7dd7cddfSDavid du Colombier 727*7dd7cddfSDavid du Colombier int 728*7dd7cddfSDavid du Colombier readtopdir(Fid*, char *buf, long off, int cnt) 729*7dd7cddfSDavid du Colombier { 730*7dd7cddfSDavid du Colombier Dir d; 731*7dd7cddfSDavid du Colombier int n; 732*7dd7cddfSDavid du Colombier Mailbox *mb; 733*7dd7cddfSDavid du Colombier 734*7dd7cddfSDavid du Colombier n = 0; 735*7dd7cddfSDavid du Colombier if(cnt == 0) 736*7dd7cddfSDavid du Colombier return 0; 737*7dd7cddfSDavid du Colombier if(off == 0){ 738*7dd7cddfSDavid du Colombier mkstat(&d, nil, nil, Qctl); 739*7dd7cddfSDavid du Colombier convD2M(&d, &buf[n]); 740*7dd7cddfSDavid du Colombier n += DIRLEN; 741*7dd7cddfSDavid du Colombier cnt--; 742*7dd7cddfSDavid du Colombier } else 743*7dd7cddfSDavid du Colombier off--; 744*7dd7cddfSDavid du Colombier 745*7dd7cddfSDavid du Colombier for(mb = mbl; cnt > 0 && mb != nil; mb = mb->next){ 746*7dd7cddfSDavid du Colombier if(off > 0){ 747*7dd7cddfSDavid du Colombier off--; 748*7dd7cddfSDavid du Colombier continue; 749*7dd7cddfSDavid du Colombier } 750*7dd7cddfSDavid du Colombier mkstat(&d, mb, nil, Qmbox); 751*7dd7cddfSDavid du Colombier convD2M(&d, &buf[n]); 752*7dd7cddfSDavid du Colombier n += DIRLEN; 753*7dd7cddfSDavid du Colombier cnt--; 754*7dd7cddfSDavid du Colombier } 755*7dd7cddfSDavid du Colombier return n; 756*7dd7cddfSDavid du Colombier } 757*7dd7cddfSDavid du Colombier 758*7dd7cddfSDavid du Colombier int 759*7dd7cddfSDavid du Colombier readmboxdir(Fid *f, char *buf, long off, int cnt) 760*7dd7cddfSDavid du Colombier { 761*7dd7cddfSDavid du Colombier Dir d; 762*7dd7cddfSDavid du Colombier int n; 763*7dd7cddfSDavid du Colombier Message *m; 764*7dd7cddfSDavid du Colombier long pos; 765*7dd7cddfSDavid du Colombier 766*7dd7cddfSDavid du Colombier // to avoid n**2 reads of the directory, use a saved finger pointer 767*7dd7cddfSDavid du Colombier if(f->mb->vers == f->fvers && off >= f->foff && f->foff > 0){ 768*7dd7cddfSDavid du Colombier m = f->fptr; 769*7dd7cddfSDavid du Colombier pos = f->foff; 770*7dd7cddfSDavid du Colombier } else { 771*7dd7cddfSDavid du Colombier m = f->mb->root->part; 772*7dd7cddfSDavid du Colombier pos = 0; 773*7dd7cddfSDavid du Colombier } 774*7dd7cddfSDavid du Colombier 775*7dd7cddfSDavid du Colombier n = 0; 776*7dd7cddfSDavid du Colombier for(; cnt > 0 && m != nil; m = m->next){ 777*7dd7cddfSDavid du Colombier // act like deleted files aren't there 778*7dd7cddfSDavid du Colombier if(m->deleted) 779*7dd7cddfSDavid du Colombier continue; 780*7dd7cddfSDavid du Colombier 781*7dd7cddfSDavid du Colombier // skip till we've passed the offset 782*7dd7cddfSDavid du Colombier if(off > pos){ 783*7dd7cddfSDavid du Colombier pos++; 784*7dd7cddfSDavid du Colombier continue; 785*7dd7cddfSDavid du Colombier } 786*7dd7cddfSDavid du Colombier 787*7dd7cddfSDavid du Colombier mkstat(&d, f->mb, m, Qdir); 788*7dd7cddfSDavid du Colombier convD2M(&d, &buf[n]); 789*7dd7cddfSDavid du Colombier n += DIRLEN; 790*7dd7cddfSDavid du Colombier cnt--; 791*7dd7cddfSDavid du Colombier pos++; 792*7dd7cddfSDavid du Colombier } 793*7dd7cddfSDavid du Colombier 794*7dd7cddfSDavid du Colombier // save a finger pointer for next read of the mbox directory 795*7dd7cddfSDavid du Colombier f->foff = pos; 796*7dd7cddfSDavid du Colombier f->fptr = m; 797*7dd7cddfSDavid du Colombier f->fvers = f->mb->vers; 798*7dd7cddfSDavid du Colombier 799*7dd7cddfSDavid du Colombier return n; 800*7dd7cddfSDavid du Colombier } 801*7dd7cddfSDavid du Colombier 802*7dd7cddfSDavid du Colombier int 803*7dd7cddfSDavid du Colombier readmsgdir(Fid *f, char *buf, long off, int cnt) 804*7dd7cddfSDavid du Colombier { 805*7dd7cddfSDavid du Colombier Dir d; 806*7dd7cddfSDavid du Colombier int i, n; 807*7dd7cddfSDavid du Colombier Message *m; 808*7dd7cddfSDavid du Colombier 809*7dd7cddfSDavid du Colombier n = 0; 810*7dd7cddfSDavid du Colombier for(i = 0; cnt > 0 && i < Qmax; i++){ 811*7dd7cddfSDavid du Colombier if(off > 0){ 812*7dd7cddfSDavid du Colombier off--; 813*7dd7cddfSDavid du Colombier continue; 814*7dd7cddfSDavid du Colombier } 815*7dd7cddfSDavid du Colombier mkstat(&d, f->mb, f->m, i); 816*7dd7cddfSDavid du Colombier convD2M(&d, &buf[n]); 817*7dd7cddfSDavid du Colombier n += DIRLEN; 818*7dd7cddfSDavid du Colombier cnt--; 819*7dd7cddfSDavid du Colombier } 820*7dd7cddfSDavid du Colombier for(m = f->m->part; cnt > 0 && m != nil; m = m->next){ 821*7dd7cddfSDavid du Colombier if(off > 0){ 822*7dd7cddfSDavid du Colombier off--; 823*7dd7cddfSDavid du Colombier continue; 824*7dd7cddfSDavid du Colombier } 825*7dd7cddfSDavid du Colombier mkstat(&d, f->mb, m, Qdir); 826*7dd7cddfSDavid du Colombier convD2M(&d, &buf[n]); 827*7dd7cddfSDavid du Colombier n += DIRLEN; 828*7dd7cddfSDavid du Colombier cnt--; 829*7dd7cddfSDavid du Colombier } 830*7dd7cddfSDavid du Colombier 831*7dd7cddfSDavid du Colombier return n; 832*7dd7cddfSDavid du Colombier } 833*7dd7cddfSDavid du Colombier 834*7dd7cddfSDavid du Colombier char* 835*7dd7cddfSDavid du Colombier rread(Fid *f) 836*7dd7cddfSDavid du Colombier { 837*7dd7cddfSDavid du Colombier char *buf; 838*7dd7cddfSDavid du Colombier long off; 839*7dd7cddfSDavid du Colombier int t, i, n, cnt; 840*7dd7cddfSDavid du Colombier char *p; 841*7dd7cddfSDavid du Colombier 842*7dd7cddfSDavid du Colombier thdr.count = 0; 843*7dd7cddfSDavid du Colombier off = rhdr.offset; 844*7dd7cddfSDavid du Colombier buf = thdr.data; 845*7dd7cddfSDavid du Colombier cnt = rhdr.count; 846*7dd7cddfSDavid du Colombier 847*7dd7cddfSDavid du Colombier t = FILE(f->qid.path); 848*7dd7cddfSDavid du Colombier if(f->qid.path & CHDIR){ 849*7dd7cddfSDavid du Colombier cnt /= DIRLEN; 850*7dd7cddfSDavid du Colombier if(off%DIRLEN) 851*7dd7cddfSDavid du Colombier return "i/o error"; 852*7dd7cddfSDavid du Colombier off /= DIRLEN; 853*7dd7cddfSDavid du Colombier 854*7dd7cddfSDavid du Colombier if(t == Qtop) { 855*7dd7cddfSDavid du Colombier qlock(&mbllock); 856*7dd7cddfSDavid du Colombier n = readtopdir(f, buf, off, cnt); 857*7dd7cddfSDavid du Colombier qunlock(&mbllock); 858*7dd7cddfSDavid du Colombier } else if(t == Qmbox) { 859*7dd7cddfSDavid du Colombier qlock(f->mb); 860*7dd7cddfSDavid du Colombier if(off == 0) 861*7dd7cddfSDavid du Colombier syncmbox(f->mb, 1); 862*7dd7cddfSDavid du Colombier n = readmboxdir(f, buf, off, cnt); 863*7dd7cddfSDavid du Colombier qunlock(f->mb); 864*7dd7cddfSDavid du Colombier } else { 865*7dd7cddfSDavid du Colombier n = readmsgdir(f, buf, off, cnt); 866*7dd7cddfSDavid du Colombier } 867*7dd7cddfSDavid du Colombier 868*7dd7cddfSDavid du Colombier thdr.count = n; 869*7dd7cddfSDavid du Colombier return nil; 870*7dd7cddfSDavid du Colombier } 871*7dd7cddfSDavid du Colombier 872*7dd7cddfSDavid du Colombier if(FILE(f->qid.path) == Qheader){ 873*7dd7cddfSDavid du Colombier thdr.count = readheader(f->m, buf, off, cnt); 874*7dd7cddfSDavid du Colombier return nil; 875*7dd7cddfSDavid du Colombier } 876*7dd7cddfSDavid du Colombier 877*7dd7cddfSDavid du Colombier if(FILE(f->qid.path) == Qinfo){ 878*7dd7cddfSDavid du Colombier thdr.count = readinfo(f->m, buf, off, cnt); 879*7dd7cddfSDavid du Colombier return nil; 880*7dd7cddfSDavid du Colombier } 881*7dd7cddfSDavid du Colombier 882*7dd7cddfSDavid du Colombier i = fileinfo(f->m, FILE(f->qid.path), &p); 883*7dd7cddfSDavid du Colombier if(off < i){ 884*7dd7cddfSDavid du Colombier if((off + cnt) > i) 885*7dd7cddfSDavid du Colombier cnt = i - off; 886*7dd7cddfSDavid du Colombier memmove(buf, p + off, cnt); 887*7dd7cddfSDavid du Colombier thdr.count = cnt; 888*7dd7cddfSDavid du Colombier } 889*7dd7cddfSDavid du Colombier return nil; 890*7dd7cddfSDavid du Colombier } 891*7dd7cddfSDavid du Colombier 892*7dd7cddfSDavid du Colombier char* 893*7dd7cddfSDavid du Colombier rwrite(Fid *f) 894*7dd7cddfSDavid du Colombier { 895*7dd7cddfSDavid du Colombier char *err; 896*7dd7cddfSDavid du Colombier char *token[1024]; 897*7dd7cddfSDavid du Colombier int t, n; 898*7dd7cddfSDavid du Colombier String *file; 899*7dd7cddfSDavid du Colombier 900*7dd7cddfSDavid du Colombier t = FILE(f->qid.path); 901*7dd7cddfSDavid du Colombier switch(t){ 902*7dd7cddfSDavid du Colombier case Qctl: 903*7dd7cddfSDavid du Colombier if(rhdr.count == 0) 904*7dd7cddfSDavid du Colombier return Ebadctl; 905*7dd7cddfSDavid du Colombier if(rhdr.data[rhdr.count-1] == '\n') 906*7dd7cddfSDavid du Colombier rhdr.data[rhdr.count-1] = 0; 907*7dd7cddfSDavid du Colombier else 908*7dd7cddfSDavid du Colombier rhdr.data[rhdr.count] = 0; 909*7dd7cddfSDavid du Colombier n = tokenize(rhdr.data, token, nelem(token)); 910*7dd7cddfSDavid du Colombier if(n == 0) 911*7dd7cddfSDavid du Colombier return Ebadctl; 912*7dd7cddfSDavid du Colombier if(strcmp(token[0], "open") == 0){ 913*7dd7cddfSDavid du Colombier file = s_new(); 914*7dd7cddfSDavid du Colombier switch(n){ 915*7dd7cddfSDavid du Colombier case 1: 916*7dd7cddfSDavid du Colombier err = Ebadctl; 917*7dd7cddfSDavid du Colombier break; 918*7dd7cddfSDavid du Colombier case 2: 919*7dd7cddfSDavid du Colombier mboxpath(token[1], getlog(), file, 0); 920*7dd7cddfSDavid du Colombier err = newmbox(s_to_c(file), nil, 0); 921*7dd7cddfSDavid du Colombier break; 922*7dd7cddfSDavid du Colombier default: 923*7dd7cddfSDavid du Colombier mboxpath(token[1], getlog(), file, 0); 924*7dd7cddfSDavid du Colombier err = newmbox(s_to_c(file), token[2], 0); 925*7dd7cddfSDavid du Colombier break; 926*7dd7cddfSDavid du Colombier } 927*7dd7cddfSDavid du Colombier s_free(file); 928*7dd7cddfSDavid du Colombier thdr.count = rhdr.count; 929*7dd7cddfSDavid du Colombier return err; 930*7dd7cddfSDavid du Colombier } 931*7dd7cddfSDavid du Colombier if(strcmp(token[0], "close") == 0){ 932*7dd7cddfSDavid du Colombier if(n < 2) 933*7dd7cddfSDavid du Colombier return nil; 934*7dd7cddfSDavid du Colombier freembox(token[1]); 935*7dd7cddfSDavid du Colombier return nil; 936*7dd7cddfSDavid du Colombier } 937*7dd7cddfSDavid du Colombier if(strcmp(token[0], "delete") == 0){ 938*7dd7cddfSDavid du Colombier if(n < 3) 939*7dd7cddfSDavid du Colombier return nil; 940*7dd7cddfSDavid du Colombier delmessages(n-1, &token[1]); 941*7dd7cddfSDavid du Colombier thdr.count = rhdr.count; 942*7dd7cddfSDavid du Colombier return nil; 943*7dd7cddfSDavid du Colombier } 944*7dd7cddfSDavid du Colombier // if(strcmp(token[0], "pooldump") == 0){ 945*7dd7cddfSDavid du Colombier // print("msgallocd %d, msgfreed %d\n", msgallocd, msgfreed); 946*7dd7cddfSDavid du Colombier // pooldump("Main"); 947*7dd7cddfSDavid du Colombier // return nil; 948*7dd7cddfSDavid du Colombier // } 949*7dd7cddfSDavid du Colombier return Ebadctl; 950*7dd7cddfSDavid du Colombier } 951*7dd7cddfSDavid du Colombier return Eperm; 952*7dd7cddfSDavid du Colombier } 953*7dd7cddfSDavid du Colombier 954*7dd7cddfSDavid du Colombier char * 955*7dd7cddfSDavid du Colombier rclunk(Fid *f) 956*7dd7cddfSDavid du Colombier { 957*7dd7cddfSDavid du Colombier Mailbox *mb; 958*7dd7cddfSDavid du Colombier 959*7dd7cddfSDavid du Colombier f->busy = 0; 960*7dd7cddfSDavid du Colombier f->open = 0; 961*7dd7cddfSDavid du Colombier if(f->mtop != nil){ 962*7dd7cddfSDavid du Colombier qlock(f->mb); 963*7dd7cddfSDavid du Colombier msgdecref(f->mb, f->mtop); 964*7dd7cddfSDavid du Colombier qunlock(f->mb); 965*7dd7cddfSDavid du Colombier } 966*7dd7cddfSDavid du Colombier f->m = f->mtop = nil; 967*7dd7cddfSDavid du Colombier mb = f->mb; 968*7dd7cddfSDavid du Colombier if(mb != nil){ 969*7dd7cddfSDavid du Colombier f->mb = nil; 970*7dd7cddfSDavid du Colombier qlock(&mbllock); 971*7dd7cddfSDavid du Colombier mboxdecref(mb); 972*7dd7cddfSDavid du Colombier qunlock(&mbllock); 973*7dd7cddfSDavid du Colombier } 974*7dd7cddfSDavid du Colombier return 0; 975*7dd7cddfSDavid du Colombier } 976*7dd7cddfSDavid du Colombier 977*7dd7cddfSDavid du Colombier char * 978*7dd7cddfSDavid du Colombier rremove(Fid *f) 979*7dd7cddfSDavid du Colombier { 980*7dd7cddfSDavid du Colombier if(f->m->deleted == 0) 981*7dd7cddfSDavid du Colombier mailplumb(f->mb, f->m, 1); 982*7dd7cddfSDavid du Colombier f->m->deleted = 1; 983*7dd7cddfSDavid du Colombier return rclunk(f); 984*7dd7cddfSDavid du Colombier } 985*7dd7cddfSDavid du Colombier 986*7dd7cddfSDavid du Colombier char * 987*7dd7cddfSDavid du Colombier rstat(Fid *f) 988*7dd7cddfSDavid du Colombier { 989*7dd7cddfSDavid du Colombier Dir d; 990*7dd7cddfSDavid du Colombier 991*7dd7cddfSDavid du Colombier if(FILE(f->qid.path) == Qmbox){ 992*7dd7cddfSDavid du Colombier qlock(f->mb); 993*7dd7cddfSDavid du Colombier syncmbox(f->mb, 1); 994*7dd7cddfSDavid du Colombier qunlock(f->mb); 995*7dd7cddfSDavid du Colombier } 996*7dd7cddfSDavid du Colombier mkstat(&d, f->mb, f->m, FILE(f->qid.path)); 997*7dd7cddfSDavid du Colombier convD2M(&d, thdr.stat); 998*7dd7cddfSDavid du Colombier return 0; 999*7dd7cddfSDavid du Colombier } 1000*7dd7cddfSDavid du Colombier 1001*7dd7cddfSDavid du Colombier char * 1002*7dd7cddfSDavid du Colombier rwstat(Fid*) 1003*7dd7cddfSDavid du Colombier { 1004*7dd7cddfSDavid du Colombier return Eperm; 1005*7dd7cddfSDavid du Colombier } 1006*7dd7cddfSDavid du Colombier 1007*7dd7cddfSDavid du Colombier Fid * 1008*7dd7cddfSDavid du Colombier newfid(int fid) 1009*7dd7cddfSDavid du Colombier { 1010*7dd7cddfSDavid du Colombier Fid *f, *ff; 1011*7dd7cddfSDavid du Colombier 1012*7dd7cddfSDavid du Colombier ff = 0; 1013*7dd7cddfSDavid du Colombier for(f = fids; f; f = f->next) 1014*7dd7cddfSDavid du Colombier if(f->fid == fid) 1015*7dd7cddfSDavid du Colombier return f; 1016*7dd7cddfSDavid du Colombier else if(!ff && !f->busy) 1017*7dd7cddfSDavid du Colombier ff = f; 1018*7dd7cddfSDavid du Colombier if(ff){ 1019*7dd7cddfSDavid du Colombier ff->fid = fid; 1020*7dd7cddfSDavid du Colombier return ff; 1021*7dd7cddfSDavid du Colombier } 1022*7dd7cddfSDavid du Colombier f = emalloc(sizeof *f); 1023*7dd7cddfSDavid du Colombier f->fid = fid; 1024*7dd7cddfSDavid du Colombier f->next = fids; 1025*7dd7cddfSDavid du Colombier fids = f; 1026*7dd7cddfSDavid du Colombier return f; 1027*7dd7cddfSDavid du Colombier } 1028*7dd7cddfSDavid du Colombier 1029*7dd7cddfSDavid du Colombier int 1030*7dd7cddfSDavid du Colombier fidmboxrefs(Mailbox *mb) 1031*7dd7cddfSDavid du Colombier { 1032*7dd7cddfSDavid du Colombier Fid *f; 1033*7dd7cddfSDavid du Colombier int refs = 0; 1034*7dd7cddfSDavid du Colombier 1035*7dd7cddfSDavid du Colombier for(f = fids; f; f = f->next){ 1036*7dd7cddfSDavid du Colombier if(f->mb == mb) 1037*7dd7cddfSDavid du Colombier refs++; 1038*7dd7cddfSDavid du Colombier } 1039*7dd7cddfSDavid du Colombier return refs; 1040*7dd7cddfSDavid du Colombier } 1041*7dd7cddfSDavid du Colombier 1042*7dd7cddfSDavid du Colombier void 1043*7dd7cddfSDavid du Colombier io(void) 1044*7dd7cddfSDavid du Colombier { 1045*7dd7cddfSDavid du Colombier char *err; 1046*7dd7cddfSDavid du Colombier int n; 1047*7dd7cddfSDavid du Colombier 1048*7dd7cddfSDavid du Colombier // start a process to watch the mailboxes 1049*7dd7cddfSDavid du Colombier switch(rfork(RFPROC|RFMEM)){ 1050*7dd7cddfSDavid du Colombier case -1: 1051*7dd7cddfSDavid du Colombier /* oh well */ 1052*7dd7cddfSDavid du Colombier break; 1053*7dd7cddfSDavid du Colombier case 0: 1054*7dd7cddfSDavid du Colombier reader(); 1055*7dd7cddfSDavid du Colombier exits(nil); 1056*7dd7cddfSDavid du Colombier default: 1057*7dd7cddfSDavid du Colombier break; 1058*7dd7cddfSDavid du Colombier } 1059*7dd7cddfSDavid du Colombier 1060*7dd7cddfSDavid du Colombier for(;;){ 1061*7dd7cddfSDavid du Colombier /* 1062*7dd7cddfSDavid du Colombier * reading from a pipe or a network device 1063*7dd7cddfSDavid du Colombier * will give an error after a few eof reads 1064*7dd7cddfSDavid du Colombier * however, we cannot tell the difference 1065*7dd7cddfSDavid du Colombier * between a zero-length read and an interrupt 1066*7dd7cddfSDavid du Colombier * on the processes writing to us, 1067*7dd7cddfSDavid du Colombier * so we wait for the error 1068*7dd7cddfSDavid du Colombier */ 1069*7dd7cddfSDavid du Colombier n = read(mfd[0], mdata, sizeof mdata); 1070*7dd7cddfSDavid du Colombier if(n == 0) 1071*7dd7cddfSDavid du Colombier continue; 1072*7dd7cddfSDavid du Colombier if(n < 0) 1073*7dd7cddfSDavid du Colombier return; 1074*7dd7cddfSDavid du Colombier if(convM2S(mdata, &rhdr, n) == 0) 1075*7dd7cddfSDavid du Colombier continue; 1076*7dd7cddfSDavid du Colombier 1077*7dd7cddfSDavid du Colombier if(debug) 1078*7dd7cddfSDavid du Colombier fprint(2, "%s:<-%F\n", argv0, &rhdr); 1079*7dd7cddfSDavid du Colombier 1080*7dd7cddfSDavid du Colombier thdr.data = mdata + MAXMSG; 1081*7dd7cddfSDavid du Colombier if(!fcalls[rhdr.type]) 1082*7dd7cddfSDavid du Colombier err = "bad fcall type"; 1083*7dd7cddfSDavid du Colombier else 1084*7dd7cddfSDavid du Colombier err = (*fcalls[rhdr.type])(newfid(rhdr.fid)); 1085*7dd7cddfSDavid du Colombier if(err){ 1086*7dd7cddfSDavid du Colombier thdr.type = Rerror; 1087*7dd7cddfSDavid du Colombier strncpy(thdr.ename, err, ERRLEN); 1088*7dd7cddfSDavid du Colombier }else{ 1089*7dd7cddfSDavid du Colombier thdr.type = rhdr.type + 1; 1090*7dd7cddfSDavid du Colombier thdr.fid = rhdr.fid; 1091*7dd7cddfSDavid du Colombier } 1092*7dd7cddfSDavid du Colombier thdr.tag = rhdr.tag; 1093*7dd7cddfSDavid du Colombier if(debug) 1094*7dd7cddfSDavid du Colombier fprint(2, "%s:->%F\n", argv0, &thdr);/**/ 1095*7dd7cddfSDavid du Colombier n = convS2M(&thdr, mdata); 1096*7dd7cddfSDavid du Colombier if(write(mfd[1], mdata, n) != n) 1097*7dd7cddfSDavid du Colombier error("mount write"); 1098*7dd7cddfSDavid du Colombier } 1099*7dd7cddfSDavid du Colombier } 1100*7dd7cddfSDavid du Colombier 1101*7dd7cddfSDavid du Colombier void 1102*7dd7cddfSDavid du Colombier reader(void) 1103*7dd7cddfSDavid du Colombier { 1104*7dd7cddfSDavid du Colombier Dir d; 1105*7dd7cddfSDavid du Colombier Mailbox *mb; 1106*7dd7cddfSDavid du Colombier 1107*7dd7cddfSDavid du Colombier sleep(15*1000); 1108*7dd7cddfSDavid du Colombier for(;;){ 1109*7dd7cddfSDavid du Colombier qlock(&mbllock); 1110*7dd7cddfSDavid du Colombier for(mb = mbl; mb != nil; mb = mb->next){ 1111*7dd7cddfSDavid du Colombier if(dirstat(mb->path, &d) < 0) 1112*7dd7cddfSDavid du Colombier continue; 1113*7dd7cddfSDavid du Colombier 1114*7dd7cddfSDavid du Colombier if(d.qid.path != mb->d.qid.path 1115*7dd7cddfSDavid du Colombier || d.qid.vers != mb->d.qid.vers){ 1116*7dd7cddfSDavid du Colombier qlock(mb); 1117*7dd7cddfSDavid du Colombier break; 1118*7dd7cddfSDavid du Colombier } 1119*7dd7cddfSDavid du Colombier } 1120*7dd7cddfSDavid du Colombier qunlock(&mbllock); 1121*7dd7cddfSDavid du Colombier if(mb != nil){ 1122*7dd7cddfSDavid du Colombier syncmbox(mb, 1); 1123*7dd7cddfSDavid du Colombier qunlock(mb); 1124*7dd7cddfSDavid du Colombier } else 1125*7dd7cddfSDavid du Colombier sleep(15*1000); 1126*7dd7cddfSDavid du Colombier } 1127*7dd7cddfSDavid du Colombier } 1128*7dd7cddfSDavid du Colombier 1129*7dd7cddfSDavid du Colombier int 1130*7dd7cddfSDavid du Colombier newid(void) 1131*7dd7cddfSDavid du Colombier { 1132*7dd7cddfSDavid du Colombier int rv; 1133*7dd7cddfSDavid du Colombier static int id; 1134*7dd7cddfSDavid du Colombier static Lock idlock; 1135*7dd7cddfSDavid du Colombier 1136*7dd7cddfSDavid du Colombier lock(&idlock); 1137*7dd7cddfSDavid du Colombier rv = ++id; 1138*7dd7cddfSDavid du Colombier unlock(&idlock); 1139*7dd7cddfSDavid du Colombier 1140*7dd7cddfSDavid du Colombier return rv; 1141*7dd7cddfSDavid du Colombier } 1142*7dd7cddfSDavid du Colombier 1143*7dd7cddfSDavid du Colombier void 1144*7dd7cddfSDavid du Colombier error(char *s) 1145*7dd7cddfSDavid du Colombier { 1146*7dd7cddfSDavid du Colombier postnote(PNGROUP, getpid(), "die yankee pig dog"); 1147*7dd7cddfSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, s); 1148*7dd7cddfSDavid du Colombier exits(s); 1149*7dd7cddfSDavid du Colombier } 1150*7dd7cddfSDavid du Colombier 1151*7dd7cddfSDavid du Colombier 1152*7dd7cddfSDavid du Colombier typedef struct Ignorance Ignorance; 1153*7dd7cddfSDavid du Colombier struct Ignorance 1154*7dd7cddfSDavid du Colombier { 1155*7dd7cddfSDavid du Colombier Ignorance *next; 1156*7dd7cddfSDavid du Colombier char *str; /* string */ 1157*7dd7cddfSDavid du Colombier int partial; /* true if not exact match */ 1158*7dd7cddfSDavid du Colombier }; 1159*7dd7cddfSDavid du Colombier Ignorance *ignorance; 1160*7dd7cddfSDavid du Colombier 1161*7dd7cddfSDavid du Colombier /* 1162*7dd7cddfSDavid du Colombier * read the file of headers to ignore 1163*7dd7cddfSDavid du Colombier */ 1164*7dd7cddfSDavid du Colombier void 1165*7dd7cddfSDavid du Colombier readignore(void) 1166*7dd7cddfSDavid du Colombier { 1167*7dd7cddfSDavid du Colombier char *p; 1168*7dd7cddfSDavid du Colombier Ignorance *i; 1169*7dd7cddfSDavid du Colombier Biobuf *b; 1170*7dd7cddfSDavid du Colombier 1171*7dd7cddfSDavid du Colombier if(ignorance != nil) 1172*7dd7cddfSDavid du Colombier return; 1173*7dd7cddfSDavid du Colombier 1174*7dd7cddfSDavid du Colombier b = Bopen("/mail/lib/ignore", OREAD); 1175*7dd7cddfSDavid du Colombier if(b == 0) 1176*7dd7cddfSDavid du Colombier return; 1177*7dd7cddfSDavid du Colombier while(p = Brdline(b, '\n')){ 1178*7dd7cddfSDavid du Colombier p[Blinelen(b)-1] = 0; 1179*7dd7cddfSDavid du Colombier while(*p && (*p == ' ' || *p == '\t')) 1180*7dd7cddfSDavid du Colombier p++; 1181*7dd7cddfSDavid du Colombier if(*p == '#') 1182*7dd7cddfSDavid du Colombier continue; 1183*7dd7cddfSDavid du Colombier i = malloc(sizeof(Ignorance)); 1184*7dd7cddfSDavid du Colombier if(i == 0) 1185*7dd7cddfSDavid du Colombier break; 1186*7dd7cddfSDavid du Colombier i->partial = strlen(p); 1187*7dd7cddfSDavid du Colombier i->str = strdup(p); 1188*7dd7cddfSDavid du Colombier if(i->str == 0){ 1189*7dd7cddfSDavid du Colombier free(i); 1190*7dd7cddfSDavid du Colombier break; 1191*7dd7cddfSDavid du Colombier } 1192*7dd7cddfSDavid du Colombier i->next = ignorance; 1193*7dd7cddfSDavid du Colombier ignorance = i; 1194*7dd7cddfSDavid du Colombier } 1195*7dd7cddfSDavid du Colombier Bterm(b); 1196*7dd7cddfSDavid du Colombier } 1197*7dd7cddfSDavid du Colombier 1198*7dd7cddfSDavid du Colombier int 1199*7dd7cddfSDavid du Colombier ignore(char *p) 1200*7dd7cddfSDavid du Colombier { 1201*7dd7cddfSDavid du Colombier Ignorance *i; 1202*7dd7cddfSDavid du Colombier 1203*7dd7cddfSDavid du Colombier readignore(); 1204*7dd7cddfSDavid du Colombier for(i = ignorance; i != nil; i = i->next) 1205*7dd7cddfSDavid du Colombier if(cistrncmp(i->str, p, i->partial) == 0) 1206*7dd7cddfSDavid du Colombier return 1; 1207*7dd7cddfSDavid du Colombier return 0; 1208*7dd7cddfSDavid du Colombier } 1209*7dd7cddfSDavid du Colombier 1210*7dd7cddfSDavid du Colombier int 1211*7dd7cddfSDavid du Colombier hdrlen(char *p, char *e) 1212*7dd7cddfSDavid du Colombier { 1213*7dd7cddfSDavid du Colombier char *ep; 1214*7dd7cddfSDavid du Colombier 1215*7dd7cddfSDavid du Colombier ep = p; 1216*7dd7cddfSDavid du Colombier do { 1217*7dd7cddfSDavid du Colombier ep = strchr(ep, '\n'); 1218*7dd7cddfSDavid du Colombier if(ep == nil){ 1219*7dd7cddfSDavid du Colombier ep = e; 1220*7dd7cddfSDavid du Colombier break; 1221*7dd7cddfSDavid du Colombier } 1222*7dd7cddfSDavid du Colombier ep++; 1223*7dd7cddfSDavid du Colombier if(ep >= e){ 1224*7dd7cddfSDavid du Colombier ep = e; 1225*7dd7cddfSDavid du Colombier break; 1226*7dd7cddfSDavid du Colombier } 1227*7dd7cddfSDavid du Colombier } while(*ep == ' ' || *ep == '\t'); 1228*7dd7cddfSDavid du Colombier return ep - p; 1229*7dd7cddfSDavid du Colombier } 1230*7dd7cddfSDavid du Colombier 1231*7dd7cddfSDavid du Colombier // rfc2047 non-ascii 1232*7dd7cddfSDavid du Colombier typedef struct Charset Charset; 1233*7dd7cddfSDavid du Colombier struct Charset { 1234*7dd7cddfSDavid du Colombier char *name; 1235*7dd7cddfSDavid du Colombier int len; 1236*7dd7cddfSDavid du Colombier int convert; 1237*7dd7cddfSDavid du Colombier } charsets[4] = 1238*7dd7cddfSDavid du Colombier { 1239*7dd7cddfSDavid du Colombier { "us-ascii", 8, 1, }, 1240*7dd7cddfSDavid du Colombier { "utf-8", 5, 0, }, 1241*7dd7cddfSDavid du Colombier { "iso-8859-1", 10, 1, }, 1242*7dd7cddfSDavid du Colombier { "big5", 4, 2, }, 1243*7dd7cddfSDavid du Colombier }; 1244*7dd7cddfSDavid du Colombier 1245*7dd7cddfSDavid du Colombier // convert a single token 1246*7dd7cddfSDavid du Colombier int 1247*7dd7cddfSDavid du Colombier tokenconvert(String *s, char *token, int len) 1248*7dd7cddfSDavid du Colombier { 1249*7dd7cddfSDavid du Colombier char decoded[1024]; 1250*7dd7cddfSDavid du Colombier char utfbuf[2*1024]; 1251*7dd7cddfSDavid du Colombier int i, havequote; 1252*7dd7cddfSDavid du Colombier char *e, *x; 1253*7dd7cddfSDavid du Colombier 1254*7dd7cddfSDavid du Colombier if(len == 0) 1255*7dd7cddfSDavid du Colombier return -1; 1256*7dd7cddfSDavid du Colombier 1257*7dd7cddfSDavid du Colombier havequote = 0; 1258*7dd7cddfSDavid du Colombier if(token[0] == '"' && token[len-1] == '"'){ 1259*7dd7cddfSDavid du Colombier havequote = 1; 1260*7dd7cddfSDavid du Colombier token++; 1261*7dd7cddfSDavid du Colombier len -= 2; 1262*7dd7cddfSDavid du Colombier } 1263*7dd7cddfSDavid du Colombier 1264*7dd7cddfSDavid du Colombier if(token[0] != '=' || token[1] != '?' || 1265*7dd7cddfSDavid du Colombier token[len-2] != '?' || token[len-1] != '=') 1266*7dd7cddfSDavid du Colombier return -1; 1267*7dd7cddfSDavid du Colombier e = token+len-2; 1268*7dd7cddfSDavid du Colombier token += 2; 1269*7dd7cddfSDavid du Colombier 1270*7dd7cddfSDavid du Colombier // bail if we don't understand the character set 1271*7dd7cddfSDavid du Colombier for(i = 0; i < nelem(charsets); i++) 1272*7dd7cddfSDavid du Colombier if(cistrncmp(charsets[i].name, token, charsets[i].len) == 0) 1273*7dd7cddfSDavid du Colombier if(token[charsets[i].len] == '?'){ 1274*7dd7cddfSDavid du Colombier token += charsets[i].len + 1; 1275*7dd7cddfSDavid du Colombier break; 1276*7dd7cddfSDavid du Colombier } 1277*7dd7cddfSDavid du Colombier if(i >= nelem(charsets)) 1278*7dd7cddfSDavid du Colombier return -1; 1279*7dd7cddfSDavid du Colombier 1280*7dd7cddfSDavid du Colombier // bail if it doesn't fit 1281*7dd7cddfSDavid du Colombier if(strlen(token) > sizeof(decoded)-1) 1282*7dd7cddfSDavid du Colombier return -1; 1283*7dd7cddfSDavid du Colombier 1284*7dd7cddfSDavid du Colombier // bail if we don't understand the encoding 1285*7dd7cddfSDavid du Colombier if(cistrncmp(token, "b?", 2) == 0){ 1286*7dd7cddfSDavid du Colombier token += 2; 1287*7dd7cddfSDavid du Colombier len = dec64((uchar*)decoded, sizeof(decoded), token, e-token); 1288*7dd7cddfSDavid du Colombier decoded[len] = 0; 1289*7dd7cddfSDavid du Colombier } else if(cistrncmp(token, "q?", 2) == 0){ 1290*7dd7cddfSDavid du Colombier token += 2; 1291*7dd7cddfSDavid du Colombier len = decquoted(decoded, token, e); 1292*7dd7cddfSDavid du Colombier if(len > 0 && decoded[len-1] == '\n') 1293*7dd7cddfSDavid du Colombier len--; 1294*7dd7cddfSDavid du Colombier decoded[len] = 0; 1295*7dd7cddfSDavid du Colombier } else 1296*7dd7cddfSDavid du Colombier return -1; 1297*7dd7cddfSDavid du Colombier 1298*7dd7cddfSDavid du Colombier if(havequote) 1299*7dd7cddfSDavid du Colombier s_append(s, "\""); 1300*7dd7cddfSDavid du Colombier switch(charsets[i].convert){ 1301*7dd7cddfSDavid du Colombier case 0: 1302*7dd7cddfSDavid du Colombier s_append(s, decoded); 1303*7dd7cddfSDavid du Colombier break; 1304*7dd7cddfSDavid du Colombier case 1: 1305*7dd7cddfSDavid du Colombier latin1toutf(utfbuf, decoded, decoded+len); 1306*7dd7cddfSDavid du Colombier s_append(s, utfbuf); 1307*7dd7cddfSDavid du Colombier break; 1308*7dd7cddfSDavid du Colombier case 2: 1309*7dd7cddfSDavid du Colombier if(xtoutf(charsets[i].name, &x, decoded, decoded+len) <= 0){ 1310*7dd7cddfSDavid du Colombier s_append(s, decoded); 1311*7dd7cddfSDavid du Colombier } else { 1312*7dd7cddfSDavid du Colombier s_append(s, x); 1313*7dd7cddfSDavid du Colombier free(x); 1314*7dd7cddfSDavid du Colombier } 1315*7dd7cddfSDavid du Colombier break; 1316*7dd7cddfSDavid du Colombier } 1317*7dd7cddfSDavid du Colombier if(havequote) 1318*7dd7cddfSDavid du Colombier s_append(s, "\""); 1319*7dd7cddfSDavid du Colombier 1320*7dd7cddfSDavid du Colombier return 0; 1321*7dd7cddfSDavid du Colombier } 1322*7dd7cddfSDavid du Colombier 1323*7dd7cddfSDavid du Colombier // convert a header line 1324*7dd7cddfSDavid du Colombier String* 1325*7dd7cddfSDavid du Colombier hdrconvert(String *s, char *line, int len) 1326*7dd7cddfSDavid du Colombier { 1327*7dd7cddfSDavid du Colombier char *end; 1328*7dd7cddfSDavid du Colombier char token[1024]; 1329*7dd7cddfSDavid du Colombier int i; 1330*7dd7cddfSDavid du Colombier 1331*7dd7cddfSDavid du Colombier end = line+len; 1332*7dd7cddfSDavid du Colombier s = s_reset(s); 1333*7dd7cddfSDavid du Colombier i = 0; 1334*7dd7cddfSDavid du Colombier if(memchr(line, '=', len) == 0){ 1335*7dd7cddfSDavid du Colombier s_nappend(s, line, len); 1336*7dd7cddfSDavid du Colombier return s; 1337*7dd7cddfSDavid du Colombier } 1338*7dd7cddfSDavid du Colombier while(line < end){ 1339*7dd7cddfSDavid du Colombier switch(*line){ 1340*7dd7cddfSDavid du Colombier case ' ': 1341*7dd7cddfSDavid du Colombier case '\t': 1342*7dd7cddfSDavid du Colombier case '\n': 1343*7dd7cddfSDavid du Colombier token[i] = 0; 1344*7dd7cddfSDavid du Colombier if(tokenconvert(s, token, i) < 0){ 1345*7dd7cddfSDavid du Colombier token[i++] = *line++; 1346*7dd7cddfSDavid du Colombier token[i] = 0; 1347*7dd7cddfSDavid du Colombier s_append(s, token); 1348*7dd7cddfSDavid du Colombier i = 0; 1349*7dd7cddfSDavid du Colombier continue; 1350*7dd7cddfSDavid du Colombier } 1351*7dd7cddfSDavid du Colombier s_putc(s, *line++); 1352*7dd7cddfSDavid du Colombier s_terminate(s); 1353*7dd7cddfSDavid du Colombier i = 0; 1354*7dd7cddfSDavid du Colombier break; 1355*7dd7cddfSDavid du Colombier 1356*7dd7cddfSDavid du Colombier default: 1357*7dd7cddfSDavid du Colombier if(i >= sizeof(token)-3){ 1358*7dd7cddfSDavid du Colombier token[i++] = *line++; 1359*7dd7cddfSDavid du Colombier token[i] = 0; 1360*7dd7cddfSDavid du Colombier s_append(s, token); 1361*7dd7cddfSDavid du Colombier i = 0; 1362*7dd7cddfSDavid du Colombier continue; 1363*7dd7cddfSDavid du Colombier } 1364*7dd7cddfSDavid du Colombier token[i++] = *line++; 1365*7dd7cddfSDavid du Colombier break; 1366*7dd7cddfSDavid du Colombier } 1367*7dd7cddfSDavid du Colombier } 1368*7dd7cddfSDavid du Colombier return s; 1369*7dd7cddfSDavid du Colombier } 1370*7dd7cddfSDavid du Colombier 1371*7dd7cddfSDavid du Colombier int 1372*7dd7cddfSDavid du Colombier readheader(Message *m, char *buf, int off, int cnt) 1373*7dd7cddfSDavid du Colombier { 1374*7dd7cddfSDavid du Colombier char *p, *e; 1375*7dd7cddfSDavid du Colombier int n, ns; 1376*7dd7cddfSDavid du Colombier char *to = buf; 1377*7dd7cddfSDavid du Colombier String *s; 1378*7dd7cddfSDavid du Colombier 1379*7dd7cddfSDavid du Colombier p = m->header; 1380*7dd7cddfSDavid du Colombier e = m->hend; 1381*7dd7cddfSDavid du Colombier s = nil; 1382*7dd7cddfSDavid du Colombier 1383*7dd7cddfSDavid du Colombier // copy in good headers 1384*7dd7cddfSDavid du Colombier while(cnt > 0 && p < e){ 1385*7dd7cddfSDavid du Colombier n = hdrlen(p, e); 1386*7dd7cddfSDavid du Colombier if(ignore(p)){ 1387*7dd7cddfSDavid du Colombier p += n; 1388*7dd7cddfSDavid du Colombier continue; 1389*7dd7cddfSDavid du Colombier } 1390*7dd7cddfSDavid du Colombier 1391*7dd7cddfSDavid du Colombier // rfc2047 processing 1392*7dd7cddfSDavid du Colombier s = hdrconvert(s, p, n); 1393*7dd7cddfSDavid du Colombier ns = s_len(s); 1394*7dd7cddfSDavid du Colombier if(off > 0){ 1395*7dd7cddfSDavid du Colombier if(ns <= off){ 1396*7dd7cddfSDavid du Colombier off -= ns; 1397*7dd7cddfSDavid du Colombier p += n; 1398*7dd7cddfSDavid du Colombier continue; 1399*7dd7cddfSDavid du Colombier } 1400*7dd7cddfSDavid du Colombier ns -= off; 1401*7dd7cddfSDavid du Colombier } 1402*7dd7cddfSDavid du Colombier if(ns > cnt) 1403*7dd7cddfSDavid du Colombier ns = cnt; 1404*7dd7cddfSDavid du Colombier memmove(to, s_to_c(s)+off, ns); 1405*7dd7cddfSDavid du Colombier to += ns; 1406*7dd7cddfSDavid du Colombier p += n; 1407*7dd7cddfSDavid du Colombier cnt -= ns; 1408*7dd7cddfSDavid du Colombier off = 0; 1409*7dd7cddfSDavid du Colombier } 1410*7dd7cddfSDavid du Colombier 1411*7dd7cddfSDavid du Colombier s_free(s); 1412*7dd7cddfSDavid du Colombier return to - buf; 1413*7dd7cddfSDavid du Colombier } 1414*7dd7cddfSDavid du Colombier 1415*7dd7cddfSDavid du Colombier int 1416*7dd7cddfSDavid du Colombier headerlen(Message *m) 1417*7dd7cddfSDavid du Colombier { 1418*7dd7cddfSDavid du Colombier char buf[1024]; 1419*7dd7cddfSDavid du Colombier int i, n; 1420*7dd7cddfSDavid du Colombier 1421*7dd7cddfSDavid du Colombier if(m->hlen >= 0) 1422*7dd7cddfSDavid du Colombier return m->hlen; 1423*7dd7cddfSDavid du Colombier for(n = 0; ; n += i){ 1424*7dd7cddfSDavid du Colombier i = readheader(m, buf, n, sizeof(buf)); 1425*7dd7cddfSDavid du Colombier if(i <= 0) 1426*7dd7cddfSDavid du Colombier break; 1427*7dd7cddfSDavid du Colombier } 1428*7dd7cddfSDavid du Colombier m->hlen = n; 1429*7dd7cddfSDavid du Colombier return n; 1430*7dd7cddfSDavid du Colombier } 1431*7dd7cddfSDavid du Colombier 1432*7dd7cddfSDavid du Colombier QLock hashlock; 1433*7dd7cddfSDavid du Colombier 1434*7dd7cddfSDavid du Colombier uint 1435*7dd7cddfSDavid du Colombier hash(ulong ppath, char *name) 1436*7dd7cddfSDavid du Colombier { 1437*7dd7cddfSDavid du Colombier uchar *p; 1438*7dd7cddfSDavid du Colombier uint h; 1439*7dd7cddfSDavid du Colombier 1440*7dd7cddfSDavid du Colombier h = 0; 1441*7dd7cddfSDavid du Colombier for(p = (uchar*)name; *p; p++) 1442*7dd7cddfSDavid du Colombier h = h*7 + *p; 1443*7dd7cddfSDavid du Colombier h += ppath; 1444*7dd7cddfSDavid du Colombier 1445*7dd7cddfSDavid du Colombier return h % Hsize; 1446*7dd7cddfSDavid du Colombier } 1447*7dd7cddfSDavid du Colombier 1448*7dd7cddfSDavid du Colombier Hash* 1449*7dd7cddfSDavid du Colombier hlook(ulong ppath, char *name) 1450*7dd7cddfSDavid du Colombier { 1451*7dd7cddfSDavid du Colombier int h; 1452*7dd7cddfSDavid du Colombier Hash *hp; 1453*7dd7cddfSDavid du Colombier 1454*7dd7cddfSDavid du Colombier qlock(&hashlock); 1455*7dd7cddfSDavid du Colombier h = hash(ppath, name); 1456*7dd7cddfSDavid du Colombier for(hp = htab[h]; hp != nil; hp = hp->next) 1457*7dd7cddfSDavid du Colombier if(ppath == hp->ppath && strcmp(name, hp->name) == 0){ 1458*7dd7cddfSDavid du Colombier qunlock(&hashlock); 1459*7dd7cddfSDavid du Colombier return hp; 1460*7dd7cddfSDavid du Colombier } 1461*7dd7cddfSDavid du Colombier qunlock(&hashlock); 1462*7dd7cddfSDavid du Colombier return nil; 1463*7dd7cddfSDavid du Colombier } 1464*7dd7cddfSDavid du Colombier 1465*7dd7cddfSDavid du Colombier void 1466*7dd7cddfSDavid du Colombier henter(ulong ppath, char *name, Qid qid, Message *m, Mailbox *mb) 1467*7dd7cddfSDavid du Colombier { 1468*7dd7cddfSDavid du Colombier int h; 1469*7dd7cddfSDavid du Colombier Hash *hp, **l; 1470*7dd7cddfSDavid du Colombier 1471*7dd7cddfSDavid du Colombier qlock(&hashlock); 1472*7dd7cddfSDavid du Colombier h = hash(ppath, name); 1473*7dd7cddfSDavid du Colombier for(l = &htab[h]; *l != nil; l = &(*l)->next){ 1474*7dd7cddfSDavid du Colombier hp = *l; 1475*7dd7cddfSDavid du Colombier if(ppath == hp->ppath && strcmp(name, hp->name) == 0){ 1476*7dd7cddfSDavid du Colombier hp->m = m; 1477*7dd7cddfSDavid du Colombier hp->mb = mb; 1478*7dd7cddfSDavid du Colombier hp->qid = qid; 1479*7dd7cddfSDavid du Colombier qunlock(&hashlock); 1480*7dd7cddfSDavid du Colombier return; 1481*7dd7cddfSDavid du Colombier } 1482*7dd7cddfSDavid du Colombier } 1483*7dd7cddfSDavid du Colombier 1484*7dd7cddfSDavid du Colombier *l = hp = emalloc(sizeof(*hp)); 1485*7dd7cddfSDavid du Colombier hp->m = m; 1486*7dd7cddfSDavid du Colombier hp->mb = mb; 1487*7dd7cddfSDavid du Colombier hp->qid = qid; 1488*7dd7cddfSDavid du Colombier hp->name = name; 1489*7dd7cddfSDavid du Colombier hp->ppath = ppath; 1490*7dd7cddfSDavid du Colombier qunlock(&hashlock); 1491*7dd7cddfSDavid du Colombier } 1492*7dd7cddfSDavid du Colombier 1493*7dd7cddfSDavid du Colombier void 1494*7dd7cddfSDavid du Colombier hfree(ulong ppath, char *name) 1495*7dd7cddfSDavid du Colombier { 1496*7dd7cddfSDavid du Colombier int h; 1497*7dd7cddfSDavid du Colombier Hash *hp, **l; 1498*7dd7cddfSDavid du Colombier 1499*7dd7cddfSDavid du Colombier qlock(&hashlock); 1500*7dd7cddfSDavid du Colombier h = hash(ppath, name); 1501*7dd7cddfSDavid du Colombier for(l = &htab[h]; *l != nil; l = &(*l)->next){ 1502*7dd7cddfSDavid du Colombier hp = *l; 1503*7dd7cddfSDavid du Colombier if(ppath == hp->ppath && strcmp(name, hp->name) == 0){ 1504*7dd7cddfSDavid du Colombier *l = hp->next; 1505*7dd7cddfSDavid du Colombier free(hp); 1506*7dd7cddfSDavid du Colombier break; 1507*7dd7cddfSDavid du Colombier } 1508*7dd7cddfSDavid du Colombier } 1509*7dd7cddfSDavid du Colombier qunlock(&hashlock); 1510*7dd7cddfSDavid du Colombier } 1511*7dd7cddfSDavid du Colombier 1512*7dd7cddfSDavid du Colombier int 1513*7dd7cddfSDavid du Colombier hashmboxrefs(Mailbox *mb) 1514*7dd7cddfSDavid du Colombier { 1515*7dd7cddfSDavid du Colombier int h; 1516*7dd7cddfSDavid du Colombier Hash *hp; 1517*7dd7cddfSDavid du Colombier int refs = 0; 1518*7dd7cddfSDavid du Colombier 1519*7dd7cddfSDavid du Colombier qlock(&hashlock); 1520*7dd7cddfSDavid du Colombier for(h = 0; h < Hsize; h++){ 1521*7dd7cddfSDavid du Colombier for(hp = htab[h]; hp != nil; hp = hp->next) 1522*7dd7cddfSDavid du Colombier if(hp->mb == mb) 1523*7dd7cddfSDavid du Colombier refs++; 1524*7dd7cddfSDavid du Colombier } 1525*7dd7cddfSDavid du Colombier qunlock(&hashlock); 1526*7dd7cddfSDavid du Colombier return refs; 1527*7dd7cddfSDavid du Colombier } 1528