xref: /plan9/sys/src/cmd/upas/ml/ml.c (revision 86a363cef6b6fa09d9392d8587eef2e5ef8d657e)
19a747e4fSDavid du Colombier #include "common.h"
29a747e4fSDavid du Colombier #include "dat.h"
39a747e4fSDavid du Colombier 
49a747e4fSDavid du Colombier Biobuf in;
59a747e4fSDavid du Colombier 
69a747e4fSDavid du Colombier Addr *al;
79a747e4fSDavid du Colombier int na;
89a747e4fSDavid du Colombier String *from;
99a747e4fSDavid du Colombier String *sender;
109a747e4fSDavid du Colombier 
1139734e7eSDavid du Colombier void printmsg(int fd, String *msg, char *replyto, char *listname);
129a747e4fSDavid du Colombier void appendtoarchive(char* listname, String *firstline, String *msg);
1339734e7eSDavid du Colombier void printsubject(int fd, Field *f, char *listname);
149a747e4fSDavid du Colombier 
159a747e4fSDavid du Colombier void
usage(void)169a747e4fSDavid du Colombier usage(void)
179a747e4fSDavid du Colombier {
189a747e4fSDavid du Colombier 	fprint(2, "usage: %s address-list-file listname\n", argv0);
199a747e4fSDavid du Colombier 	exits("usage");
209a747e4fSDavid du Colombier }
219a747e4fSDavid du Colombier 
229a747e4fSDavid du Colombier void
main(int argc,char ** argv)239a747e4fSDavid du Colombier main(int argc, char **argv)
249a747e4fSDavid du Colombier {
259a747e4fSDavid du Colombier 	String *msg;
269a747e4fSDavid du Colombier 	String *firstline;
279a747e4fSDavid du Colombier 	char *listname, *alfile;
289a747e4fSDavid du Colombier 	Waitmsg *w;
299a747e4fSDavid du Colombier 	int fd;
303ff48bf5SDavid du Colombier 	char *replytoname = nil;
319a747e4fSDavid du Colombier 
329a747e4fSDavid du Colombier 	ARGBEGIN{
333ff48bf5SDavid du Colombier 	case 'r':
343ff48bf5SDavid du Colombier 		replytoname = ARGF();
353ff48bf5SDavid du Colombier 		break;
369a747e4fSDavid du Colombier 	}ARGEND;
379a747e4fSDavid du Colombier 
389a747e4fSDavid du Colombier 	rfork(RFENVG|RFREND);
399a747e4fSDavid du Colombier 
409a747e4fSDavid du Colombier 	if(argc < 2)
419a747e4fSDavid du Colombier 		usage();
429a747e4fSDavid du Colombier 	alfile = argv[0];
439a747e4fSDavid du Colombier 	listname = argv[1];
443ff48bf5SDavid du Colombier 	if(replytoname == nil)
453ff48bf5SDavid du Colombier 		replytoname = listname;
469a747e4fSDavid du Colombier 
479a747e4fSDavid du Colombier 	readaddrs(alfile);
489a747e4fSDavid du Colombier 
499a747e4fSDavid du Colombier 	if(Binit(&in, 0, OREAD) < 0)
509a747e4fSDavid du Colombier 		sysfatal("opening input: %r");
519a747e4fSDavid du Colombier 
529a747e4fSDavid du Colombier 	msg = s_new();
539a747e4fSDavid du Colombier 	firstline = s_new();
549a747e4fSDavid du Colombier 
559a747e4fSDavid du Colombier 	/* discard the 'From ' line */
569a747e4fSDavid du Colombier 	if(s_read_line(&in, firstline) == nil)
579a747e4fSDavid du Colombier 		sysfatal("reading input: %r");
589a747e4fSDavid du Colombier 
59*86a363ceSDavid du Colombier 	/* read up to the first 128k of the message.  more is ridiculous.
6039734e7eSDavid du Colombier 	     Not if word documents are distributed.  Upped it to 2MB (pb) */
6139734e7eSDavid du Colombier 	if(s_read(&in, msg, 2*1024*1024) <= 0)
629a747e4fSDavid du Colombier 		sysfatal("reading input: %r");
639a747e4fSDavid du Colombier 
649a747e4fSDavid du Colombier 	/* parse the header */
659a747e4fSDavid du Colombier 	yyinit(s_to_c(msg), s_len(msg));
669a747e4fSDavid du Colombier 	yyparse();
679a747e4fSDavid du Colombier 
689a747e4fSDavid du Colombier 	/* get the sender */
699a747e4fSDavid du Colombier 	getaddrs();
709a747e4fSDavid du Colombier 	if(from == nil)
719a747e4fSDavid du Colombier 		from = sender;
729a747e4fSDavid du Colombier 	if(from == nil)
739a747e4fSDavid du Colombier 		sysfatal("message must contain From: or Sender:");
749a747e4fSDavid du Colombier 	if(strcmp(listname, s_to_c(from)) == 0)
759a747e4fSDavid du Colombier 		sysfatal("can't remail messages from myself");
769a747e4fSDavid du Colombier 	addaddr(s_to_c(from));
779a747e4fSDavid du Colombier 
789a747e4fSDavid du Colombier 	/* start the mailer up and return a pipe to it */
799a747e4fSDavid du Colombier 	fd = startmailer(listname);
809a747e4fSDavid du Colombier 
819a747e4fSDavid du Colombier 	/* send message adding our own reply-to and precedence */
8239734e7eSDavid du Colombier 	printmsg(fd, msg, replytoname, listname);
839a747e4fSDavid du Colombier 	close(fd);
849a747e4fSDavid du Colombier 
859a747e4fSDavid du Colombier 	/* wait for mailer to end */
869a747e4fSDavid du Colombier 	while(w = wait()){
879a747e4fSDavid du Colombier 		if(w->msg != nil && w->msg[0])
889a747e4fSDavid du Colombier 			sysfatal("%s", w->msg);
899a747e4fSDavid du Colombier 		free(w);
909a747e4fSDavid du Colombier 	}
919a747e4fSDavid du Colombier 
92*86a363ceSDavid du Colombier 	/* if the mailbox exists, cat the mail to the end of it */
939a747e4fSDavid du Colombier 	appendtoarchive(listname, firstline, msg);
949a747e4fSDavid du Colombier 	exits(0);
959a747e4fSDavid du Colombier }
969a747e4fSDavid du Colombier 
979a747e4fSDavid du Colombier /* send message filtering Reply-to out of messages */
989a747e4fSDavid du Colombier void
printmsg(int fd,String * msg,char * replyto,char * listname)9939734e7eSDavid du Colombier printmsg(int fd, String *msg, char *replyto, char *listname)
1009a747e4fSDavid du Colombier {
10139734e7eSDavid du Colombier 	Field *f, *subject;
1029a747e4fSDavid du Colombier 	Node *p;
1039a747e4fSDavid du Colombier 	char *cp, *ocp;
1049a747e4fSDavid du Colombier 
10539734e7eSDavid du Colombier 	subject = nil;
1069a747e4fSDavid du Colombier 	cp = s_to_c(msg);
1079a747e4fSDavid du Colombier 	for(f = firstfield; f; f = f->next){
1089a747e4fSDavid du Colombier 		ocp = cp;
1099a747e4fSDavid du Colombier 		for(p = f->node; p; p = p->next)
1109a747e4fSDavid du Colombier 			cp = p->end+1;
1119a747e4fSDavid du Colombier 		if(f->node->c == REPLY_TO)
1129a747e4fSDavid du Colombier 			continue;
1139a747e4fSDavid du Colombier 		if(f->node->c == PRECEDENCE)
1149a747e4fSDavid du Colombier 			continue;
11539734e7eSDavid du Colombier 		if(f->node->c == SUBJECT){
11639734e7eSDavid du Colombier 			subject = f;
11739734e7eSDavid du Colombier 			continue;
11839734e7eSDavid du Colombier 		}
1199a747e4fSDavid du Colombier 		write(fd, ocp, cp-ocp);
1209a747e4fSDavid du Colombier 	}
12139734e7eSDavid du Colombier 	printsubject(fd, subject, listname);
12239734e7eSDavid du Colombier 	fprint(fd, "Reply-To: %s\nPrecedence: bulk\n", replyto);
1239a747e4fSDavid du Colombier 	write(fd, cp, s_len(msg) - (cp - s_to_c(msg)));
1249a747e4fSDavid du Colombier }
1259a747e4fSDavid du Colombier 
126*86a363ceSDavid du Colombier /* if the mailbox exists, cat the mail to the end of it */
1279a747e4fSDavid du Colombier void
appendtoarchive(char * listname,String * firstline,String * msg)1289a747e4fSDavid du Colombier appendtoarchive(char* listname, String *firstline, String *msg)
1299a747e4fSDavid du Colombier {
1309a747e4fSDavid du Colombier 	String *mbox;
1319a747e4fSDavid du Colombier 	int fd;
1329a747e4fSDavid du Colombier 
1339a747e4fSDavid du Colombier 	mbox = s_new();
1349a747e4fSDavid du Colombier 	mboxpath("mbox", listname, mbox, 0);
1359a747e4fSDavid du Colombier 	if(access(s_to_c(mbox), 0) < 0)
1369a747e4fSDavid du Colombier 		return;
1379a747e4fSDavid du Colombier 	fd = open(s_to_c(mbox), OWRITE);
1389a747e4fSDavid du Colombier 	if(fd < 0)
1399a747e4fSDavid du Colombier 		return;
1409a747e4fSDavid du Colombier 	s_append(msg, "\n");
1419a747e4fSDavid du Colombier 	write(fd, s_to_c(firstline), s_len(firstline));
1429a747e4fSDavid du Colombier 	write(fd, s_to_c(msg), s_len(msg));
1439a747e4fSDavid du Colombier }
14439734e7eSDavid du Colombier 
14539734e7eSDavid du Colombier /* add the listname to the subject */
14639734e7eSDavid du Colombier void
printsubject(int fd,Field * f,char * listname)14739734e7eSDavid du Colombier printsubject(int fd, Field *f, char *listname)
14839734e7eSDavid du Colombier {
14939734e7eSDavid du Colombier 	char *s, *e;
15039734e7eSDavid du Colombier 	Node *p;
15139734e7eSDavid du Colombier 	char *ln;
15239734e7eSDavid du Colombier 
15339734e7eSDavid du Colombier 	if(f == nil || f->node == nil){
15439734e7eSDavid du Colombier 		fprint(fd, "Subject: [%s]\n", listname);
15539734e7eSDavid du Colombier 		return;
15639734e7eSDavid du Colombier 	}
15739734e7eSDavid du Colombier 	s = e = f->node->end + 1;
15839734e7eSDavid du Colombier 	for(p = f->node; p; p = p->next)
15939734e7eSDavid du Colombier 		e = p->end;
16039734e7eSDavid du Colombier 	*e = 0;
16139734e7eSDavid du Colombier 	ln = smprint("[%s]", listname);
16239734e7eSDavid du Colombier 	if(ln != nil && strstr(s, ln) == nil)
16339734e7eSDavid du Colombier 		fprint(fd, "Subject: %s%s\n", ln, s);
16439734e7eSDavid du Colombier 	else
16539734e7eSDavid du Colombier 		fprint(fd, "Subject:%s\n", s);
16639734e7eSDavid du Colombier 	free(ln);
16739734e7eSDavid du Colombier }
168