ref: fbc6ca33a7305c82b720eee9168790d9d937c50d
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; c = p; rfork(RFFDG); dup(c->fd[0], 0); close(c->fd[0]); close(c->fd[1]); sendul(c->sync, 0); procexecl(nil, "/bin/upas/marshal", "marshal", "-8", 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); proccreate(execmarshal, c, Stack); 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(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); } } static Fn compfn[] = { {"Post", postmesg}, {nil}, }; static void compmain(void *cp) { char *a, *f[32]; int nf; Event ev; Comp *c; Fn *p; c = cp; c->quitting = 0; 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((a = matchaddr(&mbox, &ev)) != nil) compose1(a, nil, 0); else if(matchmesg(&mbox, ev.text)) mesgopen(ev.text, nil); else if(!(ev.flags & 0x2)) winsendevent(&mbox, &ev); free(a); break; case 'x': case 'X': if((nf = tokenize(ev.text, f, nelem(f))) == 0) continue; for(p = compfn; p->name != nil; p++) if(strcmp(p->name, f[0]) == 0) p->fn(c, &f[1], nf - 1); if(p->name == nil && !(ev.flags & 0x2)) winsendevent(&mbox, &ev); break; break; } } mbox.nopen--; winclose(c); free(c->replyto); free(c->rname); free(c->rdigest); threadexits(nil); } void compose(char **to, int nto, char **cc, int ncc, Mesg *r, int quote) { static int ncompose; char *path, *ln; Biobuf *rfd, *wfd; Comp *c; int i; c = emalloc(sizeof(Comp)); if(r != nil) path = esmprint("%s%s%s.%d", mbox.path, r->name, "Reply", ncompose++); else path = esmprint("%sCompose.%d", mbox.path, ncompose++); wininit(c, path); free(path); wintagwrite(c, "Delmesg Save Post "); wfd = bwinopen(c, "body", OWRITE); for(i = 0; i < nto; i++) Bprint(wfd, "To: %s\n", to[i]); for(i = 0; i < ncc; i++) Bprint(wfd, "Cc: %s\n", cc[i]); if(r == nil){ Bprint(wfd, "\n"); }else{ if(r->messageid != nil) c->replyto = estrdup(r->messageid); 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){ path = estrjoin(mbox.path, r->name, "body", nil); rfd = Bopen(path, OREAD); free(path); if(rfd != nil) while((ln = Brdstr(rfd, '\n', 0)) != nil) if(Bprint(wfd, "> %s", ln) == -1) break; Bterm(rfd); } Bterm(wfd); } Bterm(wfd); proccreate(compmain, c, Stack); } void compose1(char *to, Mesg *resp, int quote) { compose(&to, 1, nil, 0, resp, quote); }