chiark / gitweb /
Debianization and various other fixes.
[ezmlm] / ezmlm-weed.c
1 #include "stralloc.h"
2 #include "str.h"
3 #include "byte.h"
4 #include "readwrite.h"
5 #include "substdio.h"
6 #include "getln.h"
7 #include "strerr.h"
8 #include "errtxt.h"
9
10 char buf0[256];
11 substdio ss0 = SUBSTDIO_FDBUF(read,0,buf0,sizeof(buf0));
12
13 #define FATAL "ezmlm-weed: fatal: "
14
15 void die_nomem()
16 {
17   strerr_die2x(111,FATAL,ERR_NOMEM);
18 }
19
20 void get(sa)
21 stralloc *sa;
22 {
23   int match;
24   if (getln(&ss0,sa,&match,'\n') == -1)
25     strerr_die2sys(111,FATAL,ERR_READ_INPUT);
26   if (!match) _exit(0);
27 }
28
29 stralloc line = {0};
30 stralloc line1 = {0};
31 stralloc line2 = {0};
32 stralloc line3 = {0};
33 stralloc line4 = {0};
34 stralloc line5 = {0};
35 stralloc line6 = {0};
36 stralloc line7 = {0};
37 stralloc line8 = {0};
38
39 stralloc boundary = {0};
40 stralloc dsnline = {0};
41
42 char warn1[] = "    **********************************************";
43 char warn2[] = "    **      THIS IS A WARNING MESSAGE ONLY      **";
44 char warn3[] = "    **  YOU DO NOT NEED TO RESEND YOUR MESSAGE  **";
45 char warn4[] = "    **********************************************";
46
47 int flagmds = 0;
48 int flagsw = 0;
49 int flagsr = 0;
50 int flagas = 0;
51 int flagbw = 0;
52 int flagdsn = 0;
53
54 int isboundary()
55 /* returns 1 if line.len contains the mime bondary, 0 otherwise */
56 {
57     if (line.s[0] == '-' && line.s[1] == '-' && line.len >= boundary.len + 3)
58       if (!byte_diff(line.s + 2,boundary.len,boundary.s))       /* boundary */
59         return 1;
60     return 0;
61 }
62
63 void main()
64 {
65   unsigned int i,j;
66
67   for (;;) {
68     get(&line);
69     if (line.len == 1) break;
70     if (line.s[0] == ' ' || line.s[0] == '\t') {        /* continuation */
71       if (flagdsn) {
72         if (!stralloc_catb(&dsnline,line.s,line.len - 1)) die_nomem();
73         continue;
74       }
75     }
76     flagdsn = 0;
77     if (stralloc_starts(&line,"Subject: success notice"))
78       _exit(99);
79     if (stralloc_starts(&line,"Subject: deferral notice"))
80       _exit(99);
81     if (stralloc_starts(&line,"Precedence: bulk"))
82       _exit(99);
83     if (stralloc_starts(&line,"Precedence: junk"))
84       _exit(99);
85 /* for Novell Groupwise */
86     if (stralloc_starts(&line,"Subject: Message status - delivered"))
87       _exit(99);
88     if (stralloc_starts(&line,"Subject: Message status - opened"))
89       _exit(99);
90     if (stralloc_starts(&line,"Subject: Out of Office AutoReply:"))
91       _exit(99);
92
93     if (stralloc_starts(&line,"From: Mail Delivery Subsystem <MAILER-DAEMON@"))
94       flagmds = 1;
95     if (stralloc_starts(&line,"Subject: Warning: could not send message"))
96       flagsw = 1;
97     if (stralloc_starts(&line,"Subject: Returned mail: warning: cannot send message"))
98       flagsr = 1;
99     if (stralloc_starts(&line,"Auto-Submitted: auto-generated (warning"))
100       flagas = 1;
101     if (case_startb(line.s,line.len,"Content-type: multipart/report"))
102       if (!stralloc_copyb(&dsnline,line.s,line.len - 1)) die_nomem();
103       flagdsn = 1;
104   }                     /* end of header */
105
106   if (flagdsn) {        /* always only one recipient/action */
107     flagdsn = 0;        /* will be set for correct report type */
108     for (i=0; i < dsnline.len; i += 1+byte_chr(dsnline.s+i,dsnline.len-i,';')) {
109       while (dsnline.s[i] == ' ' || dsnline.s[i] == '\t')
110         if (++i >= dsnline.len) break;
111       if (case_startb(dsnline.s + i,dsnline.len - i,"report-type=")) {
112         i += 12;
113         while (dsnline.s[i] ==' ' || dsnline.s[i] =='\t' || dsnline.s[i] =='"')
114           if (++i >= dsnline.len) break;
115         if (case_startb(dsnline.s + i,dsnline.len - i,"delivery-status"))
116           flagdsn = 1;
117       } else if (case_startb(dsnline.s + i,dsnline.len - i,"boundary=")) {
118         i += 9;
119         while (dsnline.s[i] ==' ' || dsnline.s[i] =='\t')
120           if (++i >= dsnline.len) break;
121         if (dsnline.s[i] == '"') {
122           if (++i >= dsnline.len) break;
123           j = i + byte_chr(dsnline.s + i,dsnline.len - i,'"');
124           if (j >= dsnline.len) break;
125         } else {
126           j = i;
127           while (dsnline.s[j] !=' ' && dsnline.s[j] !='\t' &&
128                 dsnline.s[j] !=';')
129             if (++j >= dsnline.len) break;
130         }                               /* got boundary */
131         if (!stralloc_copyb(&boundary,dsnline.s+i,j-i)) die_nomem();
132       }
133     }
134   }
135   if (flagdsn && boundary.len) {        /* parse DSN message */
136     get(&line);                 /* if bad format we exit(0) via get() */
137     for (;;) {
138       if (isboundary()) {
139       if (line.len == boundary.len + 5 && line.s[line.len - 1] == '-'
140                 && line.s[line.len - 2] == '-')
141         _exit(99);                      /* end: not failure report */
142         get(&line);                     /* Content-type */
143         if (case_startb(line.s,line.len,"content-type:")) {
144           i = 13;
145           while (line.s[i] == ' ' || line.s[i] == '\t')
146                 if (++i >= line.len) break;
147           if (case_startb(line.s+i,line.len-i,"message/delivery-status")) {
148             for (;;) {
149               get(&line);
150               if (isboundary()) break;
151               if (case_startb(line.s,line.len,"action:")) {
152                 i = 8;
153                 while (line.s[i] == ' ' || line.s[i] == '\t')
154                   if (++i >= line.len) break;
155                 if (case_startb(line.s + i, line.len - i,"failed"))
156                   _exit(0);     /* failure notice */
157                 else
158                   _exit(99);    /* there shouldn't be more than 1 action */
159               }
160             }
161           }
162         }
163       } else
164         get(&line);
165     }
166   }
167
168   get(&line1);
169   get(&line2);
170   get(&line3);
171   get(&line4);
172   get(&line5);
173   get(&line6);
174   get(&line7);
175   get(&line8);
176
177   if (stralloc_starts(&line1,"This is a MIME-encapsulated message"))
178   if (stralloc_starts(&line3,"--"))
179   if (stralloc_starts(&line5,warn1))
180   if (stralloc_starts(&line6,warn2))
181   if (stralloc_starts(&line7,warn3))
182   if (stralloc_starts(&line8,warn4))
183     flagbw = 1;
184
185   if (stralloc_starts(&line1,warn1))
186   if (stralloc_starts(&line2,warn2))
187   if (stralloc_starts(&line3,warn3))
188   if (stralloc_starts(&line4,warn4))
189     flagbw = 1;
190
191   if (flagmds && flagsw && flagas && flagbw) _exit(99);
192   if (flagmds && flagsr && flagbw) _exit(99);
193
194   _exit(0);
195 }