#! /usr/bin/perl -w $^W = 1; # same as -w above # (C) Copyright 2003 Rahul Dhesi, All rights reserved. # # "As is" -- No warranty. # # Copying, use, and modification are permitted, governed by # the GNU General Public License, by only those who agree # to use this program at their own risk. use strict; # unbuffered output is usually desired $| = 1; # $Source: /mi/maincvs/mail/count.pfq,v $ # $Id: count.pfq,v 1.5 2003/01/20 21:58:41 dhesi Exp $ # # Postfix queue count. # # Tested with these Postfix revisions: # 19991231-pl02 # 1.1.11 # 2.0.2 ## CONFIGURATION SECTION {{{ # Queue subdirectories directories to be scanned my @DIRS = qw(active bounce corrupt deferred incoming maildrop saved); # Default top queue directory; overridden only if -c is specified my $queuedir = '/var/spool/postfix'; ## }}} CONFIGURATION SECTION $::myname = $0; $::myname =~ s|.*/||; $::RCSHEADER = '$Source: /mi/maincvs/mail/count.pfq,v $' . "\n" . '$Id: count.pfq,v 1.5 2003/01/20 21:58:41 dhesi Exp $'; # suppresss perl warnings $::debug = $::trace = $::verbose = $::opt_h = undef; $::opt_v = $::opt_t = $::opt_x = undef; $::opt_q = undef; $::opt_X = undef; $::ddebug = undef; $::usage = "usage: $::myname [-vtxXq] [ -c confdir ] (or -h for help)"; if (@ARGV && $ARGV[0] =~ "^-.+" ) { local($^W) = 0; # suppress annoying undef warnings require "getopts.pl"; &Getopts("vtxXhqc:Z"); # Z will suppress perl warning } $::ddebug = $::opt_X; $::debug = $::ddebug || $::opt_x; $::trace = $::opt_t; $::verbose = $::debug || $::trace || $::opt_v; if ($::opt_h) { &givehelp(); exit(0); } ## (@ARGV < 1) && &usage_error; # All output goes to the OUTPUT filehandle. open(OUTPUT, ">&STDOUT"); # find instance-specific queue directory if ($::opt_c) { # try postconf first $queuedir = ''; if (open(POSTCONF, "postconf -c $::opt_c queue_directory|")) { while () { s/^\s+//; s/\s+$//; # trim leading/trailing blanks if (/^queue_directory\s+\=\s+(.*)$/) { $queuedir = $1; last; } } close(POSTCONF); } # failing that, read main.cf ourselves if (! $queuedir) { $::debug && warn "$::myname: error: can't invoke postconf to get queue_dir from $::opt_c\n"; my $cf = $::opt_c . '/main.cf'; if (open(CF, "<$cf")) { while () { chomp; s/^\s+//; s/\s+$//; # trim leading/trailing blanks if (/^queue_directory\s+\=\s+(.*)$/) { $queuedir = $1; last; } } } else { $::debug && warn "$::myname: error: can't read $cf: $!\n"; } } } $queuedir || die "$::myname: error: can't find queue dir for instance $::opt_c\n"; $::verbose && print OUTPUT "> scanning queues in $queuedir\n"; &pfq($queuedir); sub usage_error { my($msg) = @_; if ($msg) { die "$msg\n"; } else { die "$::usage\n"; } } sub givehelp { ## require 'local/page.pl'; ## &page(< scanning directory $path\n"; $count = &pfq_subdir($path); $::opt_q || printf(OUTPUT "%5d %s\n", $count, $path); $total += $count; } else { $::opt_q || warn "open($path) failed: $!\n"; } } $::opt_q || printf(OUTPUT "%5d %s\n", $total, 'TOTAL'); $::opt_q && print OUTPUT "$total\n"; } # .. called by pfq() to scan subdirectories sub pfq_subdir { my($dir) = @_; local(*DD); # make DD local opendir(DD, $dir) || do { warn "pfq: can't opendir $dir: $!\n"; return 0; }; $::ddebug && print OUTPUT "> scanning directory $dir\n"; my $entry; my $count = 0; while (defined($entry = readdir(DD))) { $entry eq '.' && next; $entry eq '..' && next; if ($entry =~ /^[a-fA-F0-9]$/) { # one-char name means dir $count += &pfq_subdir($dir . '/' . $entry); } elsif ($entry =~ /^[a-fA-F0-9]{5,}$/) { # 5 or more chars means file $count += 1; $::debug && print OUTPUT "$dir/$entry\n"; } else { $::debug && warn "pfq: invalid entry $dir/$entry\n"; } } closedir(DD); return $count; }