xref: /plan9/sys/src/cmd/upas/ml/common.c (revision f9e1cf08d3be51592e03e639fc848a68dc31a55e)
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 */
117 int
118 startmailer(char *name)
119 {
120 	int pfd[2];
121 	char **av;
122 	int ac;
123 	Addr *a;
124 
125 	putenv("upasname", "/dev/null");
126 	if(pipe(pfd) < 0)
127 		sysfatal("creating pipe: %r");
128 	switch(fork()){
129 	case -1:
130 		sysfatal("starting mailer: %r");
131 	case 0:
132 		close(pfd[1]);
133 		break;
134 	default:
135 		close(pfd[0]);
136 		return pfd[1];
137 	}
138 
139 	dup(pfd[0], 0);
140 	close(pfd[0]);
141 
142 	av = malloc(sizeof(char*)*(na+2));
143 	if(av == nil)
144 		sysfatal("starting mailer: %r");
145 	ac = 0;
146 	av[ac++] = name;
147 	for(a = al; a != nil; a = a->next)
148 		av[ac++] = a->addr;
149 	av[ac] = 0;
150 	exec("/bin/upas/send", av);
151 	sysfatal("execing mailer: %r");
152 
153 	/* not reached */
154 	return -1;
155 }
156 
157 void
158 sendnotification(char *addr, char *listname, int rem)
159 {
160 	int pfd[2];
161 	Waitmsg *w;
162 
163 	putenv("upasname", "/dev/null");
164 	if(pipe(pfd) < 0)
165 		sysfatal("creating pipe: %r");
166 	switch(fork()){
167 	case -1:
168 		sysfatal("starting mailer: %r");
169 	case 0:
170 		close(pfd[1]);
171 		dup(pfd[0], 0);
172 		close(pfd[0]);
173 		execl("/bin/upas/send", "mlnotify", addr, nil);
174 		sysfatal("execing mailer: %r");
175 		break;
176 	default:
177 		close(pfd[0]);
178 		fprint(pfd[1], "From: %s-owner\n\n", listname);
179 		if(rem)
180 			fprint(pfd[1], "You have been removed from the %s mailing list\n", listname);
181 		else{
182 			fprint(pfd[1], "You have been added to the %s mailing list\n", listname);
183 			fprint(pfd[1], "To be removed, send an email to %s-owner containing\n",
184 				listname);
185 			fprint(pfd[1], "the word 'remove' in the subject or body.\n");
186 		}
187 		close(pfd[1]);
188 
189 		/* wait for mailer to end */
190 		while(w = wait()){
191 			if(w->msg != nil && w->msg[0])
192 				sysfatal("%s", w->msg);
193 			free(w);
194 		}
195 		break;
196 	}
197 }
198