ml.c (3454B)
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 16 usage(void) 17 { 18 fprint(2, "usage: %s address-list-file listname\n", argv0); 19 exits("usage"); 20 } 21 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; 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 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 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 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 }