1 #include "common.h" 2 #include "dat.h" 3 4 String* 5 getaddr(Node *p) 6 { 7 for(; p; p = p->next){ 8 if(p->s && p->addr) 9 return p->s; 10 } 11 return nil; 12 } 13 14 /* send message adding our own reply-to and precedence */ 15 void 16 getaddrs(void) 17 { 18 Field *f; 19 20 for(f = firstfield; f; f = f->next){ 21 if(f->node->c == FROM && from == nil) 22 from = getaddr(f->node); 23 if(f->node->c == SENDER && sender == nil) 24 sender = getaddr(f->node); 25 } 26 } 27 28 /* write address file, should be append only */ 29 void 30 writeaddr(char *file, char *addr, int rem, char *listname) 31 { 32 int fd; 33 Dir nd; 34 35 fd = open(file, OWRITE); 36 if(fd < 0){ 37 fd = create(file, OWRITE, DMAPPEND|0666); 38 if(fd < 0) 39 sysfatal("creating address list %s: %r", file); 40 nulldir(&nd); 41 nd.mode = DMAPPEND|0666; 42 dirwstat(file, &nd); 43 } else 44 seek(fd, 0, 2); 45 if(rem) 46 fprint(fd, "!%s\n", addr); 47 else 48 fprint(fd, "%s\n", addr); 49 close(fd); 50 51 if(*addr != '#') 52 sendnotification(addr, listname, rem); 53 } 54 55 void 56 remaddr(char *addr) 57 { 58 Addr **l; 59 Addr *a; 60 61 for(l = &al; *l; l = &(*l)->next){ 62 a = *l; 63 if(strcmp(addr, a->addr) == 0){ 64 (*l) = a->next; 65 free(a); 66 na--; 67 break; 68 } 69 } 70 } 71 72 int 73 addaddr(char *addr) 74 { 75 Addr **l; 76 Addr *a; 77 78 for(l = &al; *l; l = &(*l)->next){ 79 if(strcmp(addr, (*l)->addr) == 0) 80 return 0; 81 } 82 na++; 83 *l = a = malloc(sizeof(*a)+strlen(addr)+1); 84 if(a == nil) 85 sysfatal("allocating: %r"); 86 a->addr = (char*)&a[1]; 87 strcpy(a->addr, addr); 88 a->next = nil; 89 *l = a; 90 return 1; 91 } 92 93 /* read address file */ 94 void 95 readaddrs(char *file) 96 { 97 Biobuf *b; 98 char *p; 99 100 b = Bopen(file, OREAD); 101 if(b == nil) 102 return; 103 104 while((p = Brdline(b, '\n')) != nil){ 105 p[Blinelen(b)-1] = 0; 106 if(*p == '#') 107 continue; 108 if(*p == '!') 109 remaddr(p+1); 110 else 111 addaddr(p); 112 } 113 Bterm(b); 114 } 115 116 /* start a mailer sending to all the receivers for list `name' */ 117 int 118 startmailer(char *name) 119 { 120 int pfd[2]; 121 char **av; 122 int ac; 123 Addr *a; 124 125 /* 126 * we used to send mail to the list from /dev/null, 127 * which is equivalent to an smtp return address of <>, 128 * but such a return address should only be used when 129 * sending a bounce to a single address. our smtpd lets 130 * such mail through, but refuses mail from <> to multiple 131 * addresses, since that's not allowed and is likely spam. 132 * thus mailing list mail to another upas system with 133 * multiple addressees was being rejected. 134 */ 135 putenv("upasname", smprint("%s-owner", name)); 136 137 if(pipe(pfd) < 0) 138 sysfatal("creating pipe: %r"); 139 switch(fork()){ 140 case -1: 141 sysfatal("starting mailer: %r"); 142 case 0: 143 close(pfd[1]); 144 break; 145 default: 146 close(pfd[0]); 147 return pfd[1]; 148 } 149 150 dup(pfd[0], 0); 151 close(pfd[0]); 152 153 av = malloc(sizeof(char*)*(na+2)); 154 if(av == nil) 155 sysfatal("starting mailer: %r"); 156 ac = 0; 157 av[ac++] = name; 158 for(a = al; a != nil; a = a->next) 159 av[ac++] = a->addr; 160 av[ac] = 0; 161 exec("/bin/upas/send", av); 162 sysfatal("execing mailer: %r"); 163 164 /* not reached */ 165 return -1; 166 } 167 168 void 169 sendnotification(char *addr, char *listname, int rem) 170 { 171 int pfd[2]; 172 Waitmsg *w; 173 174 putenv("upasname", smprint("%s-owner", listname)); 175 if(pipe(pfd) < 0) 176 sysfatal("creating pipe: %r"); 177 switch(fork()){ 178 case -1: 179 sysfatal("starting mailer: %r"); 180 case 0: 181 close(pfd[1]); 182 dup(pfd[0], 0); 183 close(pfd[0]); 184 execl("/bin/upas/send", "mlnotify", addr, nil); 185 sysfatal("execing mailer: %r"); 186 break; 187 default: 188 close(pfd[0]); 189 fprint(pfd[1], "From: %s-owner\n\n", listname); 190 if(rem) 191 fprint(pfd[1], "You have been removed from the %s mailing list\n", listname); 192 else{ 193 fprint(pfd[1], "You have been added to the %s mailing list\n", listname); 194 fprint(pfd[1], "To be removed, send an email to %s-owner containing\n", 195 listname); 196 fprint(pfd[1], "the word 'remove' in the subject or body.\n"); 197 } 198 close(pfd[1]); 199 200 /* wait for mailer to end */ 201 while(w = wait()){ 202 if(w->msg != nil && w->msg[0]) 203 sysfatal("%s", w->msg); 204 free(w); 205 } 206 break; 207 } 208 } 209