217 lines · 4.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "common.h"#include "dat.h" String*getaddr(Node *p){	for(; p; p = p->next){		if(p->s && p->addr)			return p->s;	}	return nil;} /* send message adding our own reply-to and precedence */voidgetaddrs(void){	Field *f; 	for(f = firstfield; f; f = f->next){		if(f->node->c == FROM && from == nil)			from = getaddr(f->node);		if(f->node->c == SENDER && sender == nil)			sender = getaddr(f->node);	}} /* write address file, should be append only */voidwriteaddr(char *file, char *addr, int rem, char *listname){	int fd;	Dir nd; 	fd = open(file, OWRITE);	if(fd < 0){		fd = create(file, OWRITE, DMAPPEND|0666);		if(fd < 0)			sysfatal("creating address list %s: %r", file);		nulldir(&nd);		nd.mode = DMAPPEND|0666;		dirwstat(file, &nd);	} else		seek(fd, 0, 2);	if(rem)		fprint(fd, "!%s\n", addr);	else		fprint(fd, "%s\n", addr);	close(fd); 	if(*addr != '#')		sendnotification(addr, listname, rem);} voidremaddr(char *addr){	Addr **l;	Addr *a; 	for(l = &al; *l; l = &(*l)->next){		a = *l;		if(strcmp(addr, a->addr) == 0){			(*l) = a->next;			free(a);			na--;			break;		}	}} intaddaddr(char *addr){	Addr **l;	Addr *a; 	for(l = &al; *l; l = &(*l)->next){		if(strcmp(addr, (*l)->addr) == 0)			return 0;	}	na++;	*l = a = malloc(sizeof(*a)+strlen(addr)+1);	if(a == nil)		sysfatal("allocating: %r");	a->addr = (char*)&a[1];	strcpy(a->addr, addr);	a->next = nil;	*l = a;	return 1;} /* read address file */voidreadaddrs(char *file){	Biobuf *b;	char *p; 	b = Bopen(file, OREAD);	if(b == nil)		return; 	while((p = Brdline(b, '\n')) != nil){		p[Blinelen(b)-1] = 0;		if(*p == '#')			continue;		if(*p == '!')			remaddr(p+1);		else			addaddr(p);	}	Bterm(b);} /* start a mailer sending to all the receivers for list `name' */intstartmailer(char *name){	int pfd[2];	char **av;	int ac;	Addr *a; 	/*	 * we used to send mail to the list from /dev/null,	 * which is equivalent to an smtp return address of <>,	 * but such a return address should only be used when	 * sending a bounce to a single address.  our smtpd lets	 * such mail through, but refuses mail from <> to multiple	 * addresses, since that's not allowed and is likely spam.	 * thus mailing list mail to another upas system with	 * multiple addressees was being rejected.	 */	putenv("upasname", smprint("%s-owner", name)); 	if(pipe(pfd) < 0)		sysfatal("creating pipe: %r");	switch(fork()){	case -1:		sysfatal("starting mailer: %r");	case 0:		close(pfd[1]);		break;	default:		close(pfd[0]);		return pfd[1];	} 	dup(pfd[0], 0);	close(pfd[0]); 	av = malloc(sizeof(char*)*(na+2));	if(av == nil)		sysfatal("starting mailer: %r");	ac = 0;	av[ac++] = name;	for(a = al; a != nil; a = a->next)		av[ac++] = a->addr;	av[ac] = 0;	exec("/bin/upas/send", av);	sysfatal("execing mailer: %r"); 	/* not reached */	return -1;} voidsendnotification(char *addr, char *listname, int rem){	int pfd[2];	Waitmsg *w; 	putenv("upasname", smprint("%s-owner", listname));	if(pipe(pfd) < 0)		sysfatal("creating pipe: %r");	switch(fork()){	case -1:		sysfatal("starting mailer: %r");	case 0:		close(pfd[1]);		dup(pfd[0], 0);		close(pfd[0]);		execl("/bin/upas/send", "mlnotify", addr, nil);		sysfatal("execing mailer: %r");		break;	default:		close(pfd[0]);		fprint(pfd[1], "From: %s-owner\n\n", listname);		if(rem)			fprint(pfd[1], "You have been removed from the %s mailing list\n", listname);		else{			fprint(pfd[1], "You have been added to the %s mailing list\n", listname);			fprint(pfd[1], "To be removed, send an email to %s-owner containing\n",				listname);			fprint(pfd[1], "the word 'remove' in the subject or body.\n");		}		close(pfd[1]);			/* wait for mailer to end */		while(w = wait()){			if(w->msg != nil && w->msg[0])				sysfatal("%s", w->msg);			free(w);		}		break;	}}