summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/contrib
diff options
context:
space:
mode:
authorgshapiro <gshapiro@FreeBSD.org>2000-08-12 21:55:49 +0000
committergshapiro <gshapiro@FreeBSD.org>2000-08-12 21:55:49 +0000
commit4332139a9a11f773ffe5109bed871561e3c290a1 (patch)
tree6d207932926718f38869bd08959330c09f4f3e0d /contrib/sendmail/contrib
parenta392fe0bdb7081117c445f5dcc98d5ed4013dc17 (diff)
downloadFreeBSD-src-4332139a9a11f773ffe5109bed871561e3c290a1.zip
FreeBSD-src-4332139a9a11f773ffe5109bed871561e3c290a1.tar.gz
Import of sendmail version 8.11.0 into vendor branch SENDMAIL with
release tag v8_11_0. Obtained from: ftp://ftp.sendmail.org/pub/sendmail/
Diffstat (limited to 'contrib/sendmail/contrib')
-rw-r--r--contrib/sendmail/contrib/README4
-rw-r--r--contrib/sendmail/contrib/bitdomain.c14
-rwxr-xr-xcontrib/sendmail/contrib/bounce-resender.pl282
-rw-r--r--contrib/sendmail/contrib/bsdi.mc2
-rwxr-xr-xcontrib/sendmail/contrib/cidrexpand137
-rw-r--r--contrib/sendmail/contrib/domainmap.m490
-rwxr-xr-xcontrib/sendmail/contrib/etrn.pl51
-rwxr-xr-xcontrib/sendmail/contrib/expn.pl2
-rw-r--r--contrib/sendmail/contrib/link_hash.sh36
-rw-r--r--contrib/sendmail/contrib/movemail.conf35
-rwxr-xr-xcontrib/sendmail/contrib/movemail.pl106
-rwxr-xr-xcontrib/sendmail/contrib/passwd-to-alias.pl13
-rw-r--r--contrib/sendmail/contrib/qtool.8206
-rwxr-xr-xcontrib/sendmail/contrib/qtool.pl1190
-rw-r--r--contrib/sendmail/contrib/re-mqueue.pl87
-rwxr-xr-xcontrib/sendmail/contrib/smcontrol.pl6
16 files changed, 2208 insertions, 53 deletions
diff --git a/contrib/sendmail/contrib/README b/contrib/sendmail/contrib/README
index dcf5c8f..1098f48 100644
--- a/contrib/sendmail/contrib/README
+++ b/contrib/sendmail/contrib/README
@@ -5,6 +5,6 @@ for assistance.
Some of these are patches to sendmail itself. You may need to take
care -- some of the patches may be out of date with the latest release
of sendmail. Also, the previous comment applies -- patches belong to
-the original author, not to me.
+the original author, not to us.
-Eric Allman, 26 May 1993
+$Revision: 8.2 $, Last updated $Date: 1999/09/24 05:46:47 $
diff --git a/contrib/sendmail/contrib/bitdomain.c b/contrib/sendmail/contrib/bitdomain.c
index 52d6d21..0b7073d 100644
--- a/contrib/sendmail/contrib/bitdomain.c
+++ b/contrib/sendmail/contrib/bitdomain.c
@@ -9,11 +9,11 @@
* Change directory to "netinfo" and get the file internet.listing
* The file is updated monthly.
*
- * Feed the output of this program to "makemap hash /etc/bitdomain.db"
+ * Feed the output of this program to "makemap hash /etc/mail/bitdomain.db"
* to create the table used by the "FEATURE(bitdomain)" config file macro.
* If your sendmail does not have the db library compiled in, you can instead
- * use "makemap dbm /etc/bitdomain" and
- * "FEATURE(bitdomain,`dbm -o /etc/bitdomain')"
+ * use "makemap dbm /etc/mail/bitdomain" and
+ * "FEATURE(bitdomain,`dbm -o /etc/mail/bitdomain')"
*
* The bitdomain table should be rebuilt monthly.
*/
@@ -51,7 +51,7 @@ char **argv;
{
int opt;
- while ((opt = getopt(argc, argv, "o:")) != EOF) {
+ while ((opt = getopt(argc, argv, "o:")) != -1) {
switch (opt) {
case 'o':
if (!freopen(optarg, "w", stdout)) {
@@ -187,7 +187,7 @@ char *domainlen;
case NO_DATA:
err = "registered in DNS, but not mailable";
break;
-
+
default:
err = "unknown nameserver error";
break;
@@ -210,7 +210,7 @@ valhost(host, hbsize)
int hbsize;
{
register u_char *eom, *ap;
- register int n;
+ register int n;
HEADER *hp;
querybuf answer;
int ancount, qdcount;
@@ -406,4 +406,4 @@ finish()
}
}
}
-
+
diff --git a/contrib/sendmail/contrib/bounce-resender.pl b/contrib/sendmail/contrib/bounce-resender.pl
new file mode 100755
index 0000000..9253cdd
--- /dev/null
+++ b/contrib/sendmail/contrib/bounce-resender.pl
@@ -0,0 +1,282 @@
+#!/usr/local/bin/perl -w
+#
+# bounce-resender: constructs mail queue from bounce spool for
+# subsequent reprocessing by sendmail
+#
+# usage: given a mail spool full of (only) bounced mail called "bounces":
+# # mkdir -m0700 bqueue; cd bqueue && bounce-resender < ../bounces
+# # cd ..
+# # chown -R root bqueue; chmod 600 bqueue/*
+# # /usr/lib/sendmail -bp -oQ`pwd`/bqueue | more # does it look OK?
+# # /usr/lib/sendmail -q -oQ`pwd`/bqueue -oT99d & # run the queue
+#
+# ** also read messages at end! **
+#
+# Brian R. Gaeke <brg@EECS.Berkeley.EDU> Thu Feb 18 13:40:10 PST 1999
+#
+#############################################################################
+# This script has NO WARRANTY, NO BUG FIXES, and NO SUPPORT. You will
+# need to modify it for your site and for your operating system, unless
+# you are in the EECS Instructional group at UC Berkeley. (Search forward
+# for two occurrences of "FIXME".)
+#
+
+$state = "MSG_START";
+$ctr = 0;
+$lineno = 0;
+$getnrl = 0;
+$nrl = "";
+$uname = "PhilOS"; # You don't want to change this here.
+$myname = $0;
+$myname =~ s,.*/([^/]*),$1,;
+
+chomp($hostname = `hostname`);
+chomp($uname = `uname`);
+
+# FIXME: Define the functions "major" and "minor" for your OS.
+if ($uname eq "SunOS") {
+ # from h2ph < /usr/include/sys/sysmacros.h on
+ # SunOS torus.CS.Berkeley.EDU 5.6 Generic_105182-11 i86pc i386 i86pc
+ eval 'sub O_BITSMINOR () {8;}' unless defined(&O_BITSMINOR);
+ eval 'sub O_MAXMAJ () {0x7f;}' unless defined(&O_MAXMAJ);
+ eval 'sub O_MAXMIN () {0xff;}' unless defined(&O_MAXMIN);
+ eval 'sub major {
+ local($x) = @_;
+ eval "((($x) >> &O_BITSMINOR) &O_MAXMAJ)";
+ }' unless defined(&major);
+ eval 'sub minor {
+ local($x) = @_;
+ eval "(($x) &O_MAXMIN)";
+ }' unless defined(&minor);
+} else {
+ die "How do you calculate major and minor device numbers on $uname?\n";
+}
+
+sub ignorance { $ignored{$state}++; }
+
+sub unmunge {
+ my($addr) = @_;
+ $addr =~ s/_FNORD_/ /g;
+ # remove (Real Name)
+ $addr =~ s/^(.*)\([^\)]*\)(.*)$/$1$2/
+ if $addr =~ /^.*\([^\)]*\).*$/;
+ # extract <user@host> if it appears
+ $addr =~ s/^.*<([^>]*)>.*$/$1/
+ if $addr =~ /^.*<[^>]*>.*$/;
+ # strip leading, trailing blanks
+ $addr =~ s/^\s*(.*)\s*/$1/;
+ # nuke local domain
+ # FIXME: Add a regular expression for your local domain here.
+ $addr =~
+ s/@(cory|po|pasteur|torus|parker|cochise|franklin).(ee)?cs.berkeley.edu//i;
+ return $addr;
+}
+
+print STDERR "$0: running on $hostname ($uname)\n";
+
+open(INPUT,$ARGV[0]) || die "$ARGV[0]: $!\n";
+
+sub working {
+ my($now);
+ $now = localtime;
+ print STDERR "$myname: Working... $now\n";
+}
+
+&working();
+
+while (! eof INPUT) {
+ # get a new line
+ if ($state eq "IN_MESSAGE_HEADER") {
+ # handle multi-line headers
+ if ($nrl ne "" || $getnrl != 0) {
+ $_ = $nrl;
+ $getnrl = 0;
+ $nrl = "";
+ } else {
+ $_ = <INPUT>; $lineno++;
+ }
+ unless ($_ =~ /^\s*$/) {
+ while ($nrl eq "") {
+ $nrl = <INPUT>; $lineno++;
+ if ($nrl =~ /^\s+[^\s].*$/) { # continuation line
+ chomp($_);
+ $_ .= "_FNORD_" . $nrl;
+ $nrl = "";
+ } elsif ($nrl =~ /^\s*$/) { # end of headers
+ $getnrl++;
+ last;
+ }
+ }
+ }
+ } else {
+ # normal single line
+ if ($nrl ne "") {
+ $_ = $nrl; $nrl = "";
+ } else {
+ $_ = <INPUT>; $lineno++;
+ }
+ }
+
+ if ($state eq "WAIT_FOR_FROM") {
+ if (/^From \S+.*$/) {
+ $state = "MSG_START";
+ } else {
+ &ignorance();
+ }
+ } elsif ($state eq "MSG_START") {
+ if (/^\s+boundary=\"([^\"]*)\".*$/) {
+ $boundary = $1;
+ $state = "GOT_BOUNDARY";
+ $ctr++;
+ } else {
+ &ignorance();
+ }
+ } elsif ($state eq "GOT_BOUNDARY") {
+ if (/^--$boundary/) {
+ $next = <INPUT>; $lineno++;
+ if ($next =~ /^Content-Type: message\/rfc822/) {
+ $hour = (localtime)[2];
+ $char = chr(ord("A") + $hour);
+ $ident = sprintf("%sAA%05d",$char,99999 - $ctr);
+ $qf = "qf$ident";
+ $df = "df$ident";
+ @rcpt = ();
+ open(MSGHDR,">$qf") || die "Can't write to $qf: $!\n";
+ open(MSGBODY,">$df") || die "Can't write to $df: $!\n";
+ chmod(0600, $qf, $df);
+ $state = "IN_MESSAGE_HEADER";
+ $header = $body = "";
+ $messageid = "bounce-resender-$ctr";
+ $fromline = "MAILER-DAEMON";
+ $ctencod = "7BIT";
+ # skip a bit, brother maynard (boundary is separated from
+ # the header by a blank line)
+ $next = <INPUT>; $lineno++;
+ unless ($next =~ /^\s*$/) {
+ print MSGHDR $next;
+ }
+ }
+ } else {
+ &ignorance();
+ }
+
+ $next = $char = $hour = undef;
+ } elsif ($state eq "IN_MESSAGE_HEADER") {
+ if (!(/^--$boundary/ || /^\s*$/)) {
+ if (/^Message-[iI][dD]:\s+<([^@]+)@[^>]*>.*$/) {
+ $messageid = $1;
+ } elsif (/^From:\s+(.*)$/) {
+ $fromline = $sender = $1;
+ $fromline = unmunge($fromline);
+ } elsif (/^Content-[Tt]ransfer-[Ee]ncoding:\s+(.*)$/) {
+ $ctencod = $1;
+ } elsif (/^(To|[Cc][Cc]):\s+(.*)$/) {
+ $toaddrs = $2;
+ foreach $toaddr (split(/,/,$toaddrs)) {
+ $toaddr = unmunge($toaddr);
+ push(@rcpt,$toaddr);
+ }
+ }
+ $headerline = $_;
+ # escape special chars
+ # (Perhaps not. It doesn't seem to be necessary (yet)).
+ #$headerline =~ s/([\(\)<>@,;:\\".\[\]])/\\$1/g;
+ # purely heuristic ;-)
+ $headerline =~ s/Return-Path:/?P?Return-Path:/g;
+ # save H-line to write to qf, later
+ $header .= "H$headerline";
+
+ $headerline = $toaddr = $toaddrs = undef;
+ } elsif (/^\s*$/) {
+ # write to qf
+ ($dev, $ino) = (stat($df))[0 .. 1];
+ ($maj, $min) = (major($dev), minor($dev));
+ $time = time();
+ print MSGHDR "V2\n";
+ print MSGHDR "B$ctencod\n";
+ print MSGHDR "S$sender\n";
+ print MSGHDR "I$maj/$min/$ino\n";
+ print MSGHDR "K$time\n";
+ print MSGHDR "T$time\n";
+ print MSGHDR "D$df\n";
+ print MSGHDR "N1\n";
+ print MSGHDR "MDeferred: manually-requeued bounced message\n";
+ foreach $r (@rcpt) {
+ print MSGHDR "RP:$r\n";
+ }
+ $header =~ s/_FNORD_/\n/g;
+ print MSGHDR $header;
+ print MSGHDR "HMessage-ID: <$messageid@$hostname>\n"
+ if ($messageid =~ /bounce-resender/);
+ print MSGHDR ".\n";
+ close MSGHDR;
+
+ # jump to state waiting for message body
+ $state = "IN_MESSAGE_BODY";
+
+ $dev = $ino = $maj = $min = $r = $time = undef;
+ } elsif (/^--$boundary/) {
+ # signal an error
+ print "$myname: Header without message! Line $lineno qf $qf\n";
+
+ # write to qf anyway (SAME AS ABOVE, SHOULD BE A PROCEDURE)
+ ($dev, $ino) = (stat($df))[0 .. 1];
+ ($maj, $min) = (major($dev), minor($dev));
+ $time = time();
+ print MSGHDR "V2\n";
+ print MSGHDR "B$ctencod\n";
+ print MSGHDR "S$sender\n";
+ print MSGHDR "I$maj/$min/$ino\n";
+ print MSGHDR "K$time\n";
+ print MSGHDR "T$time\n";
+ print MSGHDR "D$df\n";
+ print MSGHDR "N1\n";
+ print MSGHDR "MDeferred: manually-requeued bounced message\n";
+ foreach $r (@rcpt) {
+ print MSGHDR "RP:$r\n";
+ }
+ $header =~ s/_FNORD_/\n/g;
+ print MSGHDR $header;
+ print MSGHDR "HMessage-ID: <$messageid@$hostname>\n"
+ if ($messageid =~ /bounce-resender/);
+ print MSGHDR ".\n";
+ close MSGHDR;
+
+ # jump to state waiting for next bounce message
+ $state = "WAIT_FOR_FROM";
+
+ $dev = $ino = $maj = $min = $r = $time = undef;
+ } else {
+ # never got here
+ &ignorance();
+ }
+ } elsif ($state eq "IN_MESSAGE_BODY") {
+ if (/^--$boundary/) {
+ print MSGBODY $body;
+ close MSGBODY;
+ $state = "WAIT_FOR_FROM";
+ } else {
+ $body .= $_;
+ }
+ }
+ if ($lineno % 1900 == 0) { &working(); }
+}
+
+close INPUT;
+
+foreach $x (keys %ignored) {
+ print STDERR
+ "$myname: ignored $ignored{$x} lines of bounce spool in state $x\n";
+}
+print STDERR
+ "$myname: processed $lineno lines of input and wrote $ctr messages\n";
+print STDERR
+ "$myname: remember to chown the queue files to root before running:\n";
+chomp($pwd = `pwd`);
+print STDERR "$myname: # sendmail -q -oQ$pwd -oT99d &\n";
+
+print STDERR "$myname: to test the newly generated queue:\n";
+print STDERR "$myname: # sendmail -bp -oQ$pwd | more\n";
+
+exit 0;
+
diff --git a/contrib/sendmail/contrib/bsdi.mc b/contrib/sendmail/contrib/bsdi.mc
index 231a7bc..5175a34 100644
--- a/contrib/sendmail/contrib/bsdi.mc
+++ b/contrib/sendmail/contrib/bsdi.mc
@@ -35,7 +35,7 @@ and examples describing most of the common things people need to setup.
# See /usr/share/sendmail/README for help in building a configuration file.
#
include(`../m4/cf.m4')
-VERSIONID(`@(#)$Id$')
+VERSIONID(`@(#)$Id: bsdi.mc,v 8.1 1999/02/06 18:44:08 gshapiro Exp $')
dnl # Specify your OS type below
OSTYPE(`bsd4.4')
diff --git a/contrib/sendmail/contrib/cidrexpand b/contrib/sendmail/contrib/cidrexpand
new file mode 100755
index 0000000..b61fc2e
--- /dev/null
+++ b/contrib/sendmail/contrib/cidrexpand
@@ -0,0 +1,137 @@
+#!/usr/local/bin/perl -w
+
+# v 0.2-very-very-beta
+#
+# 17 July 2000 Derek J. Balling (dredd@megacity.org)
+#
+# The $SENDMAIL flag tells the code to lump networks in sendmail format
+# if applicable. If this flag is disabled, cidrexpand will literally create
+# a single line for each entry, which may or may not be what you want. :)
+# makes for a rather large hash table...
+#
+# Acts as a preparser on /etc/mail/access_db to allow you to use address/bit
+# notation. Caveat: the address portion MUST be the start address or your
+# results will NOT be what what you want.
+#
+#
+# usage:
+# cidrexpand < /etc/mail/access | makemap hash /etc/mail/access
+#
+#
+# Report bugs to: dredd@megacity.org
+#
+
+my $spaceregex = '\s+';
+
+while (my $arg = shift @ARGV)
+{
+ if ($arg eq '-t')
+ {
+ $spaceregex = shift;
+ }
+}
+
+use strict;
+
+my $SENDMAIL = 1;
+
+while (<>)
+{
+ my ($left,$right,$space);
+
+ if (! /^(\d+\.){3}\d+\/\d\d?$spaceregex.*/ )
+ {
+ print;
+ }
+ else
+ {
+ ($left,$space,$right) = /^((?:\d+\.){3}\d+\/\d\d?)($spaceregex)(.*)$/;
+
+ my @new_lefts = expand_network($left);
+ foreach my $nl (@new_lefts)
+ {
+ print "$nl$space$right\n";
+ }
+
+ }
+}
+
+sub expand_network
+{
+ my ($network,$mask) = split /\//, shift;
+ my @diffs = calc_changes($network,$mask);
+ my ($first,$second,$third,$fourth) = split /\./, $network;
+
+ my @rc = ();
+
+ for my $f ($first..($first+$diffs[0]))
+ {
+ if ( ( $SENDMAIL ) and ($diffs[1] == 255))
+ {
+ push @rc, "$f";
+ }
+ else
+ {
+ for my $s ($second..($second+$diffs[1]))
+ {
+ if ( ($SENDMAIL) and ($diffs[2] == 255) )
+ {
+ push @rc,"$f\.$s";
+ }
+ else
+ {
+ for my $t ($third..($third+$diffs[2]))
+ {
+ if ( ($SENDMAIL) and ($diffs[3] == 255))
+ {
+ push @rc, "$f\.$s\.$t";
+ }
+ else
+ {
+ for my $fr ($fourth..($fourth+$diffs[3]))
+ {
+ push @rc, "$f\.$s\.$t\.$fr";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return @rc;
+}
+
+sub calc_changes
+{
+ my ($network,$mask) = @_;
+
+ my @octs = split /\./, $network;
+
+ my ($first,$second,$third,$fourth) = (0,0,0,0);
+
+ my $power = 32 - $mask;
+
+ if ($mask > 24)
+ {
+ $fourth = 2**$power - 1;
+ }
+ elsif ($mask > 16)
+ {
+ $fourth = 255;
+ $third = 2**($power-8) - 1;
+ }
+ elsif ($mask > 8)
+ {
+ $fourth = 255;
+ $third = 255;
+ $second = 2**($power-16) - 1;
+ }
+ elsif ($mask > 0)
+ {
+ $fourth = 255;
+ $third = 255;
+ $second = 255;
+ $first = 2**($power-24) - 1;
+ }
+ return ($first,$second,$third,$fourth);
+}
diff --git a/contrib/sendmail/contrib/domainmap.m4 b/contrib/sendmail/contrib/domainmap.m4
new file mode 100644
index 0000000..31d284c
--- /dev/null
+++ b/contrib/sendmail/contrib/domainmap.m4
@@ -0,0 +1,90 @@
+divert(-1)changequote(<<, >>)<<
+-----------------------------------------------------------------------------
+
+ FEATURE(domainmap) Macro
+
+ The existing virtusertable feature distributed with sendmail is a good
+ basic approach to virtual hosting, but it is missing a few key
+ features:
+
+ 1. Ability to have a different map for each domain.
+ 2. Ability to perform virtual hosting for domains which are not in $=w.
+ 3. Ability to use a centralized network-accessible database (such as
+ PH) which is keyed on username alone (as opposed to the
+ fully-qualified email address).
+
+ The FEATURE(domainmap) macro neatly solves these problems.
+
+ The basic syntax of the macro is:
+ FEATURE(domainmap, `domain.com', `map definition ...')dnl
+
+ To illustrate how it works, here is an example:
+ FEATURE(domainmap, `foo.com', `dbm -o /etc/mail/foo-users')dnl
+
+ In this example, mail sent to user@foo.com will be rewritten by the
+ domainmap. The username will be looked up in the DBM map
+ /etc/mail/foo-users, which looks like this:
+ jsmith johnsmith@mailbox.foo.com
+ jdoe janedoe@sandbox.bar.com
+
+ So mail sent to jsmith@foo.com will be relayed to
+ johnsmith@mailbox.foo.com, and mail sent to jdoe@foo.com will be
+ relayed to janedoe@sandbox.bar.com.
+
+ The FEATURE(domainmap) Macro supports the user+detail syntax by
+ stripping off the +detail portion before the domainmap lookup and
+ tacking it back on to the result. Using the example above, mail sent
+ to jsmith+sometext@foo.com will be rewritten as
+ johnsmith+sometext@mailbox.foo.com.
+
+ If one of the elements in the $=w class (i.e., "local" delivery hosts)
+ is a domain specified in a FEATURE(domainmap) entry, you need to use
+ the LOCAL_USER(username) macro to specify the list of users for whom
+ domainmap lookups should not be done.
+
+ To use this macro, simply copy this file into the cf/feature directory
+ in the sendmail source tree. For more information, please see the
+ following URL:
+
+ http://www-wsg.cso.uiuc.edu/sendmail/patches/domainmap.html
+
+ Feedback is welcome.
+
+ Mark D. Roth <roth@uiuc.edu>
+
+-----------------------------------------------------------------------------
+>>changequote(`, ')undivert(-1)divert
+
+ifdef(`_DOMAIN_MAP_',`',`dnl
+LOCAL_RULE_0
+# do mapping for domains where applicable
+R$* $=O $* <@ $={MappedDomain} .> $@ $>97 $1 $2 $3 Strip extraneous routing
+R$+ <@ $={MappedDomain} .> $>DomainMapLookup $1 <@ $2 .> domain mapping
+
+LOCAL_RULESETS
+###########################################################################
+### Ruleset DomainMapLookup -- special rewriting for mapped domains ###
+###########################################################################
+
+SDomainMapLookup
+R $=L <@ $=w .> $@ $1 <@ $2 .> weed out local users, in case
+# Cw contains a mapped domain
+R $+ <@ $+ .> $1 <@ $2 > strip trailing dot
+R $+ <@ $+ . $+ > $1 <@ $(dequote $2 "_" $3 $) >
+# change "." to "_"
+R $+ <@ $+ > $: $1 <@ $(dequote "domain_" $2 $) >
+# prepend "domain_"
+R $+ + $+ <@ $*> $1 <@ $3 > <+> $2 handle user+list syntax
+R $+ <@ $* > $* $( $2 $1 $: <ERROR> $) $3
+# do actual domain map lookup
+R <ERROR> $* $#error $@ 5.1.1 $: "550 email address lookup in domain map failed"
+R $* <TEMP> $* $#error $@ 4.3.0 $: "450 domain map temporarily unavailable"
+R $+ @ $+ <+> $+ $1 + $3 @ $2 reset original user+list
+R $+ <+> $* $1 paranoid check - remove <+>
+R $+ @ $+ . $1 @ $2 strip trailing dot
+R $+ @ $+ $@ $>97 $1 @ $2 recanonify
+define(`_DOMAIN_MAP_',`1')')
+
+LOCAL_CONFIG
+C{MappedDomain} _ARG_
+K `domain_'translit(_ARG_, `.', `_') _ARG2_ -T<TEMP>
diff --git a/contrib/sendmail/contrib/etrn.pl b/contrib/sendmail/contrib/etrn.pl
index 1e2cba9..2dfb58d 100755
--- a/contrib/sendmail/contrib/etrn.pl
+++ b/contrib/sendmail/contrib/etrn.pl
@@ -15,7 +15,7 @@ $sockaddr = 'S n a4 x8';
# must have 'hostname' program.
#############################################################################
-# Copyright (c) 1996 John T. Beck <john@beck.org>
+# Copyright (c) 1996-2000 John T. Beck <john@beck.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -60,7 +60,7 @@ $0 = "$av0 - running hostname";
chop($name = `hostname || uname -n`);
$0 = "$av0 - lookup host FQDN and IP addr";
-($hostname,$aliases,$type,$len,$thisaddr) = gethostbyname($name);
+($hostname,$aliases,$type,$len,undef) = gethostbyname($name);
$0 = "$av0 - parsing args";
$usage = "Usage: $av0 [-wd] host [args]";
@@ -71,12 +71,13 @@ $server = shift(@ARGV);
@hosts = @ARGV;
die $usage unless $server;
@cwfiles = ();
+$alarm_action = "";
if (!@hosts) {
push(@hosts,$hostname);
$0 = "$av0 - parsing sendmail.cf";
- open(CF, "</etc/sendmail.cf") || die "open /etc/sendmail.cf: $!";
+ open(CF, "</etc/mail/sendmail.cf") || die "open /etc/mail/sendmail.cf: $!";
while (<CF>){
if (/^Fw.*$/){ # look for a line starting with "Fw"
$cwfile = $_;
@@ -125,6 +126,7 @@ $0 = "$av0 - building local socket";
$0 = "$av0 - gethostbyname($server)";
($name,$aliases,$type,$len,$thataddr) = gethostbyname($server);
+(!defined($name)) && die "gethostbyname failed, unknown host $server";
# get a connection
$0 = "$av0 - socket to $server";
@@ -132,22 +134,24 @@ $that = pack($sockaddr, &AF_INET, $port, $thataddr);
socket(S, &AF_INET, &SOCK_STREAM, $proto)
|| die "socket: $!";
$0 = "$av0 - connect to $server";
-print "debug = $debug server = $server\n" if $debug > 8;
+print "debug = $debug server = $server\n" if (defined($debug) && $debug > 8);
+&alarm("connect to $server");
if (! connect(S, $that)) {
- $0 = "$av0 - $server: could not connect: $!\n";
+ die "cannot connect to $server: $!\n";
}
+alarm(0);
select((select(S),$| = 1)[0]); # don't buffer output to S
# read the greeting
$0 = "$av0 - talking to $server";
-&alarm("greeting with $server",'');
+&alarm("greeting with $server");
while(<S>) {
alarm(0);
print if $watch;
if (/^(\d+)([- ])/) {
if ($1 != 220) {
$0 = "$av0 - bad numeric response from $server";
- &alarm("giving up after bad response from $server",'');
+ &alarm("giving up after bad response from $server");
&read_response($2,$watch);
alarm(0);
print STDERR "$server: NOT 220 greeting: $_"
@@ -160,13 +164,13 @@ while(<S>) {
if ($debug || $watch);
close(S);
}
- &alarm("greeting with $server",'');
+ &alarm("greeting with $server");
}
alarm(0);
# if this causes problems, remove it
$0 = "$av0 - sending helo to $server";
-&alarm("sending ehlo to $server","");
+&alarm("sending ehlo to $server");
&ps("ehlo $hostname");
$etrn_support = 0;
while(<S>) {
@@ -180,7 +184,7 @@ alarm(0);
if ($etrn_support){
print "ETRN supported\n" if ($debug);
- &alarm("sending etrn to $server",'');
+ &alarm("sending etrn to $server");
while (@hosts) {
$server = shift(@hosts);
&ps("etrn $server");
@@ -194,7 +198,7 @@ if ($etrn_support){
print "\nETRN not supported\n\n"
}
-&alarm("sending 'quit' to $server",'');
+&alarm("sending 'quit' to $server");
$0 = "$av0 - sending 'quit' to $server";
&ps("quit");
while(<S>) {
@@ -217,14 +221,25 @@ sub ps
sub alarm
{
- local($alarm_action,$alarm_redirect,$alarm_user) = @_;
- alarm(3600);
+ ($alarm_action) = @_;
+ alarm(10);
$SIG{ALRM} = 'handle_alarm';
}
sub handle_alarm
{
- &giveup($alarm_redirect,"Timed out during $alarm_action",$alarm_user);
+ &giveup($alarm_action);
+}
+
+sub giveup
+{
+ local($reason) = @_;
+ local($pk,$file,$line);
+ ($pk, $file, $line) = caller;
+
+ $0 = "$av0 - giving up on $server: $reason";
+ print "Timed out during $reason\n" if $debug;
+ exit(1);
}
# read the rest of the current smtp daemon's response (and toss it away)
@@ -241,9 +256,9 @@ sub read_response
return @resp;
}
# to pass perl -w:
-@tp;
-$flag_a;
-$flag_d;
+my $x;
+$x=$opt_d;
+$x=$opt_w;
&handle_alarm;
################### BEGIN PERL/TROFF TRANSITION
.00 ;
@@ -300,7 +315,7 @@ it is possible to eliminate bugs.
.SH ENVIRONMENT
No enviroment variables are used.
.SH FILES
-.B /etc/sendmail.cf
+.B /etc/mail/sendmail.cf
.SH SEE ALSO
.BR sendmail (8),
RFC 1985.
diff --git a/contrib/sendmail/contrib/expn.pl b/contrib/sendmail/contrib/expn.pl
index 57f8515..dd777e6 100755
--- a/contrib/sendmail/contrib/expn.pl
+++ b/contrib/sendmail/contrib/expn.pl
@@ -12,7 +12,7 @@ use IO::Socket;
# system requirements:
# must have 'nslookup' and 'hostname' programs.
-# $Header: /home/muir/bin/RCS/expn,v 3.11 1997/09/10 08:14:02 muir Exp muir $
+# $OrigHeader: /home/muir/bin/RCS/expn,v 3.11 1997/09/10 08:14:02 muir Exp muir $
# TODO:
# less magic should apply to command-line addresses
diff --git a/contrib/sendmail/contrib/link_hash.sh b/contrib/sendmail/contrib/link_hash.sh
new file mode 100644
index 0000000..e07104d
--- /dev/null
+++ b/contrib/sendmail/contrib/link_hash.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+##
+## Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+## All rights reserved.
+##
+## $Id: link_hash.sh,v 1.1.2.1 2000/04/25 00:10:47 ca Exp $
+##
+#
+# ln a certificate to its hash
+#
+SSL=openssl
+if test $# -ge 1
+then
+ for i in $@
+ do
+ C=$i.pem
+ test -f $C || C=$i
+ if test -f $C
+ then
+ H=`$SSL x509 -noout -hash < $C`.0
+ if test -h $H -o -f $H
+ then
+ echo link $H to $C exists
+ else
+ ln -s $C $H
+ fi
+ else
+ echo "$0: cannot open $C"
+ exit 2
+ fi
+ done
+else
+ echo "$0: missing name"
+ exit 1
+fi
+exit 0
diff --git a/contrib/sendmail/contrib/movemail.conf b/contrib/sendmail/contrib/movemail.conf
new file mode 100644
index 0000000..17009b8
--- /dev/null
+++ b/contrib/sendmail/contrib/movemail.conf
@@ -0,0 +1,35 @@
+# Configuration script for movemail.pl
+
+my $minutes = 60;
+my $hours = 3600;
+
+# Queue directories first..last
+
+@queues = qw(
+ /var/spool/mqueue/q1
+ /var/spool/mqueue/q2
+ /var/spool/mqueue/q3
+);
+
+# Base of subqueue name (optional).
+# If used, queue directories are $queues[n]/$subqbase*
+# Separate qf/df/xf directories are not supported.
+
+$subqbase = "subq";
+
+# Age of mail when moved. Each element of the array must be greater than the
+# previous element.
+
+@ages = (
+ 30*$minutes, # q1 to q2
+ 6*$hours # q2 to q3
+);
+
+# Location of script to move the mail
+
+$remqueue = "/usr/local/bin/re-mqueue.pl";
+
+# Lock file to prevent more than one instance running (optional)
+# Useful when running from cron
+
+$lockfile = "/var/spool/mqueue/movemail.lock";
diff --git a/contrib/sendmail/contrib/movemail.pl b/contrib/sendmail/contrib/movemail.pl
new file mode 100755
index 0000000..86bcb20
--- /dev/null
+++ b/contrib/sendmail/contrib/movemail.pl
@@ -0,0 +1,106 @@
+#!/usr/bin/perl -w
+#
+# Move old mail messages between queues by calling re-mqueue.pl.
+#
+# movemail.pl [config-script]
+#
+# Default config script is /usr/local/etc/movemail.conf.
+#
+# Graeme Hewson <graeme.hewson@oracle.com>, June 2000
+#
+
+use strict;
+
+# Load external program as subroutine to avoid
+# compilation overhead on each call
+
+sub loadsub {
+ my $fn = shift
+ or die "Filename not specified";
+ my $len = (stat($fn))[7]
+ or die "Can't stat $fn: $!";
+ open PROG, "< $fn"
+ or die "Can't open $fn: $!";
+ my $prog;
+ read PROG, $prog, $len
+ or die "Can't read $fn: $!";
+ close PROG;
+ eval join "",
+ 'return sub { my @ARGV = @_; $0 = $fn; no strict;',
+ "$prog",
+ '};';
+}
+
+my $progname = $0;
+my $lastage = -1;
+my $LOCK_EX = 2;
+my $LOCK_NB = 4;
+
+# Load and eval config script
+
+my $conffile = shift || "/usr/local/etc/movemail.conf";
+my $len = (stat($conffile))[7]
+ or die "Can't stat $conffile: $!";
+open CONF, "< $conffile"
+ or die "Can't open $conffile: $!";
+my $conf;
+read CONF, $conf, $len
+ or die "Can't read $conffile: $!";
+close CONF;
+use vars qw(@queues $subqbase @ages $remqueue $lockfile);
+eval $conf;
+
+if ($#queues < 1) {
+ print "$progname: there must be at least two queues\n";
+ exit 1;
+}
+
+if ($#ages != ($#queues - 1)) {
+ print "$progname: wrong number of ages (should be one less than number of queues)\n";
+ exit 1;
+}
+
+# Get lock or exit quietly. Useful when running from cron.
+
+if ($lockfile) {
+ open LOCK, ">>$lockfile"
+ or die "Can't open lock file: $!";
+ unless (flock LOCK, $LOCK_EX|$LOCK_NB) {
+ close LOCK;
+ exit 0;
+ }
+}
+
+my $remsub = loadsub($remqueue);
+
+# Go through directories in reverse order so as to check spool files only once
+
+for (my $n = $#queues - 1; $n >= 0; $n--) {
+ unless ($ages[$n] =~ /^\d+$/) {
+ print "$progname: invalid number $ages[$n] in ages array\n";
+ exit 1;
+ }
+ unless ($lastage < 0 || $ages[$n] < $lastage) {
+ print "$progname: age $lastage is not > previous value $ages[$n]\n";
+ exit 1;
+ }
+ $lastage = $ages[$n];
+ if ($subqbase) {
+ my $subdir;
+ opendir(DIR, $queues[$n])
+ or die "Can't open $queues[$n]: $!";
+ foreach $subdir ( grep { /^$subqbase/ } readdir DIR) {
+ &$remsub("$queues[$n]/$subdir", "$queues[$n+1]/$subdir",
+ $ages[$n]);
+ }
+ closedir(DIR);
+ } else {
+ # Not using subdirectories
+ &$remsub($queues[$n], $queues[$n+1], $ages[$n]);
+ }
+}
+
+if ($lockfile) {
+ unlink $lockfile;
+ close LOCK;
+}
diff --git a/contrib/sendmail/contrib/passwd-to-alias.pl b/contrib/sendmail/contrib/passwd-to-alias.pl
index 05a51b9..24bb7a1 100755
--- a/contrib/sendmail/contrib/passwd-to-alias.pl
+++ b/contrib/sendmail/contrib/passwd-to-alias.pl
@@ -8,22 +8,23 @@
print "# Generated from passwd by $0\n";
+$wordpat = '([a-zA-Z]+?[a-zA-Z0-9-]*)?[a-zA-Z0-9]'; # 'DB2'
while (@a = getpwent) {
($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = @a;
($fullname = $gcos) =~ s/,.*$//;
- if (!-d $dir || !-x $shell) {
- print "$name: root\n";
+ if (!-d $dir || !-x $shell || $shell =~ m!/bin/(false|true)$!) {
+ print "$name: root\n"; # handle pseudo user
}
$fullname =~ s/\.*[ _]+\.*/./g;
- $fullname =~ tr [åäöÅÄÖé] [aaoAAOe]; # <hakan@af.lu.se> 1997-06-15
- if ($fullname =~ /^[a-zA-Z][a-zA-Z-]+(\.[a-zA-Z][a-zA-Z-]+)+$/) {
-# if ($fullname =~ /^[a-zA-Z]+(\.[a-zA-Z]+)+$/) { # Kari E. Hurtta
+ $fullname =~ tr [åäéöüÅÄÖÜ] [aaeouAAOU]; # <hakan@af.lu.se> 1997-06-15
+ next if (!$fullname || lc($fullname) eq $name); # avoid nonsense
+ if ($fullname =~ /^$wordpat(\.$wordpat)*$/o) { # Ulrich Windl
print "$fullname: $name\n";
} else {
- print "# $fullname: $name\n";
+ print "# $fullname: $name\n"; # avoid strange names
}
};
diff --git a/contrib/sendmail/contrib/qtool.8 b/contrib/sendmail/contrib/qtool.8
new file mode 100644
index 0000000..4d0f1c4
--- /dev/null
+++ b/contrib/sendmail/contrib/qtool.8
@@ -0,0 +1,206 @@
+.\" Copyright (c) 1999 Sendmail, Inc. and its suppliers.
+.\" All rights reserved.
+.\"
+.\" By using this file, you agree to the terms and conditions set
+.\" forth in the LICENSE file which can be found at the top level of
+.\" the sendmail distribution.
+.\"
+.\"
+.\" $Id: qtool.8,v 8.9 1999/08/26 00:04:10 cying Exp $
+.\"
+.TH QTOOL 8 "July 12, 1999"
+.SH NAME
+.B qtool
+\- manipulate sendmail queues
+.SH SYNOPSIS
+.B qtool.pl
+.RB [options]
+target_directory source [source ...]
+.PP
+.B qtool.pl [-d/-b]
+.RB [options]
+source [source ...]
+.SH DESCRIPTION
+.B Qtool
+moves the queue files used by sendmail between queues. It uses the same
+locking mechanism as sendmail so can be safely used while sendmail is
+running.
+.PP
+With no options,
+.B qtool
+will move any queue files as specified by \fIsource\fP into
+\fItarget_directory\fP. \fISource\fP can be either an individual
+queue control file, a queue file id, or a queue directory.
+.PP
+If the -d option is specified, qtool will delete the messages specified by
+source instead of moving them.
+.PP
+If the -b option is specified, the selected messages will be bounced by
+running sendmail with the -OTimeout.queuereturn=now option.
+.SS Options
+.TP
+\fB\-b\fP
+Bounce all of the messages specified by source. The messages will be bounced
+immediately. No attempt will be made to deliver the messages.
+.TP
+\fB\-d\fP
+Delete all of the messages specified by source.
+.TP
+\fB\-e\fP \fIperl_expression\fP
+Evalute \fIperl_expression\fP for each queue file as specified
+by \fIsource\fP. If \fIperl_expression\fP evaluates to true, then that
+queue file is moved. See below for more detail on \fIperl_expression\fP.
+.TP
+\fB\-s\fP \fIseconds\fP
+Move only the queue files specified by \fIsource\fP that have a
+modification time older than \fIseconds\fP.
+.SS Perl Expressions
+You can use any valid perl expression. Inside the expression you have
+access to a hash that contains many of the fields in the control file as
+well as some other data about that queued message. The hash is called
+\fI%msg\fP. If a field has multiple values (e.g. 'Recipient'), it will be
+returned as an array, otherwise it will be returned as a scalar. Through
+\fI%msg\fP, you can access the following variables:
+.TP
+\fBauth\fP
+AUTH= parameter.
+.TP
+\fBbody_type\fP
+Body type (\fB8BITMIME\fP, \fB7BIT\fP, or undefined).
+.TP
+\fBbody_last_mod_time\fP
+The last time the body was modified since the epoch in seconds.
+.TP
+\fBbody_size\fP
+The size of the body file in bytes.
+.TP
+\fBcharset\fP
+Character set (for future use).
+.TP
+\fBcontent-length\fP
+Content-Length: header value (Solaris sendmail only).
+.TP
+\fBcontrolling_user\fP
+The controlling user.
+.TP
+\fBcontrol_last_mod_time\fP
+The last time the body was modified since the epoch in seconds.
+.TP
+\fBcontrol_size\fP
+The size of the control file in bytes.
+.TP
+\fBcreation_time\fP
+The time when the control file was created.
+.TP
+\fBdata_file_name\fP
+The data file name (deprecated).
+.TP
+\fBenvid\fP
+Original envelope id form ESMTP.
+.TP
+\fBerror_recipient\fP
+The error recipient (deprecated).
+.TP
+\fBflags\fP
+Array of characters that can be the following values:
+.PD 0
+.RS +8
+.TP 8
+w
+warning message has been sent
+.TP 8
+r
+This is an error respone or DSN
+.TP 8
+8
+has 8 bit data in body
+.TP 8
+b
+delete Bcc: headers
+.TP 8
+d
+envelope has DSN RET= parameter
+.TP 8
+n
+don't return body
+.PD
+.RE
+.TP
+\fBheaders\fP
+This is a Perl hash where the keys are rfc822 field names and the values
+are rfc822 field values. If a field has only one value it will be returned
+as a string. If a field has more than one value (e.g. 'Received') it will
+be returned as a list of strings.
+.TP
+\fBinode_number\fP
+The inode number for the data (body) file.
+.TP
+\fBnext_delivery_time\fP
+Earliest time of next delivery attempt.
+.TP
+\fBnum_delivery_attempts\fP
+Number of delivery attempts that have been made.
+.TP
+\fBmacro\fP
+Defined macro.
+.TP
+\fBmessage\fP
+Envelope status message.
+.TP
+\fBoriginal_recipient\fP
+Original recipient (ORCPT= parameter).
+.TP
+\fBpriority\fP
+Adjusted priority of message.
+.TP
+\fBrecipient\fP
+Array of character flags followed by colon and recipient name. Flags:
+.PD 0
+.RS +8
+.TP 8
+N
+Has NOTIFY= parameter.
+.TP 8
+S
+Success DSN requested.
+.TP 8
+F
+Failure DSN requested.
+.TP 8
+D
+Delay DSN requested.
+.TP 8
+P
+Primary address (not the result of alias/forward expansion).
+.PD
+.RE
+.TP
+\fBsender\fP
+Sender
+.TP
+\fBversion\fP
+Version of control file.
+.SH EXAMPLES
+.TP
+\fBqtool.pl q2 q1\fP
+Moves all of the queue files in queue q1 to queue q2.
+.TP
+\fBqtool.pl q2 q1/d6CLQh100847\fP
+Moves the message with id d6CLQh100847 in queue q1 to queue q2.
+.TP
+\fBqtool.pl q2 q1/qfd6CLQh100847\fP
+Moves the message with id d6CLQh100847 in queue q1 to queue q2.
+.TP
+\fBqtool.pl q2 q1/dfd6CLQh100847\fP
+Moves the message with id d6CLQh100847 in queue q1 to queue q2.
+.TP
+\fBqtool.pl -e '$msg{num_delivery_attempts} == 3' /q2 /q1\fP
+Moves all of the queue files that have had three attempted deliveries from
+queue q1 to queue q2.
+.SH SEE ALSO
+sendmail(8)
+.SH HISTORY
+The
+.B qtool
+command appeared in
+sendmail 8.10.
diff --git a/contrib/sendmail/contrib/qtool.pl b/contrib/sendmail/contrib/qtool.pl
new file mode 100755
index 0000000..0219fb5
--- /dev/null
+++ b/contrib/sendmail/contrib/qtool.pl
@@ -0,0 +1,1190 @@
+#!/usr/bin/env perl
+##
+## Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
+## All rights reserved.
+##
+## $Id: qtool.pl,v 8.15.16.1 2000/04/25 03:44:31 gshapiro Exp $
+##
+use strict;
+use File::Basename;
+use File::Copy;
+use File::Spec;
+use Fcntl qw(:flock :DEFAULT);
+use Getopt::Std;
+
+##
+## QTOOL
+## This program is for moving files between sendmail queues. It is
+## pretty similar to just moving the files manually, but it locks the files
+## the same way sendmail does to prevent problems.
+##
+## The syntax is the reverse of mv (ie. the target argument comes
+## first). This lets you pick the files you want to move using find and
+## xargs.
+##
+## Since you cannot delete queues while sendmail is running, QTOOL
+## assumes that when you specify a directory as a source, you mean that you
+## want all of the queue files within that directory moved, not the
+## directory itself.
+##
+## There is a mechanism for adding conditionals for moving the files.
+## Just create an Object with a check_move(source, dest) method and add it
+## to the $conditions object. See the handling of the '-s' option for an
+## example.
+##
+
+##
+## OPTION NOTES
+##
+## The -e option:
+## The -e option takes any valid perl expression and evaluates it
+## using the eval() function. Inside the expression the variable
+## '$msg' is bound to the ControlFile object for the current source
+## queue message. This lets you check for any value in the message
+## headers or the control file. Here's an example:
+##
+## ./qtool.pl -e '$msg->{num_delivery_attempts} >= 2' /q1 /q2
+##
+## This would move any queue files whose number of delivery attempts
+## is greater than or equal to 2 from the queue 'q2' to the queue 'q1'.
+##
+## See the function ControlFile::parse for a list of available
+## variables.
+##
+
+my %opts;
+my %sources;
+my $dst_name;
+my $destination;
+my $source_name;
+my $source;
+my $result;
+my $action;
+my $new_condition;
+my $conditions = new Compound();
+
+Getopt::Std::getopts('bde:s:', \%opts);
+
+sub move_action
+{
+ my $source = shift;
+ my $destination = shift;
+
+ $result = $destination->add($source);
+ if ($result)
+ {
+ print("$result.\n");
+ }
+}
+
+sub delete_action
+{
+ my $source = shift;
+
+ return $source->delete();
+}
+
+sub bounce_action
+{
+ my $source = shift;
+
+ return $source->bounce();
+}
+
+$action = \&move_action;
+if (defined $opts{d})
+{
+ $action = \&delete_action;
+}
+elsif (defined $opts{b})
+{
+ $action = \&bounce_action;
+}
+
+if (defined $opts{s})
+{
+ $new_condition = new OlderThan($opts{s});
+ $conditions->add($new_condition);
+}
+
+if (defined $opts{e})
+{
+ $new_condition = new Eval($opts{e});
+ $conditions->add($new_condition);
+}
+
+if ($action == \&move_action)
+{
+ $dst_name = shift(@ARGV);
+ if (!-d $dst_name)
+ {
+ print("The destination '$dst_name' must be an existing " .
+ "directory.\n");
+ usage();
+ exit;
+ }
+ $destination = new Queue($dst_name);
+}
+
+while (@ARGV)
+{
+ $source_name = shift(@ARGV);
+ $result = add_source(\%sources, $source_name);
+ if ($result)
+ {
+ print("$result.\n");
+ }
+}
+
+if (keys(%sources) == 0)
+{
+ print("You must at least specify at least one source.\n");
+ usage();
+ exit;
+}
+
+while (($source_name, $source) = each(%sources))
+{
+ $result = $conditions->check_move($source, $destination);
+ if ($result)
+ {
+ $result = &{$action}($source, $destination);
+ if ($result)
+ {
+ print("$result\n");
+ }
+ }
+}
+
+sub usage
+{
+ print("Usage: $0 [options] directory source ...\n");
+ print(" $0 [-d|-b] source ...\n");
+ print("options:\n");
+ print(" -b Bounce the messages specified by source.\n");
+ print(" -d Delete the messages specified by source.\n");
+ print(" -e [perl expression] Move only messages for which perl expression returns true.\n");
+ print(" -s [seconds] Move only messages older than seconds.\n");
+}
+
+##
+## ADD_SOURCE -- Adds a source to the source hash.
+##
+## Determines whether source is a file, directory, or id. Then it
+## creates a QueuedMessage or Queue for that source and adds it to the
+## list.
+##
+## Parameters:
+## sources -- A hash that contains all of the sources.
+## source_name -- The name of the source to add
+##
+## Returns:
+## error_string -- Undef if ok. Error string otherwise.
+##
+## Notes:
+## If a new source comes in with the same ID as a previous
+## source, the previous source gets overwritten in the sources
+## hash. This lets the user specify things like * and it still
+## works nicely.
+##
+
+sub add_source
+{
+ my $sources = shift;
+ my $source_name = shift;
+ my $source_base_name;
+ my $source_dir_name;
+ my $data_dir_name;
+ my $source_id;
+ my $source_prefix;
+ my $queued_message;
+ my $queue;
+ my $result;
+
+ ($source_base_name, $source_dir_name) = File::Basename::fileparse($source_name);
+ $data_dir_name = $source_dir_name;
+
+ $source_prefix = substr($source_base_name, 0, 2);
+ if (!-d $source_name && $source_prefix ne 'qf' &&
+ $source_prefix ne 'df')
+ {
+ $source_base_name = "qf$source_base_name";
+ $source_name = File::Spec->catfile("$source_dir_name",
+ "$source_base_name");
+ }
+ $source_id = substr($source_base_name, 2);
+
+ if (!-e $source_name)
+ {
+ $source_name = File::Spec->catfile("$source_dir_name", "qf",
+ "qf$source_id");
+ if (!-e $source_name)
+ {
+ return "'$source_name' does not exist";
+ }
+ $data_dir_name = File::Spec->catfile("$source_dir_name", "df");
+ $source_dir_name = File::Spec->catfile("$source_dir_name",
+ "qf");
+ }
+
+ if (-f $source_name)
+ {
+ $queued_message = new QueuedMessage($source_dir_name,
+ $source_id,
+ $data_dir_name);
+ $sources->{$source_id} = $queued_message;
+ return undef;
+ }
+
+ if (!-d $source_name)
+ {
+ return "'$source_name' is not a plain file or a directory";
+ }
+
+ $queue = new Queue($source_name);
+ $result = $queue->read();
+ if ($result)
+ {
+ return $result;
+ }
+
+ while (($source_id, $queued_message) = each(%{$queue->{files}}))
+ {
+ $sources->{$source_id} = $queued_message;
+ }
+
+ return undef;
+}
+
+##
+## LOCK_FILE -- Opens and then locks a file.
+##
+## Opens a file for read/write and uses flock to obtain a lock on the
+## file. The flock is Perl's flock which defaults to flock on systems
+## that support it. On systems without flock it falls back to fcntl
+## locking.
+##
+## Parameters:
+## file_name -- The name of the file to open and lock.
+##
+## Returns:
+## (file_handle, error_string) -- If everything works then
+## file_handle is a reference to a file handle and
+## error_string is undef. If there is a problem then
+## file_handle is undef and error_string is a string
+## explaining the problem.
+##
+
+sub lock_file
+{
+ my $file_name = shift;
+ my $result;
+
+ $result = sysopen(FILE_TO_LOCK, $file_name, Fcntl::O_RDWR);
+ if (!$result)
+ {
+ return (undef, "Unable to open '$file_name': $!");
+ }
+
+ $result = flock(FILE_TO_LOCK, Fcntl::LOCK_EX | Fcntl::LOCK_NB);
+ if (!$result)
+ {
+ return (undef, "Could not obtain lock on '$file_name': $!");
+ }
+
+ return (\*FILE_TO_LOCK, undef);
+}
+
+##
+## UNLOCK_FILE -- Unlocks a file.
+##
+## Unlocks a file using Perl's flock.
+##
+## Parameters:
+## file -- A file handle.
+##
+## Returns:
+## error_string -- If undef then no problem. Otherwise it is a
+## string that explains problem.
+##
+
+sub unlock_file
+{
+ my $file = shift;
+ my $result;
+
+ $result = flock($file, Fcntl::LOCK_UN);
+ if (!$result)
+ {
+ return "Unlock failed on '$result': $!";
+ }
+
+ return undef;
+}
+
+##
+## MOVE_FILE -- Moves a file.
+##
+## Moves a file.
+##
+## Parameters:
+## src_name -- The name of the file to be move.
+## dst_nome -- The name of the place to move it to.
+##
+## Returns:
+## error_string -- If undef then no problem. Otherwise it is a
+## string that explains problem.
+##
+
+sub move_file
+{
+ my $src_name = shift;
+ my $dst_name = shift;
+ my $result;
+
+ $result = File::Copy::move($src_name, $dst_name);
+ if (!$result)
+ {
+ return "File move from '$src_name' to '$dst_name' failed: $!";
+ }
+
+ return undef;
+}
+
+
+##
+## CONTROL_FILE - Represents a sendmail queue control file.
+##
+## This object represents represents a sendmail queue control file.
+## It can parse and lock its file.
+##
+
+
+package ControlFile;
+
+sub new
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $self = {};
+ bless $self, $class;
+ $self->initialize(@_);
+ return $self;
+}
+
+sub initialize
+{
+ my $self = shift;
+ my $queue_dir = shift;
+ $self->{id} = shift;
+
+ $self->{file_name} = $queue_dir . '/qf' . $self->{id};
+ $self->{headers} = {};
+}
+
+##
+## PARSE - Parses the control file.
+##
+## Parses the control file. It just sticks each entry into a hash.
+## If a key has more than one entry, then it points to a list of
+## entries.
+##
+
+sub parse
+{
+ my $self = shift;
+ if ($self->{parsed})
+ {
+ return;
+ }
+ my %parse_table =
+ (
+ 'A' => 'auth',
+ 'B' => 'body_type',
+ 'C' => 'controlling_user',
+ 'D' => 'data_file_name',
+ 'E' => 'error_recipient',
+ 'F' => 'flags',
+ 'H' => 'parse_header',
+ 'I' => 'inode_number',
+ 'K' => 'next_delivery_time',
+ 'L' => 'content-length',
+ 'M' => 'message',
+ 'N' => 'num_delivery_attempts',
+ 'P' => 'priority',
+ 'Q' => 'original_recipient',
+ 'R' => 'recipient',
+ 'S' => 'sender',
+ 'T' => 'creation_time',
+ 'V' => 'version',
+ 'X' => 'charset',
+ 'Z' => 'envid',
+ '$' => 'macro'
+ );
+ my $line;
+ my $line_type;
+ my $line_value;
+ my $member_name;
+ my $member;
+ my $last_type;
+
+ open(CONTROL_FILE, "$self->{file_name}");
+ while ($line = <CONTROL_FILE>)
+ {
+ $line_type = substr($line, 0, 1);
+ if ($line_type eq "\t" && $last_type eq 'H')
+ {
+ $line_type = 'H';
+ $line_value = $line;
+ }
+ else
+ {
+ $line_value = substr($line, 1);
+ }
+ $member_name = $parse_table{$line_type};
+ $last_type = $line_type;
+ if (!$member_name)
+ {
+ $member_name = 'unknown';
+ }
+ if ($self->can($member_name))
+ {
+ $self->$member_name($line_value);
+ }
+ $member = $self->{$member_name};
+ if (!$member)
+ {
+ $self->{$member_name} = $line_value;
+ next;
+ }
+ if (ref($member) eq 'ARRAY')
+ {
+ push(@{$member}, $line_value);
+ next;
+ }
+ $self->{$member_name} = [$member, $line_value];
+ }
+ close(CONTROL_FILE);
+
+ $self->{parsed} = 1;
+}
+
+sub parse_header
+{
+ my $self = shift;
+ my $line = shift;
+ my $headers = $self->{headers};
+ my $last_header = $self->{last_header};
+ my $header_name;
+ my $header_value;
+ my $first_char;
+
+ $first_char = substr($line, 0, 1);
+ if ($first_char eq "?")
+ {
+ $line = substr($line, 3);
+ }
+ elsif ($first_char eq "\t")
+ {
+ if (ref($headers->{$last_header}) eq 'ARRAY')
+ {
+ $headers->{$last_header}[-1] =
+ $headers->{$last_header}[-1] . $line;
+ }
+ else
+ {
+ $headers->{$last_header} = $headers->{$last_header} .
+ $line;
+ }
+ return;
+ }
+ ($header_name, $header_value) = split(/:/, $line, 2);
+ $self->{last_header} = $header_name;
+ if (exists $headers->{$header_name})
+ {
+ $headers->{$header_name} = [$headers->{$header_name},
+ $header_value];
+ }
+ else
+ {
+ $headers->{$header_name} = $header_value;
+ }
+}
+
+sub is_locked
+{
+ my $self = shift;
+
+ return (defined $self->{lock_handle});
+}
+
+sub lock
+{
+ my $self = shift;
+ my $lock_handle;
+ my $result;
+
+ if ($self->is_locked())
+ {
+ # Already locked
+ return undef;
+ }
+
+ ($lock_handle, $result) = ::lock_file($self->{file_name});
+ if (!$lock_handle)
+ {
+ return $result;
+ }
+
+ $self->{lock_handle} = $lock_handle;
+
+ return undef;
+}
+
+sub unlock
+{
+ my $self = shift;
+ my $result;
+
+ if (!$self->is_locked())
+ {
+ # Not locked
+ return undef;
+ }
+
+ $result = ::unlock_file($self->{lock_handle});
+
+ $self->{lock_handle} = undef;
+
+ return $result;
+}
+
+sub do_stat
+{
+ my $self = shift;
+ my $result;
+ my @result;
+
+ $result = open(QUEUE_FILE, $self->{file_name});
+ if (!$result)
+ {
+ return "Unable to open '$self->{file_name}': $!";
+ }
+ @result = stat(QUEUE_FILE);
+ if (!@result)
+ {
+ return "Unable to stat '$self->{file_name}': $!";
+ }
+ $self->{control_size} = $result[7];
+ $self->{control_last_mod_time} = $result[9];
+}
+
+sub DESTROY
+{
+ my $self = shift;
+
+ $self->unlock();
+}
+
+sub delete
+{
+ my $self = shift;
+ my $result;
+
+ $result = unlink($self->{file_name});
+ if (!$result)
+ {
+ return "Unable to delete $self->{file_name}: $!";
+ }
+ return undef;
+}
+
+
+##
+## DATA_FILE - Represents a sendmail queue data file.
+##
+## This object represents represents a sendmail queue data file.
+## It is really just a place-holder.
+##
+
+package DataFile;
+
+sub new
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $self = {};
+ bless $self, $class;
+ $self->initialize(@_);
+ return $self;
+}
+
+sub initialize
+{
+ my $self = shift;
+ my $queue_dir = shift;
+ $self->{id} = shift;
+
+ $self->{file_name} = $queue_dir . '/df' . $self->{id};
+}
+
+sub do_stat
+{
+ my $self = shift;
+ my $result;
+ my @result;
+
+ $result = open(QUEUE_FILE, $self->{file_name});
+ if (!$result)
+ {
+ return "Unable to open '$self->{file_name}': $!";
+ }
+ @result = stat(QUEUE_FILE);
+ if (!@result)
+ {
+ return "Unable to stat '$self->{file_name}': $!";
+ }
+ $self->{body_size} = $result[7];
+ $self->{body_last_mod_time} = $result[9];
+}
+
+sub delete
+{
+ my $self = shift;
+ my $result;
+
+ $result = unlink($self->{file_name});
+ if (!$result)
+ {
+ return "Unable to delete $self->{file_name}: $!";
+ }
+ return undef;
+}
+
+
+##
+## QUEUED_MESSAGE - Represents a queued sendmail message.
+##
+## This keeps track of the files that make up a queued sendmail
+## message.
+## Currently it has 'control_file' and 'data_file' as members.
+##
+## You can tie it to a fetch only hash using tie. You need to
+## pass a reference to a QueuedMessage as the third argument
+## to tie.
+##
+
+package QueuedMessage;
+
+sub new
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $self = {};
+ bless $self, $class;
+ $self->initialize(@_);
+ return $self;
+}
+
+sub initialize
+{
+ my $self = shift;
+ my $queue_dir = shift;
+ my $id = shift;
+ my $data_dir = shift;
+
+ $self->{id} = $id;
+ $self->{control_file} = new ControlFile($queue_dir, $id);
+ if ($data_dir)
+ {
+ $self->{data_file} = new DataFile($data_dir, $id);
+ }
+ else
+ {
+ $self->{data_file} = new DataFile($queue_dir, $id);
+ }
+}
+
+sub last_modified_time
+{
+ my $self = shift;
+ my @result;
+ @result = stat($self->{data_file}->{file_name});
+ return $result[9];
+}
+
+sub TIEHASH
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $self = shift;
+ return $self;
+}
+
+sub FETCH
+{
+ my $self = shift;
+ my $key = shift;
+
+ if (exists $self->{control_file}->{$key})
+ {
+ return $self->{control_file}->{$key};
+ }
+ if (exists $self->{data_file}->{$key})
+ {
+ return $self->{data_file}->{$key};
+ }
+
+ return undef;
+}
+
+sub lock
+{
+ my $self = shift;
+
+ return $self->{control_file}->lock();
+}
+
+sub unlock
+{
+ my $self = shift;
+
+ return $self->{control_file}->unlock();
+}
+
+sub move
+{
+ my $self = shift;
+ my $destination = shift;
+ my $df_dest;
+ my $qf_dest;
+ my $result;
+
+ $result = $self->lock();
+ if ($result)
+ {
+ return $result;
+ }
+
+ $qf_dest = File::Spec->catfile($destination, "qf");
+ if (-d $qf_dest)
+ {
+ $df_dest = File::Spec->catfile($destination, "df");
+ if (!-d $df_dest)
+ {
+ $df_dest = $destination;
+ }
+ }
+ else
+ {
+ $qf_dest = $destination;
+ $df_dest = $destination;
+ }
+
+ if (-e File::Spec->catfile($qf_dest, "qf$self->{id}"))
+ {
+ $result = "There is already a queued message with id '$self->{id}' in '$destination'";
+ }
+
+ if (!$result)
+ {
+ $result = ::move_file($self->{data_file}->{file_name},
+ $df_dest);
+ }
+
+ if (!$result)
+ {
+ $result = ::move_file($self->{control_file}->{file_name},
+ $qf_dest);
+ }
+
+ $self->unlock();
+
+ return $result;
+}
+
+sub parse
+{
+ my $self = shift;
+
+ return $self->{control_file}->parse();
+}
+
+sub do_stat
+{
+ my $self = shift;
+
+ $self->{control_file}->do_stat();
+ $self->{data_file}->do_stat();
+}
+
+sub setup_vars
+{
+ my $self = shift;
+
+ $self->parse();
+ $self->do_stat();
+}
+
+sub delete
+{
+ my $self = shift;
+ my $result;
+
+ $result = $self->{control_file}->delete();
+ if ($result)
+ {
+ return $result;
+ }
+ $result = $self->{data_file}->delete();
+ if ($result)
+ {
+ return $result;
+ }
+
+ return undef;
+}
+
+sub bounce
+{
+ my $self = shift;
+ my $command;
+
+ $command = "sendmail -qI$self->{id} -O Timeout.queuereturn=now";
+# print("$command\n");
+ system($command);
+}
+
+##
+## QUEUE - Represents a queued sendmail queue.
+##
+## This manages all of the messages in a queue.
+##
+
+package Queue;
+
+sub new
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $self = {};
+ bless $self, $class;
+ $self->initialize(@_);
+ return $self;
+}
+
+sub initialize
+{
+ my $self = shift;
+
+ $self->{queue_dir} = shift;
+ $self->{files} = {};
+}
+
+##
+## READ - Loads the queue with all of the objects that reside in it.
+##
+## This reads the queue's directory and creates QueuedMessage objects
+## for every file in the queue that starts with 'qf'.
+##
+
+sub read
+{
+ my $self = shift;
+ my @control_files;
+ my $queued_message;
+ my $file_name;
+ my $id;
+ my $result;
+ my $control_dir;
+ my $data_dir;
+
+ $control_dir = File::Spec->catfile($self->{queue_dir}, 'qf');
+
+ if (-e $control_dir)
+ {
+ $data_dir = File::Spec->catfile($self->{queue_dir}, 'df');
+ if (!-e $data_dir)
+ {
+ $data_dir = $self->{queue_dir};
+ }
+ }
+ else
+ {
+ $data_dir = $self->{queue_dir};
+ $control_dir = $self->{queue_dir};
+ }
+
+ $result = opendir(QUEUE_DIR, $control_dir);
+ if (!$result)
+ {
+ return "Unable to open directory '$control_dir'";
+ }
+
+ @control_files = grep { /^qf.*/ && -f "$control_dir/$_" } readdir(QUEUE_DIR);
+ closedir(QUEUE_DIR);
+ foreach $file_name (@control_files)
+ {
+ $id = substr($file_name, 2);
+ $queued_message = new QueuedMessage($control_dir, $id,
+ $data_dir);
+ $self->{files}->{$id} = $queued_message;
+ }
+
+ return undef;
+}
+
+
+##
+## ADD_QUEUED_MESSAGE - Adds a QueuedMessage to this Queue.
+##
+## Adds the QueuedMessage object to the hash and moves the files
+## associated with the QueuedMessage to this Queue's directory.
+##
+
+sub add_queued_message
+{
+ my $self = shift;
+ my $queued_message = shift;
+ my $result;
+
+ $result = $queued_message->move($self->{queue_dir});
+ if ($result)
+ {
+ return $result;
+ }
+
+ $self->{files}->{$queued_message->{id}} = $queued_message;
+
+ return $result;
+}
+
+##
+## ADD_QUEUE - Adds another Queue's QueuedMessages to this Queue.
+##
+## Adds all of the QueuedMessage objects in the passed in queue
+## to this queue.
+##
+
+sub add_queue
+{
+ my $self = shift;
+ my $queue = shift;
+ my $id;
+ my $queued_message;
+ my $result;
+
+ while (($id, $queued_message) = each %{$queue->{files}})
+ {
+ $result = $self->add_queued_message($queued_message);
+ if ($result)
+ {
+ print("$result.\n");
+ }
+ }
+}
+
+##
+## ADD - Adds an item to this queue.
+##
+## Adds either a Queue or a QueuedMessage to this Queue.
+##
+
+sub add
+{
+ my $self = shift;
+ my $source = shift;
+ my $type_name;
+ my $result;
+
+ $type_name = ref($source);
+
+ if ($type_name eq "QueuedMessage")
+ {
+ return $self->add_queued_message($source);
+ }
+
+ if ($type_name eq "Queue")
+ {
+ return $self->add_queue($source);
+ }
+
+ return "Queue does not know how to add a '$type_name'"
+}
+
+sub delete
+{
+ my $self = shift;
+ my $id;
+ my $queued_message;
+
+ while (($id, $queued_message) = each %{$self->{files}})
+ {
+ $result = $queued_message->delete();
+ if ($result)
+ {
+ print("$result.\n");
+ }
+ }
+}
+
+sub bounce
+{
+ my $self = shift;
+ my $id;
+ my $queued_message;
+
+ while (($id, $queued_message) = each %{$self->{files}})
+ {
+ $result = $queued_message->bounce();
+ if ($result)
+ {
+ print("$result.\n");
+ }
+ }
+}
+
+##
+## Condition Class
+##
+## This next section is for any class that has an interface called
+## check_move(source, dest). Each class represents some condition to
+## check for to determine whether we should move the file from
+## source to dest.
+##
+
+
+##
+## OlderThan
+##
+## This Condition Class checks the modification time of the
+## source file and returns true if the file's modification time is
+## older than the number of seconds the class was initialzed with.
+##
+
+package OlderThan;
+
+sub new
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $self = {};
+ bless $self, $class;
+ $self->initialize(@_);
+ return $self;
+}
+
+sub initialize
+{
+ my $self = shift;
+
+ $self->{age_in_seconds} = shift;
+}
+
+sub check_move
+{
+ my $self = shift;
+ my $source = shift;
+
+ if ((time() - $source->last_modified_time()) > $self->{age_in_seconds})
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+##
+## Compound
+##
+## Takes a list of Move Condition Classes. Check_move returns true
+## if every Condition Class in the list's check_move function returns
+## true.
+##
+
+package Compound;
+
+sub new
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $self = {};
+ bless $self, $class;
+ $self->initialize(@_);
+ return $self;
+}
+
+sub initialize
+{
+ my $self = shift;
+
+ $self->{condition_list} = [];
+}
+
+sub add
+{
+ my $self = shift;
+ my $new_condition = shift;
+
+ push(@{$self->{condition_list}}, $new_condition);
+}
+
+sub check_move
+{
+ my $self = shift;
+ my $source = shift;
+ my $dest = shift;
+ my $condition;
+ my $result;
+
+ foreach $condition (@{$self->{condition_list}})
+ {
+ if (!$condition->check_move($source, $dest))
+ {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+##
+## Eval
+##
+## Takes a perl expression and evaluates it. The ControlFile object
+## for the source QueuedMessage is avaliable through the name '$msg'.
+##
+
+package Eval;
+
+sub new
+{
+ my $this = shift;
+ my $class = ref($this) || $this;
+ my $self = {};
+ bless $self, $class;
+ $self->initialize(@_);
+ return $self;
+}
+
+sub initialize
+{
+ my $self = shift;
+
+ $self->{expression} = shift;
+}
+
+sub check_move
+{
+ my $self = shift;
+ my $source = shift;
+ my $dest = shift;
+ my $result;
+ my %msg;
+
+ $source->setup_vars();
+ tie(%msg, 'QueuedMessage', $source);
+ $result = eval($self->{expression});
+
+ return $result;
+}
diff --git a/contrib/sendmail/contrib/re-mqueue.pl b/contrib/sendmail/contrib/re-mqueue.pl
index 61aef43..9f8d819 100644
--- a/contrib/sendmail/contrib/re-mqueue.pl
+++ b/contrib/sendmail/contrib/re-mqueue.pl
@@ -84,9 +84,28 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# @(#)$Id: re-mqueue,v 1.3 1995/05/25 18:14:53 p-pomes Exp $
+# @(#)$OrigId: re-mqueue,v 1.3 1995/05/25 18:14:53 p-pomes Exp $
+#
+# Updated by Graeme Hewson <ghewson@uk.oracle.com> May 1999
+#
+# 'use Sys::Syslog' for Perl 5
+# Move transcript (xf) files if they exist
+# Allow zero-length df files (empty message body)
+# Preserve $! for error messages
+#
+# Updated by Graeme Hewson <ghewson@uk.oracle.com> April 2000
+#
+# Improve handling of race between re-mqueue and sendmail
+#
+# Updated by Graeme Hewson <graeme.hewson@oracle.com> June 2000
+#
+# Don't exit(0) at end so can be called as subroutine
+#
+# NB This program can't handle separate qf/df/xf subdirectories
+# as introduced in sendmail 8.10.0.
+#
-require "syslog.pl";
+use Sys::Syslog;
$LOCK_EX = 2;
$LOCK_NB = 4;
@@ -126,19 +145,19 @@ $now = time();
while ($dfile = pop(@dfiles)) {
print "Checking $dfile\n" if ($debug);
($qfile = $dfile) =~ s/^d/q/;
+ ($xfile = $dfile) =~ s/^d/x/;
($mfile = $dfile) =~ s/^df//;
- if (! -e $dfile || -z $dfile) {
- print "$dfile is gone or zero bytes - skipping\n" if ($debug);
- next;
- }
if (! -e $qfile || -z $qfile) {
print "$qfile is gone or zero bytes - skipping\n" if ($debug);
next;
}
- $mtime = $now;
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat($dfile);
+ if (! defined $mtime) {
+ print "$dfile is gone - skipping\n" if ($debug);
+ next;
+ }
# Compare timestamps
if (($mtime + $age) > $now) {
@@ -155,6 +174,10 @@ while ($dfile = pop(@dfiles)) {
print "$queueb/$qfile already exists - skipping\n" if ($debug);
next;
}
+ if (-e "$queueB/$xfile") {
+ print "$queueb/$xfile already exists - skipping\n" if ($debug);
+ next;
+ }
# Try and lock qf* file
unless (open(QF, ">>$qfile")) {
@@ -169,35 +192,67 @@ while ($dfile = pop(@dfiles)) {
}
print "$qfile now flock()ed\n" if ($debug);
+ # Check df* file again in case sendmail got in
+ if (! -e $dfile) {
+ print "$mfile sent - skipping\n" if ($debug);
+ # qf* file created by ourselves at open? (Almost certainly)
+ if (-z $qfile) {
+ unlink($qfile);
+ }
+ close(QF);
+ next;
+ }
+
# Show time! Do the link()s
if (link("$dfile", "$queueB/$dfile") == 0) {
- &syslog('err', 'link(%s, %s/%s): %m', $dfile, $queueB, $dfile);
- print STDERR "$0: link($dfile, $queueB/$dfile): $!\n";
+ $bang = $!;
+ &syslog('err', 'link(%s, %s/%s): %s', $dfile, $queueB, $dfile, $bang);
+ print STDERR "$0: link($dfile, $queueB/$dfile): $bang\n";
exit (1);
}
if (link("$qfile", "$queueB/$qfile") == 0) {
- &syslog('err', 'link(%s, %s/%s): %m', $qfile, $queueB, $qfile);
- print STDERR "$0: link($qfile, $queueB/$qfile): $!\n";
+ $bang = $!;
+ &syslog('err', 'link(%s, %s/%s): %s', $qfile, $queueB, $qfile, $bang);
+ print STDERR "$0: link($qfile, $queueB/$qfile): $bang\n";
unlink("$queueB/$dfile");
exit (1);
}
+ if (-e "$xfile") {
+ if (link("$xfile", "$queueB/$xfile") == 0) {
+ $bang = $!;
+ &syslog('err', 'link(%s, %s/%s): %s', $xfile, $queueB, $xfile, $bang);
+ print STDERR "$0: link($xfile, $queueB/$xfile): $bang\n";
+ unlink("$queueB/$dfile");
+ unlink("$queueB/$qfile");
+ exit (1);
+ }
+ }
# Links created successfully. Unlink the original files, release the
# lock, and close the file.
print "links ok\n" if ($debug);
if (unlink($qfile) == 0) {
- &syslog('err', 'unlink(%s): %m', $qfile);
- print STDERR "$0: unlink($qfile): $!\n";
+ $bang = $!;
+ &syslog('err', 'unlink(%s): %s', $qfile, $bang);
+ print STDERR "$0: unlink($qfile): $bang\n";
exit (1);
}
if (unlink($dfile) == 0) {
- &syslog('err', 'unlink(%s): %m', $dfile);
- print STDERR "$0: unlink($dfile): $!\n";
+ $bang = $!;
+ &syslog('err', 'unlink(%s): %s', $dfile, $bang);
+ print STDERR "$0: unlink($dfile): $bang\n";
exit (1);
}
+ if (-e "$xfile") {
+ if (unlink($xfile) == 0) {
+ $bang = $!;
+ &syslog('err', 'unlink(%s): %s', $xfile, $bang);
+ print STDERR "$0: unlink($xfile): $bang\n";
+ exit (1);
+ }
+ }
flock(QF, $LOCK_UN);
close(QF);
&syslog('info', '%s moved to %s', $mfile, $queueB);
print "Done with $dfile $qfile\n\n" if ($debug);
}
-exit 0;
diff --git a/contrib/sendmail/contrib/smcontrol.pl b/contrib/sendmail/contrib/smcontrol.pl
index b5ef1f8..3ecfee1 100755
--- a/contrib/sendmail/contrib/smcontrol.pl
+++ b/contrib/sendmail/contrib/smcontrol.pl
@@ -21,7 +21,7 @@ sub get_controlname
my $cn = undef;
my $qd = undef;
- open(CF, "</etc/sendmail.cf") or return $cn;
+ open(CF, "</etc/mail/sendmail.cf") or return $cn;
while (<CF>)
{
chomp;
@@ -162,7 +162,7 @@ sub munge_status
my $cooked = "";
my $daemonStatus = "";
- if ($raw =~ /^(\d+)\/(\d+)$/mg)
+ if ($raw =~ /^(\d+)\/(\d+)\/(\d+)\/(\d+)/mg)
{
$cooked .= "Current number of children: $1";
if ($2 > 0)
@@ -170,6 +170,8 @@ sub munge_status
$cooked .= " (maximum $2)";
}
$cooked .= "\n";
+ $cooked .= "QueueDir free disk space (in blocks): $3\n";
+ $cooked .= "Load average: $4\n";
}
while ($raw =~ /^(\d+) (.*)$/mg)
{
OpenPOWER on IntegriCloud