exiwhat: Ensure the SIGUSR1 signal handler is safe.
[exim.git] / src / src / exiqgrep.src
CommitLineData
059ec3d9
PH
1#!PERL_COMMAND
2# $Cambridge: exim/src/src/exiqgrep.src,v 1.1 2004/10/07 10:39:01 ph10 Exp $
3
4# Utility for searching and displaying queue information.
5# Written by Matt Hubbard 15 August 2002
6
7# Except when they appear in comments, the following placeholders in this
8# source are replaced when it is turned into a runnable script:
9#
10# BIN_DIRECTORY
11# PERL_COMMAND
12
13# PROCESSED_FLAG
14
15
16# Routine for extracting the UTC timestamp from message ID
17# lifted from eximstat utility
18
19# Version 1.1
20
21use strict;
22use Getopt::Std;
23
24# Have this variable point to your exim binary.
25my $exim = 'BIN_DIRECTORY/exim';
26my $eargs = '-bpu';
27my %id;
28my %opt;
29my $count = 0;
30my $mcount = 0;
31my @tab62 =
32 (0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, # 0-9
33 0,10,11,12,13,14,15,16,17,18,19,20, # A-K
34 21,22,23,24,25,26,27,28,29,30,31,32, # L-W
35 33,34,35, 0, 0, 0, 0, 0, # X-Z
36 0,36,37,38,39,40,41,42,43,44,45,46, # a-k
37 47,48,49,50,51,52,53,54,55,56,57,58, # l-w
38 59,60,61); # x-z
39
40my $base;
41if ($^O eq 'darwin') { # aka MacOS X
42 $base = 36;
43 } else {
44 $base = 62;
45};
46
47getopts('hf:r:y:o:s:zxlibRc',\%opt);
48if ($opt{h}) { &help; exit;}
49
50# Read message queue output into hash
51&collect();
52# Identify which messages match selection criteria
53&selection();
54# Print matching data according to display option.
55&display();
56exit;
57
58
59sub help() {
60 print <<'EOF'
61Exim message queue display utility.
62
63 -h This help message.
64
65Selection criteria:
66 -f <regexp> Match sender address sender (field is "< >" wrapped)
67 -r <regexp> Match recipient address
68 -s <regexp> Match against the size field from long output
69 -y <seconds> Message younger than
70 -o <seconds> Message older than
71 -z Frozen messages only (exclude non-frozen)
72 -x Non-frozen messages only (exclude frozen)
73
74[ NB: for regexps, provided string sits in /<string>/ ]
75
76Display options:
77 -c Display match count
78 -l Long Format [Default]
79 -i Message IDs only
80 -b Brief Format
81 -R Reverse order
82EOF
83}
84
85sub collect() {
86 open(QUEUE,"$exim $eargs |") or die("Error openning pipe: $!\n");
87 while(<QUEUE>) {
88 chomp();
89 my $line = $_;
90 #Should be 1st line of record, if not error.
bd4c9759 91 if ($line =~ /^\s*(\w+)\s+((?:\d+(?:\.\d+)?[A-Z])?)\s*(\w{6}-\w{6}-\w{2})\s+(<.*?>)/) {
059ec3d9
PH
92 my $msg = $3;
93 $id{$msg}{age} = $1;
94 $id{$msg}{size} = $2;
95 $id{$msg}{from} = $4;
96 $id{$msg}{birth} = &msg_utc($msg);
97 $id{$msg}{ages} = time - $id{$msg}{birth};
98 if ($line =~ /\*\*\* frozen \*\*\*$/) {
99 $id{$msg}{frozen} = 1;
100 } else {
101 $id{$msg}{frozen} = 0;
102 }
103 while(<QUEUE> =~ /\s+(.*?\@.*)$/) {
104 push(@{$id{$msg}{rcpt}},$1);
105 }
106 # Increment message counter.
107 $count++;
108 } else {
109 print STDERR "Line mismatch: $line\n"; exit 1;
110 }
111 }
112 close(QUEUE) or die("Error closing pipe: $!\n");
113}
114
115sub selection() {
116 foreach my $msg (keys(%id)) {
117 if ($opt{f}) {
118 # Match sender address
119 next unless ($id{$msg}{from} =~ /$opt{f}/);
120 }
121 if ($opt{r}) {
122 # Match any recipient address
123 my $match = 0;
124 foreach my $rcpt (@{$id{$msg}{rcpt}}) {
125 $match++ if ($rcpt =~ /$opt{r}/);
126 }
127 next unless ($match);
128 }
129 if ($opt{s}) {
130 # Match against the size string.
131 next unless ($id{$msg}{size} =~ /$opt{s}/);
132 }
133 if ($opt{y}) {
134 # Match younger than
135 next unless ($id{$msg}{ages} < $opt{y});
136 }
137 if ($opt{o}) {
138 # Match older than
139 next unless ($id{$msg}{ages} > $opt{o});
140 }
141 if ($opt{z}) {
142 # Exclude non frozen
143 next unless ($id{$msg}{frozen});
144 }
145 if ($opt{x}) {
146 # Exclude frozen
147 next if ($id{$msg}{frozen});
148 }
149 # Here's what we do to select the record.
150 # Should only get this far if the message passed all of
151 # the active tests.
152 $id{$msg}{d} = 1;
153 # Increment match counter.
154 $mcount++;
155 }
156}
157
158sub display() {
159 if ($opt{c}) {
160 printf("%d matches out of %d messages\n",$mcount,$count);
161 exit;
162 }
163 foreach my $msg (sort { $opt{R} ? $id{$b}{birth} <=> $id{$a}{birth} : $id{$a}{birth} <=> $id{$b}{birth} } keys(%id) ) {
164 if (exists($id{$msg}{d})) {
165 if ($opt{i}) {
166 # Just the msg ID
167 print $msg, "\n";
168 } elsif ($opt{b}) {
169 # Brief format
170 printf("%s From: %s To: %s\n",$msg,$id{$msg}{from},join(';',@{$id{$msg}{rcpt}}))
171 } else {
172 # Otherwise Long format attempted duplication of original format.
173 printf("%3s %5s %s %s%s\n",$id{$msg}{age},$id{$msg}{size},$msg,$id{$msg}{from},$id{$msg}{frozen} ? " *** frozen ***" : "");
174 foreach my $rcpt (@{$id{$msg}{rcpt}}) {
175 printf(" %s\n",$rcpt);
176 }
177 print "\n";
178 }
179 }
180 }
181}
182
183sub report() {
184 foreach my $msg (keys(%id)) {
185 print "$id{$msg}{birth} $msg\tAge: $id{$msg}{age}\tSize: $id{$msg}{size}\tFrom: $id{$msg}{from}\tTo: " . join(" ",@{$id{$msg}{rcpt}}). "\n";
186 }
187}
188
189sub msg_utc() {
190 my $id = substr((pop @_), 0, 6);
191 my $s = 0;
192 my @c = split(//, $id);
193 while($#c >= 0) { $s = $s * $base + $tab62[ord(shift @c) - ord('0')] }
194 return $s;
195}