plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }