Blob


1 #include "common.h"
2 #include "dat.h"
4 Biobuf in;
6 Addr *al;
7 int na;
8 String *from;
9 String *sender;
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);
15 void
16 usage(void)
17 {
18 fprint(2, "usage: %s address-list-file listname\n", argv0);
19 exits("usage");
20 }
22 void
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;
32 ARGBEGIN{
33 case 'r':
34 replytoname = ARGF();
35 break;
36 }ARGEND;
38 rfork(RFENVG);
40 if(argc < 2)
41 usage();
42 alfile = argv[0];
43 listname = argv[1];
44 if(replytoname == nil)
45 replytoname = listname;
47 readaddrs(alfile);
49 if(Binit(&in, 0, OREAD) < 0)
50 sysfatal("opening input: %r");
52 msg = s_new();
53 firstline = s_new();
55 /* discard the 'From ' line */
56 if(s_read_line(&in, firstline) == nil)
57 sysfatal("reading input: %r");
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");
64 /* parse the header */
65 yyinit(s_to_c(msg), s_len(msg));
66 yyparse();
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));
78 /* start the mailer up and return a pipe to it */
79 fd = startmailer(listname);
81 /* send message adding our own reply-to and precedence */
82 printmsg(fd, msg, replytoname, listname);
83 close(fd);
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 }
92 /* if the mailbox exits, cat the mail to the end of it */
93 appendtoarchive(listname, firstline, msg);
94 exits(0);
95 }
97 /* send message filtering Reply-to out of messages */
98 void
99 printmsg(int fd, String *msg, char *replyto, char *listname)
101 Field *f, *subject;
102 Node *p;
103 char *cp, *ocp;
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;
119 write(fd, ocp, cp-ocp);
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)));
126 /* if the mailbox exits, cat the mail to the end of it */
127 void
128 appendtoarchive(char* listname, String *firstline, String *msg)
130 String *mbox;
131 int fd;
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));
145 /* add the listname to the subject */
146 void
147 printsubject(int fd, Field *f, char *listname)
149 char *s, *e;
150 Node *p;
151 char *ln;
153 if(f == nil || f->node == nil){
154 fprint(fd, "Subject: [%s]\n", listname);
155 return;
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);