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