diff options
Diffstat (limited to 'src/cmd/upas/nfs/box.c')
-rw-r--r-- | src/cmd/upas/nfs/box.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/cmd/upas/nfs/box.c b/src/cmd/upas/nfs/box.c new file mode 100644 index 00000000..044edf20 --- /dev/null +++ b/src/cmd/upas/nfs/box.c @@ -0,0 +1,318 @@ +#include "a.h" + +enum +{ + BoxSubChunk = 16, + BoxChunk = 64, + MsgChunk = 256, + PartChunk = 4, + PartSubChunk = 4, +}; + +Box **boxes; +uint nboxes; +Box *rootbox; +int boxid; + +Box* +boxbyname(char *name) +{ + int i; + + /* LATER: replace with hash table */ + for(i=0; i<nboxes; i++) + if(boxes[i] && strcmp(boxes[i]->name, name) == 0) + return boxes[i]; + return nil; +} + +Box* +subbox(Box *b, char *elem) +{ + int i; + + for(i=0; i<b->nsub; i++) + if(b->sub[i] && strcmp(b->sub[i]->elem, elem) == 0) + return b->sub[i]; + return nil; +} + +Box* +boxbyid(uint id) +{ + int i; + + /* LATER: replace with binary search */ + for(i=0; i<nboxes; i++) + if(boxes[i] && boxes[i]->id == id) + return boxes[i]; + return nil; +} + +Box* +boxcreate(char *name) +{ + char *p; + Box *b, *bb; + + if((b = boxbyname(name)) != nil) + return b; + + b = emalloc(sizeof *b); + b->id = ++boxid; + b->time = time(0); + b->name = estrdup(name); + b->uidnext = 1; + p = strrchr(b->name, '/'); + if(p){ + *p = 0; + bb = boxcreate(b->name); + *p = '/'; + b->elem = p+1; + }else{ + bb = rootbox; + b->elem = b->name; + } + if(nboxes%BoxChunk == 0) + boxes = erealloc(boxes, (nboxes+BoxChunk)*sizeof boxes[0]); + boxes[nboxes++] = b; + if(bb->nsub%BoxSubChunk == 0) + bb->sub = erealloc(bb->sub, (bb->nsub+BoxSubChunk)*sizeof bb->sub[0]); + bb->sub[bb->nsub++] = b; + b->parent = bb; + return b; +} + +void +boxfree(Box *b) +{ + int i; + + if(b == nil) + return; + for(i=0; i<b->nmsg; i++) + msgfree(b->msg[i]); + free(b->msg); + free(b); +} + +Part* +partcreate(Msg *m, Part *pp) +{ + Part *p; + + if(m->npart%PartChunk == 0) + m->part = erealloc(m->part, (m->npart+PartChunk)*sizeof m->part[0]); + p = emalloc(sizeof *p); + p->msg = m; + p->ix = m->npart; + m->part[m->npart++] = p; + if(pp){ + if(pp->nsub%PartSubChunk == 0) + pp->sub = erealloc(pp->sub, (pp->nsub+PartSubChunk)*sizeof pp->sub[0]); + p->pix = pp->nsub; + p->parent = pp; + pp->sub[pp->nsub++] = p; + } + return p; +} + +void +partfree(Part *p) +{ + int i; + + if(p == nil) + return; + for(i=0; i<p->nsub; i++) + partfree(p->sub[i]); + free(p->sub); + hdrfree(p->hdr); + free(p->type); + free(p->idstr); + free(p->desc); + free(p->encoding); + free(p->charset); + free(p->raw); + free(p->rawheader); + free(p->rawbody); + free(p->mimeheader); + free(p->body); + free(p); +} + +void +msgfree(Msg *m) +{ + int i; + + if(m == nil) + return; + for(i=0; i<m->npart; i++) + free(m->part[i]); + free(m->part); + free(m); +} + +void +msgplumb(Msg *m, int delete) +{ + static int fd = -1; + Plumbmsg p; + Plumbattr a[10]; + char buf[256], date[40]; + int ai; + + if(m == nil || m->npart < 1 || m->part[0]->hdr == nil) + return; + if(m->box && strcmp(m->box->name, "mbox") != 0) + return; + + p.src = "mailfs"; + p.dst = "seemail"; + p.wdir = "/"; + p.type = "text"; + + ai = 0; + a[ai].name = "filetype"; + a[ai].value = "mail"; + + a[++ai].name = "mailtype"; + a[ai].value = delete?"delete":"new"; + a[ai-1].next = &a[ai]; + + if(m->part[0]->hdr->from){ + a[++ai].name = "sender"; + a[ai].value = m->part[0]->hdr->from; + a[ai-1].next = &a[ai]; + } + + if(m->part[0]->hdr->subject){ + a[++ai].name = "subject"; + a[ai].value = m->part[0]->hdr->subject; + a[ai-1].next = &a[ai]; + } + + if(m->part[0]->hdr->digest){ + a[++ai].name = "digest"; + a[ai].value = m->part[0]->hdr->digest; + a[ai-1].next = &a[ai]; + } + + strcpy(date, ctime(m->date)); + date[strlen(date)-1] = 0; /* newline */ + a[++ai].name = "date"; + a[ai].value = date; + a[ai-1].next = &a[ai]; + + a[ai].next = nil; + + p.attr = a; + snprint(buf, sizeof buf, "Mail/%s/%ud", m->box->name, m->id); + p.ndata = strlen(buf); + p.data = buf; + + if(fd < 0) + fd = plumbopen("send", OWRITE); + if(fd < 0) + return; + + plumbsend(fd, &p); +} + + +Msg* +msgcreate(Box *box) +{ + Msg *m; + + m = emalloc(sizeof *m); + m->box = box; + partcreate(m, nil); + m->part[0]->type = estrdup("message/rfc822"); + if(box->nmsg%MsgChunk == 0) + box->msg = erealloc(box->msg, (box->nmsg+MsgChunk)*sizeof box->msg[0]); + m->ix = box->nmsg++; + box->msg[m->ix] = m; + m->id = ++box->msgid; + return m; +} + +Msg* +msgbyimapuid(Box *box, uint uid, int docreate) +{ + int i; + Msg *msg; + + if(box == nil) + return nil; + /* LATER: binary search or something */ + for(i=0; i<box->nmsg; i++) + if(box->msg[i]->imapuid == uid) + return box->msg[i]; + if(!docreate) + return nil; + msg = msgcreate(box); + msg->imapuid = uid; + return msg; +} + +Msg* +msgbyid(Box *box, uint id) +{ + int i; + + if(box == nil) + return nil; + /* LATER: binary search or something */ + for(i=0; i<box->nmsg; i++) + if(box->msg[i]->id == id) + return box->msg[i]; + return nil; +} + +Part* +partbyid(Msg *m, uint id) +{ + if(m == nil) + return nil; + if(id >= m->npart) + return nil; + return m->part[id]; +} + +Part* +subpart(Part *p, uint a) +{ + if(p == nil || a >= p->nsub) + return nil; + return p->sub[a]; +} + +void +hdrfree(Hdr *h) +{ + if(h == nil) + return; + free(h->date); + free(h->subject); + free(h->from); + free(h->sender); + free(h->replyto); + free(h->to); + free(h->cc); + free(h->bcc); + free(h->inreplyto); + free(h->messageid); + free(h->digest); + free(h); +} + +void +boxinit(void) +{ + rootbox = emalloc(sizeof *rootbox); + rootbox->name = estrdup(""); + rootbox->time = time(0); +} + |