diff options
Diffstat (limited to 'src/cmd/upas/ml/ml.c')
-rw-r--r-- | src/cmd/upas/ml/ml.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/cmd/upas/ml/ml.c b/src/cmd/upas/ml/ml.c new file mode 100644 index 00000000..8372dc9d --- /dev/null +++ b/src/cmd/upas/ml/ml.c @@ -0,0 +1,167 @@ +#include "common.h" +#include "dat.h" + +Biobuf in; + +Addr *al; +int na; +String *from; +String *sender; + +void printmsg(int fd, String *msg, char *replyto, char *listname); +void appendtoarchive(char* listname, String *firstline, String *msg); +void printsubject(int fd, Field *f, char *listname); + +void +usage(void) +{ + fprint(2, "usage: %s address-list-file listname\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + String *msg; + String *firstline; + char *listname, *alfile; + Waitmsg *w; + int fd; + char *replytoname = nil; + + ARGBEGIN{ + case 'r': + replytoname = ARGF(); + break; + }ARGEND; + + rfork(RFENVG|RFREND); + + if(argc < 2) + usage(); + alfile = argv[0]; + listname = argv[1]; + if(replytoname == nil) + replytoname = listname; + + readaddrs(alfile); + + if(Binit(&in, 0, OREAD) < 0) + sysfatal("opening input: %r"); + + msg = s_new(); + firstline = s_new(); + + /* discard the 'From ' line */ + if(s_read_line(&in, firstline) == nil) + sysfatal("reading input: %r"); + + /* read up to the first 128k of the message. more is redculous. + Not if word documents are distributed. Upped it to 2MB (pb) */ + if(s_read(&in, msg, 2*1024*1024) <= 0) + sysfatal("reading input: %r"); + + /* parse the header */ + yyinit(s_to_c(msg), s_len(msg)); + yyparse(); + + /* get the sender */ + getaddrs(); + if(from == nil) + from = sender; + if(from == nil) + sysfatal("message must contain From: or Sender:"); + if(strcmp(listname, s_to_c(from)) == 0) + sysfatal("can't remail messages from myself"); + addaddr(s_to_c(from)); + + /* start the mailer up and return a pipe to it */ + fd = startmailer(listname); + + /* send message adding our own reply-to and precedence */ + printmsg(fd, msg, replytoname, listname); + close(fd); + + /* wait for mailer to end */ + while(w = wait()){ + if(w->msg != nil && w->msg[0]) + sysfatal("%s", w->msg); + free(w); + } + + /* if the mailbox exits, cat the mail to the end of it */ + appendtoarchive(listname, firstline, msg); + exits(0); +} + +/* send message filtering Reply-to out of messages */ +void +printmsg(int fd, String *msg, char *replyto, char *listname) +{ + Field *f, *subject; + Node *p; + char *cp, *ocp; + + subject = nil; + cp = s_to_c(msg); + for(f = firstfield; f; f = f->next){ + ocp = cp; + for(p = f->node; p; p = p->next) + cp = p->end+1; + if(f->node->c == REPLY_TO) + continue; + if(f->node->c == PRECEDENCE) + continue; + if(f->node->c == SUBJECT){ + subject = f; + continue; + } + write(fd, ocp, cp-ocp); + } + printsubject(fd, subject, listname); + fprint(fd, "Reply-To: %s\nPrecedence: bulk\n", replyto); + write(fd, cp, s_len(msg) - (cp - s_to_c(msg))); +} + +/* if the mailbox exits, cat the mail to the end of it */ +void +appendtoarchive(char* listname, String *firstline, String *msg) +{ + String *mbox; + int fd; + + mbox = s_new(); + mboxpath("mbox", listname, mbox, 0); + if(access(s_to_c(mbox), 0) < 0) + return; + fd = open(s_to_c(mbox), OWRITE); + if(fd < 0) + return; + s_append(msg, "\n"); + write(fd, s_to_c(firstline), s_len(firstline)); + write(fd, s_to_c(msg), s_len(msg)); +} + +/* add the listname to the subject */ +void +printsubject(int fd, Field *f, char *listname) +{ + char *s, *e; + Node *p; + char *ln; + + if(f == nil || f->node == nil){ + fprint(fd, "Subject: [%s]\n", listname); + return; + } + s = e = f->node->end + 1; + for(p = f->node; p; p = p->next) + e = p->end; + *e = 0; + ln = smprint("[%s]", listname); + if(ln != nil && strstr(s, ln) == nil) + fprint(fd, "Subject: %s%s\n", ln, s); + else + fprint(fd, "Subject:%s\n", s); + free(ln); +} |