180ee5cbfSDavid du Colombier #include "common.h" 280ee5cbfSDavid du Colombier #include <ctype.h> 380ee5cbfSDavid du Colombier #include <plumb.h> 480ee5cbfSDavid du Colombier #include <libsec.h> 580ee5cbfSDavid du Colombier #include "dat.h" 680ee5cbfSDavid du Colombier 780ee5cbfSDavid du Colombier enum { 880ee5cbfSDavid du Colombier Buffersize = 64*1024, 980ee5cbfSDavid du Colombier }; 1080ee5cbfSDavid du Colombier 1180ee5cbfSDavid du Colombier typedef struct Inbuf Inbuf; 1280ee5cbfSDavid du Colombier struct Inbuf 1380ee5cbfSDavid du Colombier { 1480ee5cbfSDavid du Colombier int fd; 1580ee5cbfSDavid du Colombier uchar *lim; 1680ee5cbfSDavid du Colombier uchar *rptr; 1780ee5cbfSDavid du Colombier uchar *wptr; 1880ee5cbfSDavid du Colombier uchar data[Buffersize+7]; 1980ee5cbfSDavid du Colombier }; 2080ee5cbfSDavid du Colombier 2180ee5cbfSDavid du Colombier static void 2280ee5cbfSDavid du Colombier addtomessage(Message *m, uchar *p, int n, int done) 2380ee5cbfSDavid du Colombier { 2480ee5cbfSDavid du Colombier int i, len; 2580ee5cbfSDavid du Colombier 263e748dfcSDavid du Colombier // add to message (+1 in malloc is for a trailing NUL) 2780ee5cbfSDavid du Colombier if(m->lim - m->end < n){ 2880ee5cbfSDavid du Colombier if(m->start != nil){ 2980ee5cbfSDavid du Colombier i = m->end-m->start; 3080ee5cbfSDavid du Colombier if(done) 3180ee5cbfSDavid du Colombier len = i + n; 3280ee5cbfSDavid du Colombier else 3380ee5cbfSDavid du Colombier len = (4*(i+n))/3; 3480ee5cbfSDavid du Colombier m->start = erealloc(m->start, len + 1); 3580ee5cbfSDavid du Colombier m->end = m->start + i; 3680ee5cbfSDavid du Colombier } else { 3780ee5cbfSDavid du Colombier if(done) 3880ee5cbfSDavid du Colombier len = n; 3980ee5cbfSDavid du Colombier else 4080ee5cbfSDavid du Colombier len = 2*n; 4180ee5cbfSDavid du Colombier m->start = emalloc(len + 1); 4280ee5cbfSDavid du Colombier m->end = m->start; 4380ee5cbfSDavid du Colombier } 4480ee5cbfSDavid du Colombier m->lim = m->start + len; 45901d8e21SDavid du Colombier *m->lim = '\0'; 4680ee5cbfSDavid du Colombier } 4780ee5cbfSDavid du Colombier 4880ee5cbfSDavid du Colombier memmove(m->end, p, n); 4980ee5cbfSDavid du Colombier m->end += n; 50901d8e21SDavid du Colombier *m->end = '\0'; 5180ee5cbfSDavid du Colombier } 5280ee5cbfSDavid du Colombier 5380ee5cbfSDavid du Colombier // 5480ee5cbfSDavid du Colombier // read in a single message 5580ee5cbfSDavid du Colombier // 5680ee5cbfSDavid du Colombier static int 5780ee5cbfSDavid du Colombier readmessage(Message *m, Inbuf *inb) 5880ee5cbfSDavid du Colombier { 5980ee5cbfSDavid du Colombier int i, n, done; 6080ee5cbfSDavid du Colombier uchar *p, *np; 6180ee5cbfSDavid du Colombier char sdigest[SHA1dlen*2+1]; 629a747e4fSDavid du Colombier char tmp[64]; 6380ee5cbfSDavid du Colombier 6480ee5cbfSDavid du Colombier for(done = 0; !done;){ 6580ee5cbfSDavid du Colombier n = inb->wptr - inb->rptr; 6680ee5cbfSDavid du Colombier if(n < 6){ 6780ee5cbfSDavid du Colombier if(n) 6880ee5cbfSDavid du Colombier memmove(inb->data, inb->rptr, n); 6980ee5cbfSDavid du Colombier inb->rptr = inb->data; 7080ee5cbfSDavid du Colombier inb->wptr = inb->rptr + n; 7180ee5cbfSDavid du Colombier i = read(inb->fd, inb->wptr, Buffersize); 7280ee5cbfSDavid du Colombier if(i < 0){ 739a747e4fSDavid du Colombier if(fd2path(inb->fd, tmp, sizeof tmp) < 0) 749a747e4fSDavid du Colombier strcpy(tmp, "unknown mailbox"); 759a747e4fSDavid du Colombier fprint(2, "error reading '%s': %r\n", tmp); 7680ee5cbfSDavid du Colombier return -1; 7780ee5cbfSDavid du Colombier } 7880ee5cbfSDavid du Colombier if(i == 0){ 7980ee5cbfSDavid du Colombier if(n != 0) 8080ee5cbfSDavid du Colombier addtomessage(m, inb->rptr, n, 1); 8180ee5cbfSDavid du Colombier if(m->end == m->start) 8280ee5cbfSDavid du Colombier return -1; 8380ee5cbfSDavid du Colombier break; 8480ee5cbfSDavid du Colombier } 8580ee5cbfSDavid du Colombier inb->wptr += i; 8680ee5cbfSDavid du Colombier } 8780ee5cbfSDavid du Colombier 8880ee5cbfSDavid du Colombier // look for end of message 8980ee5cbfSDavid du Colombier for(p = inb->rptr; p < inb->wptr; p = np+1){ 9080ee5cbfSDavid du Colombier // first part of search for '\nFrom ' 9180ee5cbfSDavid du Colombier np = memchr(p, '\n', inb->wptr - p); 9280ee5cbfSDavid du Colombier if(np == nil){ 9380ee5cbfSDavid du Colombier p = inb->wptr; 9480ee5cbfSDavid du Colombier break; 9580ee5cbfSDavid du Colombier } 9680ee5cbfSDavid du Colombier 9780ee5cbfSDavid du Colombier /* 9880ee5cbfSDavid du Colombier * if we've found a \n but there's 9980ee5cbfSDavid du Colombier * not enough room for '\nFrom ', don't do 10080ee5cbfSDavid du Colombier * the comparison till we've read in more. 10180ee5cbfSDavid du Colombier */ 10280ee5cbfSDavid du Colombier if(inb->wptr - np < 6){ 10380ee5cbfSDavid du Colombier p = np; 10480ee5cbfSDavid du Colombier break; 10580ee5cbfSDavid du Colombier } 10680ee5cbfSDavid du Colombier 10780ee5cbfSDavid du Colombier if(strncmp((char*)np, "\nFrom ", 6) == 0){ 10880ee5cbfSDavid du Colombier done = 1; 10980ee5cbfSDavid du Colombier p = np+1; 11080ee5cbfSDavid du Colombier break; 11180ee5cbfSDavid du Colombier } 11280ee5cbfSDavid du Colombier } 11380ee5cbfSDavid du Colombier 11480ee5cbfSDavid du Colombier // add to message (+ 1 in malloc is for a trailing null) 11580ee5cbfSDavid du Colombier n = p - inb->rptr; 11680ee5cbfSDavid du Colombier addtomessage(m, inb->rptr, n, done); 11780ee5cbfSDavid du Colombier inb->rptr += n; 11880ee5cbfSDavid du Colombier } 11980ee5cbfSDavid du Colombier 12080ee5cbfSDavid du Colombier // if it doesn't start with a 'From ', this ain't a mailbox 12180ee5cbfSDavid du Colombier if(strncmp(m->start, "From ", 5) != 0) 12280ee5cbfSDavid du Colombier return -1; 12380ee5cbfSDavid du Colombier 12480ee5cbfSDavid du Colombier // dump trailing newline, make sure there's a trailing null 12580ee5cbfSDavid du Colombier // (helps in body searches) 12680ee5cbfSDavid du Colombier if(*(m->end-1) == '\n') 12780ee5cbfSDavid du Colombier m->end--; 12880ee5cbfSDavid du Colombier *m->end = 0; 12980ee5cbfSDavid du Colombier m->bend = m->rbend = m->end; 13080ee5cbfSDavid du Colombier 13180ee5cbfSDavid du Colombier // digest message 13280ee5cbfSDavid du Colombier sha1((uchar*)m->start, m->end - m->start, m->digest, nil); 13380ee5cbfSDavid du Colombier for(i = 0; i < SHA1dlen; i++) 13480ee5cbfSDavid du Colombier sprint(sdigest+2*i, "%2.2ux", m->digest[i]); 13580ee5cbfSDavid du Colombier m->sdigest = s_copy(sdigest); 13680ee5cbfSDavid du Colombier 13780ee5cbfSDavid du Colombier return 0; 13880ee5cbfSDavid du Colombier } 13980ee5cbfSDavid du Colombier 14080ee5cbfSDavid du Colombier 14180ee5cbfSDavid du Colombier // throw out deleted messages. return number of freshly deleted messages 14280ee5cbfSDavid du Colombier int 14380ee5cbfSDavid du Colombier purgedeleted(Mailbox *mb) 14480ee5cbfSDavid du Colombier { 14580ee5cbfSDavid du Colombier Message *m, *next; 14680ee5cbfSDavid du Colombier int newdels; 14780ee5cbfSDavid du Colombier 14880ee5cbfSDavid du Colombier // forget about what's no longer in the mailbox 14980ee5cbfSDavid du Colombier newdels = 0; 15080ee5cbfSDavid du Colombier for(m = mb->root->part; m != nil; m = next){ 15180ee5cbfSDavid du Colombier next = m->next; 15280ee5cbfSDavid du Colombier if(m->deleted && m->refs == 0){ 15380ee5cbfSDavid du Colombier if(m->inmbox) 15480ee5cbfSDavid du Colombier newdels++; 15580ee5cbfSDavid du Colombier delmessage(mb, m); 15680ee5cbfSDavid du Colombier } 15780ee5cbfSDavid du Colombier } 15880ee5cbfSDavid du Colombier return newdels; 15980ee5cbfSDavid du Colombier } 16080ee5cbfSDavid du Colombier 16180ee5cbfSDavid du Colombier // 16280ee5cbfSDavid du Colombier // read in the mailbox and parse into messages. 16380ee5cbfSDavid du Colombier // 16480ee5cbfSDavid du Colombier static char* 16580ee5cbfSDavid du Colombier _readmbox(Mailbox *mb, int doplumb, Mlock *lk) 16680ee5cbfSDavid du Colombier { 1673b86f2f8SDavid du Colombier int fd, n; 16880ee5cbfSDavid du Colombier String *tmp; 1699a747e4fSDavid du Colombier Dir *d; 170*21887c0bSDavid du Colombier static char err[Errlen]; 17180ee5cbfSDavid du Colombier Message *m, **l; 17280ee5cbfSDavid du Colombier Inbuf *inb; 17380ee5cbfSDavid du Colombier char *x; 17480ee5cbfSDavid du Colombier 17580ee5cbfSDavid du Colombier l = &mb->root->part; 17680ee5cbfSDavid du Colombier 17780ee5cbfSDavid du Colombier /* 17880ee5cbfSDavid du Colombier * open the mailbox. If it doesn't exist, try the temporary one. 17980ee5cbfSDavid du Colombier */ 1803b86f2f8SDavid du Colombier n = 0; 18180ee5cbfSDavid du Colombier retry: 18280ee5cbfSDavid du Colombier fd = open(mb->path, OREAD); 18380ee5cbfSDavid du Colombier if(fd < 0){ 1843b86f2f8SDavid du Colombier rerrstr(err, sizeof(err)); 1853b86f2f8SDavid du Colombier if(strstr(err, "exclusive lock") != 0 && n++ < 20){ 1863b86f2f8SDavid du Colombier sleep(500); /* wait for lock to go away */ 1873b86f2f8SDavid du Colombier goto retry; 1883b86f2f8SDavid du Colombier } 18980ee5cbfSDavid du Colombier if(strstr(err, "exist") != 0){ 19080ee5cbfSDavid du Colombier tmp = s_copy(mb->path); 19180ee5cbfSDavid du Colombier s_append(tmp, ".tmp"); 19280ee5cbfSDavid du Colombier if(sysrename(s_to_c(tmp), mb->path) == 0){ 19380ee5cbfSDavid du Colombier s_free(tmp); 19480ee5cbfSDavid du Colombier goto retry; 19580ee5cbfSDavid du Colombier } 19680ee5cbfSDavid du Colombier s_free(tmp); 19780ee5cbfSDavid du Colombier } 19880ee5cbfSDavid du Colombier return err; 19980ee5cbfSDavid du Colombier } 20080ee5cbfSDavid du Colombier 20180ee5cbfSDavid du Colombier /* 20280ee5cbfSDavid du Colombier * a new qid.path means reread the mailbox, while 20380ee5cbfSDavid du Colombier * a new qid.vers means read any new messages 20480ee5cbfSDavid du Colombier */ 2059a747e4fSDavid du Colombier d = dirfstat(fd); 2069a747e4fSDavid du Colombier if(d == nil){ 20780ee5cbfSDavid du Colombier close(fd); 2089a747e4fSDavid du Colombier errstr(err, sizeof(err)); 20980ee5cbfSDavid du Colombier return err; 21080ee5cbfSDavid du Colombier } 2119a747e4fSDavid du Colombier if(mb->d != nil){ 2129a747e4fSDavid du Colombier if(d->qid.path == mb->d->qid.path && d->qid.vers == mb->d->qid.vers){ 21380ee5cbfSDavid du Colombier close(fd); 2149a747e4fSDavid du Colombier free(d); 21580ee5cbfSDavid du Colombier return nil; 21680ee5cbfSDavid du Colombier } 2179a747e4fSDavid du Colombier if(d->qid.path == mb->d->qid.path){ 21880ee5cbfSDavid du Colombier while(*l != nil) 21980ee5cbfSDavid du Colombier l = &(*l)->next; 2209a747e4fSDavid du Colombier seek(fd, mb->d->length, 0); 22180ee5cbfSDavid du Colombier } 2229a747e4fSDavid du Colombier free(mb->d); 2239a747e4fSDavid du Colombier } 2249a747e4fSDavid du Colombier mb->d = d; 22580ee5cbfSDavid du Colombier mb->vers++; 2269a747e4fSDavid du Colombier henter(PATH(0, Qtop), mb->name, 2279a747e4fSDavid du Colombier (Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb); 22880ee5cbfSDavid du Colombier 22980ee5cbfSDavid du Colombier inb = emalloc(sizeof(Inbuf)); 23080ee5cbfSDavid du Colombier inb->rptr = inb->wptr = inb->data; 23180ee5cbfSDavid du Colombier inb->fd = fd; 23280ee5cbfSDavid du Colombier 23380ee5cbfSDavid du Colombier // read new messages 2349a747e4fSDavid du Colombier snprint(err, sizeof err, "reading '%s'", mb->path); 2359a747e4fSDavid du Colombier logmsg(err, nil); 23680ee5cbfSDavid du Colombier for(;;){ 23780ee5cbfSDavid du Colombier if(lk != nil) 23880ee5cbfSDavid du Colombier syslockrefresh(lk); 23980ee5cbfSDavid du Colombier m = newmessage(mb->root); 24080ee5cbfSDavid du Colombier m->mallocd = 1; 24180ee5cbfSDavid du Colombier m->inmbox = 1; 24280ee5cbfSDavid du Colombier if(readmessage(m, inb) < 0){ 24380ee5cbfSDavid du Colombier delmessage(mb, m); 24480ee5cbfSDavid du Colombier mb->root->subname--; 24580ee5cbfSDavid du Colombier break; 24680ee5cbfSDavid du Colombier } 24780ee5cbfSDavid du Colombier 24880ee5cbfSDavid du Colombier // merge mailbox versions 24980ee5cbfSDavid du Colombier while(*l != nil){ 25080ee5cbfSDavid du Colombier if(memcmp((*l)->digest, m->digest, SHA1dlen) == 0){ 25180ee5cbfSDavid du Colombier // matches mail we already read, discard 25280ee5cbfSDavid du Colombier logmsg("duplicate", *l); 25380ee5cbfSDavid du Colombier delmessage(mb, m); 25480ee5cbfSDavid du Colombier mb->root->subname--; 25580ee5cbfSDavid du Colombier m = nil; 25680ee5cbfSDavid du Colombier l = &(*l)->next; 25780ee5cbfSDavid du Colombier break; 25880ee5cbfSDavid du Colombier } else { 25980ee5cbfSDavid du Colombier // old mail no longer in box, mark deleted 26080ee5cbfSDavid du Colombier logmsg("disappeared", *l); 26180ee5cbfSDavid du Colombier if(doplumb) 26280ee5cbfSDavid du Colombier mailplumb(mb, *l, 1); 26380ee5cbfSDavid du Colombier (*l)->inmbox = 0; 26480ee5cbfSDavid du Colombier (*l)->deleted = 1; 26580ee5cbfSDavid du Colombier l = &(*l)->next; 26680ee5cbfSDavid du Colombier } 26780ee5cbfSDavid du Colombier } 26880ee5cbfSDavid du Colombier if(m == nil) 26980ee5cbfSDavid du Colombier continue; 27080ee5cbfSDavid du Colombier 27180ee5cbfSDavid du Colombier x = strchr(m->start, '\n'); 27280ee5cbfSDavid du Colombier if(x == nil) 27380ee5cbfSDavid du Colombier m->header = m->end; 27480ee5cbfSDavid du Colombier else 27580ee5cbfSDavid du Colombier m->header = x + 1; 27680ee5cbfSDavid du Colombier m->mheader = m->mhend = m->header; 27780ee5cbfSDavid du Colombier parseunix(m); 2787a02f3c0SDavid du Colombier parse(m, 0, mb, 0); 27980ee5cbfSDavid du Colombier logmsg("new", m); 28080ee5cbfSDavid du Colombier 28180ee5cbfSDavid du Colombier /* chain in */ 28280ee5cbfSDavid du Colombier *l = m; 28380ee5cbfSDavid du Colombier l = &m->next; 28480ee5cbfSDavid du Colombier if(doplumb) 28580ee5cbfSDavid du Colombier mailplumb(mb, m, 0); 28680ee5cbfSDavid du Colombier 28780ee5cbfSDavid du Colombier } 28880ee5cbfSDavid du Colombier logmsg("mbox read", nil); 28980ee5cbfSDavid du Colombier 29080ee5cbfSDavid du Colombier // whatever is left has been removed from the mbox, mark deleted 29180ee5cbfSDavid du Colombier while(*l != nil){ 29280ee5cbfSDavid du Colombier if(doplumb) 29380ee5cbfSDavid du Colombier mailplumb(mb, *l, 1); 29480ee5cbfSDavid du Colombier (*l)->inmbox = 0; 29580ee5cbfSDavid du Colombier (*l)->deleted = 1; 29680ee5cbfSDavid du Colombier l = &(*l)->next; 29780ee5cbfSDavid du Colombier } 29880ee5cbfSDavid du Colombier 29980ee5cbfSDavid du Colombier close(fd); 30080ee5cbfSDavid du Colombier free(inb); 30180ee5cbfSDavid du Colombier return nil; 30280ee5cbfSDavid du Colombier } 30380ee5cbfSDavid du Colombier 30480ee5cbfSDavid du Colombier static void 30580ee5cbfSDavid du Colombier _writembox(Mailbox *mb, Mlock *lk) 30680ee5cbfSDavid du Colombier { 3079a747e4fSDavid du Colombier Dir *d; 30880ee5cbfSDavid du Colombier Message *m; 30980ee5cbfSDavid du Colombier String *tmp; 31080ee5cbfSDavid du Colombier int mode, errs; 31180ee5cbfSDavid du Colombier Biobuf *b; 31280ee5cbfSDavid du Colombier 31380ee5cbfSDavid du Colombier tmp = s_copy(mb->path); 31480ee5cbfSDavid du Colombier s_append(tmp, ".tmp"); 31580ee5cbfSDavid du Colombier 31680ee5cbfSDavid du Colombier /* 31780ee5cbfSDavid du Colombier * preserve old files permissions, if possible 31880ee5cbfSDavid du Colombier */ 3199a747e4fSDavid du Colombier d = dirstat(mb->path); 3209a747e4fSDavid du Colombier if(d != nil){ 3219a747e4fSDavid du Colombier mode = d->mode&0777; 3229a747e4fSDavid du Colombier free(d); 3239a747e4fSDavid du Colombier } else 32480ee5cbfSDavid du Colombier mode = MBOXMODE; 32580ee5cbfSDavid du Colombier 32680ee5cbfSDavid du Colombier sysremove(s_to_c(tmp)); 32780ee5cbfSDavid du Colombier b = sysopen(s_to_c(tmp), "alc", mode); 32880ee5cbfSDavid du Colombier if(b == 0){ 32980ee5cbfSDavid du Colombier fprint(2, "can't write temporary mailbox %s: %r\n", s_to_c(tmp)); 33080ee5cbfSDavid du Colombier return; 33180ee5cbfSDavid du Colombier } 33280ee5cbfSDavid du Colombier 33380ee5cbfSDavid du Colombier logmsg("writing new mbox", nil); 33480ee5cbfSDavid du Colombier errs = 0; 33580ee5cbfSDavid du Colombier for(m = mb->root->part; m != nil; m = m->next){ 33680ee5cbfSDavid du Colombier if(lk != nil) 33780ee5cbfSDavid du Colombier syslockrefresh(lk); 33880ee5cbfSDavid du Colombier if(m->deleted) 33980ee5cbfSDavid du Colombier continue; 34080ee5cbfSDavid du Colombier logmsg("writing", m); 34180ee5cbfSDavid du Colombier if(Bwrite(b, m->start, m->end - m->start) < 0) 34280ee5cbfSDavid du Colombier errs = 1; 34380ee5cbfSDavid du Colombier if(Bwrite(b, "\n", 1) < 0) 34480ee5cbfSDavid du Colombier errs = 1; 34580ee5cbfSDavid du Colombier } 34680ee5cbfSDavid du Colombier logmsg("wrote new mbox", nil); 34780ee5cbfSDavid du Colombier 34880ee5cbfSDavid du Colombier if(sysclose(b) < 0) 34980ee5cbfSDavid du Colombier errs = 1; 35080ee5cbfSDavid du Colombier 35180ee5cbfSDavid du Colombier if(errs){ 35280ee5cbfSDavid du Colombier fprint(2, "error writing temporary mail file\n"); 35380ee5cbfSDavid du Colombier s_free(tmp); 35480ee5cbfSDavid du Colombier return; 35580ee5cbfSDavid du Colombier } 35680ee5cbfSDavid du Colombier 35780ee5cbfSDavid du Colombier sysremove(mb->path); 35880ee5cbfSDavid du Colombier if(sysrename(s_to_c(tmp), mb->path) < 0) 35980ee5cbfSDavid du Colombier fprint(2, "%s: can't rename %s to %s: %r\n", argv0, 36080ee5cbfSDavid du Colombier s_to_c(tmp), mb->path); 36180ee5cbfSDavid du Colombier s_free(tmp); 3629a747e4fSDavid du Colombier if(mb->d != nil) 3639a747e4fSDavid du Colombier free(mb->d); 3649a747e4fSDavid du Colombier mb->d = dirstat(mb->path); 36580ee5cbfSDavid du Colombier } 36680ee5cbfSDavid du Colombier 36780ee5cbfSDavid du Colombier char* 36880ee5cbfSDavid du Colombier plan9syncmbox(Mailbox *mb, int doplumb) 36980ee5cbfSDavid du Colombier { 37080ee5cbfSDavid du Colombier Mlock *lk; 37180ee5cbfSDavid du Colombier char *rv; 37280ee5cbfSDavid du Colombier 37380ee5cbfSDavid du Colombier lk = nil; 37480ee5cbfSDavid du Colombier if(mb->dolock){ 375ed250ae1SDavid du Colombier lk = syslock(mb->path); 37680ee5cbfSDavid du Colombier if(lk == nil) 37780ee5cbfSDavid du Colombier return "can't lock mailbox"; 37880ee5cbfSDavid du Colombier } 37980ee5cbfSDavid du Colombier 38080ee5cbfSDavid du Colombier rv = _readmbox(mb, doplumb, lk); /* interpolate */ 38180ee5cbfSDavid du Colombier if(purgedeleted(mb) > 0) 38280ee5cbfSDavid du Colombier _writembox(mb, lk); 38380ee5cbfSDavid du Colombier 38480ee5cbfSDavid du Colombier if(lk != nil) 38580ee5cbfSDavid du Colombier sysunlock(lk); 38680ee5cbfSDavid du Colombier 38780ee5cbfSDavid du Colombier return rv; 38880ee5cbfSDavid du Colombier } 38980ee5cbfSDavid du Colombier 39080ee5cbfSDavid du Colombier // 39180ee5cbfSDavid du Colombier // look to see if we can open this mail box 39280ee5cbfSDavid du Colombier // 39380ee5cbfSDavid du Colombier char* 39480ee5cbfSDavid du Colombier plan9mbox(Mailbox *mb, char *path) 39580ee5cbfSDavid du Colombier { 396*21887c0bSDavid du Colombier static char err[Errlen]; 39780ee5cbfSDavid du Colombier String *tmp; 39880ee5cbfSDavid du Colombier 39980ee5cbfSDavid du Colombier if(access(path, AEXIST) < 0){ 4009a747e4fSDavid du Colombier errstr(err, sizeof(err)); 40180ee5cbfSDavid du Colombier tmp = s_copy(path); 40280ee5cbfSDavid du Colombier s_append(tmp, ".tmp"); 40380ee5cbfSDavid du Colombier if(access(s_to_c(tmp), AEXIST) < 0){ 40480ee5cbfSDavid du Colombier s_free(tmp); 40580ee5cbfSDavid du Colombier return err; 40680ee5cbfSDavid du Colombier } 40780ee5cbfSDavid du Colombier s_free(tmp); 40880ee5cbfSDavid du Colombier } 40980ee5cbfSDavid du Colombier 41080ee5cbfSDavid du Colombier mb->sync = plan9syncmbox; 41180ee5cbfSDavid du Colombier return nil; 41280ee5cbfSDavid du Colombier } 413