upas/fs: work in progress...

get plumbing logic out of mailbox drivers, all handled from
syncmbox() now. avoid reentrancy in syncmbox().

store attachment filename in index, so that we can return it
in mail info without fetching headers. (used to return blank
filename when read out of the index messing up attachments in
nedmail).

maintain Message.size for attachments.

get rid of string "refs" and just have a simple string intern
table (only used for Message.type and Message.charset).

Message.replyto and Message.filename are owned by the index,
so don't free in delmessage().
This commit is contained in:
cinap_lenrek 2017-06-18 18:52:54 +02:00
parent c3d372c3da
commit a1c1e00973
12 changed files with 177 additions and 760 deletions

View file

@ -371,18 +371,6 @@ cachehash(Mailbox *mb, Message *m)
(Qid){PATH(m->id, Qmax), 0, QTFILE}, m, mb); /* sleezy speedup */
}
void
newcachehash(Mailbox *mb, Message *m, int doplumb)
{
if(doplumb)
mailplumb(mb, m, 0);
else
if(insurecache(mb, m) == 0)
msgdecref(mb, m);
/* avoid cachehash on error? */
cachehash(mb, m);
}
static char *itab[] = {
"idx",
"stale",
@ -424,7 +412,7 @@ middlecache(Mailbox *mb, Message *m)
}
if(y == 0)
return 0;
dprint("middlecache %d [%D] %lud %lud\n", m->id, m->fileid, m->end - m->start, m->size);
dprint("middlecache %d [%D] %lud %lud\n", m->id, m->fileid, (ulong)(m->end - m->start), m->size);
return cachebody(mb, m);
}
@ -487,7 +475,7 @@ cachebody(Mailbox *mb, Message *m)
if(!mb->fetch || m->cstate&Cbody)
return 0;
o = m->end - m->start;
dprint("cachebody %d [%D] %lud %lud %s\n", m->id, m->fileid, o, m->size, cstate(m));
dprint("cachebody %d [%D] %lud %lud %s", m->id, m->fileid, o, m->size, cstate(m));
if(o < m->size)
if(fetch(mb, m, o, m->size - o) < 0)
return -1;

View file

