s/qmail 4.3.20
Next generation secure email transport
Loading...
Searching...
No Matches
matchup.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "genalloc.h"
3#include "alloc.h"
4#include "stralloc.h"
5#include "logmsg.h"
6#include "getln.h"
7#include "buffer.h"
8#include "readwrite.h"
9#include "exit.h"
10#include "str.h"
11#include "fmt.h"
12#include "scan.h"
13#include "case.h"
14#include "qmail.h"
15
16#define WHO "matchup"
17
18static void nomem() { logmsg(WHO,111,FATAL,"out of memory"); }
19static void die_read() { logmsg(WHO,110,ERROR,"unable to read input: "); }
20static void die_write() { logmsg(WHO,110,ERROR,"unable to write output: "); }
21static void die_write5() { logmsg(WHO,111,FATAL,"unable to write fd 5: "); }
22
23static void out(char *buf,int len)
24{
25 if (buffer_put(buffer_1,buf,len) == -1) die_write();
26}
27static void outs(char *buf)
28{
29 if (buffer_puts(buffer_1,buf) == -1) die_write();
30}
31
33buffer bo5 = BUFFER_INIT(write,5,buf5,sizeof(buf5));
34
35static void out5(char *buf,int len)
36{
37 if (buffer_put(&bo5,buf,len) == -1)
38 die_write5();
39}
40static void outs5(char *buf)
41{
42 if (buffer_puts(&bo5,buf) == -1)
43 die_write5();
44}
45
46GEN_ALLOC_typedef(ulongalloc,unsigned long,u,len,a)
47GEN_ALLOC_ready(ulongalloc,unsigned long,u,len,a,i,n,x,30,ulongalloc_ready)
48GEN_ALLOC_readyplus(ulongalloc,unsigned long,u,len,a,i,n,x,30,ulongalloc_readyplus)
49
50char strnum[FMT_ULONG];
51
52stralloc pool = {0};
53unsigned int poolbytes = 0;
54
55int nummsg = 0;
56ulongalloc msg = {0};
57ulongalloc bytes = {0};
58ulongalloc qp = {0};
59ulongalloc uid = {0};
60ulongalloc numk = {0};
61ulongalloc numd = {0};
62ulongalloc numz = {0};
63ulongalloc sender = {0};
64ulongalloc birth = {0};
65
66static int msg_find(unsigned long m)
67{
68 int i;
69 for (i = 0; i < nummsg; ++i)
70 if (msg.u[i] == m) return i;
71 return -1;
72}
73
74static int msg_add(unsigned long m)
75{
76 int i;
77 for (i = 0; i < nummsg; ++i)
78 if (msg.u[i] == m) return i;
79 i = nummsg++;
80 if (!ulongalloc_ready(&msg,nummsg)) nomem();
81 if (!ulongalloc_ready(&bytes,nummsg)) nomem();
82 if (!ulongalloc_ready(&qp,nummsg)) nomem();
83 if (!ulongalloc_ready(&uid,nummsg)) nomem();
84 if (!ulongalloc_ready(&numk,nummsg)) nomem();
85 if (!ulongalloc_ready(&numd,nummsg)) nomem();
86 if (!ulongalloc_ready(&numz,nummsg)) nomem();
87 if (!ulongalloc_ready(&sender,nummsg)) nomem();
88 if (!ulongalloc_ready(&birth,nummsg)) nomem();
89 msg.u[i] = m;
90 return i;
91}
92
93static void msg_kill(int i)
94{
95 poolbytes -= str_len(pool.s + sender.u[i]) + 1;
96 poolbytes -= str_len(pool.s + birth.u[i]) + 1;
97
98 --nummsg;
99 msg.u[i] = msg.u[nummsg];
100 bytes.u[i] = bytes.u[nummsg];
101 qp.u[i] = qp.u[nummsg];
102 uid.u[i] = uid.u[nummsg];
103 numk.u[i] = numk.u[nummsg];
104 numd.u[i] = numd.u[nummsg];
105 numz.u[i] = numz.u[nummsg];
106 sender.u[i] = sender.u[nummsg];
107 birth.u[i] = birth.u[nummsg];
108}
109
110int numdel = 0;
111ulongalloc del = {0};
112ulongalloc dmsg = {0};
113ulongalloc dchan = {0};
114ulongalloc drecip = {0};
115ulongalloc dstart = {0};
116
117static int del_find(unsigned long d)
118{
119 int i;
120 for (i = 0; i < numdel; ++i)
121 if (del.u[i] == d) return i;
122 return -1;
123}
124
125static int del_add(unsigned long d)
126{
127 int i;
128 for (i = 0; i < numdel; ++i)
129 if (del.u[i] == d) return i;
130 i = numdel++;
131 if (!ulongalloc_ready(&del,numdel)) nomem();
132 if (!ulongalloc_ready(&dmsg,numdel)) nomem();
133 if (!ulongalloc_ready(&dchan,numdel)) nomem();
134 if (!ulongalloc_ready(&drecip,numdel)) nomem();
135 if (!ulongalloc_ready(&dstart,numdel)) nomem();
136 del.u[i] = d;
137 return i;
138}
139
140static void del_kill(int i)
141{
142 poolbytes -= str_len(pool.s + dchan.u[i]) + 1;
143 poolbytes -= str_len(pool.s + drecip.u[i]) + 1;
144 poolbytes -= str_len(pool.s + dstart.u[i]) + 1;
145 --numdel;
146 del.u[i] = del.u[numdel];
147 dmsg.u[i] = dmsg.u[numdel];
148 dchan.u[i] = dchan.u[numdel];
149 drecip.u[i] = drecip.u[numdel];
150 dstart.u[i] = dstart.u[numdel];
151}
152
153stralloc pool2 = {0};
154
155static void garbage()
156{
157 int i;
158 char *x;
159
160 if (pool.len - poolbytes < poolbytes + 4096) return;
161
162 if (!stralloc_copys(&pool2,"")) nomem();
163
164 for (i = 0; i < nummsg; ++i) {
165 x = pool.s + birth.u[i];
166 birth.u[i] = pool2.len;
167 if (!stralloc_cats(&pool2,x)) nomem();
168 if (!stralloc_0(&pool2)) nomem();
169 x = pool.s + sender.u[i];
170 sender.u[i] = pool2.len;
171 if (!stralloc_cats(&pool2,x)) nomem();
172 if (!stralloc_0(&pool2)) nomem();
173 }
174
175 for (i = 0; i < numdel; ++i) {
176 x = pool.s + dstart.u[i];
177 dstart.u[i] = pool2.len;
178 if (!stralloc_cats(&pool2,x)) nomem();
179 if (!stralloc_0(&pool2)) nomem();
180 x = pool.s + dchan.u[i];
181 dchan.u[i] = pool2.len;
182 if (!stralloc_cats(&pool2,x)) nomem();
183 if (!stralloc_0(&pool2)) nomem();
184 x = pool.s + drecip.u[i];
185 drecip.u[i] = pool2.len;
186 if (!stralloc_cats(&pool2,x)) nomem();
187 if (!stralloc_0(&pool2)) nomem();
188 }
189
190 if (!stralloc_copy(&pool,&pool2)) nomem();
191
192 poolbytes = pool.len; /* redundant, but doesn't hurt */
193}
194
195stralloc line = {0};
197
198#define FIELDS 20
200
201static void clear()
202{
203 while (numdel > 0)
204 del_kill(0);
205 garbage();
206}
207
208static void starting()
209{
210 unsigned long d;
211 unsigned long m;
212 int dpos;
213
214 scan_ulong(line.s + field[3],&d);
215 scan_ulong(line.s + field[5],&m);
216
217 dpos = del_add(d);
218
219 dmsg.u[dpos] = m;
220
221 dstart.u[dpos] = pool.len;
222 if (!stralloc_cats(&pool,line.s + field[0])) nomem();
223 if (!stralloc_0(&pool)) nomem();
224
225 dchan.u[dpos] = pool.len;
226 if (!stralloc_cats(&pool,line.s + field[7])) nomem();
227 if (!stralloc_0(&pool)) nomem();
228
229 drecip.u[dpos] = pool.len;
230 if (!stralloc_cats(&pool,line.s + field[8])) nomem();
231 if (!stralloc_0(&pool)) nomem();
232 case_lowers(pool.s + drecip.u[dpos]);
233
234 poolbytes += pool.len - dstart.u[dpos];
235}
236
237static void delivery()
238{
239 unsigned long d;
240 unsigned long m;
241 int dpos;
242 int mpos;
243 char *result = "?";
244 char *reason = "";
245
246 scan_ulong(line.s + field[2],&d);
247
248 dpos = del_find(d);
249 if (dpos == -1) return;
250
251 m = dmsg.u[dpos];
252 mpos = msg_find(m);
253
254 if (str_start(line.s + field[3],"succ")) {
255 if (mpos != -1) ++numk.u[mpos];
256 result = "d k ";
257 reason = line.s + field[4];
258 }
259 else if (str_start(line.s + field[3],"fail")) {
260 if (mpos != -1) ++numd.u[mpos];
261 result = "d d ";
262 reason = line.s + field[4];
263 }
264 else if (str_start(line.s + field[3],"defer")) {
265 if (mpos != -1) ++numz.u[mpos];
266 result = "d z ";
267 reason = line.s + field[4];
268 }
269 else if (str_start(line.s + field[3],"report")) {
270 if (mpos != -1) ++numz.u[mpos];
271 result = "d z ";
272 reason = "report_mangled";
273 }
274
275 outs(result);
276
277 if (mpos != -1) {
278 outs(pool.s + birth.u[mpos]);
279 outs(" "); outs(pool.s + dstart.u[dpos]);
280 outs(" "); outs(line.s + field[0]);
281 outs(" "); out(strnum,fmt_ulong(strnum,bytes.u[mpos]));
282 outs(" "); outs(pool.s + sender.u[mpos]);
283 outs(" "); outs(pool.s + dchan.u[dpos]);
284 outs("."); outs(pool.s + drecip.u[dpos]);
285 outs(" "); out(strnum,fmt_ulong(strnum,qp.u[mpos]));
286 outs(" "); out(strnum,fmt_ulong(strnum,uid.u[mpos]));
287 outs(" "); outs(reason);
288 } else {
289 outs(pool.s + dstart.u[dpos]);
290 outs(" "); outs(pool.s + dstart.u[dpos]);
291 outs(" "); outs(line.s + field[0]);
292 outs(" 0 ? "); outs(pool.s + dchan.u[dpos]);
293 outs("."); outs(pool.s + drecip.u[dpos]);
294 outs(" ? ? "); outs(reason);
295 }
296
297 outs("\n");
298
299 del_kill(dpos);
300 garbage();
301}
302
303static void newmsg()
304{
305 unsigned long m;
306 int mpos;
307
308 scan_ulong(line.s + field[3],&m);
309 mpos = msg_find(m);
310 if (mpos == -1) return;
311 msg_kill(mpos);
312 garbage();
313}
314
315static void endmsg()
316{
317 unsigned long m;
318 int mpos;
319
320 scan_ulong(line.s + field[3],&m);
321 mpos = msg_find(m);
322 if (mpos == -1) return;
323
324 outs("m "); outs(pool.s + birth.u[mpos]);
325 outs(" "); outs(line.s + field[0]);
326 outs(" "); out(strnum,fmt_ulong(strnum,bytes.u[mpos]));
327 outs(" "); out(strnum,fmt_ulong(strnum,numk.u[mpos]));
328 outs(" "); out(strnum,fmt_ulong(strnum,numd.u[mpos]));
329 outs(" "); out(strnum,fmt_ulong(strnum,numz.u[mpos]));
330 outs(" "); outs(pool.s + sender.u[mpos]);
331 outs(" "); out(strnum,fmt_ulong(strnum,qp.u[mpos]));
332 outs(" "); out(strnum,fmt_ulong(strnum,uid.u[mpos]));
333 outs("\n");
334
335 msg_kill(mpos);
336 garbage();
337}
338
339static void info()
340{
341 unsigned long m;
342 int mpos;
343
344 scan_ulong(line.s + field[3],&m);
345 mpos = msg_add(m);
346
347 scan_ulong(line.s + field[5],&bytes.u[mpos]);
348 scan_ulong(line.s + field[9],&qp.u[mpos]);
349 scan_ulong(line.s + field[11],&uid.u[mpos]);
350
351 numk.u[mpos] = 0;
352 numd.u[mpos] = 0;
353 numz.u[mpos] = 0;
354
355 birth.u[mpos] = pool.len;
356 if (!stralloc_cats(&pool,line.s + field[0])) nomem();
357 if (!stralloc_0(&pool)) nomem();
358
359 sender.u[mpos] = pool.len;
360 if (!stralloc_cats(&pool,line.s + field[7])) nomem();
361 if (!stralloc_0(&pool)) nomem();
362 case_lowers(pool.s + sender.u[mpos]);
363
364 poolbytes += pool.len - birth.u[mpos];
365}
366
367static void extra()
368{
369 unsigned long m;
370 int mpos;
371
372 scan_ulong(line.s + field[2],&m);
373 mpos = msg_find(m);
374 if (mpos == -1) return;
375
376 scan_ulong(line.s + field[3],&numk.u[mpos]);
377 scan_ulong(line.s + field[4],&numz.u[mpos]);
378 scan_ulong(line.s + field[5],&numd.u[mpos]);
379}
380
381static void pending()
382{
383 int i;
384
385 for (i = 0; i < nummsg; ++i) {
386 outs5(pool.s + birth.u[i]);
387 outs5(" info msg ");
388 out5(strnum,fmt_ulong(strnum,msg.u[i]));
389 outs5(": bytes ");
390 out5(strnum,fmt_ulong(strnum,bytes.u[i]));
391 outs5(" from ");
392 outs5(pool.s + sender.u[i]);
393 outs5(" qp ");
394 out5(strnum,fmt_ulong(strnum,qp.u[i]));
395 outs5(" uid ");
396 out5(strnum,fmt_ulong(strnum,uid.u[i]));
397 outs5("\n");
398 outs5(pool.s + birth.u[i]);
399 outs5(" extra ");
400 out5(strnum,fmt_ulong(strnum,msg.u[i]));
401 outs5(" ");
402 out5(strnum,fmt_ulong(strnum,numk.u[i]));
403 outs5(" ");
404 out5(strnum,fmt_ulong(strnum,numz.u[i]));
405 outs5(" ");
406 out5(strnum,fmt_ulong(strnum,numd.u[i]));
407 outs5("\n");
408 }
409
410 for (i = 0; i < numdel; ++i) {
411 outs5(pool.s + dstart.u[i]);
412 outs5(" starting delivery ");
413 out5(strnum,fmt_ulong(strnum,del.u[i]));
414 outs5(": msg ");
415 out5(strnum,fmt_ulong(strnum,dmsg.u[i]));
416 outs5(" to ");
417 outs5(pool.s + dchan.u[i]);
418 outs5(" ");
419 outs5(pool.s + drecip.u[i]);
420 outs5("\n");
421 }
422
423 out5(line.s,line.len);
424 if (buffer_flush(&bo5) == -1) die_write5();
425}
426
427stralloc outline = {0};
428
429int main()
430{
431 int i;
432 int j;
433 char ch;
434
435 if (!stralloc_copys(&pool,"")) nomem();
436
437 if (!ulongalloc_ready(&msg,1)) nomem();
438 if (!ulongalloc_ready(&bytes,1)) nomem();
439 if (!ulongalloc_ready(&qp,1)) nomem();
440 if (!ulongalloc_ready(&uid,1)) nomem();
441 if (!ulongalloc_ready(&numk,1)) nomem();
442 if (!ulongalloc_ready(&numd,1)) nomem();
443 if (!ulongalloc_ready(&numz,1)) nomem();
444 if (!ulongalloc_ready(&del,1)) nomem();
445 if (!ulongalloc_ready(&dmsg,1)) nomem();
446
447 for (;;) {
448 if (getln(buffer_0,&line,&match,'\n') == -1) die_read();
449 if (!match) break;
450
451 if (!stralloc_copy(&outline,&line)) nomem();
452
453 for (i = 0; i < line.len; ++i) {
454 ch = line.s[i];
455 if ((ch == '\n') || (ch == ' ') || (ch == '\t')) line.s[i] = 0;
456 }
457 j = 0;
458 for (i = 0; i < FIELDS; ++i) {
459 while (j < line.len) if (line.s[j]) break; else ++j;
460 field[i] = j;
461 while (j < line.len) if (!line.s[j]) break; else ++j;
462 }
463 if (!stralloc_0(&line)) nomem();
464
465 if (str_equal(line.s + field[1],"status:")) ;
466 else if (str_equal(line.s + field[1],"starting")) starting();
467 else if (str_equal(line.s + field[1],"delivery")) delivery();
468 else if (str_equal(line.s + field[1],"new")) newmsg();
469 else if (str_equal(line.s + field[1],"end")) endmsg();
470 else if (str_equal(line.s + field[1],"info")) info();
471 else if (str_equal(line.s + field[1],"extra")) extra();
472 else if (str_equal(line.s + field[1],"running")) clear();
473 else if (str_equal(line.s + field[1],"exiting")) clear();
474 else if (str_equal(line.s + field[1],"number")) ;
475 else if (str_equal(line.s + field[1],"local")) ;
476 else if (str_equal(line.s + field[1],"remote")) ;
477 else if (str_equal(line.s + field[1],"warning:")) out(outline.s,outline.len);
478 else if (str_equal(line.s + field[1],"alert:")) out(outline.s,outline.len);
479 else {
480 outs("? ");
481 out(outline.s,outline.len);
482 }
483 }
484
485 if (buffer_flush(buffer_1) == -1) die_write();
486
487 pending();
488
489 _exit(0);
490}
void outs(char *s)
Definition: auto-gid.c:12
void die_write()
Definition: columnt.c:17
void nomem()
Definition: columnt.c:15
void die_read()
Definition: columnt.c:16
int stralloc_copys(stralloc *, char const *)
stralloc out
Definition: dnscname.c:12
void _exit(int)
char buf[100+FMT_ULONG]
Definition: hier.c:11
ulongalloc numk
Definition: matchup.c:60
stralloc outline
Definition: matchup.c:427
#define FIELDS
Definition: matchup.c:198
ulongalloc numz
Definition: matchup.c:62
ulongalloc dchan
Definition: matchup.c:113
ulongalloc msg
Definition: matchup.c:56
ulongalloc drecip
Definition: matchup.c:114
stralloc pool2
Definition: matchup.c:153
int nummsg
Definition: matchup.c:55
int numdel
Definition: matchup.c:110
ulongalloc bytes
Definition: matchup.c:57
ulongalloc numd
Definition: matchup.c:61
char buf5[BUFSIZE_AUTH]
Definition: matchup.c:32
ulongalloc sender
Definition: matchup.c:63
ulongalloc qp
Definition: matchup.c:58
ulongalloc birth
Definition: matchup.c:64
int field[FIELDS]
Definition: matchup.c:199
stralloc line
Definition: matchup.c:195
ulongalloc dmsg
Definition: matchup.c:112
int match
Definition: matchup.c:196
GEN_ALLOC_typedef(GEN_ALLOC_ready(ulongalloc, GEN_ALLOC_ready(unsigned long, GEN_ALLOC_ready(u, GEN_ALLOC_ready(len, GEN_ALLOC_ready(a)
Definition: matchup.c:46
#define WHO
Definition: matchup.c:16
ulongalloc dstart
Definition: matchup.c:115
int main()
Definition: matchup.c:429
buffer bo5
Definition: matchup.c:33
unsigned int poolbytes
Definition: matchup.c:53
ulongalloc uid
Definition: matchup.c:59
GEN_ALLOC_readyplus(prioq, struct prioq_elt, p, len, a, i, n, x, 100, prioq_readyplus)
Definition: prioq.c:5
char strnum[FMT_ULONG]
Definition: qmail-inject.c:505
struct message * m
int j
Definition: qmail-send.c:926
seek_pos mpos
Definition: qmail-send.c:928
struct del * d[CHANNELS]
Definition: qmail-send.c:726
#define BUFSIZE_AUTH
Definition: qmail.h:9
Definition: spawn.c:32
GEN_ALLOC_ready(GEN_ALLOC_readyplus(token822_alloc, GEN_ALLOC_readyplus(struct token822, GEN_ALLOC_readyplus(t, GEN_ALLOC_readyplus(len, GEN_ALLOC_readyplus(a, GEN_ALLOC_readyplus(i, GEN_ALLOC_readyplus(n, GEN_ALLOC_readyplus(x, GEN_ALLOC_readyplus(30, token822_ready)
Definition: token822.c:23
void write()