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
addtomessage(Message * m,uchar * p,int n,int done)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
readmessage(Message * m,Inbuf * inb)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
purgedeleted(Mailbox * mb)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*
_readmbox(Mailbox * mb,int doplumb,Mlock * lk)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
_writembox(Mailbox * mb,Mlock * lk)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*
plan9syncmbox(Mailbox * mb,int doplumb)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*
plan9mbox(Mailbox * mb,char * path)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