@ -1,416 +0,0 @@
#include "common.h"
#include <auth.h>
#include <libsec.h>
#include <bin.h>
#include "dat.h"
#define idprint(...) if(1) fprint(2, __VA_ARGS__); else {}
enum{
Maxver = 10,
};
static char *magictab[Maxver] = {
[4] "idx magic v4\n",
[7] "idx magic v7\n",
};
static int fieldstab[Maxver] = {
[4] 19,
[7] 21,
};
static char *magic;
static int Idxfields;
static int lineno;
static int idxver;
int
newid(void)
{
static int id;
return ++id;
}
void*
emalloc(ulong n)
{
void *p;
p = mallocz(n, 1);
if(!p)
sysfatal("malloc %lud: %r", n);
setmalloctag(p, getcallerpc(&n));
return p;
}
static int
Afmt(Fmt *f)
{
char buf[SHA1dlen*2 + 1];
uchar *u, i;
u = va_arg(f->args, uchar*);
if(u == 0 && f->flags & FmtSharp)
return fmtstrcpy(f, "-");
if(u == 0)
return fmtstrcpy(f, "<nildigest>");
for(i = 0; i < SHA1dlen; i++)
sprint(buf + 2*i, "%2.2ux", u[i]);
return fmtstrcpy(f, buf);
}
static int
Dfmt(Fmt *f)
{
char buf[32];
int seq;
uvlong v;
v = va_arg(f->args, uvlong);
seq = v & 0xff;
if(seq > 99)
seq = 99;
snprint(buf, sizeof buf, "%llud.%.2d", v>>8, seq);
return fmtstrcpy(f, buf);
}
static Mailbox*
shellmailbox(char *path)
{
Mailbox *mb;
mb = malloc(sizeof *mb);
if(mb == 0)
sysfatal("malloc");
memset(mb, 0, sizeof *mb);
snprint(mb->path, sizeof mb->path, "%s", path);
mb->id = newid();
mb->root = newmessage(nil);
mb->mtree = mkavltree(mtreecmp);
return mb;
}
void
shellmailboxfree(Mailbox*)
{
}
Message*
newmessage(Message *parent)
{
static int id;
Message *m;
// msgallocd++;
m = mallocz(sizeof *m, 1);
if(m == 0)
sysfatal("malloc");
m->disposition = Dnone;
// m->type = newrefs("text/plain");
// m->charset = newrefs("iso-8859-1");
m->cstate = Cidxstale;
m->flags = Frecent;
m->id = newid();
if(parent)
snprint(m->name, sizeof m->name, "%d", ++(parent->subname));
if(parent == nil)
parent = m;
m->whole = parent;
m->hlen = -1;
return m;
}
void
unnewmessage(Mailbox *mb, Message *parent, Message *m)
{
assert(parent->subname > 0);
// delmessage(mb, m);
USED(mb, m);
parent->subname -= 1;
}
static int
validmessage(Mailbox *mb, Message *m, int level)
{
if(level){
if(m->digest != 0)
goto lose;
if(m->fileid <= 1000000ull<<8)
if(m->fileid != 0)
goto lose;
}else{
if(m->digest == 0)
goto lose;
if(m->size == 0)
goto lose;
if(m->fileid <= 1000000ull<<8)
goto lose;
if(mtreefind(mb, m->digest))
goto lose;
}
return 1;
lose:
fprint(2, "invalid cache[%d] %#A size %ld %D\n", level, m->digest, m->size, m->fileid);
return 0;
}
static char*
(char *x)
{
if(x && *x)
return x;
return nil;
}
static char*
brdstr(Biobuf *b, int c, int eat)
{
char *s;
s = Brdstr(b, c, eat);
if(s)
lineno++;
return s;
}
static int
nibble(int c)
{
if(c >= '0' && c <= '9')
return c - '0';
if(c < 0x20)
c += 0x20;
if(c >= 'a' && c <= 'f')
return c - 'a'+10;
return 0xff;
}
static uchar*
hackdigest(char *s)
{
uchar t[SHA1dlen];
int i;
if(strcmp(s, "-") == 0)
return 0;
if(strlen(s) != 2*SHA1dlen){
fprint(2, "bad digest %s\n", s);
return 0;
}
for(i = 0; i < SHA1dlen; i++)
t[i] = nibble(s[2*i])<<4 | nibble(s[2*i + 1]);
memmove(s, t, SHA1dlen);
return (uchar*)s;
}
static Message*
findmessage(Mailbox *, Message *parent, int n)
{
Message *m;
for(m = parent->part; m; m = m->next)
if(!m->digest && n-- == 0)
return m;
return 0;
}
static uvlong
rdfileid(char *s, int level)
{
char *p;
uvlong uv;
uv = strtoul(s, &p, 0);
if((level == 0 && uv < 1000000) || *p != '.')
return 0;
return uv<<8 | strtoul(p + 1, 0, 10);
}
static int
rdidx(Biobuf *b, Mailbox *mb, Message *parent, int npart, int level)
{
char *f[50 + 1], *s;
uchar *digest;
int n, nparts, good, bad, redux;
Message *m, **ll, *l;
bad = good = redux = 0;
ll = &parent->part;
nparts = npart;
for(; npart != 0 && (s = brdstr(b, '\n', 1)); npart--){
//if(lineno>18&&lineno<25)idprint("%d: %d [%s]\n", lineno, level, s);
n = tokenize(s, f, nelem(f));
if(n != Idxfields){
print("%d: bad line\n", lineno);
bad++;
free(s);
continue;
}
digest = hackdigest(f[0]);
if(level == 0){
if(digest == 0)
idprint("%d: no digest\n", lineno);
m = mtreefind(mb, digest);
}else{
m = findmessage(mb, parent, nparts - npart);
if(m == 0){
// idprint("can't find message\n");
}
}
if(m){
/*
* read in mutable information.
* currently this is only flags
*/
idprint("%d seen before %d... %.2ux", level, m->id, m->cstate);
redux++;
m->flags |= strtoul(f[1], 0, 16);
m->cstate &= ~Cidxstale;
m->cstate |= Cidx;
idprint("→%.2ux\n", m->cstate);
free(s);
if(m->nparts)
rdidx(b, mb, m, m->nparts, level + 1);
ll = &m->next;
continue;
}
m = newmessage(parent);
//if(lineno>18&&lineno<25)idprint("%d: %d %d %A\n", lineno, level, m->id, digest);
// idprint("%d new %d %#A \n", level, m->id, digest);
m->digest = digest;
m->flags = strtoul(f[1], 0, 16);
m->fileid = rdfileid(f[2], level);
m->lines = atoi(f[3]);
m->ffrom = (f[4]);
m->from = (f[5]);
m->to = (f[6]);
m->cc = (f[7]);
m->bcc = (f[8]);
m->replyto = (f[9]);
m->messageid = (f[10]);
m->subject = (f[11]);
m->sender = (f[12]);
m->inreplyto = (f[13]);
// m->type = newrefs(f[14]);
m->disposition = atoi(f[15]);
m->size = strtoul(f[16], 0, 0);
m->rawbsize = strtoul(f[17], 0, 0);
switch(idxver){
case 4:
m->nparts = strtoul(f[18], 0, 0);
case 7:
m->ibadchars = strtoul(f[18], 0, 0);
m->idxaux = (f[19]);
m->nparts = strtoul(f[20], 0, 0);
}
m->cstate &= ~Cidxstale;
m->cstate |= Cidx;
m->str = s;
// free(s);
if(!validmessage(mb, m, level)){
/*
* if this was an okay message, and somebody
* wrote garbage to the index file, we lose the msg.
*/
print("%d: !validmessage\n", lineno);
bad++;
unnewmessage(mb, parent, m);
continue;
}
if(level == 0)
m->inmbox = 1;
// cachehash(mb, m); /* hokey */
l = *ll;
*ll = m;
ll = &m->next;
*ll = l;
good++;
if(m->nparts){
// fprint(2, "%d: %d parts [%s]\n", lineno, m->nparts, f[18]);
rdidx(b, mb, m, m->nparts, level + 1);
}
}
if(level == 0)
print("idx: %d %d %d\n", good, bad, redux);
return 0;
}
static int
verscmp(Biobuf *b)
{
char *s;
int i;
if((s = brdstr(b, '\n', 0)) == 0)
return -1;
for(i = 0; i < Maxver; i++)
if(magictab[i])
if(strcmp(s, magictab[i]) == 0)
break;
free(s);
if(i == Maxver)
return -1;
idxver = i;
magic = magictab[i];
Idxfields = fieldstab[i];
fprint(2, "version %d\n", i);
return 0;
}
int
mbvers(Biobuf *b)
{
char *s;
if(s = brdstr(b, '\n', 1)){
free(s);
return 0;
}
return -1;
}
int
ckidxfile(Mailbox *mb)
{
char buf[Pathlen + 4];
int r;
Biobuf *b;
snprint(buf, sizeof buf, "%s", mb->path);
b = Bopen(buf, OREAD);
if(b == nil)
return -1;
if(verscmp(b) == -1)
return -1;
if(idxver >= 7)
mbvers(b);
r = rdidx(b, mb, mb->root, -1, 0);
Bterm(b);
return r;
}
static char *bargv[] = {"/fd/0", 0};
void
main(int argc, char **argv)
{
Mailbox *mb;
fmtinstall('A', Afmt);
fmtinstall('D', Dfmt);
ARGBEGIN{
}ARGEND
if(*argv == 0)
argv = bargv;
for(; *argv; argv++){
mb = shellmailbox(*argv);
lineno = 0;
if(ckidxfile(mb) == -1)
fprint(2, "%s: %r\n", *argv);
shellmailboxfree(mb);
}
exits("");
}

View file

