shithub: riscv

ref: f7a16b5e2cc38aed7985b0144bb2655d14ea6f5a
dir: /sys/src/cmd/upas/ml/common.c/

View raw version
#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 */
void
getaddrs(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 */
void
writeaddr(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){
		sendnotification(addr, listname, rem);
		fprint(fd, "!%s\n", addr);
	}else{
		fprint(fd, "%s\n", addr);
		if(*addr != '#')
			sendnotification(addr, listname, rem);
	}
	close(fd);
}

void
remaddr(char *addr)
{
	Addr **l;
	Addr *a;

	for(l = &addrlist; *l; l = &(*l)->next){
		a = *l;
		if(strcmp(addr, a->addr) == 0){
			(*l) = a->next;
			free(a);
			naddrlist--;
			break;
		}
	}
}

int
addaddr(char *addr)
{
	Addr **l;
	Addr *a;

	for(l = &addrlist; *l; l = &(*l)->next)
		if(strcmp(addr, (*l)->addr) == 0)
			return 0;
	naddrlist++;
	*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 */
void
readaddrs(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);
}

static void
setsender(char *name)
{
	char *s;

	s = smprint("%s-bounces", name);
	putenv("upasname", s);
	free(s);
}

/* start a mailer sending to all the receivers */
int
startmailer(char *name)
{
	char **av;
	int pfd[2], ac;
	Addr *a;

	setsender(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*)*(naddrlist+2));
	if(av == nil)
		sysfatal("starting mailer: %r");
	ac = 0;
	av[ac++] = name;
	for(a = addrlist; 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;
}

void
sendnotification(char *addr, char *listname, int rem)
{
	int pfd[2];
	Waitmsg *w;

	setsender(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;
	}
}