143aadf5eSDavid du Colombier /*
243aadf5eSDavid du Colombier * Plan B (mail2fs) mail box format.
343aadf5eSDavid du Colombier *
443aadf5eSDavid du Colombier * BUG: this does not reconstruct the
543aadf5eSDavid du Colombier * raw text for attachments. So imap and others
643aadf5eSDavid du Colombier * will be unable to access any attachment using upas/fs.
743aadf5eSDavid du Colombier * As an aid, we add the path to the message directory
843aadf5eSDavid du Colombier * to the message body, so the user could build the path
943aadf5eSDavid du Colombier * for any attachment and open it.
1043aadf5eSDavid du Colombier */
1143aadf5eSDavid du Colombier
1243aadf5eSDavid du Colombier #include "common.h"
1343aadf5eSDavid du Colombier #include <ctype.h>
1443aadf5eSDavid du Colombier #include <plumb.h>
1543aadf5eSDavid du Colombier #include <libsec.h>
1643aadf5eSDavid du Colombier #include "dat.h"
1743aadf5eSDavid du Colombier
1843aadf5eSDavid du Colombier static int
readmessage(Message * m,char * msg)1943aadf5eSDavid du Colombier readmessage(Message *m, char *msg)
2043aadf5eSDavid du Colombier {
2143aadf5eSDavid du Colombier int fd, i, n;
2243aadf5eSDavid du Colombier char *buf, *name, *p;
2343aadf5eSDavid du Colombier char hdr[128], sdigest[SHA1dlen*2+1];
2443aadf5eSDavid du Colombier Dir *d;
2543aadf5eSDavid du Colombier
2643aadf5eSDavid du Colombier buf = nil;
2743aadf5eSDavid du Colombier d = nil;
2843aadf5eSDavid du Colombier name = smprint("%s/raw", msg);
2943aadf5eSDavid du Colombier if(name == nil)
3043aadf5eSDavid du Colombier return -1;
3143aadf5eSDavid du Colombier if(m->filename != nil)
3243aadf5eSDavid du Colombier s_free(m->filename);
3343aadf5eSDavid du Colombier m->filename = s_copy(name);
3443aadf5eSDavid du Colombier fd = open(name, OREAD);
3543aadf5eSDavid du Colombier if(fd < 0)
3643aadf5eSDavid du Colombier goto Fail;
3743aadf5eSDavid du Colombier n = read(fd, hdr, sizeof(hdr)-1);
3843aadf5eSDavid du Colombier if(n <= 0)
3943aadf5eSDavid du Colombier goto Fail;
4043aadf5eSDavid du Colombier hdr[n] = 0;
4143aadf5eSDavid du Colombier close(fd);
4243aadf5eSDavid du Colombier fd = -1;
4343aadf5eSDavid du Colombier p = strchr(hdr, '\n');
4443aadf5eSDavid du Colombier if(p != nil)
4543aadf5eSDavid du Colombier *++p = 0;
4643aadf5eSDavid du Colombier if(strncmp(hdr, "From ", 5) != 0)
4743aadf5eSDavid du Colombier goto Fail;
4843aadf5eSDavid du Colombier free(name);
4943aadf5eSDavid du Colombier name = smprint("%s/text", msg);
5043aadf5eSDavid du Colombier if(name == nil)
5143aadf5eSDavid du Colombier goto Fail;
5243aadf5eSDavid du Colombier fd = open(name, OREAD);
5343aadf5eSDavid du Colombier if(fd < 0)
5443aadf5eSDavid du Colombier goto Fail;
5543aadf5eSDavid du Colombier d = dirfstat(fd);
5643aadf5eSDavid du Colombier if(d == nil)
5743aadf5eSDavid du Colombier goto Fail;
5843aadf5eSDavid du Colombier buf = malloc(strlen(hdr) + d->length + strlen(msg) + 10); /* few extra chars */
5943aadf5eSDavid du Colombier if(buf == nil)
6043aadf5eSDavid du Colombier goto Fail;
6143aadf5eSDavid du Colombier strcpy(buf, hdr);
6243aadf5eSDavid du Colombier p = buf+strlen(hdr);
6343aadf5eSDavid du Colombier n = readn(fd, p, d->length);
6443aadf5eSDavid du Colombier if(n < 0)
6543aadf5eSDavid du Colombier goto Fail;
6643aadf5eSDavid du Colombier sprint(p+n, "\n[%s]\n", msg);
6743aadf5eSDavid du Colombier n += 2 + strlen(msg) + 2;
6843aadf5eSDavid du Colombier close(fd);
6943aadf5eSDavid du Colombier free(name);
7043aadf5eSDavid du Colombier free(d);
7143aadf5eSDavid du Colombier free(m->start);
7243aadf5eSDavid du Colombier m->start = buf;
7343aadf5eSDavid du Colombier m->lim = m->end = p+n;
7443aadf5eSDavid du Colombier if(*(m->end-1) == '\n')
7543aadf5eSDavid du Colombier m->end--;
7643aadf5eSDavid du Colombier *m->end = 0;
7743aadf5eSDavid du Colombier m->bend = m->rbend = m->end;
7843aadf5eSDavid du Colombier sha1((uchar*)m->start, m->end - m->start, m->digest, nil);
7943aadf5eSDavid du Colombier for(i = 0; i < SHA1dlen; i++)
8043aadf5eSDavid du Colombier sprint(sdigest+2*i, "%2.2ux", m->digest[i]);
8143aadf5eSDavid du Colombier m->sdigest = s_copy(sdigest);
8243aadf5eSDavid du Colombier return 0;
8343aadf5eSDavid du Colombier Fail:
8443aadf5eSDavid du Colombier if(fd >= 0)
8543aadf5eSDavid du Colombier close(fd);
8643aadf5eSDavid du Colombier free(name);
8743aadf5eSDavid du Colombier free(buf);
8843aadf5eSDavid du Colombier free(d);
8943aadf5eSDavid du Colombier return -1;
9043aadf5eSDavid du Colombier }
9143aadf5eSDavid du Colombier
9243aadf5eSDavid du Colombier /*
9343aadf5eSDavid du Colombier * Deleted messages are kept as spam instead.
9443aadf5eSDavid du Colombier */
9543aadf5eSDavid du Colombier static void
archive(Message * m)9643aadf5eSDavid du Colombier archive(Message *m)
9743aadf5eSDavid du Colombier {
9843aadf5eSDavid du Colombier char *dir, *p, *nname;
9943aadf5eSDavid du Colombier Dir d;
10043aadf5eSDavid du Colombier
10143aadf5eSDavid du Colombier dir = strdup(s_to_c(m->filename));
10243aadf5eSDavid du Colombier nname = nil;
10343aadf5eSDavid du Colombier if(dir == nil)
10443aadf5eSDavid du Colombier return;
10543aadf5eSDavid du Colombier p = strrchr(dir, '/');
10643aadf5eSDavid du Colombier if(p == nil)
10743aadf5eSDavid du Colombier goto Fail;
10843aadf5eSDavid du Colombier *p = 0;
10943aadf5eSDavid du Colombier p = strrchr(dir, '/');
11043aadf5eSDavid du Colombier if(p == nil)
11143aadf5eSDavid du Colombier goto Fail;
11243aadf5eSDavid du Colombier p++;
11343aadf5eSDavid du Colombier if(*p < '0' || *p > '9')
11443aadf5eSDavid du Colombier goto Fail;
11543aadf5eSDavid du Colombier nname = smprint("s.%s", p);
11643aadf5eSDavid du Colombier if(nname == nil)
11743aadf5eSDavid du Colombier goto Fail;
11843aadf5eSDavid du Colombier nulldir(&d);
11943aadf5eSDavid du Colombier d.name = nname;
12043aadf5eSDavid du Colombier dirwstat(dir, &d);
12143aadf5eSDavid du Colombier Fail:
12243aadf5eSDavid du Colombier free(dir);
12343aadf5eSDavid du Colombier free(nname);
12443aadf5eSDavid du Colombier }
12543aadf5eSDavid du Colombier
12643aadf5eSDavid du Colombier int
purgembox(Mailbox * mb,int virtual)12743aadf5eSDavid du Colombier purgembox(Mailbox *mb, int virtual)
12843aadf5eSDavid du Colombier {
12943aadf5eSDavid du Colombier Message *m, *next;
13043aadf5eSDavid du Colombier int newdels;
13143aadf5eSDavid du Colombier
13243aadf5eSDavid du Colombier /* forget about what's no longer in the mailbox */
13343aadf5eSDavid du Colombier newdels = 0;
13443aadf5eSDavid du Colombier for(m = mb->root->part; m != nil; m = next){
13543aadf5eSDavid du Colombier next = m->next;
13643aadf5eSDavid du Colombier if(m->deleted > 0 && m->refs == 0){
13743aadf5eSDavid du Colombier if(m->inmbox){
13843aadf5eSDavid du Colombier newdels++;
13943aadf5eSDavid du Colombier /*
14043aadf5eSDavid du Colombier * virtual folders are virtual,
14143aadf5eSDavid du Colombier * we do not archive
14243aadf5eSDavid du Colombier */
14343aadf5eSDavid du Colombier if(virtual == 0)
14443aadf5eSDavid du Colombier archive(m);
14543aadf5eSDavid du Colombier }
14643aadf5eSDavid du Colombier delmessage(mb, m);
14743aadf5eSDavid du Colombier }
14843aadf5eSDavid du Colombier }
14943aadf5eSDavid du Colombier return newdels;
15043aadf5eSDavid du Colombier }
15143aadf5eSDavid du Colombier
15243aadf5eSDavid du Colombier static int
mustshow(char * name)15343aadf5eSDavid du Colombier mustshow(char* name)
15443aadf5eSDavid du Colombier {
15543aadf5eSDavid du Colombier if(isdigit(name[0]))
15643aadf5eSDavid du Colombier return 1;
15743aadf5eSDavid du Colombier if(0 && name[0] == 'a' && name[1] == '.')
15843aadf5eSDavid du Colombier return 1;
15943aadf5eSDavid du Colombier if(0 && name[0] == 's' && name[1] == '.')
16043aadf5eSDavid du Colombier return 1;
16143aadf5eSDavid du Colombier return 0;
16243aadf5eSDavid du Colombier }
16343aadf5eSDavid du Colombier
16443aadf5eSDavid du Colombier static int
readpbmessage(Mailbox * mb,char * msg,int doplumb)16543aadf5eSDavid du Colombier readpbmessage(Mailbox *mb, char *msg, int doplumb)
16643aadf5eSDavid du Colombier {
16743aadf5eSDavid du Colombier Message *m, **l;
16843aadf5eSDavid du Colombier char *x;
16943aadf5eSDavid du Colombier
17043aadf5eSDavid du Colombier m = newmessage(mb->root);
17143aadf5eSDavid du Colombier m->mallocd = 1;
17243aadf5eSDavid du Colombier m->inmbox = 1;
17343aadf5eSDavid du Colombier if(readmessage(m, msg) < 0){
17443aadf5eSDavid du Colombier delmessage(mb, m);
17543aadf5eSDavid du Colombier mb->root->subname--;
17643aadf5eSDavid du Colombier return -1;
17743aadf5eSDavid du Colombier }
17843aadf5eSDavid du Colombier for(l = &mb->root->part; *l != nil; l = &(*l)->next)
17943aadf5eSDavid du Colombier if(strcmp(s_to_c((*l)->filename), s_to_c(m->filename)) == 0 &&
18043aadf5eSDavid du Colombier *l != m){
18143aadf5eSDavid du Colombier if((*l)->deleted < 0)
18243aadf5eSDavid du Colombier (*l)->deleted = 0;
18343aadf5eSDavid du Colombier delmessage(mb, m);
18443aadf5eSDavid du Colombier mb->root->subname--;
18543aadf5eSDavid du Colombier return -1;
18643aadf5eSDavid du Colombier }
18743aadf5eSDavid du Colombier x = strchr(m->start, '\n');
18843aadf5eSDavid du Colombier if(x == nil)
18943aadf5eSDavid du Colombier m->header = m->end;
19043aadf5eSDavid du Colombier else
19143aadf5eSDavid du Colombier m->header = x + 1;
19243aadf5eSDavid du Colombier m->mheader = m->mhend = m->header;
19343aadf5eSDavid du Colombier parseunix(m);
19443aadf5eSDavid du Colombier parse(m, 0, mb, 0);
19543aadf5eSDavid du Colombier logmsg("new", m);
19643aadf5eSDavid du Colombier
19743aadf5eSDavid du Colombier /* chain in */
19843aadf5eSDavid du Colombier *l = m;
19943aadf5eSDavid du Colombier if(doplumb)
20043aadf5eSDavid du Colombier mailplumb(mb, m, 0);
20143aadf5eSDavid du Colombier return 0;
20243aadf5eSDavid du Colombier }
20343aadf5eSDavid du Colombier
20443aadf5eSDavid du Colombier static int
dcmp(Dir * a,Dir * b)20543aadf5eSDavid du Colombier dcmp(Dir *a, Dir *b)
20643aadf5eSDavid du Colombier {
20743aadf5eSDavid du Colombier char *an, *bn;
20843aadf5eSDavid du Colombier
20943aadf5eSDavid du Colombier an = a->name;
21043aadf5eSDavid du Colombier bn = b->name;
21143aadf5eSDavid du Colombier if(an[0] != 0 && an[1] == '.')
21243aadf5eSDavid du Colombier an += 2;
21343aadf5eSDavid du Colombier if(bn[0] != 0 && bn[1] == '.')
21443aadf5eSDavid du Colombier bn += 2;
21543aadf5eSDavid du Colombier return strcmp(an, bn);
21643aadf5eSDavid du Colombier }
21743aadf5eSDavid du Colombier
21843aadf5eSDavid du Colombier static void
readpbmbox(Mailbox * mb,int doplumb)21943aadf5eSDavid du Colombier readpbmbox(Mailbox *mb, int doplumb)
22043aadf5eSDavid du Colombier {
22143aadf5eSDavid du Colombier int fd, i, j, nd, nmd;
22243aadf5eSDavid du Colombier char *month, *msg;
22343aadf5eSDavid du Colombier Dir *d, *md;
22443aadf5eSDavid du Colombier
22543aadf5eSDavid du Colombier fd = open(mb->path, OREAD);
22643aadf5eSDavid du Colombier if(fd < 0){
22743aadf5eSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, mb->path);
22843aadf5eSDavid du Colombier return;
22943aadf5eSDavid du Colombier }
23043aadf5eSDavid du Colombier nd = dirreadall(fd, &d);
23143aadf5eSDavid du Colombier close(fd);
23243aadf5eSDavid du Colombier if(nd > 0)
23343aadf5eSDavid du Colombier qsort(d, nd, sizeof d[0], (int (*)(void*, void*))dcmp);
23443aadf5eSDavid du Colombier for(i = 0; i < nd; i++){
23543aadf5eSDavid du Colombier month = smprint("%s/%s", mb->path, d[i].name);
23643aadf5eSDavid du Colombier if(month == nil)
23743aadf5eSDavid du Colombier break;
23843aadf5eSDavid du Colombier fd = open(month, OREAD);
23943aadf5eSDavid du Colombier if(fd < 0){
24043aadf5eSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, month);
24143aadf5eSDavid du Colombier free(month);
24243aadf5eSDavid du Colombier continue;
24343aadf5eSDavid du Colombier }
24443aadf5eSDavid du Colombier md = dirfstat(fd);
24543aadf5eSDavid du Colombier if(md != nil && (md->qid.type & QTDIR) != 0){
24643aadf5eSDavid du Colombier free(md);
24743aadf5eSDavid du Colombier md = nil;
24843aadf5eSDavid du Colombier nmd = dirreadall(fd, &md);
24943aadf5eSDavid du Colombier for(j = 0; j < nmd; j++)
25043aadf5eSDavid du Colombier if(mustshow(md[j].name)){
25143aadf5eSDavid du Colombier msg = smprint("%s/%s", month, md[j].name);
25243aadf5eSDavid du Colombier readpbmessage(mb, msg, doplumb);
25343aadf5eSDavid du Colombier free(msg);
25443aadf5eSDavid du Colombier }
25543aadf5eSDavid du Colombier }
25643aadf5eSDavid du Colombier close(fd);
25743aadf5eSDavid du Colombier free(month);
25843aadf5eSDavid du Colombier free(md);
25943aadf5eSDavid du Colombier md = nil;
26043aadf5eSDavid du Colombier }
26143aadf5eSDavid du Colombier free(d);
26243aadf5eSDavid du Colombier }
26343aadf5eSDavid du Colombier
26443aadf5eSDavid du Colombier static void
readpbvmbox(Mailbox * mb,int doplumb)26543aadf5eSDavid du Colombier readpbvmbox(Mailbox *mb, int doplumb)
26643aadf5eSDavid du Colombier {
26743aadf5eSDavid du Colombier int fd, nr;
26843aadf5eSDavid du Colombier long sz;
26943aadf5eSDavid du Colombier char *data, *ln, *p, *nln, *msg;
27043aadf5eSDavid du Colombier Dir *d;
27143aadf5eSDavid du Colombier
27243aadf5eSDavid du Colombier fd = open(mb->path, OREAD);
27343aadf5eSDavid du Colombier if(fd < 0){
27443aadf5eSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, mb->path);
27543aadf5eSDavid du Colombier return;
27643aadf5eSDavid du Colombier }
27743aadf5eSDavid du Colombier d = dirfstat(fd);
27843aadf5eSDavid du Colombier if(d == nil){
27943aadf5eSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, mb->path);
28043aadf5eSDavid du Colombier close(fd);
28143aadf5eSDavid du Colombier return;
28243aadf5eSDavid du Colombier }
28343aadf5eSDavid du Colombier sz = d->length;
28443aadf5eSDavid du Colombier free(d);
28543aadf5eSDavid du Colombier if(sz > 2 * 1024 * 1024){
28643aadf5eSDavid du Colombier sz = 2 * 1024 * 1024;
28743aadf5eSDavid du Colombier fprint(2, "%s: %s: bug: folder too big\n", argv0, mb->path);
28843aadf5eSDavid du Colombier }
28943aadf5eSDavid du Colombier data = malloc(sz+1);
29043aadf5eSDavid du Colombier if(data == nil){
29143aadf5eSDavid du Colombier close(fd);
29243aadf5eSDavid du Colombier fprint(2, "%s: no memory\n", argv0);
29343aadf5eSDavid du Colombier return;
29443aadf5eSDavid du Colombier }
29543aadf5eSDavid du Colombier nr = readn(fd, data, sz);
29643aadf5eSDavid du Colombier close(fd);
29743aadf5eSDavid du Colombier if(nr < 0){
29843aadf5eSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, mb->path);
29943aadf5eSDavid du Colombier free(data);
30043aadf5eSDavid du Colombier return;
30143aadf5eSDavid du Colombier }
30243aadf5eSDavid du Colombier data[nr] = 0;
30343aadf5eSDavid du Colombier
30443aadf5eSDavid du Colombier for(ln = data; *ln != 0; ln = nln){
30543aadf5eSDavid du Colombier nln = strchr(ln, '\n');
30643aadf5eSDavid du Colombier if(nln != nil)
30743aadf5eSDavid du Colombier *nln++ = 0;
30843aadf5eSDavid du Colombier else
30943aadf5eSDavid du Colombier nln = ln + strlen(ln);
31043aadf5eSDavid du Colombier p = strchr(ln , ' ');
31143aadf5eSDavid du Colombier if(p != nil)
31243aadf5eSDavid du Colombier *p = 0;
31343aadf5eSDavid du Colombier p = strchr(ln, '\t');
31443aadf5eSDavid du Colombier if(p != nil)
31543aadf5eSDavid du Colombier *p = 0;
31643aadf5eSDavid du Colombier p = strstr(ln, "/text");
31743aadf5eSDavid du Colombier if(p != nil)
31843aadf5eSDavid du Colombier *p = 0;
31943aadf5eSDavid du Colombier msg = smprint("/mail/box/%s/msgs/%s", user, ln);
32043aadf5eSDavid du Colombier if(msg == nil){
32143aadf5eSDavid du Colombier fprint(2, "%s: no memory\n", argv0);
32243aadf5eSDavid du Colombier continue;
32343aadf5eSDavid du Colombier }
32443aadf5eSDavid du Colombier readpbmessage(mb, msg, doplumb);
32543aadf5eSDavid du Colombier free(msg);
32643aadf5eSDavid du Colombier }
32743aadf5eSDavid du Colombier free(data);
32843aadf5eSDavid du Colombier }
32943aadf5eSDavid du Colombier
33043aadf5eSDavid du Colombier static char*
readmbox(Mailbox * mb,int doplumb,int virt)33143aadf5eSDavid du Colombier readmbox(Mailbox *mb, int doplumb, int virt)
33243aadf5eSDavid du Colombier {
33343aadf5eSDavid du Colombier int fd;
33443aadf5eSDavid du Colombier Dir *d;
33543aadf5eSDavid du Colombier Message *m;
336*21887c0bSDavid du Colombier static char err[Errlen];
33743aadf5eSDavid du Colombier
33843aadf5eSDavid du Colombier if(debug)
33943aadf5eSDavid du Colombier fprint(2, "read mbox %s\n", mb->path);
34043aadf5eSDavid du Colombier fd = open(mb->path, OREAD);
34143aadf5eSDavid du Colombier if(fd < 0){
34243aadf5eSDavid du Colombier errstr(err, sizeof(err));
34343aadf5eSDavid du Colombier return err;
34443aadf5eSDavid du Colombier }
34543aadf5eSDavid du Colombier
34643aadf5eSDavid du Colombier d = dirfstat(fd);
34743aadf5eSDavid du Colombier if(d == nil){
34843aadf5eSDavid du Colombier close(fd);
34943aadf5eSDavid du Colombier errstr(err, sizeof(err));
35043aadf5eSDavid du Colombier return err;
35143aadf5eSDavid du Colombier }
35243aadf5eSDavid du Colombier if(mb->d != nil){
35343aadf5eSDavid du Colombier if(d->qid.path == mb->d->qid.path &&
35443aadf5eSDavid du Colombier d->qid.vers == mb->d->qid.vers){
35543aadf5eSDavid du Colombier close(fd);
35643aadf5eSDavid du Colombier free(d);
35743aadf5eSDavid du Colombier return nil;
35843aadf5eSDavid du Colombier }
35943aadf5eSDavid du Colombier free(mb->d);
36043aadf5eSDavid du Colombier }
36143aadf5eSDavid du Colombier close(fd);
36243aadf5eSDavid du Colombier mb->d = d;
36343aadf5eSDavid du Colombier mb->vers++;
36443aadf5eSDavid du Colombier henter(PATH(0, Qtop), mb->name,
36543aadf5eSDavid du Colombier (Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);
36643aadf5eSDavid du Colombier snprint(err, sizeof err, "reading '%s'", mb->path);
36743aadf5eSDavid du Colombier logmsg(err, nil);
36843aadf5eSDavid du Colombier
36943aadf5eSDavid du Colombier for(m = mb->root->part; m != nil; m = m->next)
37043aadf5eSDavid du Colombier if(m->deleted == 0)
37143aadf5eSDavid du Colombier m->deleted = -1;
37243aadf5eSDavid du Colombier if(virt == 0)
37343aadf5eSDavid du Colombier readpbmbox(mb, doplumb);
37443aadf5eSDavid du Colombier else
37543aadf5eSDavid du Colombier readpbvmbox(mb, doplumb);
37643aadf5eSDavid du Colombier
37743aadf5eSDavid du Colombier /*
37843aadf5eSDavid du Colombier * messages removed from the mbox; flag them to go.
37943aadf5eSDavid du Colombier */
38043aadf5eSDavid du Colombier for(m = mb->root->part; m != nil; m = m->next)
38143aadf5eSDavid du Colombier if(m->deleted < 0 && doplumb){
38243aadf5eSDavid du Colombier m->inmbox = 0;
38343aadf5eSDavid du Colombier m->deleted = 1;
38443aadf5eSDavid du Colombier mailplumb(mb, m, 1);
38543aadf5eSDavid du Colombier }
38643aadf5eSDavid du Colombier logmsg("mbox read", nil);
38743aadf5eSDavid du Colombier return nil;
38843aadf5eSDavid du Colombier }
38943aadf5eSDavid du Colombier
39043aadf5eSDavid du Colombier static char*
mbsync(Mailbox * mb,int doplumb)39143aadf5eSDavid du Colombier mbsync(Mailbox *mb, int doplumb)
39243aadf5eSDavid du Colombier {
39343aadf5eSDavid du Colombier char *rv;
39443aadf5eSDavid du Colombier
39543aadf5eSDavid du Colombier rv = readmbox(mb, doplumb, 0);
39643aadf5eSDavid du Colombier purgembox(mb, 0);
39743aadf5eSDavid du Colombier return rv;
39843aadf5eSDavid du Colombier }
39943aadf5eSDavid du Colombier
40043aadf5eSDavid du Colombier static char*
mbvsync(Mailbox * mb,int doplumb)40143aadf5eSDavid du Colombier mbvsync(Mailbox *mb, int doplumb)
40243aadf5eSDavid du Colombier {
40343aadf5eSDavid du Colombier char *rv;
40443aadf5eSDavid du Colombier
40543aadf5eSDavid du Colombier rv = readmbox(mb, doplumb, 1);
40643aadf5eSDavid du Colombier purgembox(mb, 1);
40743aadf5eSDavid du Colombier return rv;
40843aadf5eSDavid du Colombier }
40943aadf5eSDavid du Colombier
41043aadf5eSDavid du Colombier char*
planbmbox(Mailbox * mb,char * path)41143aadf5eSDavid du Colombier planbmbox(Mailbox *mb, char *path)
41243aadf5eSDavid du Colombier {
41343aadf5eSDavid du Colombier char *list;
41443aadf5eSDavid du Colombier static char err[64];
41543aadf5eSDavid du Colombier
41643aadf5eSDavid du Colombier if(access(path, AEXIST) < 0)
41743aadf5eSDavid du Colombier return Enotme;
41843aadf5eSDavid du Colombier list = smprint("%s/list", path);
41943aadf5eSDavid du Colombier if(access(list, AEXIST) < 0){
42043aadf5eSDavid du Colombier free(list);
42143aadf5eSDavid du Colombier return Enotme;
42243aadf5eSDavid du Colombier }
42343aadf5eSDavid du Colombier free(list);
42443aadf5eSDavid du Colombier mb->sync = mbsync;
42543aadf5eSDavid du Colombier if(debug)
42643aadf5eSDavid du Colombier fprint(2, "planb mbox %s\n", path);
42743aadf5eSDavid du Colombier return nil;
42843aadf5eSDavid du Colombier }
42943aadf5eSDavid du Colombier
43043aadf5eSDavid du Colombier char*
planbvmbox(Mailbox * mb,char * path)43143aadf5eSDavid du Colombier planbvmbox(Mailbox *mb, char *path)
43243aadf5eSDavid du Colombier {
43343aadf5eSDavid du Colombier int fd, nr, i;
43443aadf5eSDavid du Colombier char buf[64];
43543aadf5eSDavid du Colombier static char err[64];
43643aadf5eSDavid du Colombier
43743aadf5eSDavid du Colombier fd = open(path, OREAD);
43843aadf5eSDavid du Colombier if(fd < 0)
43943aadf5eSDavid du Colombier return Enotme;
44043aadf5eSDavid du Colombier nr = read(fd, buf, sizeof(buf)-1);
44143aadf5eSDavid du Colombier close(fd);
44243aadf5eSDavid du Colombier if(nr < 7)
44343aadf5eSDavid du Colombier return Enotme;
44443aadf5eSDavid du Colombier buf[nr] = 0;
44543aadf5eSDavid du Colombier for(i = 0; i < 6; i++)
44643aadf5eSDavid du Colombier if(buf[i] < '0' || buf[i] > '9')
44743aadf5eSDavid du Colombier return Enotme;
44843aadf5eSDavid du Colombier if(buf[6] != '/')
44943aadf5eSDavid du Colombier return Enotme;
45043aadf5eSDavid du Colombier mb->sync = mbvsync;
45143aadf5eSDavid du Colombier if(debug)
45243aadf5eSDavid du Colombier fprint(2, "planb virtual mbox %s\n", path);
45343aadf5eSDavid du Colombier return nil;
45443aadf5eSDavid du Colombier }
455