xref: /plan9-contrib/sys/src/cmd/upas/ml/ml.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
1 #include "common.h"
2 #include "dat.h"
3 
4 Biobuf in;
5 
6 Addr *al;
7 int na;
8 String *from;
9 String *sender;
10 
11 void printmsg(int fd, String *msg, char *replyto);
12 void appendtoarchive(char* listname, String *firstline, String *msg);
13 
14 void
15 usage(void)
16 {
17 	fprint(2, "usage: %s address-list-file listname\n", argv0);
18 	exits("usage");
19 }
20 
21 void
22 main(int argc, char **argv)
23 {
24 	String *msg;
25 	String *firstline;
26 	char *listname, *alfile;
27 	Waitmsg *w;
28 	int fd;
29 	char *replytoname = nil;
30 
31 	ARGBEGIN{
32 	case 'r':
33 		replytoname = ARGF();
34 		break;
35 	}ARGEND;
36 
37 	rfork(RFENVG|RFREND);
38 
39 	if(argc < 2)
40 		usage();
41 	alfile = argv[0];
42 	listname = argv[1];
43 	if(replytoname == nil)
44 		replytoname = listname;
45 
46 	readaddrs(alfile);
47 
48 	if(Binit(&in, 0, OREAD) < 0)
49 		sysfatal("opening input: %r");
50 
51 	msg = s_new();
52 	firstline = s_new();
53 
54 	/* discard the 'From ' line */
55 	if(s_read_line(&in, firstline) == nil)
56 		sysfatal("reading input: %r");
57 
58 	/* read up to the first 128k of the message.  more is redculous */
59 	if(s_read(&in, msg, 128*1024) <= 0)
60 		sysfatal("reading input: %r");
61 
62 	/* parse the header */
63 	yyinit(s_to_c(msg), s_len(msg));
64 	yyparse();
65 
66 	/* get the sender */
67 	getaddrs();
68 	if(from == nil)
69 		from = sender;
70 	if(from == nil)
71 		sysfatal("message must contain From: or Sender:");
72 	if(strcmp(listname, s_to_c(from)) == 0)
73 		sysfatal("can't remail messages from myself");
74 	addaddr(s_to_c(from));
75 
76 	/* start the mailer up and return a pipe to it */
77 	fd = startmailer(listname);
78 
79 	/* send message adding our own reply-to and precedence */
80 	printmsg(fd, msg, replytoname);
81 	close(fd);
82 
83 	/* wait for mailer to end */
84 	while(w = wait()){
85 		if(w->msg != nil && w->msg[0])
86 			sysfatal("%s", w->msg);
87 		free(w);
88 	}
89 
90 	/* if the mailbox exits, cat the mail to the end of it */
91 	appendtoarchive(listname, firstline, msg);
92 	exits(0);
93 }
94 
95 /* send message filtering Reply-to out of messages */
96 void
97 printmsg(int fd, String *msg, char *replyto)
98 {
99 	Field *f;
100 	Node *p;
101 	char *cp, *ocp;
102 
103 	cp = s_to_c(msg);
104 	fprint(fd, "Reply-To: %s\nPrecedence: bulk\n", replyto);
105 	for(f = firstfield; f; f = f->next){
106 		ocp = cp;
107 		for(p = f->node; p; p = p->next)
108 			cp = p->end+1;
109 		if(f->node->c == REPLY_TO)
110 			continue;
111 		if(f->node->c == PRECEDENCE)
112 			continue;
113 		write(fd, ocp, cp-ocp);
114 	}
115 	write(fd, cp, s_len(msg) - (cp - s_to_c(msg)));
116 }
117 
118 /* if the mailbox exits, cat the mail to the end of it */
119 void
120 appendtoarchive(char* listname, String *firstline, String *msg)
121 {
122 	String *mbox;
123 	int fd;
124 
125 	mbox = s_new();
126 	mboxpath("mbox", listname, mbox, 0);
127 	if(access(s_to_c(mbox), 0) < 0)
128 		return;
129 	fd = open(s_to_c(mbox), OWRITE);
130 	if(fd < 0)
131 		return;
132 	s_append(msg, "\n");
133 	write(fd, s_to_c(firstline), s_len(firstline));
134 	write(fd, s_to_c(msg), s_len(msg));
135 }
136