@ -64,8 +64,10 @@ struct Idx {
char *inreplyto;
char *idxaux; /* mailbox specific */
int type; /* very few types: refstring */
int disposition; /* very few types: refstring */
char *type; /* mime info */
char disposition;
char *filename;
int nparts;
};
@ -114,10 +116,9 @@ struct Message {
char *references[Nref];
/* mime info */
char *boundary;
int charset;
char *filename;
char *charset;
char encoding;
char *boundary;
char converted;
char decoded;
char mimeflag;
@ -175,12 +176,14 @@ struct Mailbox {
char *(*ctl)(Mailbox*, int, char**);
char *(*remove)(Mailbox *, int);
char *(*rename)(Mailbox*, char*, int);
char *(*sync)(Mailbox*, int, int*);
char *(*sync)(Mailbox*);
void (*modflags)(Mailbox*, Message*, int);
void (*idxwrite)(Biobuf*, Mailbox*);
int (*idxread)(char*, Mailbox*);
void (*idxinvalid)(Mailbox*);
void *aux; /* private to Mailbox implementation */
int syncing; /* currently syncing? */
};
typedef char *Mailboxinit(Mailbox*, char*);
@ -195,7 +198,6 @@ int genericidxread(char*, Mailbox*);
void genericidxinvalid(Mailbox*);
void cachehash(Mailbox*, Message*);
void newcachehash(Mailbox*, Message*, int);
int cacheheaders(Mailbox*, Message*); /* "getcache" */
int cachebody(Mailbox*, Message*);
int cacheidx(Mailbox*, Message*);
@ -206,12 +208,11 @@ void putcache(Mailbox*, Message*); /* asymmetricial */
long cachefree(Mailbox*, Message*, int);
Message* gettopmsg(Mailbox*, Message*);
char* syncmbox(Mailbox*, int);
char* syncmbox(Mailbox*);
void* emalloc(ulong);
void* erealloc(void*, ulong);
Message* newmessage(Message*);
void unnewmessage(Mailbox*, Message*, Message*);
void delmessage(Mailbox*, Message*);
char* delmessages(int, char**);
char *flagmessages(int, char**);
void digestmessage(Mailbox*, Message*);
@ -221,7 +222,6 @@ int wraptls(int, char*);
void eprint(char*, ...);
void iprint(char *, ...);
int newid(void);
void mailplumb(Mailbox*, Message*, int);
char* newmbox(char*, char*, int, Mailbox**);
void freembox(char*);
char* removembox(char*, int);
@ -318,24 +318,14 @@ struct Hash {
Message *m;
};
uint hash(char*);
Hash *hlook(ulong, char*);
void henter(ulong, char*, Qid, Message*, Mailbox*);
void hfree(ulong, char*);
typedef struct {
char *s;
int l;
ulong ref;
} Refs;
int newrefs(char*);
void delrefs(int);
void refsinit(void);
int prrefs(Biobuf*);
int rdrefs(Biobuf*);
char *intern(char*);
void idxfree(Idx*);
int rdidxfile(Mailbox*, int);
int rdidxfile(Mailbox*);
int wridxfile(Mailbox*);
char *modflags(Mailbox*, Message*, char*);
@ -356,7 +346,6 @@ extern ulong msgallocd;
extern ulong msgfreed;
extern Mailbox *mbl;
extern Message *root;
extern Refs *rtab;
#define dprint(...) if(debug) fprint(2, __VA_ARGS__); else {}
#define Topmsg(mb, m) (m->whole == mb->root)

View file

@ -104,11 +104,6 @@ char *dirtab[] = {
[Qmboxctl] "ctl",
};
enum
{
Hsize= 1999,
};
char *mntpt;
char user[Elemlen];
int Dflag;
@ -127,7 +122,7 @@ static char hbuf[32*1024];
static uchar mbuf[16*1024 + IOHDRSZ];
static uchar mdata[16*1024 + IOHDRSZ];
static ulong path; /* incremented for each new file */
static Hash *htab[Hsize];
static Hash *htab[1024];
static Fcall rhdr;
static Fcall thdr;
static Fid *fids;
@ -136,8 +131,6 @@ static QLock synclock;
void
sanemsg(Message *m)
{
if(debug)
poolcheck(mainmem);
assert(m->refs < 100);
assert(m->next != m);
if(m->end < m->start)
@ -294,7 +287,7 @@ main(int argc, char *argv[])
cachetarg = ntoi(EARGF(usage()));
break;
case 'd':
debug = 1;
if(++debug > 1)
mainmem->flags |= POOL_PARANOIA;
break;
case 'f':
@ -527,8 +520,8 @@ fileinfo(Mailbox *mb, Message *m, int t, char **pp)
p = m->to;
break;
case Qtype:
p = rtab[m->type].s;
len = rtab[m->type].l;
p = m->type;
len = strlen(m->type);
break;
case Qunixdate:
p = buf;
@ -1015,7 +1008,7 @@ readmboxdir(Fid *f, uchar *buf, long off, int cnt, int blen)
Message *msg;
if(off == 0)
syncmbox(f->mb, 1);
syncmbox(f->mb);
n = 0;
if(f->mb->ctl){
@ -1339,11 +1332,8 @@ rclunk(Fid *f)
char *
rremove(Fid *f)
{
if(f->m != nil){
if(!f->m->deleted)
mailplumb(f->mb, f->m, 1);
if(f->m != nil && f->m->deleted == 0)
f->m->deleted = Deleted;
}
return rclunk(f);
}
@ -1353,7 +1343,7 @@ rstat(Fid *f)
Dir d;
if(FILE(f->qid.path) == Qmbox)
syncmbox(f->mb, 1);
syncmbox(f->mb);
mkstat(&d, f->mb, f->m, FILE(f->qid.path));
rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ);
rhdr.stat = mbuf;
@ -1475,7 +1465,7 @@ reader(void)
}
}
if(mb != nil) {
syncmbox(mb, 1);
syncmbox(mb);
qunlock(&synclock);
} else {
qunlock(&synclock);
@ -1610,17 +1600,15 @@ readheader(Message *m, char *buf, int off, int cnt)
}
uint
hash(ulong ppath, char *name)
hash(char *s)
{
uchar *p;
uint h;
uint c, h;
h = 0;
for(p = (uchar*)name; *p; p++)
h = h*7 + *p;
h += ppath;
while(c = *s++)
h = h*131 + c;
return h % Hsize;
return h;
}
Hash*
@ -1629,7 +1617,7 @@ hlook(ulong ppath, char *name)
int h;
Hash *hp;
h = hash(ppath, name);
h = (hash(name)+ppath) % nelem(htab);
for(hp = htab[h]; hp != nil; hp = hp->next)
if(ppath == hp->ppath && strcmp(name, hp->name) == 0)
return hp;
@ -1642,7 +1630,7 @@ henter(ulong ppath, char *name, Qid qid, Message *m, Mailbox *mb)
int h;
Hash *hp, **l;
h = hash(ppath, name);
h = (hash(name)+ppath) % nelem(htab);
for(l = &htab[h]; *l != nil; l = &(*l)->next){
hp = *l;
if(ppath == hp->ppath && strcmp(name, hp->name) == 0){
@ -1666,7 +1654,7 @@ hfree(ulong ppath, char *name)
int h;
Hash *hp, **l;
h = hash(ppath, name);
h = (hash(name)+ppath) % nelem(htab);
for(l = &htab[h]; *l != nil; l = &(*l)->next){
hp = *l;
if(ppath == hp->ppath && strcmp(name, hp->name) == 0){

View file

@ -5,15 +5,42 @@
#define idprint(...) if(iflag > 1) fprint(2, __VA_ARGS__); else {}
#define iprint(...) if(iflag) fprint(2, __VA_ARGS__); else {}
static char *magic = "idx magic v7\n";
static char *magic = "idx magic v8\n";
static char *mbmagic = "genericv1";
enum {
Idxfields = 21,
Idxfields = 22,
Idxto = 30000, /* index timeout in ms */
Idxstep = 300, /* sleep between tries */
};
typedef struct Intern Intern;
struct Intern
{
Intern *next;
char str[];
};
static Intern *itab[64];
char*
intern(char *s)
{
Intern *i, **h;
int n;
h = &itab[hash(s) % nelem(itab)];
for(i = *h; i != nil; i = i->next)
if(strcmp(s, i->str) == 0)
return i->str;
n = strlen(s)+1;
i = emalloc(sizeof(*i) + n);
memmove(i->str, s, n);
i->next = *h;
*h = i;
return i->str;
}
void
idxfree(Idx *i)
{
@ -32,6 +59,7 @@ idxfree(Idx *i)
free(i->sender);
free(i->inreplyto);
free(i->idxaux);
free(i->filename);
}
memset(i, 0, sizeof *i);
}
@ -50,7 +78,7 @@ pridxmsg(Biobuf *b, Idx *x)
Bprint(b, "%#A %ux %D %lud ", x->digest, x->flags&~Frecent, x->fileid, x->lines);
Bprint(b, "%q %q %q %q %q ", (x->ffrom), (x->from), (x->to), (x->cc), (x->bcc));
Bprint(b, "%q %q %q %q %q ", (x->replyto), (x->messageid), (x->subject), (x->sender), (x->inreplyto));
Bprint(b, "%s %d %lud %lud ", rtab[x->type].s, x->disposition, x->size, x->rawbsize);
Bprint(b, "%s %d %q %lud %lud ", x->type, x->disposition, (x->filename), x->size, x->rawbsize);
Bprint(b, "%lud %q %d\n", x->ibadchars, (x->idxaux), x->nparts);
return 0;
}
@ -87,7 +115,6 @@ pridx(Biobuf *b, Mailbox *mb)
Bprint(b, magic);
mb->idxwrite(b, mb);
// prrefs(b);
i = pridx0(b, mb, mb->root->part, 0);
return i;
}
@ -304,7 +331,7 @@ static char*
*/
static int
rdidx(Biobuf *b, Mailbox *mb, Message *parent, int npart, int level, int doplumb)
rdidx(Biobuf *b, Mailbox *mb, Message *parent, int npart, int level)
{
char *f[Idxfields + 1], *s;
uchar *digest;
@ -345,7 +372,7 @@ dead:
if(level == 0)
m->deleted &= ~Dmark;
if(m->nparts)
if(rdidx(b, mb, m, m->nparts, level + 1, 0) == -1)
if(rdidx(b, mb, m, m->nparts, level + 1) == -1)
goto dead;
ll = &m->next;
idprint("%d seen before %d... %.2ux", level, m->id, m->cstate);
@ -375,17 +402,20 @@ dead:
m->subject = (f[11]);
m->sender = (f[12]);
m->inreplyto = (f[13]);
m->type = newrefs(f[14]);
m->type = intern(f[14]);
m->disposition = atoi(f[15]);
m->size = strtoul(f[16], 0, 0);
m->rawbsize = strtoul(f[17], 0, 0);
m->ibadchars = strtoul(f[18], 0, 0);
m->idxaux = (f[19]);
m->nparts = strtoul(f[20], 0, 0);
m->filename = (f[16]);
m->size = strtoul(f[17], 0, 0);
m->rawbsize = strtoul(f[18], 0, 0);
m->ibadchars = strtoul(f[19], 0, 0);
m->idxaux = (f[20]);
m->nparts = strtoul(f[21], 0, 0);
m->cstate &= ~Cidxstale;
m->cstate |= Cidx;
m->str = s;
s = 0;
if(!validmessage(mb, m, level))
goto dead;
if(level == 0){
@ -400,10 +430,8 @@ dead:
good++;
if(m->nparts)
if(rdidx(b, mb, m, m->nparts, level + 1, 0) == -1)
if(rdidx(b, mb, m, m->nparts, level + 1) == -1)
goto dead;
if(doplumb && level == 0)
mailplumb(mb, m, 0);
}
if(level == 0 && bad + redux > 0)
iprint("idx: %d %d %d\n", good, bad, redux);
@ -493,7 +521,7 @@ unmark(Mailbox *mb)
}
int
rdidxfile0(Mailbox *mb, int doplumb)
rdidxfile0(Mailbox *mb)
{
char buf[Pathlen + 4];
int r, v;
@ -509,7 +537,7 @@ rdidxfile0(Mailbox *mb, int doplumb)
r = -1;
else{
mark(mb);
r = rdidx(b, mb, mb->root, -1, 0, doplumb);
r = rdidx(b, mb, mb->root, -1, 0);
v = unmark(mb);
if(r == 0 && v > 0)
r = -1;
@ -519,11 +547,11 @@ rdidxfile0(Mailbox *mb, int doplumb)
}
int
rdidxfile(Mailbox *mb, int doplumb)
rdidxfile(Mailbox *mb)
{
int r;
r = rdidxfile0(mb, doplumb);
r = rdidxfile0(mb);
if(r == -1 && mb->idxinvalid)
mb->idxinvalid(mb);
return r;

View file

@ -876,15 +876,6 @@ datesec(Imap *imap, int i)
return v;
}
static void
markdel(Mailbox *mb, Message *m, int doplumb)
{
if(doplumb)
mailplumb(mb, m, 1);
m->inmbox = 0;
m->deleted = Disappear;
}
static int
vcmp(vlong a, vlong b)
{
@ -903,14 +894,13 @@ fetchicmp(Fetchi *f1, Fetchi *f2)
}
static char*
imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
imap4read(Imap *imap, Mailbox *mb)
{
char *s;
int i, n, c, nnew, ndel;
int i, n, c;
Fetchi *f;
Message *m, **ll;
*new = 0;
imap4cmd(imap, "status %Z (messages uidvalidity)", imap->mbox);
if(!isokay(s = imap4resp(imap)))
return s;
@ -928,7 +918,6 @@ imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
n = imap->nuid;
if(n < imap->nmsg) idprint(imap, "partial sync %d < %d\n", n, imap->nmsg);
qsort(f, n, sizeof f[0], (int(*)(void*, void*))fetchicmp);
nnew = ndel = 0;
ll = &mb->root->part;
for(i = 0; (m = *ll) != nil || i < n; ){
c = -1;
@ -948,7 +937,6 @@ imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
i++;
continue;
}
nnew++;
m = newmessage(mb->root);
m->inmbox = 1;
m->idxaux = smprint("%llud", f[i].uid);
@ -958,22 +946,18 @@ imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
m->next = *ll;
*ll = m;
ll = &m->next;
newcachehash(mb, m, doplumb);
putcache(mb, m);
i++;
}else if(c > 0){
/* deleted message; */
idprint(imap, "deleted: %U (%U)\n", i<n? f[i].uid: 0, m? m->imapuid: 0);
ndel++;
markdel(mb, m, doplumb);
m->inmbox = 0;
m->deleted = Disappear;
ll = &m->next;
}else{
ll = &m->next;
i++;
}
}
*new = nnew;
return nil;
}
@ -995,7 +979,7 @@ imap4delete(Mailbox *mb, Message *m)
}
static char*
imap4sync(Mailbox *mb, int doplumb, int *new)
imap4sync(Mailbox *mb)
{
char *err;
Imap *imap;
@ -1003,7 +987,7 @@ imap4sync(Mailbox *mb, int doplumb, int *new)
imap = mb->aux;
if(err = imap4dial(imap))
goto out;
err = imap4read(imap, mb, doplumb, new);
err = imap4read(imap, mb);
out:
mb->waketime = (ulong)time(0) + imap->refreshtime;
return err;

View file

@ -55,25 +55,42 @@ static Mailboxinit *boxinit[] = {
plan9mbox,
};
static void delmessage(Mailbox*, Message*);
static void mailplumb(Mailbox*, Message*);
/*
* do we want to plumb flag changes?
*/
char*
syncmbox(Mailbox *mb, int doplumb)
syncmbox(Mailbox *mb)
{
char *s;
int n, d, y, a;
Message *m, *next;
if(mb->syncing)
return nil;
mb->syncing = 1;
a = mb->root->subname;
if(rdidxfile(mb, doplumb) == -2)
if(rdidxfile(mb) == -2)
wridxfile(mb);
if(s = mb->sync(mb, doplumb, &n))
if(s = mb->sync(mb))
return s;
n = 0;
d = 0;
y = 0;
for(m = mb->root->part; m; m = next){
next = m->next;
if((m->cstate & Cidx) == 0 && m->deleted == 0){
cachehash(mb, m);
if(insurecache(mb, m) == 0){
mailplumb(mb, m);
msgdecref(mb, m);
}
n++;
}
if(m->cstate & Cidxstale)
y++;
if(m->deleted == 0 || m->refs > 0)
@ -81,6 +98,7 @@ syncmbox(Mailbox *mb, int doplumb)
if(mb->delete && m->inmbox && m->deleted & Deleted)
mb->delete(mb, m);
if(!m->inmbox){
mailplumb(mb, m);
delmessage(mb, m);
d++;
}
@ -97,6 +115,9 @@ syncmbox(Mailbox *mb, int doplumb)
henter(PATH(0, Qtop), mb->name,
(Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);
}
mb->syncing = 0;
return nil;
}
@ -229,11 +250,10 @@ newmbox(char *path, char *name, int flags, Mailbox **r)
if(mb->ctl)
henter(PATH(mb->id, Qmbox), "ctl",
(Qid){PATH(mb->id, Qmboxctl), 0, QTFILE}, nil, mb);
rv = syncmbox(mb, 0);
if(r)
*r = mb;
return rv;
return syncmbox(mb);
}
/* close the named mailbox */
@ -259,7 +279,7 @@ syncallmboxes(void)
Mailbox *m;
for(m = mbl; m != nil; m = m->next)
if(err = syncmbox(m, 1))
if(err = syncmbox(m))
eprint("syncmbox: %s\n", err);
}
@ -329,7 +349,6 @@ gettopmsg(Mailbox *mb, Message *m)
void
datesec(Mailbox *mb, Message *m)
{
char *s;
vlong v;
Tm tm;
@ -342,11 +361,10 @@ datesec(Mailbox *mb, Message *m)
else if(rxtotm(m, &tm) >= 0)
v = tm2sec(&tm);
else{
s = rtab[m->type].s;
logmsg(gettopmsg(mb, m), "%s:%s: datasec %s %s\n", mb->path,
m->whole? m->whole->name: "?",
m->name, s);
if(Topmsg(mb, m) || strcmp(s, "message/rfc822") == 0)
m->name, m->type);
if(Topmsg(mb, m) || strcmp(m->type, "message/rfc822") == 0)
abort();
v = 0;
}
@ -377,14 +395,12 @@ parseattachments(Message *m, Mailbox *mb)
Message *nm, **l;
/* if there's a boundary, recurse... */
sanemsg(m);
// dprint("parseattachments %p %ld\n", m->start, m->end - m->start);
dprint("parseattachments %p %ld bonudary %s\n", m->start, (ulong)(m->end - m->start), m->boundary);
if(m->boundary != nil){
p = m->body;
nm = nil;
l = &m->part;
for(i = 0;;){
sanemsg(m);
x = strstr(p, m->boundary);
/* two sequential boundaries; ignore nil message */
if(nm && x == p){
@ -401,7 +417,6 @@ sanemsg(m);
if(x == nil){
if(nm != nil){
nm->rbend = nm->bend = nm->end = m->bend;
sanemsg(nm);
if(nm->end == nm->start)
nm->mimeflag |= Mtrunc;
}
@ -414,9 +429,7 @@ sanemsg(nm);
}
if(nm != nil)
{
nm->rbend = nm->bend = nm->end = x;
sanemsg(nm);}
x += strlen(m->boundary);
/* is this the last part? ignore anything after it */
@ -435,6 +448,7 @@ sanemsg(nm);}
nm->mheader = nm->header = nm->body = nm->rbody = nm->start;
}
for(nm = m->part; nm != nil; nm = nm->next){
nm->size = nm->end - nm->start;
parse(mb, nm, 0, 1);
cachehash(mb, nm); /* botchy place for this */
}
@ -442,7 +456,7 @@ sanemsg(nm);}
}
/* if we've got an rfc822 message, recurse... */
if(strcmp(rtab[m->type].s, "message/rfc822") == 0){
if(strcmp(m->type, "message/rfc822") == 0){
if((nm = haschild(m, 0)) == nil){
nm = newmessage(m);
m->part = nm;
@ -452,6 +466,7 @@ sanemsg(nm);}
nm->end = nm->bend = nm->rbend = m->bend;
if(nm->end == nm->start)
nm->mimeflag |= Mtrunc;
nm->size = nm->end - nm->start;
parse(mb, nm, 0, 0);
cachehash(mb, nm); /* botchy place for this */
}
@ -543,16 +558,12 @@ promote(char *s)
void
parsebody(Message *m, Mailbox *mb)
{
char *s;
int l;
Message *nm;
/* recurse */
s = rtab[m->type].s;
l = rtab[m->type].l;
if(l >= 10 && strncmp(s, "multipart/", 10) == 0)
if(strncmp(m->type, "multipart/", 10) == 0)
parseattachments(m, mb);
else if(l == 14 && strcmp(s, "message/rfc822") == 0){
else if(strcmp(m->type, "message/rfc822") == 0){
decode(m);
parseattachments(m, mb);
nm = m->part;
@ -566,7 +577,7 @@ parsebody(Message *m, Mailbox *mb)
m->replyto = promote(nm->replyto);
m->subject = promote(nm->subject);
}
}else if(strncmp(rtab[m->type].s, "text/", 5) == 0)
}else if(strncmp(m->type, "text/", 5) == 0)
sanemsg(m);
m->rawbsize = m->rbend - m->rbody;
m->cstate |= Cbody;
@ -651,7 +662,9 @@ setfilename(Message *m, char *p)
{
char buf[Pathlen];
free(m->filename);
dprint("setfilename %p %s -> %s\n", m, m->filename, p);
if(m->filename != nil)
return;
getstring(p, buf, buf + sizeof buf - 1, 0);
m->filename = smprint("%s", buf);
for(p = m->filename; *p; p++)
@ -909,7 +922,7 @@ ctype(Message *m, Header *h, char*, char *p)
e = buf + sizeof buf - 1;
p = getstring(skipwhite(p + h->len), buf, e, 1);
m->type = newrefs(buf);
m->type = intern(buf);
for(; *p; p = skiptosemi(p))
if(isattribute(&p, "boundary")){
@ -922,12 +935,10 @@ ctype(Message *m, Header *h, char*, char *p)
* the preamble, is not displayed or saved
*/
} else if(isattribute(&p, "name")){
if(m->filename == nil)
setfilename(m, p);
} else if(isattribute(&p, "charset")){
p = getstring(p, buf, e, 0);
lowercase(buf);
m->charset = newrefs(buf);
p = getstring(p, buf, e, 1);
m->charset = intern(buf);
}
return (char*)~0;
}
@ -971,9 +982,8 @@ newmessage(Message *parent)
m = emalloc(sizeof *m);
dprint("newmessage %ld %p %p\n", msgallocd, parent, m);
m->disposition = Dnone;
m->type = newrefs("text/plain");
m->charset = newrefs("iso-8859-1");
m->type = intern("text/plain");
m->charset = intern("iso-8859-1");
m->cstate = Cidxstale;
m->flags = Frecent;
m->id = newid();
@ -987,7 +997,7 @@ newmessage(Message *parent)
}
/* delete a message from a mailbox */
void
static void
delmessage(Mailbox *mb, Message *m)
{
Message **l;
@ -1014,17 +1024,13 @@ delmessage(Mailbox *mb, Message *m)
mtreedelete(mb, m);
cachefree(mb, m, 1);
}
delrefs(m->type);
delrefs(m->charset);
idxfree(m);
while(m->part)
delmessage(mb, m->part);
free(m->unixfrom);
free(m->unixheader);
free(m->date822);
free(m->inreplyto);
free(m->boundary);
free(m->filename);
free(m);
}
@ -1057,7 +1063,6 @@ delmessages(int ac, char **av)
for(m = mb->root->part; m != nil; m = m->next)
if(strcmp(m->name, av[i]) == 0){
if(!m->deleted){
mailplumb(mb, m, 1);
needwrite = 1;
m->deleted = Deleted;
logmsg(m, "deleting");
@ -1065,7 +1070,7 @@ delmessages(int ac, char **av)
break;
}
if(needwrite)
syncmbox(mb, 1);
syncmbox(mb);
return 0;
}
@ -1095,7 +1100,7 @@ flagmessages(int argc, char **argv)
needwrite = 1;
}
if(needwrite)
syncmbox(mb, 1);
syncmbox(mb);
return rerr;
}
@ -1112,7 +1117,7 @@ msgdecref(Mailbox *mb, Message *m)
m->refs--;
if(m->refs == 0){
if(m->deleted)
syncmbox(mb, 1);
syncmbox(mb);
else
putcache(mb, m);
}
@ -1144,7 +1149,7 @@ mboxdecref(Mailbox *mb)
assert(mb->refs > 0);
mb->refs--;
if(mb->refs == 0){
syncmbox(mb, 1);
syncmbox(mb);
delmessage(mb, mb->root);
if(mb->ctl)
hfree(PATH(mb->id, Qmbox), "ctl");
@ -1187,6 +1192,7 @@ decode(Message *m)
if(m->decoded)
return;
dprint("decode %d %p\n", m->encoding, m);
switch(m->encoding){
case Ebase64:
len = m->bend - m->body;
@ -1197,7 +1203,7 @@ decode(Message *m)
free(x);
break;
}
if(strncmp(rtab[m->type].s, "text/", 5) == 0)
if(strncmp(m->type, "text/", 5) == 0)
len = deccr(x, len);
if(m->ballocd)
free(m->body);
@ -1231,10 +1237,11 @@ convert(Message *m)
/* don't convert if we're not a leaf, not text, or already converted */
if(m->converted)
return;
dprint("convert type=%q charset=%q %p\n", m->type, m->charset, m);
m->converted = 1;
if(m->part != nil || cistrncmp(rtab[m->type].s, "text", 4) != 0)
if(m->part != nil || strncmp(m->type, "text", 4) != 0 || *m->charset == 0)
return;
len = xtoutf(rtab[m->charset].s, &x, m->body, m->bend);
len = xtoutf(m->charset, &x, m->body, m->bend);
if(len > 0){
if(m->ballocd)
free(m->body);
@ -1376,9 +1383,9 @@ xtoutf(char *charset, char **out, char *in, char *e)
int totcs[2], fromtcs[2], n, len, sofar;
/* might not need to convert */
if(cistrcmp(charset, "us-ascii") == 0 || cistrcmp(charset, "utf-8") == 0)
if(strcmp(charset, "us-ascii") == 0 || strcmp(charset, "utf-8") == 0)
return 0;
if(cistrcmp(charset, "iso-8859-1") == 0)
if(strcmp(charset, "iso-8859-1") == 0)
return latin1toutf(out, in, e);
len = e - in + 1;
@ -1495,16 +1502,15 @@ myplumbsend(int fd, Plumbmsg *m)
return n;
}
void
mailplumb(Mailbox *mb, Message *m, int delete)
static void
mailplumb(Mailbox *mb, Message *m)
{
char buf[256], dbuf[SHA1dlen*2 + 1], len[10], date[30], *from, *subject;
int ai, cache;
int ai;
Plumbmsg p;
Plumbattr a[7];
static int fd = -1;
cache = insurecache(mb, m) == 0; /* living dangerously if deleted */
subject = m->subject;
if(subject == nil)
subject = "";
@ -1517,15 +1523,15 @@ mailplumb(Mailbox *mb, Message *m, int delete)
from = "";
sprint(len, "%lud", m->size);
if(biffing && !delete)
if(biffing && m->inmbox)
fprint(2, "[ %s / %s / %s ]\n", from, subject, len);
if(!plumbing)
goto out;
return;
if(fd < 0)
fd = plumbopen("send", OWRITE);
if(fd < 0)
goto out;
return;
p.src = "mailfs";
p.dst = "seemail";
@ -1545,7 +1551,7 @@ mailplumb(Mailbox *mb, Message *m, int delete)
a[ai-1].next = &a[ai];
a[++ai].name = "mailtype";
a[ai].value = delete? "delete": "new";
a[ai].value = !m->inmbox ? "delete": "new";
a[ai-1].next = &a[ai];
snprint(date, sizeof date, "", m->fileid);
@ -1567,9 +1573,6 @@ mailplumb(Mailbox *mb, Message *m, int delete)
p.data = buf;
myplumbsend(fd, &p);
out:
if(cache)
msgdecref(mb, m);
}
/*

View file

@ -109,9 +109,9 @@ dircmp(Dir *a, Dir *b)
}
static char*
mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
mdirread(Mdir* mdir, Mailbox* mb)
{
int i, nnew, ndel, fd, n, c;
int i, fd, n, c;
uvlong uv;
Dir *d;
Message *m, **ll;
@ -127,7 +127,6 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
close(fd);
return err;
}
*new = nnew = 0;
if(mb->d){
if(d->qid.path == mb->d->qid.path)
if(d->qid.vers == mb->d->qid.vers){
@ -149,7 +148,6 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
}
qsort(d, n, sizeof *d, (int(*)(void*, void*))dircmp);
ndel = 0;
ll = &mb->root->part;
for(i = 0; (m = *ll) != nil || i < n; ){
if(i < n && dirskip(d + i, &uv)){
@ -170,7 +168,6 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
i++;
continue;
}
nnew++;
m = newmessage(mb->root);
m->fileid = uv;
m->size = d[i].length;
@ -178,15 +175,10 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
m->next = *ll;
*ll = m;
ll = &m->next;
newcachehash(mb, m, doplumb);
putcache(mb, m);
i++;
}else if(c > 0){
/* deleted message; */
mdprint(mdir, "deleted: %s (%D)\n", i<n? d[i].name: 0, m? m->fileid: 0);
ndel++;
if(doplumb)
mailplumb(mb, m, 1);
m->inmbox = 0;
m->deleted = Disappear;
ll = &m->next;
@ -196,11 +188,8 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
i++;
}
}
free(d);
logmsg(nil, "mbox read: %d new %d deleted", nnew, ndel);
finished:
*new = nnew;
return nil;
}
@ -220,13 +209,13 @@ mdirdelete(Mailbox *mb, Message *m)
}
static char*
mdirsync(Mailbox* mb, int doplumb, int *new)
mdirsync(Mailbox* mb)
{
Mdir *mdir;
mdir = mb->aux;
mdprint(mdir, "mdirsync()\n");
return mdirread(mdir, mb, doplumb, new);
return mdirread(mdir, mb);
}
static char*

