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