ref: ed0a057803a11e12326211123433100647d6c8f9
dir: /comp.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <thread.h> #include <regexp.h> #include "mail.h" typedef struct Fn Fn; struct Fn { char *name; void (*fn)(Comp *, char **, int); }; void execmarshal(void *p) { Comp *c; char *dashr; c = p; rfork(RFFDG); dup(c->fd[0], 0); close(c->fd[0]); close(c->fd[1]); dashr = (c->rpath != nil) ? "-R" : nil; procexecl(c->sync, "/bin/upas/marshal", "marshal", "-8", dashr, c->rpath, nil); } static void postmesg(Comp *c, char **, int nf) { char *buf, wpath[64], *path; int n, fd; Mesg *m; snprint(wpath, sizeof(wpath), "/mnt/acme/%d/body", c->id); if(nf != 0){ fprint(2, "Post: too many args\n"); return; } if((fd = open(wpath, OREAD)) == -1){ fprint(2, "open body: %r\n"); return; } if(pipe(c->fd) == -1) sysfatal("pipe: %r\n"); c->sync = chancreate(sizeof(ulong), 0); procrfork(execmarshal, c, Stack, RFNOTEG); recvul(c->sync); chanfree(c->sync); close(c->fd[0]); buf = emalloc(Bufsz); while((n = read(fd, buf, Bufsz)) > 0) if(write(c->fd[1], buf, n) != n) break; close(c->fd[1]); close(fd); if(n == -1) return; if(fprint(c->ctl, "name %s:Sent\n", c->path) == -1) sysfatal("write ctl: %r"); if(c->replyto != nil){ if((m = mesglookup(c->rname, c->rdigest)) == nil) return; m->flags |= Fresp; path = estrjoin(mbox.path, "/", m->name, "/flags", nil); if((fd = open(path, OWRITE)) != -1){ fprint(fd, "+a"); close(fd); } mbredraw(m, 0, 0); free(path); } fprint(c->ctl, "clean\n"); } static void compquit(Comp *c, char **, int) { c->quitting = 1; } static Fn compfn[] = { {"Post", postmesg}, {"Del", compquit}, {nil}, }; static void compmain(void *cp) { char *f[32]; int nf; Event ev; Comp *c, **pc; Fn *p; c = cp; c->quitting = 0; c->qnext = mbox.opencomp; mbox.opencomp = c; fprint(c->ctl, "clean\n"); mbox.nopen++; while(!c->quitting){ if(winevent(c, &ev) != 'M') continue; if(strcmp(ev.text, "Del") == 0) break; switch(ev.type){ case 'l': case 'L': if(matchmesg(&mbox, ev.text)) mesgopen(ev.text, nil); else winreturn(c, &ev); break; case 'x': case 'X': if((nf = tokenize(ev.text, f, nelem(f))) == 0) continue; for(p = compfn; p->fn != nil; p++) if(strcmp(p->name, f[0]) == 0){ p->fn(c, &f[1], nf - 1); break; } if(p->name == nil && !(ev.flags & 0x2)) winreturn(c, &ev); break; break; } } for(pc = &mbox.opencomp; *pc != nil; pc = &(*pc)->qnext) if(*pc == c){ *pc = c->qnext; break; } mbox.nopen--; c->qnext = nil; winclose(c); free(c->replyto); free(c->rname); free(c->rdigest); free(c->rpath); threadexits(nil); } static Biobuf* openbody(Mesg *r) { Biobuf *f; int q0, q1; char *s; assert(r->state & Sopen); wingetsel(r, &q0, &q1); if(q1 - q0 != 0){ s = smprint("/mnt/acme/%d/xdata", r->id); f = Bopen(s, OREAD); free(s); }else f = mesgopenbody(r); return f; } void compose(char *to, Mesg *r, int quote, int all) { static int ncompose; Biobuf *rfd, *wfd; Comp *c; char *ln; c = emalloc(sizeof(Comp)); if(r != nil) c->path = esmprint("%s%s%s.%d", mbox.path, r->name, "Reply", ncompose++); else c->path = esmprint("%sCompose.%d", mbox.path, ncompose++); wininit(c, c->path); wintagwrite(c, "Post "); wfd = bwinopen(c, "body", OWRITE); if(r == nil || !all) Bprint(wfd, "To: %s\n", to); else{ if(strlen(r->from) > 0) Bprint(wfd, "To: %s\n", r->from); if(strlen(r->to) > 0) Bprint(wfd, "To: %s\n", r->to); if(strlen(r->cc) > 0) Bprint(wfd, "CC: %s\n", r->cc); } if(r == nil) Bprint(wfd, "Subject: "); else{ if(r->messageid != nil) c->replyto = estrdup(r->messageid); c->rpath = estrjoin(mbox.path, r->name, nil); c->rname = estrdup(r->name); c->rdigest = estrdup(r->digest); Bprint(wfd, "Subject: "); if(r->subject != nil && cistrncmp(r->subject, "Re", 2) != 0) Bprint(wfd, "Re: "); Bprint(wfd, "%s\n\n", r->subject); if(quote){ Bprint(wfd, "Quoth %s:\n", r->fromcolon); rfd = openbody(r); if(rfd != nil) while((ln = Brdstr(rfd, '\n', 0)) != nil) if(Bprint(wfd, "> %s", ln) == -1) break; Bterm(rfd); } Bterm(wfd); } Bterm(wfd); fprint(c->addr, "$"); fprint(c->ctl, "dot=addr"); threadcreate(compmain, c, Stack); }