URI:
       tbox.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tbox.c (5107B)
       ---
            1 #include "a.h"
            2 
            3 enum
            4 {
            5         BoxSubChunk = 16,
            6         BoxChunk = 64,
            7         MsgChunk = 256,
            8         PartChunk = 4,
            9         PartSubChunk = 4
           10 };
           11 
           12 Box **boxes;
           13 uint nboxes;
           14 Box *rootbox;
           15 int boxid;
           16 
           17 Box*
           18 boxbyname(char *name)
           19 {
           20         int i;
           21 
           22         /* LATER: replace with hash table */
           23         for(i=0; i<nboxes; i++)
           24                 if(boxes[i] && strcmp(boxes[i]->name, name) == 0)
           25                         return boxes[i];
           26         return nil;
           27 }
           28 
           29 Box*
           30 subbox(Box *b, char *elem)
           31 {
           32         int i;
           33 
           34         for(i=0; i<b->nsub; i++)
           35                 if(b->sub[i] && strcmp(b->sub[i]->elem, elem) == 0)
           36                         return b->sub[i];
           37         return nil;
           38 }
           39 
           40 Box*
           41 boxbyid(uint id)
           42 {
           43         int i;
           44 
           45         /* LATER: replace with binary search */
           46         for(i=0; i<nboxes; i++)
           47                 if(boxes[i] && boxes[i]->id == id)
           48                         return boxes[i];
           49         return nil;
           50 }
           51 
           52 Box*
           53 boxcreate(char *name)
           54 {
           55         char *p;
           56         Box *b, *bb;
           57 
           58         if((b = boxbyname(name)) != nil)
           59                 return b;
           60 
           61         b = emalloc(sizeof *b);
           62         b->id = ++boxid;
           63         b->time = time(0);
           64         b->name = estrdup(name);
           65         b->uidnext = 1;
           66         p = strrchr(b->name, '/');
           67         if(p){
           68                 *p = 0;
           69                 bb = boxcreate(b->name);
           70                 *p = '/';
           71                 b->elem = p+1;
           72         }else{
           73                 bb = rootbox;
           74                 b->elem = b->name;
           75         }
           76         if(nboxes%BoxChunk == 0)
           77                 boxes = erealloc(boxes, (nboxes+BoxChunk)*sizeof boxes[0]);
           78         boxes[nboxes++] = b;
           79         if(bb->nsub%BoxSubChunk == 0)
           80                 bb->sub = erealloc(bb->sub, (bb->nsub+BoxSubChunk)*sizeof bb->sub[0]);
           81         bb->sub[bb->nsub++] = b;
           82         b->parent = bb;
           83         return b;
           84 }
           85 
           86 void
           87 boxfree(Box *b)
           88 {
           89         int i;
           90 
           91         if(b == nil)
           92                 return;
           93         for(i=0; i<b->nmsg; i++)
           94                 msgfree(b->msg[i]);
           95         free(b->msg);
           96         free(b);
           97 }
           98 
           99 Part*
          100 partcreate(Msg *m, Part *pp)
          101 {
          102         Part *p;
          103 
          104         if(m->npart%PartChunk == 0)
          105                 m->part = erealloc(m->part, (m->npart+PartChunk)*sizeof m->part[0]);
          106         p = emalloc(sizeof *p);
          107         p->msg = m;
          108         p->ix = m->npart;
          109         m->part[m->npart++] = p;
          110         if(pp){
          111                 if(pp->nsub%PartSubChunk == 0)
          112                         pp->sub = erealloc(pp->sub, (pp->nsub+PartSubChunk)*sizeof pp->sub[0]);
          113                 p->pix = pp->nsub;
          114                 p->parent = pp;
          115                 pp->sub[pp->nsub++] = p;
          116         }
          117         return p;
          118 }
          119 
          120 void
          121 partfree(Part *p)
          122 {
          123         int i;
          124 
          125         if(p == nil)
          126                 return;
          127         for(i=0; i<p->nsub; i++)
          128                 partfree(p->sub[i]);
          129         free(p->sub);
          130         hdrfree(p->hdr);
          131         free(p->type);
          132         free(p->idstr);
          133         free(p->desc);
          134         free(p->encoding);
          135         free(p->charset);
          136         free(p->raw);
          137         free(p->rawheader);
          138         free(p->rawbody);
          139         free(p->mimeheader);
          140         free(p->body);
          141         free(p);
          142 }
          143 
          144 void
          145 msgfree(Msg *m)
          146 {
          147         int i;
          148 
          149         if(m == nil)
          150                 return;
          151         for(i=0; i<m->npart; i++)
          152                 free(m->part[i]);
          153         free(m->part);
          154         free(m);
          155 }
          156 
          157 void
          158 msgplumb(Msg *m, int delete)
          159 {
          160         static int fd = -1;
          161         Plumbmsg p;
          162         Plumbattr a[10];
          163         char buf[256], date[40];
          164         int ai;
          165 
          166         if(m == nil || m->npart < 1 || m->part[0]->hdr == nil)
          167                 return;
          168         if(m->box && strcmp(m->box->name, "mbox") != 0)
          169                 return;
          170 
          171         p.src = "mailfs";
          172         p.dst = "seemail";
          173         p.wdir = "/";
          174         p.type = "text";
          175 
          176         ai = 0;
          177         a[ai].name = "filetype";
          178         a[ai].value = "mail";
          179 
          180         a[++ai].name = "mailtype";
          181         a[ai].value = delete?"delete":"new";
          182         a[ai-1].next = &a[ai];
          183 
          184         if(m->part[0]->hdr->from){
          185                 a[++ai].name = "sender";
          186                 a[ai].value = m->part[0]->hdr->from;
          187                 a[ai-1].next = &a[ai];
          188         }
          189 
          190         if(m->part[0]->hdr->subject){
          191                 a[++ai].name = "subject";
          192                 a[ai].value = m->part[0]->hdr->subject;
          193                 a[ai-1].next = &a[ai];
          194         }
          195 
          196         if(m->part[0]->hdr->digest){
          197                 a[++ai].name = "digest";
          198                 a[ai].value = m->part[0]->hdr->digest;
          199                 a[ai-1].next = &a[ai];
          200         }
          201 
          202         strcpy(date, ctime(m->date));
          203         date[strlen(date)-1] = 0;        /* newline */
          204         a[++ai].name = "date";
          205         a[ai].value = date;
          206         a[ai-1].next = &a[ai];
          207 
          208         a[ai].next = nil;
          209 
          210         p.attr = a;
          211 #ifdef PLAN9PORT
          212         snprint(buf, sizeof buf, "Mail/%s/%ud", m->box->name, m->id);
          213 #else
          214         snprint(buf, sizeof buf, "/mail/fs/%s/%ud", m->box->name, m->id);
          215 #endif
          216         p.ndata = strlen(buf);
          217         p.data = buf;
          218 
          219         if(fd < 0)
          220                 fd = plumbopen("send", OWRITE);
          221         if(fd < 0)
          222                 return;
          223 
          224         plumbsend(fd, &p);
          225 }
          226 
          227 
          228 Msg*
          229 msgcreate(Box *box)
          230 {
          231         Msg *m;
          232 
          233         m = emalloc(sizeof *m);
          234         m->box = box;
          235         partcreate(m, nil);
          236         m->part[0]->type = estrdup("message/rfc822");
          237         if(box->nmsg%MsgChunk == 0)
          238                 box->msg = erealloc(box->msg, (box->nmsg+MsgChunk)*sizeof box->msg[0]);
          239         m->ix = box->nmsg++;
          240         box->msg[m->ix] = m;
          241         m->id = ++box->msgid;
          242         return m;
          243 }
          244 
          245 Msg*
          246 msgbyimapuid(Box *box, uint uid, int docreate)
          247 {
          248         int i;
          249         Msg *msg;
          250 
          251         if(box == nil)
          252                 return nil;
          253         /* LATER: binary search or something */
          254         for(i=0; i<box->nmsg; i++)
          255                 if(box->msg[i]->imapuid == uid)
          256                         return box->msg[i];
          257         if(!docreate)
          258                 return nil;
          259         msg = msgcreate(box);
          260         msg->imapuid = uid;
          261         return msg;
          262 }
          263 
          264 Msg*
          265 msgbyid(Box *box, uint id)
          266 {
          267         int i;
          268 
          269         if(box == nil)
          270                 return nil;
          271         /* LATER: binary search or something */
          272         for(i=0; i<box->nmsg; i++)
          273                 if(box->msg[i]->id == id)
          274                         return box->msg[i];
          275         return nil;
          276 }
          277 
          278 Part*
          279 partbyid(Msg *m, uint id)
          280 {
          281         if(m == nil)
          282                 return nil;
          283         if(id >= m->npart)
          284                 return nil;
          285         return m->part[id];
          286 }
          287 
          288 Part*
          289 subpart(Part *p, uint a)
          290 {
          291         if(p == nil || a >= p->nsub)
          292                 return nil;
          293         return p->sub[a];
          294 }
          295 
          296 void
          297 hdrfree(Hdr *h)
          298 {
          299         if(h == nil)
          300                 return;
          301         free(h->date);
          302         free(h->subject);
          303         free(h->from);
          304         free(h->sender);
          305         free(h->replyto);
          306         free(h->to);
          307         free(h->cc);
          308         free(h->bcc);
          309         free(h->inreplyto);
          310         free(h->messageid);
          311         free(h->digest);
          312         free(h);
          313 }
          314 
          315 void
          316 boxinit(void)
          317 {
          318         rootbox = emalloc(sizeof *rootbox);
          319         rootbox->name = estrdup("");
          320         rootbox->time = time(0);
          321 }