View file

@ -14,7 +14,6 @@ OFILES=\
mtree.$O\
plan9.$O\
pop3.$O\
ref.$O\
remove.$O\
rename.$O\
strtotm.$O\
@ -36,6 +35,3 @@ CFLAGS=$CFLAGS -I../common
acid:V:
$CC -a $CFLAGS fs.c>a$O
chkidx: mtree.$O chkidx.$O
$LD $LDFLAGS -o $target $prereq

View file

@ -179,17 +179,15 @@ readmessage(Mailbox *mb, Message *m, Inbuf *b)
int
purgedeleted(Mailbox *mb)
{
Message *m, *next;
Message *m;
int newdels;
/* forget about what's no longer in the mailbox */
newdels = 0;
for(m = mb->root->part; m != nil; m = next){
next = m->next;
if(m->deleted && m->refs == 0){
if(m->inmbox)
for(m = mb->root->part; m != nil; m = m->next){
if(m->deleted && m->inmbox){
newdels++;
delmessage(mb, m);
m->inmbox = 0;
}
}
return newdels;
@ -217,10 +215,9 @@ mergemsg(Message *m, Message *x)
* read in the mailbox and parse into messages.
*/
static char*
readmbox(Mailbox *mb, int doplumb, int *new, Mlock *lk)
readmbox(Mailbox *mb, Mlock *lk)
{
char *p, *x, buf[Pathlen];
int nnew;
Biobuf *in;
Dir *d;
Inbuf b;
@ -256,7 +253,6 @@ retry:
}
if(mb->d != nil){
if(d->qid.path == mb->d->qid.path && d->qid.vers == mb->d->qid.vers){
*new = 0;
Bterm(in);
free(d);
return nil;
@ -276,7 +272,6 @@ retry:
/* read new messages */
logmsg(nil, "reading %s", mb->path);
nnew = 0;
for(;;){
if(lk != nil)
syslockrefresh(lk);
@ -306,8 +301,6 @@ retry:
} else {
/* old mail no longer in box, mark deleted */
logmsg(*l, "disappeared");
if(doplumb)
mailplumb(mb, *l, 1);
(*l)->inmbox = 0;
(*l)->deleted = Disappear;
l = &(*l)->next;
@ -324,9 +317,6 @@ retry:
parse(mb, m, 0, 0);
if(m != *l && m->deleted != Dup){
logmsg(m, "new");
newcachehash(mb, m, doplumb);
putcache(mb, m);
nnew++;
}
/* chain in */
*l = m;
@ -336,15 +326,12 @@ retry:
/* whatever is left has been removed from the mbox, mark deleted */
while(*l != nil){
if(doplumb)
mailplumb(mb, *l, 1);
(*l)->inmbox = 0;
(*l)->deleted = Deleted;
l = &(*l)->next;
}
Bterm(in);
*new = nnew;
return nil;
}
@ -408,7 +395,7 @@ writembox(Mailbox *mb, Mlock *lk)
}
char*
plan9syncmbox(Mailbox *mb, int doplumb, int *new)
plan9syncmbox(Mailbox *mb)
{
char *rv;
Mlock *lk;
@ -420,7 +407,7 @@ plan9syncmbox(Mailbox *mb, int doplumb, int *new)
return "can't lock mailbox";
}
rv = readmbox(mb, doplumb, new, lk); /* interpolate */
rv = readmbox(mb, lk); /* interpolate */
if(purgedeleted(mb) > 0)
writembox(mb, lk);

View file

@ -359,14 +359,13 @@ pop3download(Mailbox *mb, Pop *pop, Message *m)
* we'll use it to make our lives easier.
*/
static char*
pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
pop3read(Pop *pop, Mailbox *mb)
{
char *s, *p, *uidl, *f[2];
int mno, ignore, nnew;
int mno, ignore;
Message *m, *next, **l;
Popm *a;
*new = 0;
/* Some POP servers disallow UIDL if the maildrop is empty. */
pop3cmd(pop, "STAT");
if(!isokay(s = pop3resp(pop)))
@ -409,8 +408,6 @@ pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
break;
}else{
/* old mail no longer in box mark deleted */
if(doplumb)
mailplumb(mb, *l, 1);
(*l)->inmbox = 0;
(*l)->deleted = Deleted;
l = &(*l)->next;
@ -434,15 +431,12 @@ pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
/* whatever is left has been removed from the mbox, mark as deleted */
while(*l != nil) {
if(doplumb)
mailplumb(mb, *l, 1);
(*l)->inmbox = 0;
(*l)->deleted = Disappear;
l = &(*l)->next;
}
/* download new messages */
nnew = 0;
if(pop->pipeline){
switch(rfork(RFPROC|RFMEM)){
case -1:
@ -469,20 +463,14 @@ pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
if(m->start != nil || m->deleted)
continue;
if(s = pop3download(mb, pop, m)) {
/* message disappeared? unchain */
eprint("pop3: download %d: %s\n", mesgno(m), s);
delmessage(mb, m);
mb->root->subname--;
unnewmessage(mb, mb->root, m);
continue;
}
nnew++;
parse(mb, m, 1, 0);
newcachehash(mb, m, doplumb);
putcache(mb, m);
}
if(pop->pipeline)
waitpid();
*new = nnew;
return nil;
}
@ -492,7 +480,7 @@ pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
static void
pop3purge(Pop *pop, Mailbox *mb)
{
Message *m, *next;
Message *m;
if(pop->pipeline){
switch(rfork(RFPROC|RFMEM)){
@ -504,27 +492,21 @@ pop3purge(Pop *pop, Mailbox *mb)
break;
case 0:
for(m = mb->root->part; m != nil; m = next){
next = m->next;
if(m->deleted && m->refs == 0){
if(m->inmbox)
for(m = mb->root->part; m != nil; m = m->next){
if(m->deleted && m->inmbox)
Bprint(&pop->bout, "DELE %d\r\n", mesgno(m));
}
}
Bflush(&pop->bout);
_exits("");
}
}
for(m = mb->root->part; m != nil; m = next) {
next = m->next;
if(m->deleted && m->refs == 0) {
if(m->inmbox) {
for(m = mb->root->part; m != nil; m = m->next) {
if(m->deleted && m->inmbox) {
if(!pop->pipeline)
pop3cmd(pop, "DELE %d", mesgno(m));
if(isokay(pop3resp(pop)))
delmessage(mb, m);
} else
delmessage(mb, m);
if(!isokay(pop3resp(pop)))
continue;
m->inmbox = 0;
}
}
}
@ -532,16 +514,15 @@ pop3purge(Pop *pop, Mailbox *mb)
/* connect to pop3 server, sync mailbox */
static char*
pop3sync(Mailbox *mb, int doplumb, int *new)
pop3sync(Mailbox *mb)
{
char *err;
Pop *pop;
pop = mb->aux;
if(err = pop3dial(pop))
goto out;
if((err = pop3read(pop, mb, doplumb, new)) == nil)
if((err = pop3read(pop, mb)) == nil)
pop3purge(pop, mb);
pop3hangup(pop);
out:

View file

@ -1,100 +0,0 @@
#include "common.h"
#include <libsec.h>
#include "dat.h"
/* all the data that's fit to cache */
typedef struct{
char *s;
int l;
ulong ref;
}Refs;
Refs *rtab;
int nrtab;
int nralloc;
int
newrefs(char *s)
{
int l, i;
Refs *r;
l = strlen(s);
for(i = 0; i < nrtab; i++){
r = rtab + i;
if(r->ref == 0)
goto enter;
if(l == r->l && strcmp(r->s, s) == 0){
r->ref++;
return i;
}
}
if(nrtab == nralloc)
rtab = erealloc(rtab, sizeof *rtab*(nralloc += 50));
nrtab = i + 1;
enter:
r = rtab + i;
r->s = strdup(s);
r->l = l;
r->ref = 1;
return i;
}
void
delrefs(int i)
{
Refs *r;
r = rtab + i;
if(--r->ref > 0)
return;
free(r->s);
memset(r, 0, sizeof *r);
}
void
refsinit(void)
{
newrefs("");
}
static char *sep = "--------\n";
int
prrefs(Biobuf *b)
{
int i, n;
n = 0;
for(i = 1; i < nrtab; i++){
if(rtab[i].ref == 0)
continue;
Bprint(b, "%s ", rtab[i].s);
if(n++%8 == 7)
Bprint(b, "\n");
}
if(n%8 != 7)
Bprint(b, "\n");
Bprint(b, sep);
return 0;
}
int
rdrefs(Biobuf *b)
{
char *f[10], *s;
int i, n;
while(s = Brdstr(b, '\n', 1)){
if(strcmp(s, sep) == 0){
free(s);
return 0;
}
n = tokenize(s, f, nelem(f));
for(i = 0; i < n; i++)
newrefs(f[i]);
free(s);
}
return -1;
}