Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#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;
        }
}