|
1 #include <sys/types.h> |
|
2 #include <sys/stat.h> |
|
3 #include "readwrite.h" |
|
4 #include "sig.h" |
|
5 #include "env.h" |
|
6 #include "byte.h" |
|
7 #include "exit.h" |
|
8 #include "fork.h" |
|
9 #include "open.h" |
|
10 #include "wait.h" |
|
11 #include "lock.h" |
|
12 #include "seek.h" |
|
13 #include "substdio.h" |
|
14 #include "getln.h" |
|
15 #include "strerr.h" |
|
16 #include "subfd.h" |
|
17 #include "sgetopt.h" |
|
18 #include "alloc.h" |
|
19 #include "error.h" |
|
20 #include "stralloc.h" |
|
21 #include "fmt.h" |
|
22 #include "str.h" |
|
23 #include "now.h" |
|
24 #include "case.h" |
|
25 #include "quote.h" |
|
26 #include "qmail.h" |
|
27 #include "slurpclose.h" |
|
28 #include "myctime.h" |
|
29 #include "gfrom.h" |
|
30 #include "auto_patrn.h" |
|
31 |
|
32 void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); } |
|
33 |
|
34 void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); } |
|
35 void temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); } |
|
36 void temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); } |
|
37 void temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); } |
|
38 void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); } |
|
39 void temp_slowlock() |
|
40 { strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); } |
|
41 void temp_qmail(fn) char *fn; |
|
42 { strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); } |
|
43 |
|
44 int flagdoit; |
|
45 int flag99; |
|
46 |
|
47 char *user; |
|
48 char *homedir; |
|
49 char *local; |
|
50 char *dash; |
|
51 char *ext; |
|
52 char *host; |
|
53 char *sender; |
|
54 char *aliasempty; |
|
55 |
|
56 stralloc safeext = {0}; |
|
57 stralloc ufline = {0}; |
|
58 stralloc rpline = {0}; |
|
59 stralloc envrecip = {0}; |
|
60 stralloc dtline = {0}; |
|
61 stralloc qme = {0}; |
|
62 stralloc ueo = {0}; |
|
63 stralloc cmds = {0}; |
|
64 stralloc messline = {0}; |
|
65 stralloc foo = {0}; |
|
66 |
|
67 char buf[1024]; |
|
68 char outbuf[1024]; |
|
69 |
|
70 /* child process */ |
|
71 |
|
72 char fntmptph[80 + FMT_ULONG * 2]; |
|
73 char fnnewtph[80 + FMT_ULONG * 2]; |
|
74 void tryunlinktmp() { unlink(fntmptph); } |
|
75 void sigalrm() { tryunlinktmp(); _exit(3); } |
|
76 |
|
77 void maildir_child(dir) |
|
78 char *dir; |
|
79 { |
|
80 unsigned long pid; |
|
81 unsigned long time; |
|
82 char host[64]; |
|
83 char *s; |
|
84 int loop; |
|
85 struct stat st; |
|
86 int fd; |
|
87 substdio ss; |
|
88 substdio ssout; |
|
89 |
|
90 sig_alarmcatch(sigalrm); |
|
91 if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); } |
|
92 pid = getpid(); |
|
93 host[0] = 0; |
|
94 gethostname(host,sizeof(host)); |
|
95 for (loop = 0;;++loop) |
|
96 { |
|
97 time = now(); |
|
98 s = fntmptph; |
|
99 s += fmt_str(s,"tmp/"); |
|
100 s += fmt_ulong(s,time); *s++ = '.'; |
|
101 s += fmt_ulong(s,pid); *s++ = '.'; |
|
102 s += fmt_strn(s,host,sizeof(host)); *s++ = 0; |
|
103 if (stat(fntmptph,&st) == -1) if (errno == error_noent) break; |
|
104 /* really should never get to this point */ |
|
105 if (loop == 2) _exit(1); |
|
106 sleep(2); |
|
107 } |
|
108 str_copy(fnnewtph,fntmptph); |
|
109 byte_copy(fnnewtph,3,"new"); |
|
110 |
|
111 alarm(86400); |
|
112 fd = open_excl(fntmptph); |
|
113 if (fd == -1) _exit(1); |
|
114 |
|
115 substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); |
|
116 substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); |
|
117 if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail; |
|
118 if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail; |
|
119 |
|
120 switch(substdio_copy(&ssout,&ss)) |
|
121 { |
|
122 case -2: tryunlinktmp(); _exit(4); |
|
123 case -3: goto fail; |
|
124 } |
|
125 |
|
126 if (substdio_flush(&ssout) == -1) goto fail; |
|
127 if (fsync(fd) == -1) goto fail; |
|
128 if (close(fd) == -1) goto fail; /* NFS dorks */ |
|
129 |
|
130 if (link(fntmptph,fnnewtph) == -1) goto fail; |
|
131 /* if it was error_exist, almost certainly successful; i hate NFS */ |
|
132 tryunlinktmp(); _exit(0); |
|
133 |
|
134 fail: tryunlinktmp(); _exit(1); |
|
135 } |
|
136 |
|
137 /* end child process */ |
|
138 |
|
139 void maildir(fn) |
|
140 char *fn; |
|
141 { |
|
142 int child; |
|
143 int wstat; |
|
144 |
|
145 if (seek_begin(0) == -1) temp_rewind(); |
|
146 |
|
147 switch(child = fork()) |
|
148 { |
|
149 case -1: |
|
150 temp_fork(); |
|
151 case 0: |
|
152 maildir_child(fn); |
|
153 _exit(111); |
|
154 } |
|
155 |
|
156 wait_pid(&wstat,child); |
|
157 if (wait_crashed(wstat)) |
|
158 temp_childcrashed(); |
|
159 switch(wait_exitcode(wstat)) |
|
160 { |
|
161 case 0: break; |
|
162 case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)"); |
|
163 case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)"); |
|
164 case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)"); |
|
165 default: strerr_die1x(111,"Temporary error on maildir delivery. (#4.3.0)"); |
|
166 } |
|
167 } |
|
168 |
|
169 void mailfile(fn) |
|
170 char *fn; |
|
171 { |
|
172 int fd; |
|
173 substdio ss; |
|
174 substdio ssout; |
|
175 int match; |
|
176 seek_pos pos; |
|
177 int flaglocked; |
|
178 |
|
179 if (seek_begin(0) == -1) temp_rewind(); |
|
180 |
|
181 fd = open_append(fn); |
|
182 if (fd == -1) |
|
183 strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.2.1)"); |
|
184 |
|
185 sig_alarmcatch(temp_slowlock); |
|
186 alarm(30); |
|
187 flaglocked = (lock_ex(fd) != -1); |
|
188 alarm(0); |
|
189 sig_alarmdefault(); |
|
190 |
|
191 seek_end(fd); |
|
192 pos = seek_cur(fd); |
|
193 |
|
194 substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); |
|
195 substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); |
|
196 if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs; |
|
197 if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs; |
|
198 if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs; |
|
199 for (;;) |
|
200 { |
|
201 if (getln(&ss,&messline,&match,'\n') != 0) |
|
202 { |
|
203 strerr_warn3("Unable to read message: ",error_str(errno),". (#4.3.0)",0); |
|
204 if (flaglocked) seek_trunc(fd,pos); close(fd); |
|
205 _exit(111); |
|
206 } |
|
207 if (!match && !messline.len) break; |
|
208 if (gfrom(messline.s,messline.len)) |
|
209 if (substdio_bput(&ssout,">",1)) goto writeerrs; |
|
210 if (substdio_bput(&ssout,messline.s,messline.len)) goto writeerrs; |
|
211 if (!match) |
|
212 { |
|
213 if (substdio_bputs(&ssout,"\n")) goto writeerrs; |
|
214 break; |
|
215 } |
|
216 } |
|
217 if (substdio_bputs(&ssout,"\n")) goto writeerrs; |
|
218 if (substdio_flush(&ssout)) goto writeerrs; |
|
219 if (fsync(fd) == -1) goto writeerrs; |
|
220 close(fd); |
|
221 return; |
|
222 |
|
223 writeerrs: |
|
224 strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0); |
|
225 if (flaglocked) seek_trunc(fd,pos); |
|
226 close(fd); |
|
227 _exit(111); |
|
228 } |
|
229 |
|
230 void mailprogram(prog) |
|
231 char *prog; |
|
232 { |
|
233 int child; |
|
234 char *(args[4]); |
|
235 int wstat; |
|
236 |
|
237 if (seek_begin(0) == -1) temp_rewind(); |
|
238 |
|
239 switch(child = fork()) |
|
240 { |
|
241 case -1: |
|
242 temp_fork(); |
|
243 case 0: |
|
244 args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0; |
|
245 sig_pipedefault(); |
|
246 execv(*args,args); |
|
247 strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)"); |
|
248 } |
|
249 |
|
250 wait_pid(&wstat,child); |
|
251 if (wait_crashed(wstat)) |
|
252 temp_childcrashed(); |
|
253 switch(wait_exitcode(wstat)) |
|
254 { |
|
255 case 100: |
|
256 case 64: case 65: case 70: case 76: case 77: case 78: case 112: _exit(100); |
|
257 case 0: break; |
|
258 case 99: flag99 = 1; break; |
|
259 default: _exit(111); |
|
260 } |
|
261 } |
|
262 |
|
263 unsigned long mailforward_qp = 0; |
|
264 |
|
265 void mailforward(recips) |
|
266 char **recips; |
|
267 { |
|
268 struct qmail qqt; |
|
269 char *qqx; |
|
270 substdio ss; |
|
271 int match; |
|
272 |
|
273 if (seek_begin(0) == -1) temp_rewind(); |
|
274 substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); |
|
275 |
|
276 if (qmail_open(&qqt) == -1) temp_fork(); |
|
277 mailforward_qp = qmail_qp(&qqt); |
|
278 qmail_put(&qqt,dtline.s,dtline.len); |
|
279 do |
|
280 { |
|
281 if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; } |
|
282 qmail_put(&qqt,messline.s,messline.len); |
|
283 } |
|
284 while (match); |
|
285 qmail_from(&qqt,ueo.s); |
|
286 while (*recips) qmail_to(&qqt,*recips++); |
|
287 qqx = qmail_close(&qqt); |
|
288 if (!*qqx) return; |
|
289 strerr_die3x(*qqx == 'D' ? 100 : 111,"Unable to forward message: ",qqx + 1,"."); |
|
290 } |
|
291 |
|
292 void bouncexf() |
|
293 { |
|
294 int match; |
|
295 substdio ss; |
|
296 |
|
297 if (seek_begin(0) == -1) temp_rewind(); |
|
298 substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); |
|
299 for (;;) |
|
300 { |
|
301 if (getln(&ss,&messline,&match,'\n') != 0) temp_read(); |
|
302 if (!match) break; |
|
303 if (messline.len <= 1) |
|
304 break; |
|
305 if (messline.len == dtline.len) |
|
306 if (!str_diffn(messline.s,dtline.s,dtline.len)) |
|
307 strerr_die1x(100,"This message is looping: it already has my Delivered-To line. (#5.4.6)"); |
|
308 } |
|
309 } |
|
310 |
|
311 void checkhome() |
|
312 { |
|
313 struct stat st; |
|
314 |
|
315 if (stat(".",&st) == -1) |
|
316 strerr_die3x(111,"Unable to stat home directory: ",error_str(errno),". (#4.3.0)"); |
|
317 if (st.st_mode & auto_patrn) |
|
318 strerr_die1x(111,"Uh-oh: home directory is writable. (#4.7.0)"); |
|
319 if (st.st_mode & 01000) |
|
320 if (flagdoit) |
|
321 strerr_die1x(111,"Home directory is sticky: user is editing his .qmail file. (#4.2.1)"); |
|
322 else |
|
323 strerr_warn1("Warning: home directory is sticky.",0); |
|
324 } |
|
325 |
|
326 int qmeox(dashowner) |
|
327 char *dashowner; |
|
328 { |
|
329 struct stat st; |
|
330 |
|
331 if (!stralloc_copys(&qme,".qmail")) temp_nomem(); |
|
332 if (!stralloc_cats(&qme,dash)) temp_nomem(); |
|
333 if (!stralloc_cat(&qme,&safeext)) temp_nomem(); |
|
334 if (!stralloc_cats(&qme,dashowner)) temp_nomem(); |
|
335 if (!stralloc_0(&qme)) temp_nomem(); |
|
336 if (stat(qme.s,&st) == -1) |
|
337 { |
|
338 if (error_temp(errno)) temp_qmail(qme.s); |
|
339 return -1; |
|
340 } |
|
341 return 0; |
|
342 } |
|
343 |
|
344 int qmeexists(fd,cutable) |
|
345 int *fd; |
|
346 int *cutable; |
|
347 { |
|
348 struct stat st; |
|
349 |
|
350 if (!stralloc_0(&qme)) temp_nomem(); |
|
351 |
|
352 *fd = open_read(qme.s); |
|
353 if (*fd == -1) { |
|
354 if (error_temp(errno)) temp_qmail(qme.s); |
|
355 if (errno == error_perm) temp_qmail(qme.s); |
|
356 if (errno == error_acces) temp_qmail(qme.s); |
|
357 return 0; |
|
358 } |
|
359 |
|
360 if (fstat(*fd,&st) == -1) temp_qmail(qme.s); |
|
361 if ((st.st_mode & S_IFMT) == S_IFREG) { |
|
362 if (st.st_mode & auto_patrn) |
|
363 strerr_die1x(111,"Uh-oh: .qmail file is writable. (#4.7.0)"); |
|
364 *cutable = !!(st.st_mode & 0100); |
|
365 return 1; |
|
366 } |
|
367 close(*fd); |
|
368 return 0; |
|
369 } |
|
370 |
|
371 /* "" "": "" */ |
|
372 /* "-/" "": "-/" "-/default" */ |
|
373 /* "-/" "a": "-/a" "-/default" */ |
|
374 /* "-/" "a-": "-/a-" "-/a-default" "-/default" */ |
|
375 /* "-/" "a-b": "-/a-b" "-/a-default" "-/default" */ |
|
376 /* "-/" "a-b-": "-/a-b-" "-/a-b-default" "-/a-default" "-/default" */ |
|
377 /* "-/" "a-b-c": "-/a-b-c" "-/a-b-default" "-/a-default" "-/default" */ |
|
378 |
|
379 void qmesearch(fd,cutable) |
|
380 int *fd; |
|
381 int *cutable; |
|
382 { |
|
383 int i; |
|
384 |
|
385 if (!stralloc_copys(&qme,".qmail")) temp_nomem(); |
|
386 if (!stralloc_cats(&qme,dash)) temp_nomem(); |
|
387 if (!stralloc_cat(&qme,&safeext)) temp_nomem(); |
|
388 if (qmeexists(fd,cutable)) { |
|
389 if (safeext.len >= 7) { |
|
390 i = safeext.len - 7; |
|
391 if (!byte_diff("default",7,safeext.s + i)) |
|
392 if (i <= str_len(ext)) /* paranoia */ |
|
393 if (!env_put2("DEFAULT",ext + i)) temp_nomem(); |
|
394 } |
|
395 return; |
|
396 } |
|
397 |
|
398 for (i = safeext.len;i >= 0;--i) |
|
399 if (!i || (safeext.s[i - 1] == '-')) { |
|
400 if (!stralloc_copys(&qme,".qmail")) temp_nomem(); |
|
401 if (!stralloc_cats(&qme,dash)) temp_nomem(); |
|
402 if (!stralloc_catb(&qme,safeext.s,i)) temp_nomem(); |
|
403 if (!stralloc_cats(&qme,"default")) temp_nomem(); |
|
404 if (qmeexists(fd,cutable)) { |
|
405 if (i <= str_len(ext)) /* paranoia */ |
|
406 if (!env_put2("DEFAULT",ext + i)) temp_nomem(); |
|
407 return; |
|
408 } |
|
409 } |
|
410 |
|
411 *fd = -1; |
|
412 } |
|
413 |
|
414 unsigned long count_file = 0; |
|
415 unsigned long count_forward = 0; |
|
416 unsigned long count_program = 0; |
|
417 char count_buf[FMT_ULONG]; |
|
418 |
|
419 void count_print() |
|
420 { |
|
421 substdio_puts(subfdoutsmall,"did "); |
|
422 substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_file)); |
|
423 substdio_puts(subfdoutsmall,"+"); |
|
424 substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_forward)); |
|
425 substdio_puts(subfdoutsmall,"+"); |
|
426 substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_program)); |
|
427 substdio_puts(subfdoutsmall,"\n"); |
|
428 if (mailforward_qp) |
|
429 { |
|
430 substdio_puts(subfdoutsmall,"qp "); |
|
431 substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,mailforward_qp)); |
|
432 substdio_puts(subfdoutsmall,"\n"); |
|
433 } |
|
434 substdio_flush(subfdoutsmall); |
|
435 } |
|
436 |
|
437 void sayit(type,cmd,len) |
|
438 char *type; |
|
439 char *cmd; |
|
440 int len; |
|
441 { |
|
442 substdio_puts(subfdoutsmall,type); |
|
443 substdio_put(subfdoutsmall,cmd,len); |
|
444 substdio_putsflush(subfdoutsmall,"\n"); |
|
445 } |
|
446 |
|
447 void main(argc,argv) |
|
448 int argc; |
|
449 char **argv; |
|
450 { |
|
451 int opt; |
|
452 int i; |
|
453 int j; |
|
454 int k; |
|
455 int fd; |
|
456 int numforward; |
|
457 char **recips; |
|
458 datetime_sec starttime; |
|
459 int flagforwardonly; |
|
460 char *x; |
|
461 |
|
462 umask(077); |
|
463 sig_pipeignore(); |
|
464 |
|
465 if (!env_init()) temp_nomem(); |
|
466 |
|
467 flagdoit = 1; |
|
468 while ((opt = getopt(argc,argv,"nN")) != opteof) |
|
469 switch(opt) |
|
470 { |
|
471 case 'n': flagdoit = 0; break; |
|
472 case 'N': flagdoit = 1; break; |
|
473 default: |
|
474 usage(); |
|
475 } |
|
476 argc -= optind; |
|
477 argv += optind; |
|
478 |
|
479 if (!(user = *argv++)) usage(); |
|
480 if (!(homedir = *argv++)) usage(); |
|
481 if (!(local = *argv++)) usage(); |
|
482 if (!(dash = *argv++)) usage(); |
|
483 if (!(ext = *argv++)) usage(); |
|
484 if (!(host = *argv++)) usage(); |
|
485 if (!(sender = *argv++)) usage(); |
|
486 if (!(aliasempty = *argv++)) usage(); |
|
487 if (*argv) usage(); |
|
488 |
|
489 if (homedir[0] != '/') usage(); |
|
490 if (chdir(homedir) == -1) |
|
491 strerr_die5x(111,"Unable to switch to ",homedir,": ",error_str(errno),". (#4.3.0)"); |
|
492 checkhome(); |
|
493 |
|
494 if (!env_put2("HOST",host)) temp_nomem(); |
|
495 if (!env_put2("HOME",homedir)) temp_nomem(); |
|
496 if (!env_put2("USER",user)) temp_nomem(); |
|
497 if (!env_put2("LOCAL",local)) temp_nomem(); |
|
498 |
|
499 if (!stralloc_copys(&envrecip,local)) temp_nomem(); |
|
500 if (!stralloc_cats(&envrecip,"@")) temp_nomem(); |
|
501 if (!stralloc_cats(&envrecip,host)) temp_nomem(); |
|
502 |
|
503 if (!stralloc_copy(&foo,&envrecip)) temp_nomem(); |
|
504 if (!stralloc_0(&foo)) temp_nomem(); |
|
505 if (!env_put2("RECIPIENT",foo.s)) temp_nomem(); |
|
506 |
|
507 if (!stralloc_copys(&dtline,"Delivered-To: ")) temp_nomem(); |
|
508 if (!stralloc_cat(&dtline,&envrecip)) temp_nomem(); |
|
509 for (i = 0;i < dtline.len;++i) if (dtline.s[i] == '\n') dtline.s[i] = '_'; |
|
510 if (!stralloc_cats(&dtline,"\n")) temp_nomem(); |
|
511 |
|
512 if (!stralloc_copy(&foo,&dtline)) temp_nomem(); |
|
513 if (!stralloc_0(&foo)) temp_nomem(); |
|
514 if (!env_put2("DTLINE",foo.s)) temp_nomem(); |
|
515 |
|
516 if (flagdoit) |
|
517 bouncexf(); |
|
518 |
|
519 if (!env_put2("SENDER",sender)) temp_nomem(); |
|
520 |
|
521 if (!quote2(&foo,sender)) temp_nomem(); |
|
522 if (!stralloc_copys(&rpline,"Return-Path: <")) temp_nomem(); |
|
523 if (!stralloc_cat(&rpline,&foo)) temp_nomem(); |
|
524 for (i = 0;i < rpline.len;++i) if (rpline.s[i] == '\n') rpline.s[i] = '_'; |
|
525 if (!stralloc_cats(&rpline,">\n")) temp_nomem(); |
|
526 |
|
527 if (!stralloc_copy(&foo,&rpline)) temp_nomem(); |
|
528 if (!stralloc_0(&foo)) temp_nomem(); |
|
529 if (!env_put2("RPLINE",foo.s)) temp_nomem(); |
|
530 |
|
531 if (!stralloc_copys(&ufline,"From ")) temp_nomem(); |
|
532 if (*sender) |
|
533 { |
|
534 int len; int i; char ch; |
|
535 |
|
536 len = str_len(sender); |
|
537 if (!stralloc_readyplus(&ufline,len)) temp_nomem(); |
|
538 for (i = 0;i < len;++i) |
|
539 { |
|
540 ch = sender[i]; |
|
541 if ((ch == ' ') || (ch == '\t') || (ch == '\n')) ch = '-'; |
|
542 ufline.s[ufline.len + i] = ch; |
|
543 } |
|
544 ufline.len += len; |
|
545 } |
|
546 else |
|
547 if (!stralloc_cats(&ufline,"MAILER-DAEMON")) temp_nomem(); |
|
548 if (!stralloc_cats(&ufline," ")) temp_nomem(); |
|
549 starttime = now(); |
|
550 if (!stralloc_cats(&ufline,myctime(starttime))) temp_nomem(); |
|
551 |
|
552 if (!stralloc_copy(&foo,&ufline)) temp_nomem(); |
|
553 if (!stralloc_0(&foo)) temp_nomem(); |
|
554 if (!env_put2("UFLINE",foo.s)) temp_nomem(); |
|
555 |
|
556 x = ext; |
|
557 if (!env_put2("EXT",x)) temp_nomem(); |
|
558 x += str_chr(x,'-'); if (*x) ++x; |
|
559 if (!env_put2("EXT2",x)) temp_nomem(); |
|
560 x += str_chr(x,'-'); if (*x) ++x; |
|
561 if (!env_put2("EXT3",x)) temp_nomem(); |
|
562 x += str_chr(x,'-'); if (*x) ++x; |
|
563 if (!env_put2("EXT4",x)) temp_nomem(); |
|
564 |
|
565 if (!stralloc_copys(&safeext,ext)) temp_nomem(); |
|
566 case_lowerb(safeext.s,safeext.len); |
|
567 for (i = 0;i < safeext.len;++i) |
|
568 if (safeext.s[i] == '.') |
|
569 safeext.s[i] = ':'; |
|
570 |
|
571 i = str_len(host); |
|
572 i = byte_rchr(host,i,'.'); |
|
573 if (!stralloc_copyb(&foo,host,i)) temp_nomem(); |
|
574 if (!stralloc_0(&foo)) temp_nomem(); |
|
575 if (!env_put2("HOST2",foo.s)) temp_nomem(); |
|
576 i = byte_rchr(host,i,'.'); |
|
577 if (!stralloc_copyb(&foo,host,i)) temp_nomem(); |
|
578 if (!stralloc_0(&foo)) temp_nomem(); |
|
579 if (!env_put2("HOST3",foo.s)) temp_nomem(); |
|
580 i = byte_rchr(host,i,'.'); |
|
581 if (!stralloc_copyb(&foo,host,i)) temp_nomem(); |
|
582 if (!stralloc_0(&foo)) temp_nomem(); |
|
583 if (!env_put2("HOST4",foo.s)) temp_nomem(); |
|
584 |
|
585 flagforwardonly = 0; |
|
586 qmesearch(&fd,&flagforwardonly); |
|
587 if (fd == -1) |
|
588 if (*dash) |
|
589 strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)"); |
|
590 |
|
591 if (!stralloc_copys(&ueo,sender)) temp_nomem(); |
|
592 if (str_diff(sender,"")) |
|
593 if (str_diff(sender,"#@[]")) |
|
594 if (qmeox("-owner") == 0) |
|
595 { |
|
596 if (qmeox("-owner-default") == 0) |
|
597 { |
|
598 if (!stralloc_copys(&ueo,local)) temp_nomem(); |
|
599 if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem(); |
|
600 if (!stralloc_cats(&ueo,host)) temp_nomem(); |
|
601 if (!stralloc_cats(&ueo,"-@[]")) temp_nomem(); |
|
602 } |
|
603 else |
|
604 { |
|
605 if (!stralloc_copys(&ueo,local)) temp_nomem(); |
|
606 if (!stralloc_cats(&ueo,"-owner@")) temp_nomem(); |
|
607 if (!stralloc_cats(&ueo,host)) temp_nomem(); |
|
608 } |
|
609 } |
|
610 if (!stralloc_0(&ueo)) temp_nomem(); |
|
611 if (!env_put2("NEWSENDER",ueo.s)) temp_nomem(); |
|
612 |
|
613 if (!stralloc_ready(&cmds,0)) temp_nomem(); |
|
614 cmds.len = 0; |
|
615 if (fd != -1) |
|
616 if (slurpclose(fd,&cmds,256) == -1) temp_nomem(); |
|
617 |
|
618 if (!cmds.len) |
|
619 { |
|
620 if (!stralloc_copys(&cmds,aliasempty)) temp_nomem(); |
|
621 flagforwardonly = 0; |
|
622 } |
|
623 if (!cmds.len || (cmds.s[cmds.len - 1] != '\n')) |
|
624 if (!stralloc_cats(&cmds,"\n")) temp_nomem(); |
|
625 |
|
626 numforward = 0; |
|
627 i = 0; |
|
628 for (j = 0;j < cmds.len;++j) |
|
629 if (cmds.s[j] == '\n') |
|
630 { |
|
631 switch(cmds.s[i]) { case '#': case '.': case '/': case '|': break; |
|
632 default: ++numforward; } |
|
633 i = j + 1; |
|
634 } |
|
635 |
|
636 recips = (char **) alloc((numforward + 1) * sizeof(char *)); |
|
637 if (!recips) temp_nomem(); |
|
638 numforward = 0; |
|
639 |
|
640 flag99 = 0; |
|
641 |
|
642 i = 0; |
|
643 for (j = 0;j < cmds.len;++j) |
|
644 if (cmds.s[j] == '\n') |
|
645 { |
|
646 cmds.s[j] = 0; |
|
647 k = j; |
|
648 while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')) |
|
649 cmds.s[--k] = 0; |
|
650 switch(cmds.s[i]) |
|
651 { |
|
652 case 0: /* k == i */ |
|
653 if (i) break; |
|
654 strerr_die1x(111,"Uh-oh: first line of .qmail file is blank. (#4.2.1)"); |
|
655 case '#': |
|
656 break; |
|
657 case '.': |
|
658 case '/': |
|
659 ++count_file; |
|
660 if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)"); |
|
661 if (cmds.s[k - 1] == '/') |
|
662 if (flagdoit) maildir(cmds.s + i); |
|
663 else sayit("maildir ",cmds.s + i,k - i); |
|
664 else |
|
665 if (flagdoit) mailfile(cmds.s + i); |
|
666 else sayit("mbox ",cmds.s + i,k - i); |
|
667 break; |
|
668 case '|': |
|
669 ++count_program; |
|
670 if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)"); |
|
671 if (flagdoit) mailprogram(cmds.s + i + 1); |
|
672 else sayit("program ",cmds.s + i + 1,k - i - 1); |
|
673 break; |
|
674 case '+': |
|
675 if (str_equal(cmds.s + i + 1,"list")) |
|
676 flagforwardonly = 1; |
|
677 break; |
|
678 case '&': |
|
679 ++i; |
|
680 default: |
|
681 ++count_forward; |
|
682 if (flagdoit) recips[numforward++] = cmds.s + i; |
|
683 else sayit("forward ",cmds.s + i,k - i); |
|
684 break; |
|
685 } |
|
686 i = j + 1; |
|
687 if (flag99) break; |
|
688 } |
|
689 |
|
690 if (numforward) if (flagdoit) |
|
691 { |
|
692 recips[numforward] = 0; |
|
693 mailforward(recips); |
|
694 } |
|
695 |
|
696 count_print(); |
|
697 _exit(0); |
|
698 } |