xref: /plan9/sys/src/cmd/upas/ml/common.c (revision 2715b72ad01e83fb7071c22cc0015e1c17a12770)
19a747e4fSDavid du Colombier #include "common.h"
29a747e4fSDavid du Colombier #include "dat.h"
39a747e4fSDavid du Colombier 
49a747e4fSDavid du Colombier String*
getaddr(Node * p)59a747e4fSDavid du Colombier getaddr(Node *p)
69a747e4fSDavid du Colombier {
79a747e4fSDavid du Colombier 	for(; p; p = p->next){
89a747e4fSDavid du Colombier 		if(p->s && p->addr)
99a747e4fSDavid du Colombier 			return p->s;
109a747e4fSDavid du Colombier 	}
119a747e4fSDavid du Colombier 	return nil;
129a747e4fSDavid du Colombier }
139a747e4fSDavid du Colombier 
1486a363ceSDavid du Colombier /* send message adding our own reply-to and precedence */
159a747e4fSDavid du Colombier void
getaddrs(void)169a747e4fSDavid du Colombier getaddrs(void)
179a747e4fSDavid du Colombier {
189a747e4fSDavid du Colombier 	Field *f;
199a747e4fSDavid du Colombier 
209a747e4fSDavid du Colombier 	for(f = firstfield; f; f = f->next){
219a747e4fSDavid du Colombier 		if(f->node->c == FROM && from == nil)
229a747e4fSDavid du Colombier 			from = getaddr(f->node);
239a747e4fSDavid du Colombier 		if(f->node->c == SENDER && sender == nil)
249a747e4fSDavid du Colombier 			sender = getaddr(f->node);
259a747e4fSDavid du Colombier 	}
269a747e4fSDavid du Colombier }
279a747e4fSDavid du Colombier 
289a747e4fSDavid du Colombier /* write address file, should be append only */
299a747e4fSDavid du Colombier void
writeaddr(char * file,char * addr,int rem,char * listname)309a747e4fSDavid du Colombier writeaddr(char *file, char *addr, int rem, char *listname)
319a747e4fSDavid du Colombier {
329a747e4fSDavid du Colombier 	int fd;
33d3c05884SDavid du Colombier 	Dir nd;
349a747e4fSDavid du Colombier 
359a747e4fSDavid du Colombier 	fd = open(file, OWRITE);
369a747e4fSDavid du Colombier 	if(fd < 0){
379a747e4fSDavid du Colombier 		fd = create(file, OWRITE, DMAPPEND|0666);
389a747e4fSDavid du Colombier 		if(fd < 0)
399a747e4fSDavid du Colombier 			sysfatal("creating address list %s: %r", file);
40d3c05884SDavid du Colombier 		nulldir(&nd);
41d3c05884SDavid du Colombier 		nd.mode = DMAPPEND|0666;
42d3c05884SDavid du Colombier 		dirwstat(file, &nd);
439a747e4fSDavid du Colombier 	} else
449a747e4fSDavid du Colombier 		seek(fd, 0, 2);
459a747e4fSDavid du Colombier 	if(rem)
469a747e4fSDavid du Colombier 		fprint(fd, "!%s\n", addr);
479a747e4fSDavid du Colombier 	else
489a747e4fSDavid du Colombier 		fprint(fd, "%s\n", addr);
499a747e4fSDavid du Colombier 	close(fd);
509a747e4fSDavid du Colombier 
519a747e4fSDavid du Colombier 	if(*addr != '#')
529a747e4fSDavid du Colombier 		sendnotification(addr, listname, rem);
539a747e4fSDavid du Colombier }
549a747e4fSDavid du Colombier 
559a747e4fSDavid du Colombier void
remaddr(char * addr)569a747e4fSDavid du Colombier remaddr(char *addr)
579a747e4fSDavid du Colombier {
589a747e4fSDavid du Colombier 	Addr **l;
599a747e4fSDavid du Colombier 	Addr *a;
609a747e4fSDavid du Colombier 
619a747e4fSDavid du Colombier 	for(l = &al; *l; l = &(*l)->next){
629a747e4fSDavid du Colombier 		a = *l;
639a747e4fSDavid du Colombier 		if(strcmp(addr, a->addr) == 0){
649a747e4fSDavid du Colombier 			(*l) = a->next;
659a747e4fSDavid du Colombier 			free(a);
669a747e4fSDavid du Colombier 			na--;
679a747e4fSDavid du Colombier 			break;
689a747e4fSDavid du Colombier 		}
699a747e4fSDavid du Colombier 	}
709a747e4fSDavid du Colombier }
719a747e4fSDavid du Colombier 
729a747e4fSDavid du Colombier int
addaddr(char * addr)739a747e4fSDavid du Colombier addaddr(char *addr)
749a747e4fSDavid du Colombier {
759a747e4fSDavid du Colombier 	Addr **l;
769a747e4fSDavid du Colombier 	Addr *a;
779a747e4fSDavid du Colombier 
789a747e4fSDavid du Colombier 	for(l = &al; *l; l = &(*l)->next){
799a747e4fSDavid du Colombier 		if(strcmp(addr, (*l)->addr) == 0)
809a747e4fSDavid du Colombier 			return 0;
819a747e4fSDavid du Colombier 	}
829a747e4fSDavid du Colombier 	na++;
839a747e4fSDavid du Colombier 	*l = a = malloc(sizeof(*a)+strlen(addr)+1);
849a747e4fSDavid du Colombier 	if(a == nil)
859a747e4fSDavid du Colombier 		sysfatal("allocating: %r");
869a747e4fSDavid du Colombier 	a->addr = (char*)&a[1];
879a747e4fSDavid du Colombier 	strcpy(a->addr, addr);
889a747e4fSDavid du Colombier 	a->next = nil;
899a747e4fSDavid du Colombier 	*l = a;
909a747e4fSDavid du Colombier 	return 1;
919a747e4fSDavid du Colombier }
929a747e4fSDavid du Colombier 
939a747e4fSDavid du Colombier /* read address file */
949a747e4fSDavid du Colombier void
readaddrs(char * file)959a747e4fSDavid du Colombier readaddrs(char *file)
969a747e4fSDavid du Colombier {
979a747e4fSDavid du Colombier 	Biobuf *b;
989a747e4fSDavid du Colombier 	char *p;
999a747e4fSDavid du Colombier 
1009a747e4fSDavid du Colombier 	b = Bopen(file, OREAD);
1019a747e4fSDavid du Colombier 	if(b == nil)
1029a747e4fSDavid du Colombier 		return;
1039a747e4fSDavid du Colombier 
1049a747e4fSDavid du Colombier 	while((p = Brdline(b, '\n')) != nil){
1059a747e4fSDavid du Colombier 		p[Blinelen(b)-1] = 0;
1069a747e4fSDavid du Colombier 		if(*p == '#')
1079a747e4fSDavid du Colombier 			continue;
1089a747e4fSDavid du Colombier 		if(*p == '!')
1099a747e4fSDavid du Colombier 			remaddr(p+1);
1109a747e4fSDavid du Colombier 		else
1119a747e4fSDavid du Colombier 			addaddr(p);
1129a747e4fSDavid du Colombier 	}
1139a747e4fSDavid du Colombier 	Bterm(b);
1149a747e4fSDavid du Colombier }
1159a747e4fSDavid du Colombier 
116*2715b72aSDavid du Colombier /* start a mailer sending to all the receivers for list `name' */
1179a747e4fSDavid du Colombier int
startmailer(char * name)1189a747e4fSDavid du Colombier startmailer(char *name)
1199a747e4fSDavid du Colombier {
1209a747e4fSDavid du Colombier 	int pfd[2];
1219a747e4fSDavid du Colombier 	char **av;
1229a747e4fSDavid du Colombier 	int ac;
1239a747e4fSDavid du Colombier 	Addr *a;
1249a747e4fSDavid du Colombier 
125*2715b72aSDavid du Colombier 	/*
126*2715b72aSDavid du Colombier 	 * we used to send mail to the list from /dev/null,
127*2715b72aSDavid du Colombier 	 * which is equivalent to an smtp return address of <>,
128*2715b72aSDavid du Colombier 	 * but such a return address should only be used when
129*2715b72aSDavid du Colombier 	 * sending a bounce to a single address.  our smtpd lets
130*2715b72aSDavid du Colombier 	 * such mail through, but refuses mail from <> to multiple
131*2715b72aSDavid du Colombier 	 * addresses, since that's not allowed and is likely spam.
132*2715b72aSDavid du Colombier 	 * thus mailing list mail to another upas system with
133*2715b72aSDavid du Colombier 	 * multiple addressees was being rejected.
134*2715b72aSDavid du Colombier 	 */
135*2715b72aSDavid du Colombier 	putenv("upasname", smprint("%s-owner", name));
136*2715b72aSDavid du Colombier 
1379a747e4fSDavid du Colombier 	if(pipe(pfd) < 0)
1389a747e4fSDavid du Colombier 		sysfatal("creating pipe: %r");
1399a747e4fSDavid du Colombier 	switch(fork()){
1409a747e4fSDavid du Colombier 	case -1:
1419a747e4fSDavid du Colombier 		sysfatal("starting mailer: %r");
1429a747e4fSDavid du Colombier 	case 0:
1439a747e4fSDavid du Colombier 		close(pfd[1]);
1449a747e4fSDavid du Colombier 		break;
1459a747e4fSDavid du Colombier 	default:
1469a747e4fSDavid du Colombier 		close(pfd[0]);
1479a747e4fSDavid du Colombier 		return pfd[1];
1489a747e4fSDavid du Colombier 	}
1499a747e4fSDavid du Colombier 
1509a747e4fSDavid du Colombier 	dup(pfd[0], 0);
1519a747e4fSDavid du Colombier 	close(pfd[0]);
1529a747e4fSDavid du Colombier 
1539a747e4fSDavid du Colombier 	av = malloc(sizeof(char*)*(na+2));
1549a747e4fSDavid du Colombier 	if(av == nil)
1559a747e4fSDavid du Colombier 		sysfatal("starting mailer: %r");
1569a747e4fSDavid du Colombier 	ac = 0;
1579a747e4fSDavid du Colombier 	av[ac++] = name;
1589a747e4fSDavid du Colombier 	for(a = al; a != nil; a = a->next)
1599a747e4fSDavid du Colombier 		av[ac++] = a->addr;
1609a747e4fSDavid du Colombier 	av[ac] = 0;
1619a747e4fSDavid du Colombier 	exec("/bin/upas/send", av);
1629a747e4fSDavid du Colombier 	sysfatal("execing mailer: %r");
1639a747e4fSDavid du Colombier 
1649a747e4fSDavid du Colombier 	/* not reached */
1659a747e4fSDavid du Colombier 	return -1;
1669a747e4fSDavid du Colombier }
1679a747e4fSDavid du Colombier 
1689a747e4fSDavid du Colombier void
sendnotification(char * addr,char * listname,int rem)1699a747e4fSDavid du Colombier sendnotification(char *addr, char *listname, int rem)
1709a747e4fSDavid du Colombier {
1719a747e4fSDavid du Colombier 	int pfd[2];
1729a747e4fSDavid du Colombier 	Waitmsg *w;
1739a747e4fSDavid du Colombier 
174*2715b72aSDavid du Colombier 	putenv("upasname", smprint("%s-owner", listname));
1759a747e4fSDavid du Colombier 	if(pipe(pfd) < 0)
1769a747e4fSDavid du Colombier 		sysfatal("creating pipe: %r");
1779a747e4fSDavid du Colombier 	switch(fork()){
1789a747e4fSDavid du Colombier 	case -1:
1799a747e4fSDavid du Colombier 		sysfatal("starting mailer: %r");
1809a747e4fSDavid du Colombier 	case 0:
1819a747e4fSDavid du Colombier 		close(pfd[1]);
1829a747e4fSDavid du Colombier 		dup(pfd[0], 0);
1839a747e4fSDavid du Colombier 		close(pfd[0]);
184f19e7b74SDavid du Colombier 		execl("/bin/upas/send", "mlnotify", addr, nil);
1859a747e4fSDavid du Colombier 		sysfatal("execing mailer: %r");
1869a747e4fSDavid du Colombier 		break;
1879a747e4fSDavid du Colombier 	default:
1889a747e4fSDavid du Colombier 		close(pfd[0]);
1899a747e4fSDavid du Colombier 		fprint(pfd[1], "From: %s-owner\n\n", listname);
1909a747e4fSDavid du Colombier 		if(rem)
19186a363ceSDavid du Colombier 			fprint(pfd[1], "You have been removed from the %s mailing list\n", listname);
1929a747e4fSDavid du Colombier 		else{
1939a747e4fSDavid du Colombier 			fprint(pfd[1], "You have been added to the %s mailing list\n", listname);
1949a747e4fSDavid du Colombier 			fprint(pfd[1], "To be removed, send an email to %s-owner containing\n",
1959a747e4fSDavid du Colombier 				listname);
1969a747e4fSDavid du Colombier 			fprint(pfd[1], "the word 'remove' in the subject or body.\n");
1979a747e4fSDavid du Colombier 		}
1989a747e4fSDavid du Colombier 		close(pfd[1]);
1999a747e4fSDavid du Colombier 
2009a747e4fSDavid du Colombier 		/* wait for mailer to end */
2019a747e4fSDavid du Colombier 		while(w = wait()){
2029a747e4fSDavid du Colombier 			if(w->msg != nil && w->msg[0])
2039a747e4fSDavid du Colombier 				sysfatal("%s", w->msg);
2049a747e4fSDavid du Colombier 			free(w);
2059a747e4fSDavid du Colombier 		}
2069a747e4fSDavid du Colombier 		break;
2079a747e4fSDavid du Colombier 	}
2089a747e4fSDavid du Colombier }
209