16#define WHO "qmail-mrtg"
82static void outs(
char *s)
84 if (buffer_puts(&
bo,s) == -1)
_exit(1);
85 if (buffer_puts(&
bo,
"\n") == -1)
_exit(1);
86 if (buffer_flush(&
bo) == -1)
_exit(1);
93 if (buffer_put(&
bo,
num,fmt_ulong(
num,(
unsigned long) i)) == -1)
_exit(1);
94 if (buffer_puts(&
bo,
"\n") == -1)
_exit(1);
95 if (buffer_flush(&
bo) == -1)
_exit(1);
101static void mrtg_results(
char flag)
132static void mrtg_sendlog(
char *
in,
char flag)
137 case '1':
if (case_starts(
in,
"delivery")) {
138 i = str_chr(
in,
':') + 2;
139 if (case_starts(
in + i,
"success:"))
success++;
143 case '2':
if (case_starts(
in,
"info msg")) {
144 i = str_chr(
in,
':') + 8;
145 if ((
j = str_chr(
in + i,
' ')))
in[i +
j] =
'\0';
148 case '3':
if (case_starts(
in,
"status:")) {
149 i = str_rchr(
in,
'c') + 4;
150 k = str_rchr(
in,
'r') + 7;
151 if ((
j = str_chr(
in + i,
'/')))
in[i +
j] =
'\0';
153 if ((
j = str_chr(
in +
k,
'/')))
in[
k +
j] =
'\0';
156 case '4':
if (case_starts(
in,
"delivery")) {
157 i = str_chr(
in,
':') + 2;
158 if (case_starts(
in + i,
"failure:"))
failure++;
159 if (case_starts(
in + i,
"deferral:"))
deferral++;
161 case '5':
if (case_starts(
in,
"bounce msg"))
bounces++;
162 if (case_starts(
in,
"triple bounce:"))
triples++;
164 case '6':
if (case_starts(
in,
"delivery")) {
166 if (case_starts(
in + i,
"qmtp:_ok"))
qmtp++;
167 if (case_starts(
in + i,
"qmtps:_ok"))
qmtps++;
173static void mrtg_smtplog(
char *
in,
char flag)
183 case 'a':
if (case_starts(
in + a,
"Accept"))
asessions++;
186 case 'b':
if (case_starts(
in + a,
"Accept::ORIG:"))
aorig++;
187 if (case_starts(
in + a,
"Accept::RCPT:"))
arcpt++;
189 case 'c':
if (case_starts(
in + r,
"Reject::SNDR::Invalid_Relay"))
rsend++;
190 if (case_starts(
in + r,
"Reject::SNDR::Bad_Helo"))
rhelo++;
191 if (case_starts(
in + r,
"Reject::SNDR::DNS_Helo"))
rhelo++;
193 case 'd':
if (case_starts(
in + r,
"Reject::ORIG::Bad_Mailfrom"))
rorigbad++;
194 if (case_starts(
in + r,
"Reject::ORIG::DNS_MF"))
rorigdns++;
196 case 'e':
if (case_starts(
in + r,
"Reject::RCPT::Bad_Rcptto"))
rrcptbad++;
197 if (case_starts(
in + r,
"Reject::RCPT::Failed_Rcptto"))
rrcptfail++;
199 case 'f':
if (case_starts(
in + r,
"Reject::DATA::Invalid_Size"))
rsize++;
200 if (case_starts(
in + r,
"Reject::DATA::Bad_MIME"))
rmime++;
201 if (case_starts(
in + r,
"Reject::DATA::MIME_Attach"))
rmime++;
202 if (case_starts(
in + r,
"Reject::DATA::Bad_Loader"))
rloader++;
204 case 'g':
if (case_starts(
in + r,
"Reject::DATA::Spam_Message"))
rspam++;
205 if (case_starts(
in + r,
"Reject::DATA::Virus_Infected"))
rvirus++;
207 case 'h':
if (case_starts(
in + a,
"Accept::AUTH:"))
aauth++;
208 if (case_starts(
in + r,
"Reject::AUTH:"))
rauth++;
210 case 'i':
if (case_starts(
in +
p,
"P:ESMTPS"))
atls++;
211 if (case_starts(
in + r,
"Reject::TLS:"))
rtls++;
213 case 'j':
if (case_starts(
in + a,
"Accept::SPF:"))
spfpass++;
214 if (case_starts(
in + r,
"Reject::SPF:"))
spfail++;
216 case 'k':
if (case_starts(
in +
d,
"Deferred::SNDR::Grey_Listed"))
grey++;
218 case 'm':
if (case_starts(
in + r,
"Rejected::SNDR::DKIM_Signature"))
rdkim++;
220 case 'z':
if (case_starts(
in,
"tcpserver") || case_starts(
in,
"sslserver") || case_starts(
in,
"rblsmtpd")) {
221 a = str_chr(
in,
':') + 2;
222 if (case_starts(
in + a,
"ok"))
sok++;
223 if (case_starts(
in + a,
"deny"))
sdeny++;
224 r = str_chr(
in + a,
':') + 2;
225 if (case_starts(
in + a + r,
"451"))
rbl++;
226 if (case_starts(
in + a + r,
"553"))
rbl++;
227 if (case_starts(
in + a + r + 1,
"reetdelay:"))
greet++;
233static void mrtg_pop3log(
char *
in,
char flag)
238 case 'A': a = str_chr(
in,
'A'); r = str_chr(
in,
'R');
239 if (case_starts(
in + a,
"Accept::AUTH:"))
apop++;
240 if (case_starts(
in + r,
"Reject::AUTH:"))
rpop++;
242 case 'B':
if (case_starts(
in,
"tcpserver:") || case_starts(
in,
"sslserver:")) {
243 a = str_chr(
in,
':') + 2;
244 if (case_starts(
in + a,
"ok"))
pok++;
245 if (case_starts(
in + a,
"deny"))
pdeny++;
251int main(
int argc,
char *
const argv[])
258 unsigned long calltime;
259 unsigned long seconds;
260 unsigned long nanoseconds;
261 unsigned int history = 305;
268 logmsg(
WHO,100,USAGE,
"qmail-mrtg [ -1 | -2 | -3 | -4 | -5 | -6 |\
269 -a | -b | -c | -d | -e | -f | -g | -h | -i | -j | -k | -m | -z | -A | -B ] [time (min)] \n\
270 qmail-mrtg needs to be called every [time] minutes (i.e. by crontab) - default 305 secs");
272 flag = *(argv[1] + 1);
273 if (argc == 3) { scan_ulong(argv[2],&u); history = 60 * u + 5; }
287 if (
line.s[0] ==
'@') {
297 seconds += nanoseconds >> 28;
298 nanoseconds &= 0xfffffff;
302 seconds -= 4611686018427387914ULL;
303 seconds = seconds > 0 ? seconds : 0;
305 outs(
"Error: No TAI64N timestamp available.");
310 if (seconds <= calltime && seconds >= (calltime - history)) {
311 if (flag >=
'1' && flag <=
'9') mrtg_sendlog(
line.s +
TAI64NLEN + 2,flag);
312 else if (flag >=
'a' && flag <=
'z') mrtg_smtplog(
line.s +
TAI64NLEN + 2,flag);
313 else if (flag >=
'A' && flag <=
'Z') mrtg_pop3log(
line.s +
TAI64NLEN + 2,flag);
319 outs(
"Warning: Not enough time left between calls");
void c(char *, char *, char *, int, int, int)
void p(char *, char *, int, int, int)
char bufspace[BUFSIZE_LINE]
char bufsmall[BUFFER_SMALL]