aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/upas/ml/ml.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-10-29 16:26:44 +0000
committerrsc <devnull@localhost>2005-10-29 16:26:44 +0000
commit5cdb17983ae6e6367ad7a940cb219eab247a9304 (patch)
tree8ca1ef49af2a96e7daebe624d91fdf679814a057 /src/cmd/upas/ml/ml.c
parentcd3745196389579fb78b9b01ef1daefb5a57aa71 (diff)
downloadplan9port-5cdb17983ae6e6367ad7a940cb219eab247a9304.tar.gz
plan9port-5cdb17983ae6e6367ad7a940cb219eab247a9304.tar.bz2
plan9port-5cdb17983ae6e6367ad7a940cb219eab247a9304.zip
Thanks to John Cummings.
Diffstat (limited to 'src/cmd/upas/ml/ml.c')
-rw-r--r--src/cmd/upas/ml/ml.c167
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);
+}