Blame


1 5cdb1798 2005-10-29 devnull #include "common.h"
2 5cdb1798 2005-10-29 devnull #include "send.h"
3 5cdb1798 2005-10-29 devnull
4 5cdb1798 2005-10-29 devnull /* globals to all files */
5 5cdb1798 2005-10-29 devnull int rmail;
6 5cdb1798 2005-10-29 devnull char *thissys, *altthissys;
7 5cdb1798 2005-10-29 devnull int nflg;
8 5cdb1798 2005-10-29 devnull int xflg;
9 5cdb1798 2005-10-29 devnull int debug;
10 5cdb1798 2005-10-29 devnull int rflg;
11 5cdb1798 2005-10-29 devnull int iflg = 1;
12 5cdb1798 2005-10-29 devnull int nosummary;
13 5cdb1798 2005-10-29 devnull
14 5cdb1798 2005-10-29 devnull /* global to this file */
15 5cdb1798 2005-10-29 devnull static String *errstring;
16 5cdb1798 2005-10-29 devnull static message *mp;
17 5cdb1798 2005-10-29 devnull static int interrupt;
18 5cdb1798 2005-10-29 devnull static int savemail;
19 5cdb1798 2005-10-29 devnull static Biobuf in;
20 5cdb1798 2005-10-29 devnull static int forked;
21 5cdb1798 2005-10-29 devnull static int add822headers = 1;
22 5cdb1798 2005-10-29 devnull static String *arglist;
23 5cdb1798 2005-10-29 devnull
24 5cdb1798 2005-10-29 devnull /* predeclared */
25 5cdb1798 2005-10-29 devnull static int send(dest *, message *, int);
26 5cdb1798 2005-10-29 devnull static void lesstedious(void);
27 5cdb1798 2005-10-29 devnull static void save_mail(message *);
28 5cdb1798 2005-10-29 devnull static int complain_mail(dest *, message *);
29 5cdb1798 2005-10-29 devnull static int pipe_mail(dest *, message *);
30 5cdb1798 2005-10-29 devnull static void appaddr(String *, dest *);
31 5cdb1798 2005-10-29 devnull static void mkerrstring(String *, message *, dest *, dest *, char *, int);
32 5cdb1798 2005-10-29 devnull static int replymsg(String *, message *, dest *);
33 5cdb1798 2005-10-29 devnull static int catchint(void*, char*);
34 5cdb1798 2005-10-29 devnull
35 5cdb1798 2005-10-29 devnull void
36 5cdb1798 2005-10-29 devnull usage(void)
37 5cdb1798 2005-10-29 devnull {
38 5cdb1798 2005-10-29 devnull fprint(2, "usage: mail [-birtx] list-of-addresses\n");
39 5cdb1798 2005-10-29 devnull exits("usage");
40 5cdb1798 2005-10-29 devnull }
41 5cdb1798 2005-10-29 devnull
42 5cdb1798 2005-10-29 devnull void
43 5cdb1798 2005-10-29 devnull main(int argc, char *argv[])
44 5cdb1798 2005-10-29 devnull {
45 5cdb1798 2005-10-29 devnull dest *dp=0;
46 5cdb1798 2005-10-29 devnull int checkforward;
47 5cdb1798 2005-10-29 devnull char *base;
48 5cdb1798 2005-10-29 devnull int rv;
49 5cdb1798 2005-10-29 devnull
50 5cdb1798 2005-10-29 devnull /* process args */
51 5cdb1798 2005-10-29 devnull ARGBEGIN{
52 5cdb1798 2005-10-29 devnull case '#':
53 5cdb1798 2005-10-29 devnull nflg = 1;
54 5cdb1798 2005-10-29 devnull break;
55 5cdb1798 2005-10-29 devnull case 'b':
56 5cdb1798 2005-10-29 devnull add822headers = 0;
57 5cdb1798 2005-10-29 devnull break;
58 5cdb1798 2005-10-29 devnull case 'x':
59 5cdb1798 2005-10-29 devnull nflg = 1;
60 5cdb1798 2005-10-29 devnull xflg = 1;
61 5cdb1798 2005-10-29 devnull break;
62 5cdb1798 2005-10-29 devnull case 'd':
63 5cdb1798 2005-10-29 devnull debug = 1;
64 5cdb1798 2005-10-29 devnull break;
65 5cdb1798 2005-10-29 devnull case 'i':
66 5cdb1798 2005-10-29 devnull iflg = 0;
67 5cdb1798 2005-10-29 devnull break;
68 5cdb1798 2005-10-29 devnull case 'r':
69 5cdb1798 2005-10-29 devnull rflg = 1;
70 5cdb1798 2005-10-29 devnull break;
71 5cdb1798 2005-10-29 devnull default:
72 5cdb1798 2005-10-29 devnull usage();
73 5cdb1798 2005-10-29 devnull }ARGEND
74 5cdb1798 2005-10-29 devnull
75 5cdb1798 2005-10-29 devnull while(*argv){
76 5cdb1798 2005-10-29 devnull if(shellchars(*argv)){
77 5cdb1798 2005-10-29 devnull fprint(2, "illegal characters in destination\n");
78 5cdb1798 2005-10-29 devnull exits("syntax");
79 5cdb1798 2005-10-29 devnull }
80 5cdb1798 2005-10-29 devnull d_insert(&dp, d_new(s_copy(*argv++)));
81 5cdb1798 2005-10-29 devnull }
82 5cdb1798 2005-10-29 devnull
83 5cdb1798 2005-10-29 devnull if (dp == 0)
84 5cdb1798 2005-10-29 devnull usage();
85 5cdb1798 2005-10-29 devnull arglist = d_to(dp);
86 5cdb1798 2005-10-29 devnull
87 5cdb1798 2005-10-29 devnull /*
88 5cdb1798 2005-10-29 devnull * get context:
89 5cdb1798 2005-10-29 devnull * - whether we're rmail or mail
90 5cdb1798 2005-10-29 devnull */
91 5cdb1798 2005-10-29 devnull base = basename(argv0);
92 5cdb1798 2005-10-29 devnull checkforward = rmail = (strcmp(base, "rmail")==0) | rflg;
93 5cdb1798 2005-10-29 devnull thissys = sysname_read();
94 5cdb1798 2005-10-29 devnull altthissys = alt_sysname_read();
95 5cdb1798 2005-10-29 devnull if(rmail)
96 5cdb1798 2005-10-29 devnull add822headers = 0;
97 5cdb1798 2005-10-29 devnull
98 5cdb1798 2005-10-29 devnull /*
99 5cdb1798 2005-10-29 devnull * read the mail. If an interrupt occurs while reading, save in
100 5cdb1798 2005-10-29 devnull * dead.letter
101 5cdb1798 2005-10-29 devnull */
102 5cdb1798 2005-10-29 devnull if (!nflg) {
103 5cdb1798 2005-10-29 devnull Binit(&in, 0, OREAD);
104 5cdb1798 2005-10-29 devnull if(!rmail)
105 5cdb1798 2005-10-29 devnull atnotify(catchint, 1);
106 5cdb1798 2005-10-29 devnull mp = m_read(&in, rmail, !iflg);
107 5cdb1798 2005-10-29 devnull if (mp == 0)
108 5cdb1798 2005-10-29 devnull exit(0);
109 5cdb1798 2005-10-29 devnull if (interrupt != 0) {
110 5cdb1798 2005-10-29 devnull save_mail(mp);
111 5cdb1798 2005-10-29 devnull exit(1);
112 5cdb1798 2005-10-29 devnull }
113 5cdb1798 2005-10-29 devnull } else {
114 5cdb1798 2005-10-29 devnull mp = m_new();
115 5cdb1798 2005-10-29 devnull if(default_from(mp) < 0){
116 5cdb1798 2005-10-29 devnull fprint(2, "%s: can't determine login name\n", argv0);
117 5cdb1798 2005-10-29 devnull exit(1);
118 5cdb1798 2005-10-29 devnull }
119 5cdb1798 2005-10-29 devnull }
120 5cdb1798 2005-10-29 devnull errstring = s_new();
121 5cdb1798 2005-10-29 devnull getrules();
122 5cdb1798 2005-10-29 devnull
123 5cdb1798 2005-10-29 devnull /*
124 5cdb1798 2005-10-29 devnull * If this is a gateway, translate the sender address into a local
125 5cdb1798 2005-10-29 devnull * address. This only happens if mail to the local address is
126 5cdb1798 2005-10-29 devnull * forwarded to the sender.
127 5cdb1798 2005-10-29 devnull */
128 5cdb1798 2005-10-29 devnull gateway(mp);
129 5cdb1798 2005-10-29 devnull
130 5cdb1798 2005-10-29 devnull /*
131 5cdb1798 2005-10-29 devnull * Protect against shell characters in the sender name for
132 5cdb1798 2005-10-29 devnull * security reasons.
133 5cdb1798 2005-10-29 devnull */
134 5cdb1798 2005-10-29 devnull mp->sender = escapespecial(mp->sender);
135 5cdb1798 2005-10-29 devnull if (shellchars(s_to_c(mp->sender)))
136 5cdb1798 2005-10-29 devnull mp->replyaddr = s_copy("postmaster");
137 5cdb1798 2005-10-29 devnull else
138 5cdb1798 2005-10-29 devnull mp->replyaddr = s_clone(mp->sender);
139 5cdb1798 2005-10-29 devnull
140 5cdb1798 2005-10-29 devnull /*
141 5cdb1798 2005-10-29 devnull * reject messages that have been looping for too long
142 5cdb1798 2005-10-29 devnull */
143 5cdb1798 2005-10-29 devnull if(mp->received > 32)
144 5cdb1798 2005-10-29 devnull exit(refuse(dp, mp, "possible forward loop", 0, 0));
145 5cdb1798 2005-10-29 devnull
146 5cdb1798 2005-10-29 devnull /*
147 5cdb1798 2005-10-29 devnull * reject messages that are too long. We don't do it earlier
148 5cdb1798 2005-10-29 devnull * in m_read since we haven't set up enough things yet.
149 5cdb1798 2005-10-29 devnull */
150 5cdb1798 2005-10-29 devnull if(mp->size < 0)
151 5cdb1798 2005-10-29 devnull exit(refuse(dp, mp, "message too long", 0, 0));
152 5cdb1798 2005-10-29 devnull
153 5cdb1798 2005-10-29 devnull rv = send(dp, mp, checkforward);
154 5cdb1798 2005-10-29 devnull if(savemail)
155 5cdb1798 2005-10-29 devnull save_mail(mp);
156 5cdb1798 2005-10-29 devnull if(mp)
157 5cdb1798 2005-10-29 devnull m_free(mp);
158 5cdb1798 2005-10-29 devnull exit(rv);
159 5cdb1798 2005-10-29 devnull }
160 5cdb1798 2005-10-29 devnull
161 5cdb1798 2005-10-29 devnull /* send a message to a list of sites */
162 5cdb1798 2005-10-29 devnull static int
163 5cdb1798 2005-10-29 devnull send(dest *destp, message *mp, int checkforward)
164 5cdb1798 2005-10-29 devnull {
165 5cdb1798 2005-10-29 devnull dest *dp; /* destination being acted upon */
166 5cdb1798 2005-10-29 devnull dest *bound; /* bound destinations */
167 5cdb1798 2005-10-29 devnull int errors=0;
168 5cdb1798 2005-10-29 devnull
169 5cdb1798 2005-10-29 devnull /* bind the destinations to actions */
170 5cdb1798 2005-10-29 devnull bound = up_bind(destp, mp, checkforward);
171 5cdb1798 2005-10-29 devnull if(add822headers && mp->haveto == 0){
172 5cdb1798 2005-10-29 devnull if(nosummary)
173 5cdb1798 2005-10-29 devnull mp->to = d_to(bound);
174 5cdb1798 2005-10-29 devnull else
175 5cdb1798 2005-10-29 devnull mp->to = arglist;
176 5cdb1798 2005-10-29 devnull }
177 5cdb1798 2005-10-29 devnull
178 5cdb1798 2005-10-29 devnull /* loop through and execute commands */
179 5cdb1798 2005-10-29 devnull for (dp = d_rm(&bound); dp != 0; dp = d_rm(&bound)) {
180 5cdb1798 2005-10-29 devnull switch (dp->status) {
181 5cdb1798 2005-10-29 devnull case d_cat:
182 5cdb1798 2005-10-29 devnull errors += cat_mail(dp, mp);
183 5cdb1798 2005-10-29 devnull break;
184 5cdb1798 2005-10-29 devnull case d_pipeto:
185 5cdb1798 2005-10-29 devnull case d_pipe:
186 5cdb1798 2005-10-29 devnull if (!rmail && !nflg && !forked) {
187 5cdb1798 2005-10-29 devnull forked = 1;
188 5cdb1798 2005-10-29 devnull lesstedious();
189 5cdb1798 2005-10-29 devnull }
190 5cdb1798 2005-10-29 devnull errors += pipe_mail(dp, mp);
191 5cdb1798 2005-10-29 devnull break;
192 5cdb1798 2005-10-29 devnull default:
193 5cdb1798 2005-10-29 devnull errors += complain_mail(dp, mp);
194 5cdb1798 2005-10-29 devnull break;
195 5cdb1798 2005-10-29 devnull }
196 5cdb1798 2005-10-29 devnull }
197 5cdb1798 2005-10-29 devnull
198 5cdb1798 2005-10-29 devnull return errors;
199 5cdb1798 2005-10-29 devnull }
200 5cdb1798 2005-10-29 devnull
201 5cdb1798 2005-10-29 devnull /* avoid user tedium (as Mike Lesk said in a previous version) */
202 5cdb1798 2005-10-29 devnull static void
203 5cdb1798 2005-10-29 devnull lesstedious(void)
204 5cdb1798 2005-10-29 devnull {
205 5cdb1798 2005-10-29 devnull int i;
206 5cdb1798 2005-10-29 devnull
207 5cdb1798 2005-10-29 devnull if(debug)
208 5cdb1798 2005-10-29 devnull return;
209 5cdb1798 2005-10-29 devnull
210 5cdb1798 2005-10-29 devnull switch(fork()){
211 5cdb1798 2005-10-29 devnull case -1:
212 5cdb1798 2005-10-29 devnull break;
213 5cdb1798 2005-10-29 devnull case 0:
214 5cdb1798 2005-10-29 devnull sysdetach();
215 5cdb1798 2005-10-29 devnull for(i=0; i<3; i++)
216 5cdb1798 2005-10-29 devnull close(i);
217 5cdb1798 2005-10-29 devnull savemail = 0;
218 5cdb1798 2005-10-29 devnull break;
219 5cdb1798 2005-10-29 devnull default:
220 5cdb1798 2005-10-29 devnull exit(0);
221 5cdb1798 2005-10-29 devnull }
222 5cdb1798 2005-10-29 devnull }
223 5cdb1798 2005-10-29 devnull
224 5cdb1798 2005-10-29 devnull
225 5cdb1798 2005-10-29 devnull /* save the mail */
226 5cdb1798 2005-10-29 devnull static void
227 5cdb1798 2005-10-29 devnull save_mail(message *mp)
228 5cdb1798 2005-10-29 devnull {
229 5cdb1798 2005-10-29 devnull Biobuf *fp;
230 5cdb1798 2005-10-29 devnull String *file;
231 5cdb1798 2005-10-29 devnull
232 5cdb1798 2005-10-29 devnull file = s_new();
233 5cdb1798 2005-10-29 devnull deadletter(file);
234 5cdb1798 2005-10-29 devnull fp = sysopen(s_to_c(file), "cAt", 0660);
235 5cdb1798 2005-10-29 devnull if (fp == 0)
236 5cdb1798 2005-10-29 devnull return;
237 5cdb1798 2005-10-29 devnull m_bprint(mp, fp);
238 5cdb1798 2005-10-29 devnull sysclose(fp);
239 5cdb1798 2005-10-29 devnull fprint(2, "saved in %s\n", s_to_c(file));
240 5cdb1798 2005-10-29 devnull s_free(file);
241 5cdb1798 2005-10-29 devnull }
242 5cdb1798 2005-10-29 devnull
243 5cdb1798 2005-10-29 devnull /* remember the interrupt happened */
244 5cdb1798 2005-10-29 devnull
245 5cdb1798 2005-10-29 devnull static int
246 5cdb1798 2005-10-29 devnull catchint(void *a, char *msg)
247 5cdb1798 2005-10-29 devnull {
248 5cdb1798 2005-10-29 devnull USED(a);
249 5cdb1798 2005-10-29 devnull if(strstr(msg, "interrupt") || strstr(msg, "hangup")) {
250 5cdb1798 2005-10-29 devnull interrupt = 1;
251 5cdb1798 2005-10-29 devnull return 1;
252 5cdb1798 2005-10-29 devnull }
253 5cdb1798 2005-10-29 devnull return 0;
254 5cdb1798 2005-10-29 devnull }
255 5cdb1798 2005-10-29 devnull
256 5cdb1798 2005-10-29 devnull /* dispose of incorrect addresses */
257 5cdb1798 2005-10-29 devnull static int
258 5cdb1798 2005-10-29 devnull complain_mail(dest *dp, message *mp)
259 5cdb1798 2005-10-29 devnull {
260 5cdb1798 2005-10-29 devnull char *msg;
261 5cdb1798 2005-10-29 devnull
262 5cdb1798 2005-10-29 devnull switch (dp->status) {
263 5cdb1798 2005-10-29 devnull case d_undefined:
264 5cdb1798 2005-10-29 devnull msg = "Invalid address"; /* a little different, for debugging */
265 5cdb1798 2005-10-29 devnull break;
266 5cdb1798 2005-10-29 devnull case d_syntax:
267 5cdb1798 2005-10-29 devnull msg = "invalid address";
268 5cdb1798 2005-10-29 devnull break;
269 5cdb1798 2005-10-29 devnull case d_unknown:
270 5cdb1798 2005-10-29 devnull msg = "unknown user";
271 5cdb1798 2005-10-29 devnull break;
272 5cdb1798 2005-10-29 devnull case d_eloop:
273 5cdb1798 2005-10-29 devnull case d_loop:
274 5cdb1798 2005-10-29 devnull msg = "forwarding loop";
275 5cdb1798 2005-10-29 devnull break;
276 5cdb1798 2005-10-29 devnull case d_noforward:
277 5cdb1798 2005-10-29 devnull if(dp->pstat && *s_to_c(dp->repl2))
278 5cdb1798 2005-10-29 devnull return refuse(dp, mp, s_to_c(dp->repl2), dp->pstat, 0);
279 5cdb1798 2005-10-29 devnull else
280 5cdb1798 2005-10-29 devnull msg = "destination unknown or forwarding disallowed";
281 5cdb1798 2005-10-29 devnull break;
282 5cdb1798 2005-10-29 devnull case d_pipe:
283 5cdb1798 2005-10-29 devnull msg = "broken pipe";
284 5cdb1798 2005-10-29 devnull break;
285 5cdb1798 2005-10-29 devnull case d_cat:
286 5cdb1798 2005-10-29 devnull msg = "broken cat";
287 5cdb1798 2005-10-29 devnull break;
288 5cdb1798 2005-10-29 devnull case d_translate:
289 5cdb1798 2005-10-29 devnull if(dp->pstat && *s_to_c(dp->repl2))
290 5cdb1798 2005-10-29 devnull return refuse(dp, mp, s_to_c(dp->repl2), dp->pstat, 0);
291 5cdb1798 2005-10-29 devnull else
292 5cdb1798 2005-10-29 devnull msg = "name translation failed";
293 5cdb1798 2005-10-29 devnull break;
294 5cdb1798 2005-10-29 devnull case d_alias:
295 5cdb1798 2005-10-29 devnull msg = "broken alias";
296 5cdb1798 2005-10-29 devnull break;
297 5cdb1798 2005-10-29 devnull case d_badmbox:
298 5cdb1798 2005-10-29 devnull msg = "corrupted mailbox";
299 5cdb1798 2005-10-29 devnull break;
300 5cdb1798 2005-10-29 devnull case d_resource:
301 5cdb1798 2005-10-29 devnull return refuse(dp, mp, "out of some resource. Try again later.", 0, 1);
302 5cdb1798 2005-10-29 devnull default:
303 5cdb1798 2005-10-29 devnull msg = "unknown d_";
304 5cdb1798 2005-10-29 devnull break;
305 5cdb1798 2005-10-29 devnull }
306 5cdb1798 2005-10-29 devnull if (nflg) {
307 5cdb1798 2005-10-29 devnull print("%s: %s\n", msg, s_to_c(dp->addr));
308 5cdb1798 2005-10-29 devnull return 0;
309 5cdb1798 2005-10-29 devnull }
310 5cdb1798 2005-10-29 devnull return refuse(dp, mp, msg, 0, 0);
311 5cdb1798 2005-10-29 devnull }
312 5cdb1798 2005-10-29 devnull
313 5cdb1798 2005-10-29 devnull /* dispose of remote addresses */
314 5cdb1798 2005-10-29 devnull static int
315 5cdb1798 2005-10-29 devnull pipe_mail(dest *dp, message *mp)
316 5cdb1798 2005-10-29 devnull {
317 5cdb1798 2005-10-29 devnull dest *next, *list=0;
318 5cdb1798 2005-10-29 devnull String *cmd;
319 5cdb1798 2005-10-29 devnull process *pp;
320 5cdb1798 2005-10-29 devnull int status;
321 5cdb1798 2005-10-29 devnull char *none;
322 5cdb1798 2005-10-29 devnull String *errstring=s_new();
323 5cdb1798 2005-10-29 devnull
324 5cdb1798 2005-10-29 devnull if (dp->status == d_pipeto)
325 5cdb1798 2005-10-29 devnull none = "none";
326 5cdb1798 2005-10-29 devnull else
327 5cdb1798 2005-10-29 devnull none = 0;
328 5cdb1798 2005-10-29 devnull /*
329 5cdb1798 2005-10-29 devnull * collect the arguments
330 5cdb1798 2005-10-29 devnull */
331 5cdb1798 2005-10-29 devnull next = d_rm_same(&dp);
332 5cdb1798 2005-10-29 devnull if(xflg)
333 5cdb1798 2005-10-29 devnull cmd = s_new();
334 5cdb1798 2005-10-29 devnull else
335 5cdb1798 2005-10-29 devnull cmd = s_clone(next->repl1);
336 5cdb1798 2005-10-29 devnull for(; next != 0; next = d_rm_same(&dp)){
337 5cdb1798 2005-10-29 devnull if(xflg){
338 5cdb1798 2005-10-29 devnull s_append(cmd, s_to_c(next->addr));
339 5cdb1798 2005-10-29 devnull s_append(cmd, "\n");
340 5cdb1798 2005-10-29 devnull } else {
341 5cdb1798 2005-10-29 devnull if (next->repl2 != 0) {
342 5cdb1798 2005-10-29 devnull s_append(cmd, " ");
343 5cdb1798 2005-10-29 devnull s_append(cmd, s_to_c(next->repl2));
344 5cdb1798 2005-10-29 devnull }
345 5cdb1798 2005-10-29 devnull }
346 5cdb1798 2005-10-29 devnull d_insert(&list, next);
347 5cdb1798 2005-10-29 devnull }
348 5cdb1798 2005-10-29 devnull
349 5cdb1798 2005-10-29 devnull if (nflg) {
350 5cdb1798 2005-10-29 devnull if(xflg)
351 5cdb1798 2005-10-29 devnull print("%s", s_to_c(cmd));
352 5cdb1798 2005-10-29 devnull else
353 5cdb1798 2005-10-29 devnull print("%s\n", s_to_c(cmd));
354 5cdb1798 2005-10-29 devnull s_free(cmd);
355 5cdb1798 2005-10-29 devnull return 0;
356 5cdb1798 2005-10-29 devnull }
357 5cdb1798 2005-10-29 devnull
358 5cdb1798 2005-10-29 devnull /*
359 5cdb1798 2005-10-29 devnull * run the process
360 5cdb1798 2005-10-29 devnull */
361 5cdb1798 2005-10-29 devnull pp = proc_start(s_to_c(cmd), instream(), 0, outstream(), 1, none);
362 5cdb1798 2005-10-29 devnull if(pp==0 || pp->std[0]==0 || pp->std[2]==0)
363 5cdb1798 2005-10-29 devnull return refuse(list, mp, "out of processes, pipes, or memory", 0, 1);
364 5cdb1798 2005-10-29 devnull pipesig(0);
365 5cdb1798 2005-10-29 devnull m_print(mp, pp->std[0]->fp, thissys, 0);
366 5cdb1798 2005-10-29 devnull pipesigoff();
367 5cdb1798 2005-10-29 devnull stream_free(pp->std[0]);
368 5cdb1798 2005-10-29 devnull pp->std[0] = 0;
369 5cdb1798 2005-10-29 devnull while(s_read_line(pp->std[2]->fp, errstring))
370 5cdb1798 2005-10-29 devnull ;
371 5cdb1798 2005-10-29 devnull status = proc_wait(pp);
372 5cdb1798 2005-10-29 devnull proc_free(pp);
373 5cdb1798 2005-10-29 devnull s_free(cmd);
374 5cdb1798 2005-10-29 devnull
375 5cdb1798 2005-10-29 devnull /*
376 5cdb1798 2005-10-29 devnull * return status
377 5cdb1798 2005-10-29 devnull */
378 5cdb1798 2005-10-29 devnull if (status != 0)
379 5cdb1798 2005-10-29 devnull return refuse(list, mp, s_to_c(errstring), status, 0);
380 5cdb1798 2005-10-29 devnull loglist(list, mp, "remote");
381 5cdb1798 2005-10-29 devnull return 0;
382 5cdb1798 2005-10-29 devnull }
383 5cdb1798 2005-10-29 devnull
384 5cdb1798 2005-10-29 devnull static void
385 5cdb1798 2005-10-29 devnull appaddr(String *sp, dest *dp)
386 5cdb1798 2005-10-29 devnull {
387 5cdb1798 2005-10-29 devnull dest *parent;
388 5cdb1798 2005-10-29 devnull String *s;
389 5cdb1798 2005-10-29 devnull
390 5cdb1798 2005-10-29 devnull if (dp->parent != 0) {
391 5cdb1798 2005-10-29 devnull for(parent=dp->parent; parent->parent!=0; parent=parent->parent)
392 5cdb1798 2005-10-29 devnull ;
393 5cdb1798 2005-10-29 devnull s = unescapespecial(s_clone(parent->addr));
394 5cdb1798 2005-10-29 devnull s_append(sp, s_to_c(s));
395 5cdb1798 2005-10-29 devnull s_free(s);
396 5cdb1798 2005-10-29 devnull s_append(sp, "' alias `");
397 5cdb1798 2005-10-29 devnull }
398 5cdb1798 2005-10-29 devnull s = unescapespecial(s_clone(dp->addr));
399 5cdb1798 2005-10-29 devnull s_append(sp, s_to_c(s));
400 5cdb1798 2005-10-29 devnull s_free(s);
401 5cdb1798 2005-10-29 devnull }
402 5cdb1798 2005-10-29 devnull
403 5cdb1798 2005-10-29 devnull /*
404 5cdb1798 2005-10-29 devnull * reject delivery
405 5cdb1798 2005-10-29 devnull *
406 5cdb1798 2005-10-29 devnull * returns 0 - if mail has been disposed of
407 5cdb1798 2005-10-29 devnull * other - if mail has not been disposed
408 5cdb1798 2005-10-29 devnull */
409 5cdb1798 2005-10-29 devnull int
410 5cdb1798 2005-10-29 devnull refuse(dest *list, message *mp, char *cp, int status, int outofresources)
411 5cdb1798 2005-10-29 devnull {
412 5cdb1798 2005-10-29 devnull String *errstring=s_new();
413 5cdb1798 2005-10-29 devnull dest *dp;
414 5cdb1798 2005-10-29 devnull int rv;
415 5cdb1798 2005-10-29 devnull
416 5cdb1798 2005-10-29 devnull dp = d_rm(&list);
417 5cdb1798 2005-10-29 devnull mkerrstring(errstring, mp, dp, list, cp, status);
418 5cdb1798 2005-10-29 devnull
419 5cdb1798 2005-10-29 devnull /*
420 5cdb1798 2005-10-29 devnull * log first in case we get into trouble
421 5cdb1798 2005-10-29 devnull */
422 5cdb1798 2005-10-29 devnull logrefusal(dp, mp, s_to_c(errstring));
423 5cdb1798 2005-10-29 devnull
424 5cdb1798 2005-10-29 devnull /*
425 5cdb1798 2005-10-29 devnull * bulk mail is never replied to, if we're out of resources,
426 5cdb1798 2005-10-29 devnull * let the sender try again
427 5cdb1798 2005-10-29 devnull */
428 5cdb1798 2005-10-29 devnull if(rmail){
429 5cdb1798 2005-10-29 devnull /* accept it or request a retry */
430 5cdb1798 2005-10-29 devnull if(outofresources){
431 5cdb1798 2005-10-29 devnull fprint(2, "Mail %s\n", s_to_c(errstring));
432 5cdb1798 2005-10-29 devnull rv = 1; /* try again later */
433 5cdb1798 2005-10-29 devnull } else if(mp->bulk)
434 5cdb1798 2005-10-29 devnull rv = 0; /* silently discard bulk */
435 5cdb1798 2005-10-29 devnull else
436 5cdb1798 2005-10-29 devnull rv = replymsg(errstring, mp, dp); /* try later if we can't reply */
437 5cdb1798 2005-10-29 devnull } else {
438 5cdb1798 2005-10-29 devnull /* aysnchronous delivery only happens if !rmail */
439 5cdb1798 2005-10-29 devnull if(forked){
440 5cdb1798 2005-10-29 devnull /*
441 5cdb1798 2005-10-29 devnull * if spun off for asynchronous delivery, we own the mail now.
442 5cdb1798 2005-10-29 devnull * return it or dump it on the floor. rv really doesn't matter.
443 5cdb1798 2005-10-29 devnull */
444 5cdb1798 2005-10-29 devnull rv = 0;
445 5cdb1798 2005-10-29 devnull if(!outofresources && !mp->bulk)
446 5cdb1798 2005-10-29 devnull replymsg(errstring, mp, dp);
447 5cdb1798 2005-10-29 devnull } else {
448 5cdb1798 2005-10-29 devnull fprint(2, "Mail %s\n", s_to_c(errstring));
449 5cdb1798 2005-10-29 devnull savemail = 1;
450 5cdb1798 2005-10-29 devnull rv = 1;
451 5cdb1798 2005-10-29 devnull }
452 5cdb1798 2005-10-29 devnull }
453 5cdb1798 2005-10-29 devnull
454 5cdb1798 2005-10-29 devnull s_free(errstring);
455 5cdb1798 2005-10-29 devnull return rv;
456 5cdb1798 2005-10-29 devnull }
457 5cdb1798 2005-10-29 devnull
458 5cdb1798 2005-10-29 devnull /* make the error message */
459 5cdb1798 2005-10-29 devnull static void
460 5cdb1798 2005-10-29 devnull mkerrstring(String *errstring, message *mp, dest *dp, dest *list, char *cp, int status)
461 5cdb1798 2005-10-29 devnull {
462 5cdb1798 2005-10-29 devnull dest *next;
463 5cdb1798 2005-10-29 devnull char smsg[64];
464 5cdb1798 2005-10-29 devnull String *sender;
465 5cdb1798 2005-10-29 devnull
466 5cdb1798 2005-10-29 devnull sender = unescapespecial(s_clone(mp->sender));
467 5cdb1798 2005-10-29 devnull
468 5cdb1798 2005-10-29 devnull /* list all aliases */
469 5cdb1798 2005-10-29 devnull s_append(errstring, " from '");
470 5cdb1798 2005-10-29 devnull s_append(errstring, s_to_c(sender));
471 5cdb1798 2005-10-29 devnull s_append(errstring, "'\nto '");
472 5cdb1798 2005-10-29 devnull appaddr(errstring, dp);
473 5cdb1798 2005-10-29 devnull for(next = d_rm(&list); next != 0; next = d_rm(&list)) {
474 5cdb1798 2005-10-29 devnull s_append(errstring, "'\nand '");
475 5cdb1798 2005-10-29 devnull appaddr(errstring, next);
476 5cdb1798 2005-10-29 devnull d_insert(&dp, next);
477 5cdb1798 2005-10-29 devnull }
478 5cdb1798 2005-10-29 devnull s_append(errstring, "'\nfailed with error '");
479 5cdb1798 2005-10-29 devnull s_append(errstring, cp);
480 5cdb1798 2005-10-29 devnull s_append(errstring, "'.\n");
481 5cdb1798 2005-10-29 devnull
482 5cdb1798 2005-10-29 devnull /* >> and | deserve different flavored messages */
483 5cdb1798 2005-10-29 devnull switch(dp->status) {
484 5cdb1798 2005-10-29 devnull case d_pipe:
485 5cdb1798 2005-10-29 devnull s_append(errstring, "The mailer `");
486 5cdb1798 2005-10-29 devnull s_append(errstring, s_to_c(dp->repl1));
487 5cdb1798 2005-10-29 devnull sprint(smsg, "' returned error status %x.\n\n", status);
488 5cdb1798 2005-10-29 devnull s_append(errstring, smsg);
489 5cdb1798 2005-10-29 devnull break;
490 5cdb1798 2005-10-29 devnull }
491 5cdb1798 2005-10-29 devnull
492 5cdb1798 2005-10-29 devnull s_free(sender);
493 5cdb1798 2005-10-29 devnull }
494 5cdb1798 2005-10-29 devnull
495 5cdb1798 2005-10-29 devnull /*
496 5cdb1798 2005-10-29 devnull * create a new boundary
497 5cdb1798 2005-10-29 devnull */
498 5cdb1798 2005-10-29 devnull static String*
499 5cdb1798 2005-10-29 devnull mkboundary(void)
500 5cdb1798 2005-10-29 devnull {
501 5cdb1798 2005-10-29 devnull char buf[32];
502 5cdb1798 2005-10-29 devnull int i;
503 5cdb1798 2005-10-29 devnull static int already;
504 5cdb1798 2005-10-29 devnull
505 5cdb1798 2005-10-29 devnull if(already == 0){
506 5cdb1798 2005-10-29 devnull srand((time(0)<<16)|getpid());
507 5cdb1798 2005-10-29 devnull already = 1;
508 5cdb1798 2005-10-29 devnull }
509 5cdb1798 2005-10-29 devnull strcpy(buf, "upas-");
510 5cdb1798 2005-10-29 devnull for(i = 5; i < sizeof(buf)-1; i++)
511 5cdb1798 2005-10-29 devnull buf[i] = 'a' + nrand(26);
512 5cdb1798 2005-10-29 devnull buf[i] = 0;
513 5cdb1798 2005-10-29 devnull return s_copy(buf);
514 5cdb1798 2005-10-29 devnull }
515 5cdb1798 2005-10-29 devnull
516 5cdb1798 2005-10-29 devnull /*
517 5cdb1798 2005-10-29 devnull * reply with up to 1024 characters of the
518 5cdb1798 2005-10-29 devnull * original message
519 5cdb1798 2005-10-29 devnull */
520 5cdb1798 2005-10-29 devnull static int
521 5cdb1798 2005-10-29 devnull replymsg(String *errstring, message *mp, dest *dp)
522 5cdb1798 2005-10-29 devnull {
523 5cdb1798 2005-10-29 devnull message *refp = m_new();
524 5cdb1798 2005-10-29 devnull dest *ndp;
525 5cdb1798 2005-10-29 devnull char *rcvr;
526 5cdb1798 2005-10-29 devnull int rv;
527 5cdb1798 2005-10-29 devnull String *boundary;
528 5cdb1798 2005-10-29 devnull
529 5cdb1798 2005-10-29 devnull boundary = mkboundary();
530 5cdb1798 2005-10-29 devnull
531 5cdb1798 2005-10-29 devnull refp->bulk = 1;
532 5cdb1798 2005-10-29 devnull refp->rfc822headers = 1;
533 5cdb1798 2005-10-29 devnull rcvr = dp->status==d_eloop ? "postmaster" : s_to_c(mp->replyaddr);
534 5cdb1798 2005-10-29 devnull ndp = d_new(s_copy(rcvr));
535 5cdb1798 2005-10-29 devnull s_append(refp->sender, "postmaster");
536 5cdb1798 2005-10-29 devnull s_append(refp->replyaddr, "/dev/null");
537 5cdb1798 2005-10-29 devnull s_append(refp->date, thedate());
538 5cdb1798 2005-10-29 devnull refp->haveto = 1;
539 5cdb1798 2005-10-29 devnull s_append(refp->body, "To: ");
540 5cdb1798 2005-10-29 devnull s_append(refp->body, rcvr);
541 5cdb1798 2005-10-29 devnull s_append(refp->body, "\n");
542 5cdb1798 2005-10-29 devnull s_append(refp->body, "Subject: bounced mail\n");
543 5cdb1798 2005-10-29 devnull s_append(refp->body, "MIME-Version: 1.0\n");
544 5cdb1798 2005-10-29 devnull s_append(refp->body, "Content-Type: multipart/mixed;\n");
545 5cdb1798 2005-10-29 devnull s_append(refp->body, "\tboundary=\"");
546 5cdb1798 2005-10-29 devnull s_append(refp->body, s_to_c(boundary));
547 5cdb1798 2005-10-29 devnull s_append(refp->body, "\"\n");
548 5cdb1798 2005-10-29 devnull s_append(refp->body, "Content-Disposition: inline\n");
549 5cdb1798 2005-10-29 devnull s_append(refp->body, "\n");
550 5cdb1798 2005-10-29 devnull s_append(refp->body, "This is a multi-part message in MIME format.\n");
551 5cdb1798 2005-10-29 devnull s_append(refp->body, "--");
552 5cdb1798 2005-10-29 devnull s_append(refp->body, s_to_c(boundary));
553 5cdb1798 2005-10-29 devnull s_append(refp->body, "\n");
554 5cdb1798 2005-10-29 devnull s_append(refp->body, "Content-Disposition: inline\n");
555 5cdb1798 2005-10-29 devnull s_append(refp->body, "Content-Type: text/plain; charset=\"US-ASCII\"\n");
556 5cdb1798 2005-10-29 devnull s_append(refp->body, "Content-Transfer-Encoding: 7bit\n");
557 5cdb1798 2005-10-29 devnull s_append(refp->body, "\n");
558 5cdb1798 2005-10-29 devnull s_append(refp->body, "The attached mail");
559 5cdb1798 2005-10-29 devnull s_append(refp->body, s_to_c(errstring));
560 5cdb1798 2005-10-29 devnull s_append(refp->body, "--");
561 5cdb1798 2005-10-29 devnull s_append(refp->body, s_to_c(boundary));
562 5cdb1798 2005-10-29 devnull s_append(refp->body, "\n");
563 5cdb1798 2005-10-29 devnull s_append(refp->body, "Content-Type: message/rfc822\n");
564 5cdb1798 2005-10-29 devnull s_append(refp->body, "Content-Disposition: inline\n\n");
565 5cdb1798 2005-10-29 devnull s_append(refp->body, s_to_c(mp->body));
566 5cdb1798 2005-10-29 devnull s_append(refp->body, "--");
567 5cdb1798 2005-10-29 devnull s_append(refp->body, s_to_c(boundary));
568 5cdb1798 2005-10-29 devnull s_append(refp->body, "--\n");
569 5cdb1798 2005-10-29 devnull
570 5cdb1798 2005-10-29 devnull refp->size = s_len(refp->body);
571 5cdb1798 2005-10-29 devnull rv = send(ndp, refp, 0);
572 5cdb1798 2005-10-29 devnull m_free(refp);
573 5cdb1798 2005-10-29 devnull d_free(ndp);
574 5cdb1798 2005-10-29 devnull return rv;
575 5cdb1798 2005-10-29 devnull }