16#define WHO "qmail-mrtg"
83static void outs(
char *s)
85 if (buffer_puts(&
bo,s) == -1)
_exit(1);
86 if (buffer_puts(&
bo,
"\n") == -1)
_exit(1);
87 if (buffer_flush(&
bo) == -1)
_exit(1);
94 if (buffer_put(&
bo,
num,fmt_ulong(
num,(
unsigned long) i)) == -1)
_exit(1);
95 if (buffer_puts(&
bo,
"\n") == -1)
_exit(1);
96 if (buffer_flush(&
bo) == -1)
_exit(1);
102static void mrtg_results(
char flag)
133static void mrtg_sendlog(
char *
in,
char flag)
138 case '1':
if (case_starts(
in,
"delivery")) {
139 i = str_chr(
in,
':') + 2;
140 if (case_starts(
in + i,
"success:"))
success++;
144 case '2':
if (case_starts(
in,
"info msg")) {
145 i = str_chr(
in,
':') + 8;
146 if ((
j = str_chr(
in + i,
' ')))
in[i +
j] =
'\0';
149 case '3':
if (case_starts(
in,
"status:")) {
150 i = str_rchr(
in,
'c') + 4;
151 k = str_rchr(
in,
'r') + 7;
152 if ((
j = str_chr(
in + i,
'/')))
in[i +
j] =
'\0';
154 if ((
j = str_chr(
in +
k,
'/')))
in[
k +
j] =
'\0';
157 case '4':
if (case_starts(
in,
"delivery")) {
158 i = str_chr(
in,
':') + 2;
159 if (case_starts(
in + i,
"failure:"))
failure++;
160 if (case_starts(
in + i,
"deferral:"))
deferral++;
162 case '5':
if (case_starts(
in,
"bounce msg"))
bounces++;
163 if (case_starts(
in,
"triple bounce:"))
triples++;
165 case '6':
if (case_starts(
in,
"delivery")) {
167 if (case_starts(
in + i,
"qmtp:_ok"))
qmtp++;
168 if (case_starts(
in + i,
"qmtps:_ok"))
qmtps++;
174static void mrtg_smtplog(
char *
in,
char flag)
176 int A, D, P, R,
c, r = 0;
184 case 'a':
if (case_starts(
in + A,
"Accept"))
asessions++;
187 case 'b':
if (case_starts(
in + A,
"Accept::ORIG:"))
aorig++;
188 if (case_starts(
in + A,
"Accept::RCPT:"))
arcpt++;
189 if (case_starts(
in + A,
"Accept::SPF:Rcpthosts"))
arcpt++;
190 if (case_starts(
in + A,
"Accept::SPF:Recipients"))
arcpt++;
192 case 'c':
if (case_starts(
in + R,
"Reject::SNDR::Invalid_Relay"))
rsend++;
193 if (case_starts(
in + R,
"Reject::SNDR::Bad_Helo"))
rhelo++;
194 if (case_starts(
in + R,
"Reject::SNDR::DNS_Helo"))
rhelo++;
196 case 'd':
if (case_starts(
in + R,
"Reject::ORIG::Bad_Mailfrom"))
rorigbad++;
197 if (case_starts(
in + R,
"Reject::ORIG::DNS_MF"))
rorigdns++;
199 case 'e':
if (case_starts(
in + R,
"Reject::RCPT::Bad_Rcptto"))
rrcptbad++;
200 if (case_starts(
in + R,
"Reject::RCPT::Failed_Rcptto"))
rrcptfail++;
202 case 'f':
if (case_starts(
in + R,
"Reject::DATA::Invalid_Size"))
rsize++;
203 if (case_starts(
in + R,
"Reject::DATA::Bad_MIME"))
rmime++;
204 if (case_starts(
in + R,
"Reject::DATA::MIME_Attach"))
rmime++;
205 if (case_starts(
in + R,
"Reject::DATA::Bad_Loader"))
rloader++;
207 case 'g':
if (case_starts(
in + R,
"Reject::DATA::Spam_Message"))
rspam++;
208 if (case_starts(
in + R,
"Reject::DATA::Virus_Infected"))
rvirus++;
210 case 'h':
if (case_starts(
in + A,
"Accept::AUTH:"))
aauth++;
211 if (case_starts(
in + R,
"Reject::AUTH:"))
rauth++;
213 case 'i':
if (case_starts(
in + P,
"P:ESMTPS"))
atls++;
214 if (case_starts(
in + R,
"Reject::TLS:"))
rtls++;
216 case 'j':
if (case_starts(
in + A,
"Accept::SPF:"))
spfpass++;
217 if (case_starts(
in + R,
"Reject::SPF:"))
spfail++;
219 case 'k':
if (case_starts(
in + D,
"Deferred::SNDR::Grey_Listed"))
grey++;
220 if (case_starts(
in,
"rblsmtpd")) {
221 c = str_chr(
in,
':') + 2;
222 r = str_chr(
in + r,
':') + 2;
223 if (case_starts(
in + c + r + 1,
"reetdelay:"))
greet++;
226 case 'm':
if (case_starts(
in + A,
"Accepted::SNDR::DKIM_Signature"))
adkim++;
227 if (case_starts(
in + R,
"Rejected::SNDR::DKIM_Signature"))
rdkim++;
229 case 'z':
if (case_starts(
in,
"tcpserver") || case_starts(
in,
"sslserver") || case_starts(
in,
"rblsmtpd")) {
230 c = str_chr(
in,
':') + 2;
231 if (case_starts(
in + c,
"ok"))
sok++;
232 if (case_starts(
in + c,
"deny"))
sdeny++;
233 r = str_chr(
in + r,
':') + 2;
234 if (case_starts(
in + c + r,
"451"))
rbl++;
235 if (case_starts(
in + c + r,
"553"))
rbl++;
241static void mrtg_pop3log(
char *
in,
char flag)
246 case 'A': A = str_chr(
in,
'A'); R = str_chr(
in,
'R');
247 if (case_starts(
in + A,
"Accept::AUTH:"))
apop++;
248 if (case_starts(
in + R,
"Reject::AUTH:"))
rpop++;
250 case 'B':
if (case_starts(
in,
"tcpserver:") || case_starts(
in,
"sslserver:")) {
251 c = str_chr(
in,
':') + 2;
252 if (case_starts(
in + c,
"ok"))
pok++;
253 if (case_starts(
in + c,
"deny"))
pdeny++;
259int main(
int argc,
char *
const argv[])
266 unsigned long calltime;
267 unsigned long seconds;
268 unsigned long nanoseconds;
269 unsigned int history = 305;
276 logmsg(
WHO,100,USAGE,
"qmail-mrtg [ -1 | -2 | -3 | -4 | -5 | -6 |\
277 -a | -b | -c | -d | -e | -f | -g | -h | -i | -j | -k | -m | -z | -A | -B ] [time (min)] \n\
278 qmail-mrtg needs to be called every [time] minutes (i.e. by crontab) - default 305 secs");
280 flag = *(argv[1] + 1);
281 if (argc == 3) { scan_ulong(argv[2],&u); history = 60 * u + 5; }
295 if (
line.s[0] ==
'@') {
305 seconds += nanoseconds >> 28;
306 nanoseconds &= 0xfffffff;
310 seconds -= 4611686018427387914ULL;
311 seconds = seconds > 0 ? seconds : 0;
313 outs(
"Error: No TAI64N timestamp available.");
318 if (seconds <= calltime && seconds >= (calltime - history)) {
319 if (flag >=
'1' && flag <=
'9') mrtg_sendlog(
line.s +
TAI64NLEN + 2,flag);
320 else if (flag >=
'a' && flag <=
'z') mrtg_smtplog(
line.s +
TAI64NLEN + 2,flag);
321 else if (flag >=
'A' && flag <=
'Z') mrtg_pop3log(
line.s +
TAI64NLEN + 2,flag);
327 outs(
"Warning: Not enough time left between calls");
void c(char *, char *, char *, int, int, int)
char bufspace[BUFSIZE_LINE]
char bufsmall[BUFFER_SMALL]