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, char *listname);
12 void appendtoarchive(char* listname, String *firstline, String *msg);
13 void printsubject(int fd, Field *f, char *listname);
14 
15 void
usage(void)16 usage(void)
17 {
18 	fprint(2, "usage: %s address-list-file listname\n", argv0);
19 	exits("usage");
20 }
21 
22 void
main(int argc,char ** argv)23 main(int argc, char **argv)
24 {
25 	String *msg;
26 	String *firstline;
27 	char *listname, *alfile;
28 	Waitmsg *w;
29 	int fd;
30 	char *replytoname = nil;
31 
32 	ARGBEGIN{
33 	case 'r':
34 		replytoname = ARGF();
35 		break;
36 	}ARGEND;
37 
38 	rfork(RFENVG);
39 
40 	if(argc < 2)
41 		usage();
42 	alfile = argv[0];
43 	listname = argv[1];
44 	if(replytoname == nil)
45 		replytoname = listname;
46 
47 	readaddrs(alfile);
48 
49 	if(Binit(&in, 0, OREAD) < 0)
50 		sysfatal("opening input: %r");
51 
52 	msg = s_new();
53 	firstline = s_new();
54 
55 	/* discard the 'From ' line */
56 	if(s_read_line(&in, firstline) == nil)
57 		sysfatal("reading input: %r");
58 
59 	/* read up to the first 128k of the message.  more is redculous.
60 	     Not if word documents are distributed.  Upped it to 2MB (pb) */
61 	if(s_read(&in, msg, 2*1024*1024) <= 0)
62 		sysfatal("reading input: %r");
63 
64 	/* parse the header */
65 	yyinit(s_to_c(msg), s_len(msg));
66 	yyparse();
67 
68 	/* get the sender */
69 	getaddrs();
70 	if(from == nil)
71 		from = sender;
72 	if(from == nil)
73 		sysfatal("message must contain From: or Sender:");
74 	if(strcmp(listname, s_to_c(from)) == 0)
75 		sysfatal("can't remail messages from myself");
76 	addaddr(s_to_c(from));
77 
78 	/* start the mailer up and return a pipe to it */
79 	fd = startmailer(listname);
80 
81 	/* send message adding our own reply-to and precedence */
82 	printmsg(fd, msg, replytoname, listname);
83 	close(fd);
84 
85 	/* wait for mailer to end */
86 	while(w = wait()){
87 		if(w->msg != nil && w->msg[0])
88 			sysfatal("%s", w->msg);
89 		free(w);
90 	}
91 
92 	/* if the mailbox exits, cat the mail to the end of it */
93 	appendtoarchive(listname, firstline, msg);
94 	exits(0);
95 }
96 
97 /* send message filtering Reply-to out of messages */
98 void
printmsg(int fd,String * msg,char * replyto,char * listname)99 printmsg(int fd, String *msg, char *replyto, char *listname)
100 {
101 	Field *f, *subject;
102 	Node *p;
103 	char *cp, *ocp;
104 
105 	subject = nil;
106 	cp = s_to_c(msg);
107 	for(f = firstfield; f; f = f->next){
108 		ocp = cp;
109 		for(p = f->node; p; p = p->next)
110 			cp = p->end+1;
111 		if(f->node->c == REPLY_TO)
112 			continue;
113 		if(f->node->c == PRECEDENCE)
114 			continue;
115 		if(f->node->c == SUBJECT){
116 			subject = f;
117 			continue;
118 		}
119 		write(fd, ocp, cp-ocp);
120 	}
121 	printsubject(fd, subject, listname);
122 	fprint(fd, "Reply-To: %s\nPrecedence: bulk\n", replyto);
123 	write(fd, cp, s_len(msg) - (cp - s_to_c(msg)));
124 }
125 
126 /* if the mailbox exits, cat the mail to the end of it */
127 void
appendtoarchive(char * listname,String * firstline,String * msg)128 appendtoarchive(char* listname, String *firstline, String *msg)
129 {
130 	String *mbox;
131 	int fd;
132 
133 	mbox = s_new();
134 	mboxpath("mbox", listname, mbox, 0);
135 	if(access(s_to_c(mbox), 0) < 0)
136 		return;
137 	fd = open(s_to_c(mbox), OWRITE);
138 	if(fd < 0)
139 		return;
140 	s_append(msg, "\n");
141 	write(fd, s_to_c(firstline), s_len(firstline));
142 	write(fd, s_to_c(msg), s_len(msg));
143 }
144 
145 /* add the listname to the subject */
146 void
printsubject(int fd,Field * f,char * listname)147 printsubject(int fd, Field *f, char *listname)
148 {
149 	char *s, *e;
150 	Node *p;
151 	char *ln;
152 
153 	if(f == nil || f->node == nil){
154 		fprint(fd, "Subject: [%s]\n", listname);
155 		return;
156 	}
157 	s = e = f->node->end + 1;
158 	for(p = f->node; p; p = p->next)
159 		e = p->end;
160 	*e = 0;
161 	ln = smprint("[%s]", listname);
162 	if(ln != nil && strstr(s, ln) == nil)
163 		fprint(fd, "Subject: %s%s\n", ln, s);
164 	else
165 		fprint(fd, "Subject:%s\n", s);
166 	free(ln);
167 }
168