ref: 8f73c6436a0a0a39f6e1de79b4fd6f21af38d841
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)
compose(a, nil, 0, 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, Mesg *r, int quote, int all)
{
static int ncompose;
char *path, *ln;
Biobuf *rfd, *wfd;
Comp *c;
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);
if(r == nil || !all)
Bprint(wfd, "To: %s", 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, "\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);
}