xref: /plan9/sys/src/cmd/upas/ml/common.c (revision 0b459c2cb92b7c9d88818e9a2f72e678e5bc4553)
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 messae 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 *d;
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 		d = dirstat(file);
41 		d->mode = DMAPPEND|0666;
42 		dirwstat(file, d);
43 		free(d);
44 	} else
45 		seek(fd, 0, 2);
46 	if(rem)
47 		fprint(fd, "!%s\n", addr);
48 	else
49 		fprint(fd, "%s\n", addr);
50 	close(fd);
51 
52 	if(*addr != '#')
53 		sendnotification(addr, listname, rem);
54 }
55 
56 void
57 remaddr(char *addr)
58 {
59 	Addr **l;
60 	Addr *a;
61 
62 	for(l = &al; *l; l = &(*l)->next){
63 		a = *l;
64 		if(strcmp(addr, a->addr) == 0){
65 			(*l) = a->next;
66 			free(a);
67 			na--;
68 			break;
69 		}
70 	}
71 }
72 
73 int
74 addaddr(char *addr)
75 {
76 	Addr **l;
77 	Addr *a;
78 
79 	for(l = &al; *l; l = &(*l)->next){
80 		if(strcmp(addr, (*l)->addr) == 0)
81 			return 0;
82 	}
83 	na++;
84 	*l = a = malloc(sizeof(*a)+strlen(addr)+1);
85 	if(a == nil)
86 		sysfatal("allocating: %r");
87 	a->addr = (char*)&a[1];
88 	strcpy(a->addr, addr);
89 	a->next = nil;
90 	*l = a;
91 	return 1;
92 }
93 
94 /* read address file */
95 void
96 readaddrs(char *file)
97 {
98 	Biobuf *b;
99 	char *p;
100 
101 	b = Bopen(file, OREAD);
102 	if(b == nil)
103 		return;
104 
105 	while((p = Brdline(b, '\n')) != nil){
106 		p[Blinelen(b)-1] = 0;
107 		if(*p == '#')
108 			continue;
109 		if(*p == '!')
110 			remaddr(p+1);
111 		else
112 			addaddr(p);
113 	}
114 	Bterm(b);
115 }
116 
117 /* start a mailer sending to all the receivers */
118 int
119 startmailer(char *name)
120 {
121 	int pfd[2];
122 	char **av;
123 	int ac;
124 	Addr *a;
125 
126 	putenv("upasname", "/dev/null");
127 	if(pipe(pfd) < 0)
128 		sysfatal("creating pipe: %r");
129 	switch(fork()){
130 	case -1:
131 		sysfatal("starting mailer: %r");
132 	case 0:
133 		close(pfd[1]);
134 		break;
135 	default:
136 		close(pfd[0]);
137 		return pfd[1];
138 	}
139 
140 	dup(pfd[0], 0);
141 	close(pfd[0]);
142 
143 	av = malloc(sizeof(char*)*(na+2));
144 	if(av == nil)
145 		sysfatal("starting mailer: %r");
146 	ac = 0;
147 	av[ac++] = name;
148 	for(a = al; a != nil; a = a->next)
149 		av[ac++] = a->addr;
150 	av[ac] = 0;
151 	exec("/bin/upas/send", av);
152 	sysfatal("execing mailer: %r");
153 
154 	/* not reached */
155 	return -1;
156 }
157 
158 void
159 sendnotification(char *addr, char *listname, int rem)
160 {
161 	int pfd[2];
162 	Waitmsg *w;
163 
164 	putenv("upasname", "/dev/null");
165 	if(pipe(pfd) < 0)
166 		sysfatal("creating pipe: %r");
167 	switch(fork()){
168 	case -1:
169 		sysfatal("starting mailer: %r");
170 	case 0:
171 		close(pfd[1]);
172 		dup(pfd[0], 0);
173 		close(pfd[0]);
174 		execl("/bin/upas/send", "mlnotify", addr, 0);
175 		sysfatal("execing mailer: %r");
176 		break;
177 	default:
178 		close(pfd[0]);
179 		fprint(pfd[1], "From: %s-owner\n\n", listname);
180 		if(rem)
181 			fprint(pfd[1], "You have removed from the %s mailing list\n", listname);
182 		else{
183 			fprint(pfd[1], "You have been added to the %s mailing list\n", listname);
184 			fprint(pfd[1], "To be removed, send an email to %s-owner containing\n",
185 				listname);
186 			fprint(pfd[1], "the word 'remove' in the subject or body.\n");
187 		}
188 		close(pfd[1]);
189 
190 		/* wait for mailer to end */
191 		while(w = wait()){
192 			if(w->msg != nil && w->msg[0])
193 				sysfatal("%s", w->msg);
194 			free(w);
195 		}
196 		break;
197 	}
198 }
199