- 'spool:s' => \$G::spool, # exim spool dir
- 'bp' => \$G::mailq_bp, # List the queue (noop - default)
- 'bpa' => \$G::mailq_bpa, # ... with generated address as well
- 'bpc' => \$G::mailq_bpc, # ... but just show a count of messages
- 'bpr' => \$G::mailq_bpr, # ... do not sort
- 'bpra' => \$G::mailq_bpra, # ... with generated addresses, unsorted
- 'bpru' => \$G::mailq_bpru, # ... only undelivered addresses, unsorted
- 'bpu' => \$G::mailq_bpu, # ... only undelivered addresses
- 'and' => \$G::and, # 'and' the criteria (default)
- 'or' => \$G::or, # 'or' the criteria
- 'f:s' => \$G::qgrep_f, # from regexp
- 'r:s' => \$G::qgrep_r, # recipient regexp
- #'s:s' => \$G::qgrep_s, # match against size field
- 'y:s' => \$G::qgrep_y, # message younger than (secs)
- 'o:s' => \$G::qgrep_o, # message older than (secs)
- 'z' => \$G::qgrep_z, # frozen only
- 'x' => \$G::qgrep_x, # non-frozen only
- 'c' => \$G::qgrep_c, # display match count
- 'l' => \$G::qgrep_l, # long format (default)
- 'i' => \$G::qgrep_i, # message ids only
- 'b' => \$G::qgrep_b, # brief format
- 'flatq' => \$G::flatq, # brief format
- 'show-vars:s' => \$G::show_vars, # display the contents of these vars
- 'show-rules' => \$G::show_rules # display compiled match rules
-) || exit(1);
-
-push(@ARGV, "\$sender_address =~ /$G::qgrep_f/") if ($G::qgrep_f);
-push(@ARGV, "\$recipients =~ /$G::qgrep_r/") if ($G::qgrep_r);
-push(@ARGV, "\$message_age < $G::qgrep_y") if ($G::qgrep_y);
-push(@ARGV, "\$message_age > $G::qgrep_o") if ($G::qgrep_o);
-push(@ARGV, "\$deliver_freeze") if ($G::qgrep_z);
-push(@ARGV, "!\$deliver_freeze") if ($G::qgrep_x);
-$G::mailq_bp = $G::mailq_bp; # shut up -w
-$G::and = $G::and; # shut up -w
-$spool = $G::spool if ($G::spool);
-my $count_only = 1 if ($G::mailq_bpc || $G::qgrep_c);
-my $unsorted = 1 if ($G::mailq_bpr || $G::mailq_bpra || $G::mailq_bpru);
-my $msg = get_all_msgs($spool, $unsorted);
-my $crit = process_criteria(\@ARGV);
-my $e = Exim::SpoolFile->new();
-my $tcount = 0 if ($count_only);
-my $mcount = 0 if ($count_only);
-$e->set_spool($spool);
-$e->set_undelivered_only(1) if ($G::mailq_bpru || $G::mailq_bpu);
-$e->set_show_generated(1) if ($G::mailq_bpa || $G::mailq_bpra);
-$e->output_long() if ($G::qgrep_l);
-$e->output_idonly() if ($G::qgrep_i);
-$e->output_brief() if ($G::qgrep_b);
-$e->output_flatq() if ($G::flatq);
+ 'spool=s' => \$G::spool, # exim spool dir
+ 'C|Config=s' => \$G::config, # use alternative Exim configuration file
+ 'input-dir=s' => \$G::input_dir, # name of the "input" dir
+ 'queue=s' => \$G::queue, # name of the queue
+ 'finput' => \$G::finput, # same as "--input-dir Finput"
+ 'bp' => \$G::mailq_bp, # List the queue (noop - default)
+ 'bpa' => \$G::mailq_bpa, # ... with generated address as well
+ 'bpc' => \$G::mailq_bpc, # ... but just show a count of messages
+ 'bpr' => \$G::mailq_bpr, # ... do not sort
+ 'bpra' => \$G::mailq_bpra, # ... with generated addresses, unsorted
+ 'bpru' => \$G::mailq_bpru, # ... only undelivered addresses, unsorted
+ 'bpu' => \$G::mailq_bpu, # ... only undelivered addresses
+ 'and' => \$G::and, # 'and' the criteria (default)
+ 'or' => \$G::or, # 'or' the criteria
+ 'f=s' => \$G::qgrep_f, # from regexp
+ 'r=s' => \$G::qgrep_r, # recipient regexp
+ 's=s' => \$G::qgrep_s, # match against size field
+ 'y=s' => \$G::qgrep_y, # message younger than (secs)
+ 'o=s' => \$G::qgrep_o, # message older than (secs)
+ 'z' => \$G::qgrep_z, # frozen only
+ 'x' => \$G::qgrep_x, # non-frozen only
+ 'c' => \$G::qgrep_c, # display match count
+ 'l' => \$G::qgrep_l, # long format (default)
+ 'i' => \$G::qgrep_i, # message ids only
+ 'b' => \$G::qgrep_b, # brief format
+ 'size' => \$G::size_only, # sum the size of the matching msgs
+ 'not' => \$G::negate, # flip every test
+ 'R|reverse' => \$G::reverse, # reverse output (-R is qgrep option)
+ 'sort=s' => \@G::sort, # allow you to choose variables to sort by
+ 'freeze=s' => \$G::freeze, # freeze data in this file
+ 'thaw=s' => \$G::thaw, # thaw data from this file
+ 'unsorted' => \$G::unsorted, # unsorted, regardless of output format
+ 'random' => \$G::random, # (poorly) randomize evaluation order
+ 'flatq' => \$G::flatq, # brief format
+ 'caseful' => \$G::caseful, # in '=' criteria, respect case
+ 'caseless' => \$G::caseless, # ...ignore case (default)
+ 'charset=s' => \$charset, # charset for $bh and $h variables
+ 'show-vars=s' => \$G::show_vars, # display the contents of these vars
+ 'just-vars' => \$G::just_vars, # only display vars, no other info
+ 'show-rules' => \$G::show_rules, # display compiled match rules
+ 'show-tests' => \$G::show_tests, # display tests as applied to each message
+ 'man' => sub { pod2usage(-verbose => 2, -exit => 0, -noperldoc => system('perldoc -V >/dev/null 2>&1')) },
+ 'help' => sub { pod2usage(-verbose => 1, -exit => 0) },
+ 'version' => sub {
+ print "$p_name: $0\n",
+ "build: EXIM_RELEASE_VERSIONEXIM_VARIANT_VERSION\n",
+ "perl(runtime): $]\n";
+ exit 0;
+ },
+) or pod2usage;
+
+# if both freeze and thaw specified, only thaw as it is less destructive
+$G::freeze = undef if ($G::freeze && $G::thaw);
+freeze_start() if ($G::freeze);
+thaw_start() if ($G::thaw);
+
+# massage sort options (make '$var,Var:' be 'var','var')
+for (my $i = scalar(@G::sort)-1; $i >= 0; $i--) {
+ $G::sort[$i] = lc($G::sort[$i]);
+ $G::sort[$i] =~ s/[\$:\s]//g;
+ if ((my @vars = split(/,/, $G::sort[$i])) > 1) {
+ $G::sort[$i] = $vars[0]; shift(@vars); # replace current slot w/ first var
+ splice(@G::sort, $i+1, 0, @vars); # add other vars after current pos
+ }
+}
+push(@G::sort, "message_exim_id") if (@G::sort);
+die "empty value provided to --sort not allowed, exiting\n"
+ if (grep /^\s*$/, @G::sort);
+
+# massage the qgrep options into standard criteria
+push(@ARGV, "\$sender_address =~ /$G::qgrep_f/") if ($G::qgrep_f);
+push(@ARGV, "\$recipients =~ /$G::qgrep_r/") if ($G::qgrep_r);
+push(@ARGV, "\$shown_message_size eq $G::qgrep_s") if ($G::qgrep_s);
+push(@ARGV, "\$message_age < $G::qgrep_y") if ($G::qgrep_y);
+push(@ARGV, "\$message_age > $G::qgrep_o") if ($G::qgrep_o);
+push(@ARGV, "\$deliver_freeze") if ($G::qgrep_z);
+push(@ARGV, "!\$deliver_freeze") if ($G::qgrep_x);
+
+$G::mailq_bp = $G::mailq_bp; # shut up -w
+$G::and = $G::and; # shut up -w
+$G::msg_ids = {}; # short circuit when crit is only MID
+$G::caseless = $G::caseful ? 0 : 1; # nocase by default, case if both
+@G::recipients_crit = (); # holds per-recip criteria
+$spool = defined $G::spool ? $G::spool
+ : do { chomp($_ = `$exim @{[defined $G::config ? "-C $G::config" : '']} -n -bP spool_directory`)
+ and $_ or $spool };
+my $input_dir = (defined $G::queue ? "$G::queue/" : '')
+ . (defined $G::input_dir || ($G::finput ? "Finput" : "input"));
+my $count_only = 1 if ($G::mailq_bpc || $G::qgrep_c);
+my $unsorted = 1 if ($G::mailq_bpr || $G::mailq_bpra ||
+ $G::mailq_bpru || $G::unsorted);
+my $msg = $G::thaw ? thaw_message_list()
+ : get_all_msgs($spool, $input_dir, $unsorted,
+ $G::reverse, $G::random);
+die "Problem accessing thaw file\n" if ($G::thaw && !$msg);
+my $crit = process_criteria(\@ARGV);
+my $e = Exim::SpoolFile->new();
+my $tcount = 0 if ($count_only); # holds count of all messages
+my $mcount = 0 if ($count_only); # holds count of matching messages
+my $total_size = 0 if ($G::size_only);
+$e->set_undelivered_only(1) if ($G::mailq_bpru || $G::mailq_bpu);
+$e->set_show_generated(1) if ($G::mailq_bpra || $G::mailq_bpa);
+$e->output_long() if ($G::qgrep_l);
+$e->output_idonly() if ($G::qgrep_i);
+$e->output_brief() if ($G::qgrep_b);
+$e->output_flatq() if ($G::flatq);
+$e->output_vars_only() if ($G::just_vars && $G::show_vars);