romain@pyramid.pyramid.com (Romain Kang) (03/19/90)
If you're really curious and you've got Internet or UUNET access, you can grab the whole sendmail source (about 500-600KB compressed). As far as I know, no one has seriously examined sendmail statistics. There's an obvious problem with multiple instances of sendmail pounding on the statistics file, even on uniprocessor machines. I would expect busy machines to undercount messages and bytes in some proportion to the sendmail load. Naturally, you could flock() the statistics file to gain greater accuracy but you would also introduce a bottleneck. In the absence of serious study, this would not make sense. Serious study would dictate clearing statistics every time the sendmail configuration was re-frozen, since the index associated with each mailer depends on the order of mailer declaration in sendmail.cf. Having said that, here's a perl script that displays the data. Running it on pyramid yields: Messages since 89/08/01 20:53:35: M# #msg from kB from #msg to kB to MAILER 0 45385 138851 76985 117250 local 1 0 0 3643 10725 prog 2 216639 1028497 239446 1015560 uux 3 43855 130507 230458 528055 ether #! /usr/local/bin/perl3 # # quick hack; apologies for lack of programming style... # $MSTATS = '/usr/lib/sendmail.st'; $CONFIG = '/usr/lib/sendmail.cf'; do readcf(); open MSTATS || die "Can't open $MSTATS"; @st = stat MSTATS; die "stat($MSTATS) failed" if ($#st < 0); # $st[7] = st_size if (($n = read(MSTATS, $buf, $st[7])) != $st[7]) { die "read returned $n (expected $st[7])"; } close MSTATS; # ($n - (sizeof(time_t) + sizeof(ushort) + pad)) / (4 * sizeof(long)); $nmailers = ($n - (4 + 2 + 2))/(4*4); $marray = 'L' . 4 * $nmailers; ($stat_itime, $stat_isize, @marray) = unpack("LSxx$marray", $buf); @lt = localtime($stat_itime); $lt[4]++; printf "Messages since %02d/%02d/%02d %02d:%02d:%02d:\n", reverse(@lt[0..5]); printf "M# %10s %10s %10s %10s\t%s\n", '#msg from', 'kB from', '#msg to', 'kB to', 'MAILER'; for ($i = 0; $i < $nmailers; $i++) { @m = @marray[$i, $i+$nmailers, $i+2*$nmailers, $i+3*$nmailers]; if ($m[0] || $m[2]) { printf "%2d %10d %10d %10d %10d\t%s\n", $i, @m, $Mailername[$i]; } } sub readcf { if (!open CONFIG) { warn "Can't get mailer names from $CONFIG"; return; } while (<CONFIG>) { chop; if (/^M([^,]+)/) { push(Mailername, $1); } } close CONFIG; }