ref: e51c4bc6e493a9cd0d9e9d7f1d24c57ae77bab65
dir: /sys/src/cmd/upas/ml/common.c/
#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; } }