/* * 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; }}
/*
* 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 */
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)
fprint(fd, "!%s\n", addr);
else
fprint(fd, "%s\n", addr);
close(fd);
if(*addr != '#')
sendnotification(addr, listname, rem);
}
void
remaddr(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;
}
}
}
int
addaddr(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 */
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);
}
/* start a mailer sending to all the receivers for list `name' */
int
startmailer(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;
}
void
sendnotification(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;
}
}