#include <avl.h>
enum {
/* cache states */
Cidx = 1<<0,
Cidxstale = 1<<1,
Cheader = 1<<2,
Cbody = 1<<3,
/* encodings */
Enone= 0,
Ebase64,
Equoted,
/* dispositions */
Dnone= 0,
Dinline,
Dfile,
Dignore,
/* mb create flags */
DMcreate = 0x02000000,
/* rm flags */
Rrecur = 1<<0,
Rtrunc = 1<<1,
/* m->deleted flags */
Deleted = 1<<0,
Dup = 1<<1,
Dead = 1<<2,
Disappear = 1<<3,
Dmark = 1<<4, /* temporary mark for idx scan */
/* mime flags */
Mtrunc = 1<<0, /* message had no boundary */
Maxmsg = 75*1024*1024, /* maxmessage size; debugging */
Maxcache = 512*1024, /* target cache size; set low for debugging */
Nctab = 15, /* max # of cached messages >10 */
Nref = 10,
};
typedef struct Idx Idx;
struct Idx {
char *str; /* as read from idx file */
uchar *digest;
uchar flags;
uvlong fileid;
ulong lines;
ulong size;
ulong rawbsize; /* nasty imap4d */
ulong ibadchars;
char *ffrom;
char *from;
char *to;
char *cc;
char *bcc;
char *replyto;
char *messageid;
char *subject;
char *sender;
char *inreplyto;
char *idxaux; /* mailbox specific */
int type; /* very few types: refstring */
int disposition; /* very few types: refstring */
int nparts;
};
typedef struct Message Message;
struct Message {
int id;
int refs;
int subname;
char name[12];
/* top-level indexed information */
Idx;
/* caching help */
uchar cstate;
ulong infolen;
ulong csize;
/*
* a plethoria of pointers into message
* and some status. not valid unless cached
*/
char *start; /* start of message */
char *end; /* end of message */
char *header; /* start of header */
char *hend; /* end of header */
int hlen; /* length of header minus ignored fields */
char *mheader; /* start of mime header */
char *mhend; /* end of mime header */
char *body; /* start of body */
char *bend; /* end of body */
char *rbody; /* raw (unprocessed) body */
char *rbend; /* end of raw (unprocessed) body */
char mallocd; /* message is malloc'd */
char ballocd; /* body is malloc'd */
char hallocd; /* header is malloc'd */
int badchars; /* running count of bad chars. */
char deleted;
char inmbox;
/* mail info */
char *unixheader;
char *unixfrom;
char *date822;
char *references[Nref];
/* mime info */
char *boundary;
int charset;
char *filename;
char encoding;
char converted;
char decoded;
char mimeflag;
Message *next;
Message *part;
Message *whole;
union{
char *lim; /* used by plan9; not compatable with cache */
vlong imapuid; /* used by imap4 */
void *aux;
};
};
typedef struct {
Avl;
Message *m;
} Mtree;
typedef struct Mcache Mcache;
struct Mcache {
uvlong cached;
int ntab;
Message *ctab[Nctab];
};
typedef struct Mailbox Mailbox;
struct Mailbox {
QLock;
long idxsem; /* abort on concurrent index access */
long syncsem; /* abort on concurrent syncs */
int refs;
Mailbox *next;
int id;
int flags;
char rmflags;
char dolock; /* lock when syncing? */
char addfrom;
char name[Elemlen];
char path[Pathlen];
Dir *d;
Message *root;
Avltree *mtree;
ulong vers; /* goes up each time mailbox is changed */
/* cache tracking */
Mcache;
/* index tracking */
Qid qid;
ulong waketime;
void (*close)(Mailbox*);
void (*decache)(Mailbox*, Message*);
int (*fetch)(Mailbox*, Message*, uvlong, ulong);
void (*delete)(Mailbox*, Message*);
char *(*ctl)(Mailbox*, int, char**);
char *(*remove)(Mailbox *, int);
char *(*rename)(Mailbox*, char*, int);
char *(*sync)(Mailbox*, int, int*);
void (*modflags)(Mailbox*, Message*, int);
void (*idxwrite)(Biobuf*, Mailbox*);
int (*idxread)(char*, Mailbox*);
void (*idxinvalid)(Mailbox*);
void *aux; /* private to Mailbox implementation */
};
/* print argument tango; can't varargck 2 types. should fix compiler */
typedef struct Mpair Mpair;
struct Mpair {
Mailbox *mb;
Message *m;
};
Mpair mpair(Mailbox*, Message*);
typedef char *Mailboxinit(Mailbox*, char*);
Mailboxinit plan9mbox;
Mailboxinit planbmbox;
Mailboxinit pop3mbox;
Mailboxinit imap4mbox;
Mailboxinit mdirmbox;
void genericidxwrite(Biobuf*, Mailbox*);
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*);
int insurecache(Mailbox*, Message*);
/**/
void putcache(Mailbox*, Message*); /* asymmetricial */
long cachefree(Mailbox*, Message*, int);
Message* gettopmsg(Mailbox*, Message*);
char* syncmbox(Mailbox*, int);
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*);
uintptr absbos(void);
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);
void syncallmboxes(void);
void logmsg(Message*, char*, ...);
void msgincref(Message*);
void msgdecref(Mailbox*, Message*);
void mboxincref(Mailbox*);
void mboxdecref(Mailbox*);
char *mboxrename(char*, char*, int);
void convert(Message*);
void decode(Message*);
int decquoted(char*, char*, char*, int);
int xtoutf(char*, char**, char*, char*);
ulong countlines(Message*);
void parse(Mailbox*, Message*, int, int);
void parseheaders(Mailbox*, Message*, int, int);
void parsebody(Message*, Mailbox*);
char* date822tounix(Message*, char*);
int fidmboxrefs(Mailbox*);
int hashmboxrefs(Mailbox*);
void checkmboxrefs(void);
int strtotm(char*, Tm*);
char* lowercase(char*);
char* sputc(char*, char*, int);
char* seappend(char*, char*, char*, int);
int hdrlen(char*, char*);
char* rfc2047(char*, char*, char*, int, int);
char* localremove(Mailbox*, int);
char* localrename(Mailbox*, char*, int);
void rmidx(char*, int);
int vremove(char*);
int rename(char *, char*, int);
int mtreecmp(Avl*, Avl*);
int mtreeisdup(Mailbox *, Message *);
Message* mtreefind(Mailbox*, uchar*);
void mtreeadd(Mailbox*, Message*);
void mtreedelete(Mailbox*, Message*);
enum {
/* mail sub-objects; must be sorted */
Qbcc,
Qbody,
Qcc,
Qdate,
Qdigest,
Qdisposition,
Qffrom,
Qfileid,
Qfilename,
Qflags,
Qfrom,
Qheader,
Qinfo,
Qinreplyto,
Qlines,
Qmessageid,
Qmimeheader,
Qraw,
Qrawbody,
Qrawheader,
Qrawunix,
Qreferences,
Qreplyto,
Qsender,
Qsize,
Qsubject,
Qto,
Qtype,
Qunixdate,
Qunixheader,
Qmax,
/* other files */
Qtop,
Qmbox,
Qdir,
Qctl,
Qmboxctl,
};
#define PATH(id, f) ((((id) & 0xfffff)<<10) | (f))
#define FILE(p) ((p) & 0x3ff)
/* hash table to aid in name lookup, all files have an entry */
typedef struct Hash Hash;
struct Hash {
Hash *next;
char *name;
ulong ppath;
Qid qid;
Mailbox *mb;
Message *m;
};
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*);
void idxfree(Idx*);
int rdidxfile(Mailbox*, int);
int wridxfile(Mailbox*);
char *modflags(Mailbox*, Message*, char*);
int getmtokens(char *, char**, int, int);
extern char Enotme[];
extern char *mntpt;
extern char user[Elemlen];
extern char *dirtab[];
extern int Sflag;
extern int iflag;
extern int biffing;
extern ulong cachetarg;
extern int debug;
extern int lflag;
extern int plumbing;
extern ulong msgallocd;
extern ulong msgfreed;
extern Mailbox *mbl;
extern Message *root;
extern QLock mbllock;
extern Refs *rtab;
#define dprint(...) if(debug) fprint(2, __VA_ARGS__); else {}
#define Topmsg(mb, m) (m->whole == mb->root)
#pragma varargck type "A" uchar*
#pragma varargck type "D" uvlong
#pragma varargck type "P" Mpair
#pragma varargck type "Δ" uvlong
#pragma varargck argpos eprint 1
#pragma varargck argpos iprint 1
#pragma varargck argpos logmsg 2
|