box.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 }