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:
parent
c3d372c3da
commit
a1c1e00973
12 changed files with 177 additions and 760 deletions
|
@ -371,18 +371,6 @@ cachehash(Mailbox *mb, Message *m)
|
||||||
(Qid){PATH(m->id, Qmax), 0, QTFILE}, m, mb); /* sleezy speedup */
|
(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[] = {
|
static char *itab[] = {
|
||||||
"idx",
|
"idx",
|
||||||
"stale",
|
"stale",
|
||||||
|
@ -424,7 +412,7 @@ middlecache(Mailbox *mb, Message *m)
|
||||||
}
|
}
|
||||||
if(y == 0)
|
if(y == 0)
|
||||||
return 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);
|
return cachebody(mb, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,7 +475,7 @@ cachebody(Mailbox *mb, Message *m)
|
||||||
if(!mb->fetch || m->cstate&Cbody)
|
if(!mb->fetch || m->cstate&Cbody)
|
||||||
return 0;
|
return 0;
|
||||||
o = m->end - m->start;
|
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(o < m->size)
|
||||||
if(fetch(mb, m, o, m->size - o) < 0)
|
if(fetch(mb, m, o, m->size - o) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -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("");
|
|
||||||
}
|
|
|
@ -62,10 +62,12 @@ struct Idx {
|
||||||
char *subject;
|
char *subject;
|
||||||
char *sender;
|
char *sender;
|
||||||
char *inreplyto;
|
char *inreplyto;
|
||||||
char *idxaux; /* mailbox specific */
|
char *idxaux; /* mailbox specific */
|
||||||
|
|
||||||
|
char *type; /* mime info */
|
||||||
|
char disposition;
|
||||||
|
char *filename;
|
||||||
|
|
||||||
int type; /* very few types: refstring */
|
|
||||||
int disposition; /* very few types: refstring */
|
|
||||||
int nparts;
|
int nparts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -114,10 +116,9 @@ struct Message {
|
||||||
char *references[Nref];
|
char *references[Nref];
|
||||||
|
|
||||||
/* mime info */
|
/* mime info */
|
||||||
char *boundary;
|
char *charset;
|
||||||
int charset;
|
|
||||||
char *filename;
|
|
||||||
char encoding;
|
char encoding;
|
||||||
|
char *boundary;
|
||||||
char converted;
|
char converted;
|
||||||
char decoded;
|
char decoded;
|
||||||
char mimeflag;
|
char mimeflag;
|
||||||
|
@ -175,12 +176,14 @@ struct Mailbox {
|
||||||
char *(*ctl)(Mailbox*, int, char**);
|
char *(*ctl)(Mailbox*, int, char**);
|
||||||
char *(*remove)(Mailbox *, int);
|
char *(*remove)(Mailbox *, int);
|
||||||
char *(*rename)(Mailbox*, char*, int);
|
char *(*rename)(Mailbox*, char*, int);
|
||||||
char *(*sync)(Mailbox*, int, int*);
|
char *(*sync)(Mailbox*);
|
||||||
void (*modflags)(Mailbox*, Message*, int);
|
void (*modflags)(Mailbox*, Message*, int);
|
||||||
void (*idxwrite)(Biobuf*, Mailbox*);
|
void (*idxwrite)(Biobuf*, Mailbox*);
|
||||||
int (*idxread)(char*, Mailbox*);
|
int (*idxread)(char*, Mailbox*);
|
||||||
void (*idxinvalid)(Mailbox*);
|
void (*idxinvalid)(Mailbox*);
|
||||||
void *aux; /* private to Mailbox implementation */
|
void *aux; /* private to Mailbox implementation */
|
||||||
|
|
||||||
|
int syncing; /* currently syncing? */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef char *Mailboxinit(Mailbox*, char*);
|
typedef char *Mailboxinit(Mailbox*, char*);
|
||||||
|
@ -195,7 +198,6 @@ int genericidxread(char*, Mailbox*);
|
||||||
void genericidxinvalid(Mailbox*);
|
void genericidxinvalid(Mailbox*);
|
||||||
|
|
||||||
void cachehash(Mailbox*, Message*);
|
void cachehash(Mailbox*, Message*);
|
||||||
void newcachehash(Mailbox*, Message*, int);
|
|
||||||
int cacheheaders(Mailbox*, Message*); /* "getcache" */
|
int cacheheaders(Mailbox*, Message*); /* "getcache" */
|
||||||
int cachebody(Mailbox*, Message*);
|
int cachebody(Mailbox*, Message*);
|
||||||
int cacheidx(Mailbox*, Message*);
|
int cacheidx(Mailbox*, Message*);
|
||||||
|
@ -206,12 +208,11 @@ void putcache(Mailbox*, Message*); /* asymmetricial */
|
||||||
long cachefree(Mailbox*, Message*, int);
|
long cachefree(Mailbox*, Message*, int);
|
||||||
|
|
||||||
Message* gettopmsg(Mailbox*, Message*);
|
Message* gettopmsg(Mailbox*, Message*);
|
||||||
char* syncmbox(Mailbox*, int);
|
char* syncmbox(Mailbox*);
|
||||||
void* emalloc(ulong);
|
void* emalloc(ulong);
|
||||||
void* erealloc(void*, ulong);
|
void* erealloc(void*, ulong);
|
||||||
Message* newmessage(Message*);
|
Message* newmessage(Message*);
|
||||||
void unnewmessage(Mailbox*, Message*, Message*);
|
void unnewmessage(Mailbox*, Message*, Message*);
|
||||||
void delmessage(Mailbox*, Message*);
|
|
||||||
char* delmessages(int, char**);
|
char* delmessages(int, char**);
|
||||||
char *flagmessages(int, char**);
|
char *flagmessages(int, char**);
|
||||||
void digestmessage(Mailbox*, Message*);
|
void digestmessage(Mailbox*, Message*);
|
||||||
|
@ -221,7 +222,6 @@ int wraptls(int, char*);
|
||||||
void eprint(char*, ...);
|
void eprint(char*, ...);
|
||||||
void iprint(char *, ...);
|
void iprint(char *, ...);
|
||||||
int newid(void);
|
int newid(void);
|
||||||
void mailplumb(Mailbox*, Message*, int);
|
|
||||||
char* newmbox(char*, char*, int, Mailbox**);
|
char* newmbox(char*, char*, int, Mailbox**);
|
||||||
void freembox(char*);
|
void freembox(char*);
|
||||||
char* removembox(char*, int);
|
char* removembox(char*, int);
|
||||||
|
@ -318,24 +318,14 @@ struct Hash {
|
||||||
Message *m;
|
Message *m;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint hash(char*);
|
||||||
Hash *hlook(ulong, char*);
|
Hash *hlook(ulong, char*);
|
||||||
void henter(ulong, char*, Qid, Message*, Mailbox*);
|
void henter(ulong, char*, Qid, Message*, Mailbox*);
|
||||||
void hfree(ulong, char*);
|
void hfree(ulong, char*);
|
||||||
|
|
||||||
typedef struct {
|
char *intern(char*);
|
||||||
char *s;
|
|
||||||
int l;
|
|
||||||
ulong ref;
|
|
||||||
} Refs;
|
|
||||||
|
|
||||||
int newrefs(char*);
|
|
||||||
void delrefs(int);
|
|
||||||
void refsinit(void);
|
|
||||||
int prrefs(Biobuf*);
|
|
||||||
int rdrefs(Biobuf*);
|
|
||||||
|
|
||||||
void idxfree(Idx*);
|
void idxfree(Idx*);
|
||||||
int rdidxfile(Mailbox*, int);
|
int rdidxfile(Mailbox*);
|
||||||
int wridxfile(Mailbox*);
|
int wridxfile(Mailbox*);
|
||||||
|
|
||||||
char *modflags(Mailbox*, Message*, char*);
|
char *modflags(Mailbox*, Message*, char*);
|
||||||
|
@ -356,7 +346,6 @@ extern ulong msgallocd;
|
||||||
extern ulong msgfreed;
|
extern ulong msgfreed;
|
||||||
extern Mailbox *mbl;
|
extern Mailbox *mbl;
|
||||||
extern Message *root;
|
extern Message *root;
|
||||||
extern Refs *rtab;
|
|
||||||
|
|
||||||
#define dprint(...) if(debug) fprint(2, __VA_ARGS__); else {}
|
#define dprint(...) if(debug) fprint(2, __VA_ARGS__); else {}
|
||||||
#define Topmsg(mb, m) (m->whole == mb->root)
|
#define Topmsg(mb, m) (m->whole == mb->root)
|
||||||
|
|
|
@ -104,11 +104,6 @@ char *dirtab[] = {
|
||||||
[Qmboxctl] "ctl",
|
[Qmboxctl] "ctl",
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
Hsize= 1999,
|
|
||||||
};
|
|
||||||
|
|
||||||
char *mntpt;
|
char *mntpt;
|
||||||
char user[Elemlen];
|
char user[Elemlen];
|
||||||
int Dflag;
|
int Dflag;
|
||||||
|
@ -127,7 +122,7 @@ static char hbuf[32*1024];
|
||||||
static uchar mbuf[16*1024 + IOHDRSZ];
|
static uchar mbuf[16*1024 + IOHDRSZ];
|
||||||
static uchar mdata[16*1024 + IOHDRSZ];
|
static uchar mdata[16*1024 + IOHDRSZ];
|
||||||
static ulong path; /* incremented for each new file */
|
static ulong path; /* incremented for each new file */
|
||||||
static Hash *htab[Hsize];
|
static Hash *htab[1024];
|
||||||
static Fcall rhdr;
|
static Fcall rhdr;
|
||||||
static Fcall thdr;
|
static Fcall thdr;
|
||||||
static Fid *fids;
|
static Fid *fids;
|
||||||
|
@ -136,8 +131,6 @@ static QLock synclock;
|
||||||
void
|
void
|
||||||
sanemsg(Message *m)
|
sanemsg(Message *m)
|
||||||
{
|
{
|
||||||
if(debug)
|
|
||||||
poolcheck(mainmem);
|
|
||||||
assert(m->refs < 100);
|
assert(m->refs < 100);
|
||||||
assert(m->next != m);
|
assert(m->next != m);
|
||||||
if(m->end < m->start)
|
if(m->end < m->start)
|
||||||
|
@ -294,8 +287,8 @@ main(int argc, char *argv[])
|
||||||
cachetarg = ntoi(EARGF(usage()));
|
cachetarg = ntoi(EARGF(usage()));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
debug = 1;
|
if(++debug > 1)
|
||||||
mainmem->flags |= POOL_PARANOIA;
|
mainmem->flags |= POOL_PARANOIA;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
mboxfile = EARGF(usage());
|
mboxfile = EARGF(usage());
|
||||||
|
@ -527,8 +520,8 @@ fileinfo(Mailbox *mb, Message *m, int t, char **pp)
|
||||||
p = m->to;
|
p = m->to;
|
||||||
break;
|
break;
|
||||||
case Qtype:
|
case Qtype:
|
||||||
p = rtab[m->type].s;
|
p = m->type;
|
||||||
len = rtab[m->type].l;
|
len = strlen(m->type);
|
||||||
break;
|
break;
|
||||||
case Qunixdate:
|
case Qunixdate:
|
||||||
p = buf;
|
p = buf;
|
||||||
|
@ -1015,7 +1008,7 @@ readmboxdir(Fid *f, uchar *buf, long off, int cnt, int blen)
|
||||||
Message *msg;
|
Message *msg;
|
||||||
|
|
||||||
if(off == 0)
|
if(off == 0)
|
||||||
syncmbox(f->mb, 1);
|
syncmbox(f->mb);
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
if(f->mb->ctl){
|
if(f->mb->ctl){
|
||||||
|
@ -1339,11 +1332,8 @@ rclunk(Fid *f)
|
||||||
char *
|
char *
|
||||||
rremove(Fid *f)
|
rremove(Fid *f)
|
||||||
{
|
{
|
||||||
if(f->m != nil){
|
if(f->m != nil && f->m->deleted == 0)
|
||||||
if(!f->m->deleted)
|
|
||||||
mailplumb(f->mb, f->m, 1);
|
|
||||||
f->m->deleted = Deleted;
|
f->m->deleted = Deleted;
|
||||||
}
|
|
||||||
return rclunk(f);
|
return rclunk(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,7 +1343,7 @@ rstat(Fid *f)
|
||||||
Dir d;
|
Dir d;
|
||||||
|
|
||||||
if(FILE(f->qid.path) == Qmbox)
|
if(FILE(f->qid.path) == Qmbox)
|
||||||
syncmbox(f->mb, 1);
|
syncmbox(f->mb);
|
||||||
mkstat(&d, f->mb, f->m, FILE(f->qid.path));
|
mkstat(&d, f->mb, f->m, FILE(f->qid.path));
|
||||||
rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ);
|
rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ);
|
||||||
rhdr.stat = mbuf;
|
rhdr.stat = mbuf;
|
||||||
|
@ -1475,7 +1465,7 @@ reader(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(mb != nil) {
|
if(mb != nil) {
|
||||||
syncmbox(mb, 1);
|
syncmbox(mb);
|
||||||
qunlock(&synclock);
|
qunlock(&synclock);
|
||||||
} else {
|
} else {
|
||||||
qunlock(&synclock);
|
qunlock(&synclock);
|
||||||
|
@ -1610,17 +1600,15 @@ readheader(Message *m, char *buf, int off, int cnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint
|
uint
|
||||||
hash(ulong ppath, char *name)
|
hash(char *s)
|
||||||
{
|
{
|
||||||
uchar *p;
|
uint c, h;
|
||||||
uint h;
|
|
||||||
|
|
||||||
h = 0;
|
h = 0;
|
||||||
for(p = (uchar*)name; *p; p++)
|
while(c = *s++)
|
||||||
h = h*7 + *p;
|
h = h*131 + c;
|
||||||
h += ppath;
|
|
||||||
|
|
||||||
return h % Hsize;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hash*
|
Hash*
|
||||||
|
@ -1629,7 +1617,7 @@ hlook(ulong ppath, char *name)
|
||||||
int h;
|
int h;
|
||||||
Hash *hp;
|
Hash *hp;
|
||||||
|
|
||||||
h = hash(ppath, name);
|
h = (hash(name)+ppath) % nelem(htab);
|
||||||
for(hp = htab[h]; hp != nil; hp = hp->next)
|
for(hp = htab[h]; hp != nil; hp = hp->next)
|
||||||
if(ppath == hp->ppath && strcmp(name, hp->name) == 0)
|
if(ppath == hp->ppath && strcmp(name, hp->name) == 0)
|
||||||
return hp;
|
return hp;
|
||||||
|
@ -1642,7 +1630,7 @@ henter(ulong ppath, char *name, Qid qid, Message *m, Mailbox *mb)
|
||||||
int h;
|
int h;
|
||||||
Hash *hp, **l;
|
Hash *hp, **l;
|
||||||
|
|
||||||
h = hash(ppath, name);
|
h = (hash(name)+ppath) % nelem(htab);
|
||||||
for(l = &htab[h]; *l != nil; l = &(*l)->next){
|
for(l = &htab[h]; *l != nil; l = &(*l)->next){
|
||||||
hp = *l;
|
hp = *l;
|
||||||
if(ppath == hp->ppath && strcmp(name, hp->name) == 0){
|
if(ppath == hp->ppath && strcmp(name, hp->name) == 0){
|
||||||
|
@ -1666,7 +1654,7 @@ hfree(ulong ppath, char *name)
|
||||||
int h;
|
int h;
|
||||||
Hash *hp, **l;
|
Hash *hp, **l;
|
||||||
|
|
||||||
h = hash(ppath, name);
|
h = (hash(name)+ppath) % nelem(htab);
|
||||||
for(l = &htab[h]; *l != nil; l = &(*l)->next){
|
for(l = &htab[h]; *l != nil; l = &(*l)->next){
|
||||||
hp = *l;
|
hp = *l;
|
||||||
if(ppath == hp->ppath && strcmp(name, hp->name) == 0){
|
if(ppath == hp->ppath && strcmp(name, hp->name) == 0){
|
||||||
|
|
|
@ -5,15 +5,42 @@
|
||||||
#define idprint(...) if(iflag > 1) fprint(2, __VA_ARGS__); else {}
|
#define idprint(...) if(iflag > 1) fprint(2, __VA_ARGS__); else {}
|
||||||
#define iprint(...) if(iflag) 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";
|
static char *mbmagic = "genericv1";
|
||||||
enum {
|
enum {
|
||||||
Idxfields = 21,
|
Idxfields = 22,
|
||||||
|
|
||||||
Idxto = 30000, /* index timeout in ms */
|
Idxto = 30000, /* index timeout in ms */
|
||||||
Idxstep = 300, /* sleep between tries */
|
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
|
void
|
||||||
idxfree(Idx *i)
|
idxfree(Idx *i)
|
||||||
{
|
{
|
||||||
|
@ -32,6 +59,7 @@ idxfree(Idx *i)
|
||||||
free(i->sender);
|
free(i->sender);
|
||||||
free(i->inreplyto);
|
free(i->inreplyto);
|
||||||
free(i->idxaux);
|
free(i->idxaux);
|
||||||
|
free(i->filename);
|
||||||
}
|
}
|
||||||
memset(i, 0, sizeof *i);
|
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, "%#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->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, "%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);
|
Bprint(b, "%lud %q %d\n", x->ibadchars, ∂(x->idxaux), x->nparts);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +115,6 @@ pridx(Biobuf *b, Mailbox *mb)
|
||||||
|
|
||||||
Bprint(b, magic);
|
Bprint(b, magic);
|
||||||
mb->idxwrite(b, mb);
|
mb->idxwrite(b, mb);
|
||||||
// prrefs(b);
|
|
||||||
i = pridx0(b, mb, mb->root->part, 0);
|
i = pridx0(b, mb, mb->root->part, 0);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -304,7 +331,7 @@ static char*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
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;
|
char *f[Idxfields + 1], *s;
|
||||||
uchar *digest;
|
uchar *digest;
|
||||||
|
@ -345,7 +372,7 @@ dead:
|
||||||
if(level == 0)
|
if(level == 0)
|
||||||
m->deleted &= ~Dmark;
|
m->deleted &= ~Dmark;
|
||||||
if(m->nparts)
|
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;
|
goto dead;
|
||||||
ll = &m->next;
|
ll = &m->next;
|
||||||
idprint("%d seen before %d... %.2ux", level, m->id, m->cstate);
|
idprint("%d seen before %d... %.2ux", level, m->id, m->cstate);
|
||||||
|
@ -375,17 +402,20 @@ dead:
|
||||||
m->subject = ∫(f[11]);
|
m->subject = ∫(f[11]);
|
||||||
m->sender = ∫(f[12]);
|
m->sender = ∫(f[12]);
|
||||||
m->inreplyto = ∫(f[13]);
|
m->inreplyto = ∫(f[13]);
|
||||||
m->type = newrefs(f[14]);
|
m->type = intern(f[14]);
|
||||||
m->disposition = atoi(f[15]);
|
m->disposition = atoi(f[15]);
|
||||||
m->size = strtoul(f[16], 0, 0);
|
m->filename = ∫(f[16]);
|
||||||
m->rawbsize = strtoul(f[17], 0, 0);
|
m->size = strtoul(f[17], 0, 0);
|
||||||
m->ibadchars = strtoul(f[18], 0, 0);
|
m->rawbsize = strtoul(f[18], 0, 0);
|
||||||
m->idxaux = ∫(f[19]);
|
m->ibadchars = strtoul(f[19], 0, 0);
|
||||||
m->nparts = strtoul(f[20], 0, 0);
|
m->idxaux = ∫(f[20]);
|
||||||
|
m->nparts = strtoul(f[21], 0, 0);
|
||||||
|
|
||||||
m->cstate &= ~Cidxstale;
|
m->cstate &= ~Cidxstale;
|
||||||
m->cstate |= Cidx;
|
m->cstate |= Cidx;
|
||||||
m->str = s;
|
m->str = s;
|
||||||
s = 0;
|
s = 0;
|
||||||
|
|
||||||
if(!validmessage(mb, m, level))
|
if(!validmessage(mb, m, level))
|
||||||
goto dead;
|
goto dead;
|
||||||
if(level == 0){
|
if(level == 0){
|
||||||
|
@ -400,10 +430,8 @@ dead:
|
||||||
good++;
|
good++;
|
||||||
|
|
||||||
if(m->nparts)
|
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;
|
goto dead;
|
||||||
if(doplumb && level == 0)
|
|
||||||
mailplumb(mb, m, 0);
|
|
||||||
}
|
}
|
||||||
if(level == 0 && bad + redux > 0)
|
if(level == 0 && bad + redux > 0)
|
||||||
iprint("idx: %d %d %d\n", good, bad, redux);
|
iprint("idx: %d %d %d\n", good, bad, redux);
|
||||||
|
@ -493,7 +521,7 @@ unmark(Mailbox *mb)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rdidxfile0(Mailbox *mb, int doplumb)
|
rdidxfile0(Mailbox *mb)
|
||||||
{
|
{
|
||||||
char buf[Pathlen + 4];
|
char buf[Pathlen + 4];
|
||||||
int r, v;
|
int r, v;
|
||||||
|
@ -509,7 +537,7 @@ rdidxfile0(Mailbox *mb, int doplumb)
|
||||||
r = -1;
|
r = -1;
|
||||||
else{
|
else{
|
||||||
mark(mb);
|
mark(mb);
|
||||||
r = rdidx(b, mb, mb->root, -1, 0, doplumb);
|
r = rdidx(b, mb, mb->root, -1, 0);
|
||||||
v = unmark(mb);
|
v = unmark(mb);
|
||||||
if(r == 0 && v > 0)
|
if(r == 0 && v > 0)
|
||||||
r = -1;
|
r = -1;
|
||||||
|
@ -519,11 +547,11 @@ rdidxfile0(Mailbox *mb, int doplumb)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rdidxfile(Mailbox *mb, int doplumb)
|
rdidxfile(Mailbox *mb)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = rdidxfile0(mb, doplumb);
|
r = rdidxfile0(mb);
|
||||||
if(r == -1 && mb->idxinvalid)
|
if(r == -1 && mb->idxinvalid)
|
||||||
mb->idxinvalid(mb);
|
mb->idxinvalid(mb);
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -876,15 +876,6 @@ datesec(Imap *imap, int i)
|
||||||
return v;
|
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
|
static int
|
||||||
vcmp(vlong a, vlong b)
|
vcmp(vlong a, vlong b)
|
||||||
{
|
{
|
||||||
|
@ -903,14 +894,13 @@ fetchicmp(Fetchi *f1, Fetchi *f2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
|
imap4read(Imap *imap, Mailbox *mb)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
int i, n, c, nnew, ndel;
|
int i, n, c;
|
||||||
Fetchi *f;
|
Fetchi *f;
|
||||||
Message *m, **ll;
|
Message *m, **ll;
|
||||||
|
|
||||||
*new = 0;
|
|
||||||
imap4cmd(imap, "status %Z (messages uidvalidity)", imap->mbox);
|
imap4cmd(imap, "status %Z (messages uidvalidity)", imap->mbox);
|
||||||
if(!isokay(s = imap4resp(imap)))
|
if(!isokay(s = imap4resp(imap)))
|
||||||
return s;
|
return s;
|
||||||
|
@ -928,7 +918,6 @@ imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
|
||||||
n = imap->nuid;
|
n = imap->nuid;
|
||||||
if(n < imap->nmsg) idprint(imap, "partial sync %d < %d\n", n, imap->nmsg);
|
if(n < imap->nmsg) idprint(imap, "partial sync %d < %d\n", n, imap->nmsg);
|
||||||
qsort(f, n, sizeof f[0], (int(*)(void*, void*))fetchicmp);
|
qsort(f, n, sizeof f[0], (int(*)(void*, void*))fetchicmp);
|
||||||
nnew = ndel = 0;
|
|
||||||
ll = &mb->root->part;
|
ll = &mb->root->part;
|
||||||
for(i = 0; (m = *ll) != nil || i < n; ){
|
for(i = 0; (m = *ll) != nil || i < n; ){
|
||||||
c = -1;
|
c = -1;
|
||||||
|
@ -948,7 +937,6 @@ imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nnew++;
|
|
||||||
m = newmessage(mb->root);
|
m = newmessage(mb->root);
|
||||||
m->inmbox = 1;
|
m->inmbox = 1;
|
||||||
m->idxaux = smprint("%llud", f[i].uid);
|
m->idxaux = smprint("%llud", f[i].uid);
|
||||||
|
@ -958,22 +946,18 @@ imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
|
||||||
m->next = *ll;
|
m->next = *ll;
|
||||||
*ll = m;
|
*ll = m;
|
||||||
ll = &m->next;
|
ll = &m->next;
|
||||||
newcachehash(mb, m, doplumb);
|
|
||||||
putcache(mb, m);
|
|
||||||
i++;
|
i++;
|
||||||
}else if(c > 0){
|
}else if(c > 0){
|
||||||
/* deleted message; */
|
/* deleted message; */
|
||||||
idprint(imap, "deleted: %U (%U)\n", i<n? f[i].uid: 0, m? m->imapuid: 0);
|
idprint(imap, "deleted: %U (%U)\n", i<n? f[i].uid: 0, m? m->imapuid: 0);
|
||||||
ndel++;
|
m->inmbox = 0;
|
||||||
markdel(mb, m, doplumb);
|
m->deleted = Disappear;
|
||||||
ll = &m->next;
|
ll = &m->next;
|
||||||
}else{
|
}else{
|
||||||
ll = &m->next;
|
ll = &m->next;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*new = nnew;
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,7 +979,7 @@ imap4delete(Mailbox *mb, Message *m)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
imap4sync(Mailbox *mb, int doplumb, int *new)
|
imap4sync(Mailbox *mb)
|
||||||
{
|
{
|
||||||
char *err;
|
char *err;
|
||||||
Imap *imap;
|
Imap *imap;
|
||||||
|
@ -1003,7 +987,7 @@ imap4sync(Mailbox *mb, int doplumb, int *new)
|
||||||
imap = mb->aux;
|
imap = mb->aux;
|
||||||
if(err = imap4dial(imap))
|
if(err = imap4dial(imap))
|
||||||
goto out;
|
goto out;
|
||||||
err = imap4read(imap, mb, doplumb, new);
|
err = imap4read(imap, mb);
|
||||||
out:
|
out:
|
||||||
mb->waketime = (ulong)time(0) + imap->refreshtime;
|
mb->waketime = (ulong)time(0) + imap->refreshtime;
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -55,25 +55,42 @@ static Mailboxinit *boxinit[] = {
|
||||||
plan9mbox,
|
plan9mbox,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void delmessage(Mailbox*, Message*);
|
||||||
|
static void mailplumb(Mailbox*, Message*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do we want to plumb flag changes?
|
* do we want to plumb flag changes?
|
||||||
*/
|
*/
|
||||||
char*
|
char*
|
||||||
syncmbox(Mailbox *mb, int doplumb)
|
syncmbox(Mailbox *mb)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
int n, d, y, a;
|
int n, d, y, a;
|
||||||
Message *m, *next;
|
Message *m, *next;
|
||||||
|
|
||||||
|
if(mb->syncing)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
mb->syncing = 1;
|
||||||
|
|
||||||
a = mb->root->subname;
|
a = mb->root->subname;
|
||||||
if(rdidxfile(mb, doplumb) == -2)
|
if(rdidxfile(mb) == -2)
|
||||||
wridxfile(mb);
|
wridxfile(mb);
|
||||||
if(s = mb->sync(mb, doplumb, &n))
|
if(s = mb->sync(mb))
|
||||||
return s;
|
return s;
|
||||||
|
n = 0;
|
||||||
d = 0;
|
d = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
for(m = mb->root->part; m; m = next){
|
for(m = mb->root->part; m; m = next){
|
||||||
next = 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)
|
if(m->cstate & Cidxstale)
|
||||||
y++;
|
y++;
|
||||||
if(m->deleted == 0 || m->refs > 0)
|
if(m->deleted == 0 || m->refs > 0)
|
||||||
|
@ -81,6 +98,7 @@ syncmbox(Mailbox *mb, int doplumb)
|
||||||
if(mb->delete && m->inmbox && m->deleted & Deleted)
|
if(mb->delete && m->inmbox && m->deleted & Deleted)
|
||||||
mb->delete(mb, m);
|
mb->delete(mb, m);
|
||||||
if(!m->inmbox){
|
if(!m->inmbox){
|
||||||
|
mailplumb(mb, m);
|
||||||
delmessage(mb, m);
|
delmessage(mb, m);
|
||||||
d++;
|
d++;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +115,9 @@ syncmbox(Mailbox *mb, int doplumb)
|
||||||
henter(PATH(0, Qtop), mb->name,
|
henter(PATH(0, Qtop), mb->name,
|
||||||
(Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);
|
(Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mb->syncing = 0;
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,11 +250,10 @@ newmbox(char *path, char *name, int flags, Mailbox **r)
|
||||||
if(mb->ctl)
|
if(mb->ctl)
|
||||||
henter(PATH(mb->id, Qmbox), "ctl",
|
henter(PATH(mb->id, Qmbox), "ctl",
|
||||||
(Qid){PATH(mb->id, Qmboxctl), 0, QTFILE}, nil, mb);
|
(Qid){PATH(mb->id, Qmboxctl), 0, QTFILE}, nil, mb);
|
||||||
rv = syncmbox(mb, 0);
|
|
||||||
if(r)
|
if(r)
|
||||||
*r = mb;
|
*r = mb;
|
||||||
|
|
||||||
return rv;
|
return syncmbox(mb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close the named mailbox */
|
/* close the named mailbox */
|
||||||
|
@ -259,7 +279,7 @@ syncallmboxes(void)
|
||||||
Mailbox *m;
|
Mailbox *m;
|
||||||
|
|
||||||
for(m = mbl; m != nil; m = m->next)
|
for(m = mbl; m != nil; m = m->next)
|
||||||
if(err = syncmbox(m, 1))
|
if(err = syncmbox(m))
|
||||||
eprint("syncmbox: %s\n", err);
|
eprint("syncmbox: %s\n", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +349,6 @@ gettopmsg(Mailbox *mb, Message *m)
|
||||||
void
|
void
|
||||||
datesec(Mailbox *mb, Message *m)
|
datesec(Mailbox *mb, Message *m)
|
||||||
{
|
{
|
||||||
char *s;
|
|
||||||
vlong v;
|
vlong v;
|
||||||
Tm tm;
|
Tm tm;
|
||||||
|
|
||||||
|
@ -342,11 +361,10 @@ datesec(Mailbox *mb, Message *m)
|
||||||
else if(rxtotm(m, &tm) >= 0)
|
else if(rxtotm(m, &tm) >= 0)
|
||||||
v = tm2sec(&tm);
|
v = tm2sec(&tm);
|
||||||
else{
|
else{
|
||||||
s = rtab[m->type].s;
|
|
||||||
logmsg(gettopmsg(mb, m), "%s:%s: datasec %s %s\n", mb->path,
|
logmsg(gettopmsg(mb, m), "%s:%s: datasec %s %s\n", mb->path,
|
||||||
m->whole? m->whole->name: "?",
|
m->whole? m->whole->name: "?",
|
||||||
m->name, s);
|
m->name, m->type);
|
||||||
if(Topmsg(mb, m) || strcmp(s, "message/rfc822") == 0)
|
if(Topmsg(mb, m) || strcmp(m->type, "message/rfc822") == 0)
|
||||||
abort();
|
abort();
|
||||||
v = 0;
|
v = 0;
|
||||||
}
|
}
|
||||||
|
@ -377,14 +395,12 @@ parseattachments(Message *m, Mailbox *mb)
|
||||||
Message *nm, **l;
|
Message *nm, **l;
|
||||||
|
|
||||||
/* if there's a boundary, recurse... */
|
/* if there's a boundary, recurse... */
|
||||||
sanemsg(m);
|
dprint("parseattachments %p %ld bonudary %s\n", m->start, (ulong)(m->end - m->start), m->boundary);
|
||||||
// dprint("parseattachments %p %ld\n", m->start, m->end - m->start);
|
|
||||||
if(m->boundary != nil){
|
if(m->boundary != nil){
|
||||||
p = m->body;
|
p = m->body;
|
||||||
nm = nil;
|
nm = nil;
|
||||||
l = &m->part;
|
l = &m->part;
|
||||||
for(i = 0;;){
|
for(i = 0;;){
|
||||||
sanemsg(m);
|
|
||||||
x = strstr(p, m->boundary);
|
x = strstr(p, m->boundary);
|
||||||
/* two sequential boundaries; ignore nil message */
|
/* two sequential boundaries; ignore nil message */
|
||||||
if(nm && x == p){
|
if(nm && x == p){
|
||||||
|
@ -401,7 +417,6 @@ sanemsg(m);
|
||||||
if(x == nil){
|
if(x == nil){
|
||||||
if(nm != nil){
|
if(nm != nil){
|
||||||
nm->rbend = nm->bend = nm->end = m->bend;
|
nm->rbend = nm->bend = nm->end = m->bend;
|
||||||
sanemsg(nm);
|
|
||||||
if(nm->end == nm->start)
|
if(nm->end == nm->start)
|
||||||
nm->mimeflag |= Mtrunc;
|
nm->mimeflag |= Mtrunc;
|
||||||
}
|
}
|
||||||
|
@ -414,9 +429,7 @@ sanemsg(nm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nm != nil)
|
if(nm != nil)
|
||||||
{
|
|
||||||
nm->rbend = nm->bend = nm->end = x;
|
nm->rbend = nm->bend = nm->end = x;
|
||||||
sanemsg(nm);}
|
|
||||||
x += strlen(m->boundary);
|
x += strlen(m->boundary);
|
||||||
|
|
||||||
/* is this the last part? ignore anything after it */
|
/* 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;
|
nm->mheader = nm->header = nm->body = nm->rbody = nm->start;
|
||||||
}
|
}
|
||||||
for(nm = m->part; nm != nil; nm = nm->next){
|
for(nm = m->part; nm != nil; nm = nm->next){
|
||||||
|
nm->size = nm->end - nm->start;
|
||||||
parse(mb, nm, 0, 1);
|
parse(mb, nm, 0, 1);
|
||||||
cachehash(mb, nm); /* botchy place for this */
|
cachehash(mb, nm); /* botchy place for this */
|
||||||
}
|
}
|
||||||
|
@ -442,7 +456,7 @@ sanemsg(nm);}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we've got an rfc822 message, recurse... */
|
/* 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){
|
if((nm = haschild(m, 0)) == nil){
|
||||||
nm = newmessage(m);
|
nm = newmessage(m);
|
||||||
m->part = nm;
|
m->part = nm;
|
||||||
|
@ -452,6 +466,7 @@ sanemsg(nm);}
|
||||||
nm->end = nm->bend = nm->rbend = m->bend;
|
nm->end = nm->bend = nm->rbend = m->bend;
|
||||||
if(nm->end == nm->start)
|
if(nm->end == nm->start)
|
||||||
nm->mimeflag |= Mtrunc;
|
nm->mimeflag |= Mtrunc;
|
||||||
|
nm->size = nm->end - nm->start;
|
||||||
parse(mb, nm, 0, 0);
|
parse(mb, nm, 0, 0);
|
||||||
cachehash(mb, nm); /* botchy place for this */
|
cachehash(mb, nm); /* botchy place for this */
|
||||||
}
|
}
|
||||||
|
@ -543,16 +558,12 @@ promote(char *s)
|
||||||
void
|
void
|
||||||
parsebody(Message *m, Mailbox *mb)
|
parsebody(Message *m, Mailbox *mb)
|
||||||
{
|
{
|
||||||
char *s;
|
|
||||||
int l;
|
|
||||||
Message *nm;
|
Message *nm;
|
||||||
|
|
||||||
/* recurse */
|
/* recurse */
|
||||||
s = rtab[m->type].s;
|
if(strncmp(m->type, "multipart/", 10) == 0)
|
||||||
l = rtab[m->type].l;
|
|
||||||
if(l >= 10 && strncmp(s, "multipart/", 10) == 0)
|
|
||||||
parseattachments(m, mb);
|
parseattachments(m, mb);
|
||||||
else if(l == 14 && strcmp(s, "message/rfc822") == 0){
|
else if(strcmp(m->type, "message/rfc822") == 0){
|
||||||
decode(m);
|
decode(m);
|
||||||
parseattachments(m, mb);
|
parseattachments(m, mb);
|
||||||
nm = m->part;
|
nm = m->part;
|
||||||
|
@ -566,7 +577,7 @@ parsebody(Message *m, Mailbox *mb)
|
||||||
m->replyto = promote(nm->replyto);
|
m->replyto = promote(nm->replyto);
|
||||||
m->subject = promote(nm->subject);
|
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);
|
sanemsg(m);
|
||||||
m->rawbsize = m->rbend - m->rbody;
|
m->rawbsize = m->rbend - m->rbody;
|
||||||
m->cstate |= Cbody;
|
m->cstate |= Cbody;
|
||||||
|
@ -651,7 +662,9 @@ setfilename(Message *m, char *p)
|
||||||
{
|
{
|
||||||
char buf[Pathlen];
|
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);
|
getstring(p, buf, buf + sizeof buf - 1, 0);
|
||||||
m->filename = smprint("%s", buf);
|
m->filename = smprint("%s", buf);
|
||||||
for(p = m->filename; *p; p++)
|
for(p = m->filename; *p; p++)
|
||||||
|
@ -909,7 +922,7 @@ ctype(Message *m, Header *h, char*, char *p)
|
||||||
|
|
||||||
e = buf + sizeof buf - 1;
|
e = buf + sizeof buf - 1;
|
||||||
p = getstring(skipwhite(p + h->len), buf, e, 1);
|
p = getstring(skipwhite(p + h->len), buf, e, 1);
|
||||||
m->type = newrefs(buf);
|
m->type = intern(buf);
|
||||||
|
|
||||||
for(; *p; p = skiptosemi(p))
|
for(; *p; p = skiptosemi(p))
|
||||||
if(isattribute(&p, "boundary")){
|
if(isattribute(&p, "boundary")){
|
||||||
|
@ -922,12 +935,10 @@ ctype(Message *m, Header *h, char*, char *p)
|
||||||
* the preamble, is not displayed or saved
|
* the preamble, is not displayed or saved
|
||||||
*/
|
*/
|
||||||
} else if(isattribute(&p, "name")){
|
} else if(isattribute(&p, "name")){
|
||||||
if(m->filename == nil)
|
setfilename(m, p);
|
||||||
setfilename(m, p);
|
|
||||||
} else if(isattribute(&p, "charset")){
|
} else if(isattribute(&p, "charset")){
|
||||||
p = getstring(p, buf, e, 0);
|
p = getstring(p, buf, e, 1);
|
||||||
lowercase(buf);
|
m->charset = intern(buf);
|
||||||
m->charset = newrefs(buf);
|
|
||||||
}
|
}
|
||||||
return (char*)~0;
|
return (char*)~0;
|
||||||
}
|
}
|
||||||
|
@ -971,9 +982,8 @@ newmessage(Message *parent)
|
||||||
|
|
||||||
m = emalloc(sizeof *m);
|
m = emalloc(sizeof *m);
|
||||||
dprint("newmessage %ld %p %p\n", msgallocd, parent, m);
|
dprint("newmessage %ld %p %p\n", msgallocd, parent, m);
|
||||||
m->disposition = Dnone;
|
m->type = intern("text/plain");
|
||||||
m->type = newrefs("text/plain");
|
m->charset = intern("iso-8859-1");
|
||||||
m->charset = newrefs("iso-8859-1");
|
|
||||||
m->cstate = Cidxstale;
|
m->cstate = Cidxstale;
|
||||||
m->flags = Frecent;
|
m->flags = Frecent;
|
||||||
m->id = newid();
|
m->id = newid();
|
||||||
|
@ -987,7 +997,7 @@ newmessage(Message *parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* delete a message from a mailbox */
|
/* delete a message from a mailbox */
|
||||||
void
|
static void
|
||||||
delmessage(Mailbox *mb, Message *m)
|
delmessage(Mailbox *mb, Message *m)
|
||||||
{
|
{
|
||||||
Message **l;
|
Message **l;
|
||||||
|
@ -1014,17 +1024,13 @@ delmessage(Mailbox *mb, Message *m)
|
||||||
mtreedelete(mb, m);
|
mtreedelete(mb, m);
|
||||||
cachefree(mb, m, 1);
|
cachefree(mb, m, 1);
|
||||||
}
|
}
|
||||||
delrefs(m->type);
|
|
||||||
delrefs(m->charset);
|
|
||||||
idxfree(m);
|
idxfree(m);
|
||||||
while(m->part)
|
while(m->part)
|
||||||
delmessage(mb, m->part);
|
delmessage(mb, m->part);
|
||||||
free(m->unixfrom);
|
free(m->unixfrom);
|
||||||
free(m->unixheader);
|
free(m->unixheader);
|
||||||
free(m->date822);
|
free(m->date822);
|
||||||
free(m->inreplyto);
|
|
||||||
free(m->boundary);
|
free(m->boundary);
|
||||||
free(m->filename);
|
|
||||||
|
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
@ -1057,7 +1063,6 @@ delmessages(int ac, char **av)
|
||||||
for(m = mb->root->part; m != nil; m = m->next)
|
for(m = mb->root->part; m != nil; m = m->next)
|
||||||
if(strcmp(m->name, av[i]) == 0){
|
if(strcmp(m->name, av[i]) == 0){
|
||||||
if(!m->deleted){
|
if(!m->deleted){
|
||||||
mailplumb(mb, m, 1);
|
|
||||||
needwrite = 1;
|
needwrite = 1;
|
||||||
m->deleted = Deleted;
|
m->deleted = Deleted;
|
||||||
logmsg(m, "deleting");
|
logmsg(m, "deleting");
|
||||||
|
@ -1065,7 +1070,7 @@ delmessages(int ac, char **av)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(needwrite)
|
if(needwrite)
|
||||||
syncmbox(mb, 1);
|
syncmbox(mb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,7 +1100,7 @@ flagmessages(int argc, char **argv)
|
||||||
needwrite = 1;
|
needwrite = 1;
|
||||||
}
|
}
|
||||||
if(needwrite)
|
if(needwrite)
|
||||||
syncmbox(mb, 1);
|
syncmbox(mb);
|
||||||
return rerr;
|
return rerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,7 +1117,7 @@ msgdecref(Mailbox *mb, Message *m)
|
||||||
m->refs--;
|
m->refs--;
|
||||||
if(m->refs == 0){
|
if(m->refs == 0){
|
||||||
if(m->deleted)
|
if(m->deleted)
|
||||||
syncmbox(mb, 1);
|
syncmbox(mb);
|
||||||
else
|
else
|
||||||
putcache(mb, m);
|
putcache(mb, m);
|
||||||
}
|
}
|
||||||
|
@ -1144,7 +1149,7 @@ mboxdecref(Mailbox *mb)
|
||||||
assert(mb->refs > 0);
|
assert(mb->refs > 0);
|
||||||
mb->refs--;
|
mb->refs--;
|
||||||
if(mb->refs == 0){
|
if(mb->refs == 0){
|
||||||
syncmbox(mb, 1);
|
syncmbox(mb);
|
||||||
delmessage(mb, mb->root);
|
delmessage(mb, mb->root);
|
||||||
if(mb->ctl)
|
if(mb->ctl)
|
||||||
hfree(PATH(mb->id, Qmbox), "ctl");
|
hfree(PATH(mb->id, Qmbox), "ctl");
|
||||||
|
@ -1187,6 +1192,7 @@ decode(Message *m)
|
||||||
|
|
||||||
if(m->decoded)
|
if(m->decoded)
|
||||||
return;
|
return;
|
||||||
|
dprint("decode %d %p\n", m->encoding, m);
|
||||||
switch(m->encoding){
|
switch(m->encoding){
|
||||||
case Ebase64:
|
case Ebase64:
|
||||||
len = m->bend - m->body;
|
len = m->bend - m->body;
|
||||||
|
@ -1197,7 +1203,7 @@ decode(Message *m)
|
||||||
free(x);
|
free(x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(strncmp(rtab[m->type].s, "text/", 5) == 0)
|
if(strncmp(m->type, "text/", 5) == 0)
|
||||||
len = deccr(x, len);
|
len = deccr(x, len);
|
||||||
if(m->ballocd)
|
if(m->ballocd)
|
||||||
free(m->body);
|
free(m->body);
|
||||||
|
@ -1231,10 +1237,11 @@ convert(Message *m)
|
||||||
/* don't convert if we're not a leaf, not text, or already converted */
|
/* don't convert if we're not a leaf, not text, or already converted */
|
||||||
if(m->converted)
|
if(m->converted)
|
||||||
return;
|
return;
|
||||||
|
dprint("convert type=%q charset=%q %p\n", m->type, m->charset, m);
|
||||||
m->converted = 1;
|
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;
|
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(len > 0){
|
||||||
if(m->ballocd)
|
if(m->ballocd)
|
||||||
free(m->body);
|
free(m->body);
|
||||||
|
@ -1376,9 +1383,9 @@ xtoutf(char *charset, char **out, char *in, char *e)
|
||||||
int totcs[2], fromtcs[2], n, len, sofar;
|
int totcs[2], fromtcs[2], n, len, sofar;
|
||||||
|
|
||||||
/* might not need to convert */
|
/* 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;
|
return 0;
|
||||||
if(cistrcmp(charset, "iso-8859-1") == 0)
|
if(strcmp(charset, "iso-8859-1") == 0)
|
||||||
return latin1toutf(out, in, e);
|
return latin1toutf(out, in, e);
|
||||||
|
|
||||||
len = e - in + 1;
|
len = e - in + 1;
|
||||||
|
@ -1495,16 +1502,15 @@ myplumbsend(int fd, Plumbmsg *m)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
mailplumb(Mailbox *mb, Message *m, int delete)
|
mailplumb(Mailbox *mb, Message *m)
|
||||||
{
|
{
|
||||||
char buf[256], dbuf[SHA1dlen*2 + 1], len[10], date[30], *from, *subject;
|
char buf[256], dbuf[SHA1dlen*2 + 1], len[10], date[30], *from, *subject;
|
||||||
int ai, cache;
|
int ai;
|
||||||
Plumbmsg p;
|
Plumbmsg p;
|
||||||
Plumbattr a[7];
|
Plumbattr a[7];
|
||||||
static int fd = -1;
|
static int fd = -1;
|
||||||
|
|
||||||
cache = insurecache(mb, m) == 0; /* living dangerously if deleted */
|
|
||||||
subject = m->subject;
|
subject = m->subject;
|
||||||
if(subject == nil)
|
if(subject == nil)
|
||||||
subject = "";
|
subject = "";
|
||||||
|
@ -1517,15 +1523,15 @@ mailplumb(Mailbox *mb, Message *m, int delete)
|
||||||
from = "";
|
from = "";
|
||||||
|
|
||||||
sprint(len, "%lud", m->size);
|
sprint(len, "%lud", m->size);
|
||||||
if(biffing && !delete)
|
if(biffing && m->inmbox)
|
||||||
fprint(2, "[ %s / %s / %s ]\n", from, subject, len);
|
fprint(2, "[ %s / %s / %s ]\n", from, subject, len);
|
||||||
if(!plumbing)
|
if(!plumbing)
|
||||||
goto out;
|
return;
|
||||||
|
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
fd = plumbopen("send", OWRITE);
|
fd = plumbopen("send", OWRITE);
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
goto out;
|
return;
|
||||||
|
|
||||||
p.src = "mailfs";
|
p.src = "mailfs";
|
||||||
p.dst = "seemail";
|
p.dst = "seemail";
|
||||||
|
@ -1545,7 +1551,7 @@ mailplumb(Mailbox *mb, Message *m, int delete)
|
||||||
a[ai-1].next = &a[ai];
|
a[ai-1].next = &a[ai];
|
||||||
|
|
||||||
a[++ai].name = "mailtype";
|
a[++ai].name = "mailtype";
|
||||||
a[ai].value = delete? "delete": "new";
|
a[ai].value = !m->inmbox ? "delete": "new";
|
||||||
a[ai-1].next = &a[ai];
|
a[ai-1].next = &a[ai];
|
||||||
|
|
||||||
snprint(date, sizeof date, "%Δ", m->fileid);
|
snprint(date, sizeof date, "%Δ", m->fileid);
|
||||||
|
@ -1567,9 +1573,6 @@ mailplumb(Mailbox *mb, Message *m, int delete)
|
||||||
p.data = buf;
|
p.data = buf;
|
||||||
|
|
||||||
myplumbsend(fd, &p);
|
myplumbsend(fd, &p);
|
||||||
out:
|
|
||||||
if(cache)
|
|
||||||
msgdecref(mb, m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -109,9 +109,9 @@ dircmp(Dir *a, Dir *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
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;
|
uvlong uv;
|
||||||
Dir *d;
|
Dir *d;
|
||||||
Message *m, **ll;
|
Message *m, **ll;
|
||||||
|
@ -127,7 +127,6 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
|
||||||
close(fd);
|
close(fd);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
*new = nnew = 0;
|
|
||||||
if(mb->d){
|
if(mb->d){
|
||||||
if(d->qid.path == mb->d->qid.path)
|
if(d->qid.path == mb->d->qid.path)
|
||||||
if(d->qid.vers == mb->d->qid.vers){
|
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);
|
qsort(d, n, sizeof *d, (int(*)(void*, void*))dircmp);
|
||||||
ndel = 0;
|
|
||||||
ll = &mb->root->part;
|
ll = &mb->root->part;
|
||||||
for(i = 0; (m = *ll) != nil || i < n; ){
|
for(i = 0; (m = *ll) != nil || i < n; ){
|
||||||
if(i < n && dirskip(d + i, &uv)){
|
if(i < n && dirskip(d + i, &uv)){
|
||||||
|
@ -170,7 +168,6 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nnew++;
|
|
||||||
m = newmessage(mb->root);
|
m = newmessage(mb->root);
|
||||||
m->fileid = uv;
|
m->fileid = uv;
|
||||||
m->size = d[i].length;
|
m->size = d[i].length;
|
||||||
|
@ -178,15 +175,10 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
|
||||||
m->next = *ll;
|
m->next = *ll;
|
||||||
*ll = m;
|
*ll = m;
|
||||||
ll = &m->next;
|
ll = &m->next;
|
||||||
newcachehash(mb, m, doplumb);
|
|
||||||
putcache(mb, m);
|
|
||||||
i++;
|
i++;
|
||||||
}else if(c > 0){
|
}else if(c > 0){
|
||||||
/* deleted message; */
|
/* deleted message; */
|
||||||
mdprint(mdir, "deleted: %s (%D)\n", i<n? d[i].name: 0, m? m->fileid: 0);
|
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->inmbox = 0;
|
||||||
m->deleted = Disappear;
|
m->deleted = Disappear;
|
||||||
ll = &m->next;
|
ll = &m->next;
|
||||||
|
@ -196,11 +188,8 @@ mdirread(Mdir* mdir, Mailbox* mb, int doplumb, int *new)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(d);
|
free(d);
|
||||||
logmsg(nil, "mbox read: %d new %d deleted", nnew, ndel);
|
|
||||||
finished:
|
finished:
|
||||||
*new = nnew;
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,13 +209,13 @@ mdirdelete(Mailbox *mb, Message *m)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
mdirsync(Mailbox* mb, int doplumb, int *new)
|
mdirsync(Mailbox* mb)
|
||||||
{
|
{
|
||||||
Mdir *mdir;
|
Mdir *mdir;
|
||||||
|
|
||||||
mdir = mb->aux;
|
mdir = mb->aux;
|
||||||
mdprint(mdir, "mdirsync()\n");
|
mdprint(mdir, "mdirsync()\n");
|
||||||
return mdirread(mdir, mb, doplumb, new);
|
return mdirread(mdir, mb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
|
|
|
@ -14,7 +14,6 @@ OFILES=\
|
||||||
mtree.$O\
|
mtree.$O\
|
||||||
plan9.$O\
|
plan9.$O\
|
||||||
pop3.$O\
|
pop3.$O\
|
||||||
ref.$O\
|
|
||||||
remove.$O\
|
remove.$O\
|
||||||
rename.$O\
|
rename.$O\
|
||||||
strtotm.$O\
|
strtotm.$O\
|
||||||
|
@ -36,6 +35,3 @@ CFLAGS=$CFLAGS -I../common
|
||||||
|
|
||||||
acid:V:
|
acid:V:
|
||||||
$CC -a $CFLAGS fs.c>a$O
|
$CC -a $CFLAGS fs.c>a$O
|
||||||
|
|
||||||
chkidx: mtree.$O chkidx.$O
|
|
||||||
$LD $LDFLAGS -o $target $prereq
|
|
||||||
|
|
|
@ -179,17 +179,15 @@ readmessage(Mailbox *mb, Message *m, Inbuf *b)
|
||||||
int
|
int
|
||||||
purgedeleted(Mailbox *mb)
|
purgedeleted(Mailbox *mb)
|
||||||
{
|
{
|
||||||
Message *m, *next;
|
Message *m;
|
||||||
int newdels;
|
int newdels;
|
||||||
|
|
||||||
/* forget about what's no longer in the mailbox */
|
/* forget about what's no longer in the mailbox */
|
||||||
newdels = 0;
|
newdels = 0;
|
||||||
for(m = mb->root->part; m != nil; m = next){
|
for(m = mb->root->part; m != nil; m = m->next){
|
||||||
next = m->next;
|
if(m->deleted && m->inmbox){
|
||||||
if(m->deleted && m->refs == 0){
|
newdels++;
|
||||||
if(m->inmbox)
|
m->inmbox = 0;
|
||||||
newdels++;
|
|
||||||
delmessage(mb, m);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newdels;
|
return newdels;
|
||||||
|
@ -217,10 +215,9 @@ mergemsg(Message *m, Message *x)
|
||||||
* read in the mailbox and parse into messages.
|
* read in the mailbox and parse into messages.
|
||||||
*/
|
*/
|
||||||
static char*
|
static char*
|
||||||
readmbox(Mailbox *mb, int doplumb, int *new, Mlock *lk)
|
readmbox(Mailbox *mb, Mlock *lk)
|
||||||
{
|
{
|
||||||
char *p, *x, buf[Pathlen];
|
char *p, *x, buf[Pathlen];
|
||||||
int nnew;
|
|
||||||
Biobuf *in;
|
Biobuf *in;
|
||||||
Dir *d;
|
Dir *d;
|
||||||
Inbuf b;
|
Inbuf b;
|
||||||
|
@ -256,7 +253,6 @@ retry:
|
||||||
}
|
}
|
||||||
if(mb->d != nil){
|
if(mb->d != nil){
|
||||||
if(d->qid.path == mb->d->qid.path && d->qid.vers == mb->d->qid.vers){
|
if(d->qid.path == mb->d->qid.path && d->qid.vers == mb->d->qid.vers){
|
||||||
*new = 0;
|
|
||||||
Bterm(in);
|
Bterm(in);
|
||||||
free(d);
|
free(d);
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -276,7 +272,6 @@ retry:
|
||||||
|
|
||||||
/* read new messages */
|
/* read new messages */
|
||||||
logmsg(nil, "reading %s", mb->path);
|
logmsg(nil, "reading %s", mb->path);
|
||||||
nnew = 0;
|
|
||||||
for(;;){
|
for(;;){
|
||||||
if(lk != nil)
|
if(lk != nil)
|
||||||
syslockrefresh(lk);
|
syslockrefresh(lk);
|
||||||
|
@ -306,8 +301,6 @@ retry:
|
||||||
} else {
|
} else {
|
||||||
/* old mail no longer in box, mark deleted */
|
/* old mail no longer in box, mark deleted */
|
||||||
logmsg(*l, "disappeared");
|
logmsg(*l, "disappeared");
|
||||||
if(doplumb)
|
|
||||||
mailplumb(mb, *l, 1);
|
|
||||||
(*l)->inmbox = 0;
|
(*l)->inmbox = 0;
|
||||||
(*l)->deleted = Disappear;
|
(*l)->deleted = Disappear;
|
||||||
l = &(*l)->next;
|
l = &(*l)->next;
|
||||||
|
@ -324,9 +317,6 @@ retry:
|
||||||
parse(mb, m, 0, 0);
|
parse(mb, m, 0, 0);
|
||||||
if(m != *l && m->deleted != Dup){
|
if(m != *l && m->deleted != Dup){
|
||||||
logmsg(m, "new");
|
logmsg(m, "new");
|
||||||
newcachehash(mb, m, doplumb);
|
|
||||||
putcache(mb, m);
|
|
||||||
nnew++;
|
|
||||||
}
|
}
|
||||||
/* chain in */
|
/* chain in */
|
||||||
*l = m;
|
*l = m;
|
||||||
|
@ -336,15 +326,12 @@ retry:
|
||||||
|
|
||||||
/* whatever is left has been removed from the mbox, mark deleted */
|
/* whatever is left has been removed from the mbox, mark deleted */
|
||||||
while(*l != nil){
|
while(*l != nil){
|
||||||
if(doplumb)
|
|
||||||
mailplumb(mb, *l, 1);
|
|
||||||
(*l)->inmbox = 0;
|
(*l)->inmbox = 0;
|
||||||
(*l)->deleted = Deleted;
|
(*l)->deleted = Deleted;
|
||||||
l = &(*l)->next;
|
l = &(*l)->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bterm(in);
|
Bterm(in);
|
||||||
*new = nnew;
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +395,7 @@ writembox(Mailbox *mb, Mlock *lk)
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
plan9syncmbox(Mailbox *mb, int doplumb, int *new)
|
plan9syncmbox(Mailbox *mb)
|
||||||
{
|
{
|
||||||
char *rv;
|
char *rv;
|
||||||
Mlock *lk;
|
Mlock *lk;
|
||||||
|
@ -420,7 +407,7 @@ plan9syncmbox(Mailbox *mb, int doplumb, int *new)
|
||||||
return "can't lock mailbox";
|
return "can't lock mailbox";
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = readmbox(mb, doplumb, new, lk); /* interpolate */
|
rv = readmbox(mb, lk); /* interpolate */
|
||||||
if(purgedeleted(mb) > 0)
|
if(purgedeleted(mb) > 0)
|
||||||
writembox(mb, lk);
|
writembox(mb, lk);
|
||||||
|
|
||||||
|
|
|
@ -359,14 +359,13 @@ pop3download(Mailbox *mb, Pop *pop, Message *m)
|
||||||
* we'll use it to make our lives easier.
|
* we'll use it to make our lives easier.
|
||||||
*/
|
*/
|
||||||
static char*
|
static char*
|
||||||
pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
|
pop3read(Pop *pop, Mailbox *mb)
|
||||||
{
|
{
|
||||||
char *s, *p, *uidl, *f[2];
|
char *s, *p, *uidl, *f[2];
|
||||||
int mno, ignore, nnew;
|
int mno, ignore;
|
||||||
Message *m, *next, **l;
|
Message *m, *next, **l;
|
||||||
Popm *a;
|
Popm *a;
|
||||||
|
|
||||||
*new = 0;
|
|
||||||
/* Some POP servers disallow UIDL if the maildrop is empty. */
|
/* Some POP servers disallow UIDL if the maildrop is empty. */
|
||||||
pop3cmd(pop, "STAT");
|
pop3cmd(pop, "STAT");
|
||||||
if(!isokay(s = pop3resp(pop)))
|
if(!isokay(s = pop3resp(pop)))
|
||||||
|
@ -409,8 +408,6 @@ pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
|
||||||
break;
|
break;
|
||||||
}else{
|
}else{
|
||||||
/* old mail no longer in box mark deleted */
|
/* old mail no longer in box mark deleted */
|
||||||
if(doplumb)
|
|
||||||
mailplumb(mb, *l, 1);
|
|
||||||
(*l)->inmbox = 0;
|
(*l)->inmbox = 0;
|
||||||
(*l)->deleted = Deleted;
|
(*l)->deleted = Deleted;
|
||||||
l = &(*l)->next;
|
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 */
|
/* whatever is left has been removed from the mbox, mark as deleted */
|
||||||
while(*l != nil) {
|
while(*l != nil) {
|
||||||
if(doplumb)
|
|
||||||
mailplumb(mb, *l, 1);
|
|
||||||
(*l)->inmbox = 0;
|
(*l)->inmbox = 0;
|
||||||
(*l)->deleted = Disappear;
|
(*l)->deleted = Disappear;
|
||||||
l = &(*l)->next;
|
l = &(*l)->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* download new messages */
|
/* download new messages */
|
||||||
nnew = 0;
|
|
||||||
if(pop->pipeline){
|
if(pop->pipeline){
|
||||||
switch(rfork(RFPROC|RFMEM)){
|
switch(rfork(RFPROC|RFMEM)){
|
||||||
case -1:
|
case -1:
|
||||||
|
@ -469,20 +463,14 @@ pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
|
||||||
if(m->start != nil || m->deleted)
|
if(m->start != nil || m->deleted)
|
||||||
continue;
|
continue;
|
||||||
if(s = pop3download(mb, pop, m)) {
|
if(s = pop3download(mb, pop, m)) {
|
||||||
/* message disappeared? unchain */
|
|
||||||
eprint("pop3: download %d: %s\n", mesgno(m), s);
|
eprint("pop3: download %d: %s\n", mesgno(m), s);
|
||||||
delmessage(mb, m);
|
unnewmessage(mb, mb->root, m);
|
||||||
mb->root->subname--;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nnew++;
|
|
||||||
parse(mb, m, 1, 0);
|
parse(mb, m, 1, 0);
|
||||||
newcachehash(mb, m, doplumb);
|
|
||||||
putcache(mb, m);
|
|
||||||
}
|
}
|
||||||
if(pop->pipeline)
|
if(pop->pipeline)
|
||||||
waitpid();
|
waitpid();
|
||||||
*new = nnew;
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +480,7 @@ pop3read(Pop *pop, Mailbox *mb, int doplumb, int *new)
|
||||||
static void
|
static void
|
||||||
pop3purge(Pop *pop, Mailbox *mb)
|
pop3purge(Pop *pop, Mailbox *mb)
|
||||||
{
|
{
|
||||||
Message *m, *next;
|
Message *m;
|
||||||
|
|
||||||
if(pop->pipeline){
|
if(pop->pipeline){
|
||||||
switch(rfork(RFPROC|RFMEM)){
|
switch(rfork(RFPROC|RFMEM)){
|
||||||
|
@ -504,27 +492,21 @@ pop3purge(Pop *pop, Mailbox *mb)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
for(m = mb->root->part; m != nil; m = next){
|
for(m = mb->root->part; m != nil; m = m->next){
|
||||||
next = m->next;
|
if(m->deleted && m->inmbox)
|
||||||
if(m->deleted && m->refs == 0){
|
Bprint(&pop->bout, "DELE %d\r\n", mesgno(m));
|
||||||
if(m->inmbox)
|
|
||||||
Bprint(&pop->bout, "DELE %d\r\n", mesgno(m));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Bflush(&pop->bout);
|
Bflush(&pop->bout);
|
||||||
_exits("");
|
_exits("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(m = mb->root->part; m != nil; m = next) {
|
for(m = mb->root->part; m != nil; m = m->next) {
|
||||||
next = m->next;
|
if(m->deleted && m->inmbox) {
|
||||||
if(m->deleted && m->refs == 0) {
|
if(!pop->pipeline)
|
||||||
if(m->inmbox) {
|
pop3cmd(pop, "DELE %d", mesgno(m));
|
||||||
if(!pop->pipeline)
|
if(!isokay(pop3resp(pop)))
|
||||||
pop3cmd(pop, "DELE %d", mesgno(m));
|
continue;
|
||||||
if(isokay(pop3resp(pop)))
|
m->inmbox = 0;
|
||||||
delmessage(mb, m);
|
|
||||||
} else
|
|
||||||
delmessage(mb, m);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -532,16 +514,15 @@ pop3purge(Pop *pop, Mailbox *mb)
|
||||||
|
|
||||||
/* connect to pop3 server, sync mailbox */
|
/* connect to pop3 server, sync mailbox */
|
||||||
static char*
|
static char*
|
||||||
pop3sync(Mailbox *mb, int doplumb, int *new)
|
pop3sync(Mailbox *mb)
|
||||||
{
|
{
|
||||||
char *err;
|
char *err;
|
||||||
Pop *pop;
|
Pop *pop;
|
||||||
|
|
||||||
pop = mb->aux;
|
pop = mb->aux;
|
||||||
|
|
||||||
if(err = pop3dial(pop))
|
if(err = pop3dial(pop))
|
||||||
goto out;
|
goto out;
|
||||||
if((err = pop3read(pop, mb, doplumb, new)) == nil)
|
if((err = pop3read(pop, mb)) == nil)
|
||||||
pop3purge(pop, mb);
|
pop3purge(pop, mb);
|
||||||
pop3hangup(pop);
|
pop3hangup(pop);
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in a new issue