a
This commit is contained in:
504
directadmin-1.62.4/scripts/packages/majordomo-1.94.5/digest
vendored
Normal file
504
directadmin-1.62.4/scripts/packages/majordomo-1.94.5/digest
vendored
Normal file
@@ -0,0 +1,504 @@
|
||||
#!/bin/perl
|
||||
|
||||
# Original from J Greely <jgreely@cis.ohio-state.edu>, 9/30/92
|
||||
#
|
||||
# Heavily modified by Brent Chapman <Brent@GreatCircle.COM>
|
||||
|
||||
# $Source: /sources/cvsrepos/majordomo/digest,v $
|
||||
# $Revision: 1.24 $
|
||||
# $Date: 2000/01/07 11:04:34 $
|
||||
# $Author: cwilson $
|
||||
# $State: Exp $
|
||||
#
|
||||
# $Header: /sources/cvsrepos/majordomo/digest,v 1.24 2000/01/07 11:04:34 cwilson Exp $
|
||||
#
|
||||
#
|
||||
|
||||
# Before doing anything else tell the world I am majordomo
|
||||
# The mj_ prefix is reserved for tools that are part of majordomo proper.
|
||||
$main'program_name = 'mj_digest'; # ';
|
||||
|
||||
|
||||
&init;
|
||||
&readconfig;
|
||||
$TEMP = (defined $TMPDIR && -d $TMPDIR) ?
|
||||
"$TMPDIR/digest.$$" : "/usr/tmp/digest.$$";
|
||||
|
||||
if (defined($opt_r)) {
|
||||
&receive_message;
|
||||
if (&should_be_sent(1)) {
|
||||
&make_digest;
|
||||
}
|
||||
} elsif (defined($opt_R)) {
|
||||
&receive_message;
|
||||
} elsif (defined($opt_m)) {
|
||||
&make_digest;
|
||||
} elsif (defined($opt_p)) {
|
||||
if (&should_be_sent(1)) {
|
||||
&make_digest;
|
||||
}
|
||||
} else {
|
||||
&abort("Usage: digest {-r|-R|-m|-p} [-c config|(-C -l list)]\nStopped");
|
||||
}
|
||||
|
||||
&free_lock($lockfile);
|
||||
|
||||
exit(0);
|
||||
|
||||
sub receive_message {
|
||||
$i = 0;
|
||||
do {
|
||||
$file = sprintf("%s/%03d", $V{'INCOMING'}, ++$i);
|
||||
} until (! -e $file);
|
||||
|
||||
print STDERR "Receiving $i\n";
|
||||
open(MSG, ">$file") || &abort("open(MSG, \">$file\"): $!");
|
||||
|
||||
# copy the message
|
||||
while (<STDIN>) {
|
||||
print MSG $_;
|
||||
}
|
||||
|
||||
close(MSG);
|
||||
}
|
||||
|
||||
#
|
||||
# Use config variables to determine if a digest should be contructed
|
||||
# and sent, or not. Measures line count and byte count of messages
|
||||
# as they would appear in the digest, not as they exist in the spool
|
||||
# dir. Side-effect: $file is the last file that should be included
|
||||
# in this digest, based on the config variables.
|
||||
#
|
||||
sub should_be_sent {
|
||||
# fudge factors for headers and footers
|
||||
$sum = 600 + length($HEADER) + length($HEADERS) + length($TRAILER);
|
||||
$lines = 25 + ($HEADER =~ s/\n/\n/g) + ($HEADERS =~ s/\n/\n/g) +
|
||||
($TRAILER =~ s/\n/\n/g);
|
||||
##print "start: lines = $lines\n";
|
||||
$i = shift;
|
||||
while (1) {
|
||||
$nextfile = sprintf("%s/%03d", $V{'INCOMING'}, $i++);
|
||||
last unless (-e $nextfile);
|
||||
$file = $nextfile;
|
||||
open(COUNT, "<$file") || &abort("open(COUNT, \"<$file\"): $!");
|
||||
|
||||
$/ = ''; # grab the header
|
||||
$head = <COUNT>;
|
||||
|
||||
# only count From/Date/Subject header fields to get a
|
||||
# more accurate size and line count.
|
||||
$head =~ s/\n\s+/ /g;
|
||||
$head =~ /^(From:\s+.*)/i && ($sum += length($1)+1, $lines++);
|
||||
$head =~ /^(Subject:\s+.*)/i && ($sum += length($1)+1, $lines++);
|
||||
$head =~ /^(Date:\s+.*)/i && ($sum += length($1)+1, $lines++);
|
||||
$sum++, $lines++;
|
||||
|
||||
# count the body of the message
|
||||
undef $/;
|
||||
$body = <COUNT>;
|
||||
$sum += length($body);
|
||||
$lines += ($body =~ s/\n/\n/g); # count newlines
|
||||
|
||||
$/ = "\n";
|
||||
close(COUNT);
|
||||
$sum += length($EB) + 3, $lines += 3; # account for message delimiter
|
||||
|
||||
##printf "After message %03d, lines = $lines\n", $i-1;
|
||||
|
||||
if ($V{'DIGEST_SIZE'} && $sum > $V{'DIGEST_SIZE'}) {
|
||||
return(1);
|
||||
}
|
||||
if ($V{'DIGEST_LINES'} && $lines > $V{'DIGEST_LINES'}) {
|
||||
return(1);
|
||||
}
|
||||
if ($V{'MAX_AGE'} && (-M $file) > $V{'MAX_AGE'}) {
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#
|
||||
# Loop through calling 'should_be_sent' to find out how large each digest
|
||||
# should be and calling send_digest to construct and send each digest.
|
||||
# All the files in the spool directory are sent. This could be modified
|
||||
# to only send "complete" digests.
|
||||
#
|
||||
# Note that this will quietly terminate if there are no messages in the
|
||||
# spool. I find this preferable to an abort.
|
||||
#
|
||||
sub make_digest {
|
||||
# disable age detection
|
||||
$V{'MAX_AGE'} = 0;
|
||||
# use 'should_be_sent' to find out how large each digest should be
|
||||
# and loop through the spool dir until it's empty
|
||||
$fnum = 0;
|
||||
$nextfile = sprintf("%s/%03d", $V{'INCOMING'}, ++$fnum);
|
||||
while (-e $nextfile) {
|
||||
# starts at $fnum, sets '$file' to the last file to use
|
||||
&should_be_sent($fnum);
|
||||
&send_digest($file);
|
||||
($fnum) = $file =~ m#/(\d+)$#;
|
||||
$nextfile = sprintf("%s/%03d", $V{'INCOMING'}, ++$fnum);
|
||||
$NUMBER++;
|
||||
}
|
||||
|
||||
if (! $opt_d) {
|
||||
if ( ! defined($opt_C) ) {
|
||||
open(NUM_FILE, ">$V{'NUM_FILE'}") ||
|
||||
&abort("open(NUM_FILE, \">$NUM_FILE\"): $!");
|
||||
printf NUM_FILE "%d\n", $NUMBER;
|
||||
close(NUM_FILE);
|
||||
} else { # hurrah we are using the majordomo config file
|
||||
$config_opts{$opt_l,"digest_issue"} = $NUMBER;
|
||||
&config'writeconfig($listdir, $opt_l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Contruct and send a digest using files in the spool directory up to and
|
||||
# including the "last file" specified as the first argument.
|
||||
#
|
||||
sub send_digest {
|
||||
local($lastfile) = shift;
|
||||
if (opendir(DIR, $V{'INCOMING'})) {
|
||||
@files = grep(/^\d+$/, readdir(DIR));
|
||||
closedir(DIR);
|
||||
}
|
||||
else {
|
||||
&abort("Error opening $V{'INCOMING'}: $!\nStopped ");
|
||||
}
|
||||
&abort("No messages.\nStopped ") unless @files;
|
||||
open(TEMP,">$TEMP") || &abort("$TEMP: $!\n");
|
||||
print STDERR "producing $V{'NAME'} V$VOLUME #$NUMBER\n";
|
||||
foreach (sort(@files)) {
|
||||
$message = "$V{'INCOMING'}/$_";
|
||||
open(message) || &abort("$message: $!\n");
|
||||
print STDERR "\tprocessing $message\n";
|
||||
push(@processed,$message);
|
||||
|
||||
$/ = '';
|
||||
$head = <message>;
|
||||
$head =~ s/\n\s+/ /g;
|
||||
$body = "";
|
||||
$subj = ($head =~ /^Subject:\s+(.*)/i)? $1: "[none]";
|
||||
($from) = $head =~ /^From:\s+(.*)/i;
|
||||
($date) = $head =~ /^Date:\s+(.*)/i;
|
||||
|
||||
undef $/;
|
||||
$body = <message>;
|
||||
close(message);
|
||||
|
||||
# trim message fronter and footers inserted by resend in
|
||||
# non digest version of list
|
||||
if ($RMHEADER) {
|
||||
$body =~ s/$RMHEADER/\n/;
|
||||
}
|
||||
if ($RMTRAILER) {
|
||||
$body =~ s/$RMTRAILER/\n/;
|
||||
}
|
||||
|
||||
# escape ^From <user> <weekday> <month> <day> <hr:min:sec> ...
|
||||
$body =~
|
||||
s/^From (\S+\s+\w{3}\s+\w{3}\s+\d+\s+\d+:\d+:\d+)/>From $1/g;
|
||||
$body =~ s/^-/- -/g; # escape encapsulation boundaries in message
|
||||
# trim trailing \n's
|
||||
$len = length($body) - 1;
|
||||
$len-- while (substr($body,$len,1) eq "\n");
|
||||
substr($body,$len+1) = "";
|
||||
|
||||
$/ = "\n";
|
||||
|
||||
## note -- RFC 1153 claims the following headers should be retained, and
|
||||
## presented in the following order:
|
||||
## Date:, From:, To:, Cc:, Subject:, Message-ID:, and Keywords:
|
||||
|
||||
push(@subj,$subj);
|
||||
print TEMP <<EOF;
|
||||
Date: $date
|
||||
From: $from
|
||||
Subject: $subj
|
||||
|
||||
$body
|
||||
|
||||
$EB
|
||||
|
||||
EOF
|
||||
last if ($message eq $lastfile);
|
||||
}
|
||||
close(TEMP);
|
||||
|
||||
|
||||
if ($opt_d) {
|
||||
$DIGEST = "$TMPDIR/testdigest.$NUMBER";
|
||||
} else {
|
||||
$DIGEST = sprintf("%s/v%02d.n%03d", $V{'ARCHIVE'}, $VOLUME, $NUMBER);
|
||||
}
|
||||
open(DIGEST, ">$DIGEST") || &abort("open(DIGEST, \">$DIGEST\"): $!");
|
||||
|
||||
print DIGEST <<EOF;
|
||||
From: $V{'FROM'} ($V{'NAME'})
|
||||
To: $V{'TO'}
|
||||
Subject: $V{'NAME'} V$VOLUME #$NUMBER
|
||||
Reply-To: $V{'REPLY-TO'}
|
||||
Sender: $V{'ERRORS-TO'}
|
||||
Errors-To: $V{'ERRORS-TO'}
|
||||
Precedence: $Precedence
|
||||
$HEADERS
|
||||
|
||||
EOF
|
||||
|
||||
$PDATE = &getdate();
|
||||
$volstr = sprintf("Volume %02d : Number %03d\n\n",$VOLUME,$NUMBER);
|
||||
$width = length($V{'NAME'}) + length($PDATE) + length($volstr);
|
||||
if ($width < 76) {
|
||||
$center = " " x int((78 - $width) / 2);
|
||||
} else {
|
||||
$center = " ";
|
||||
}
|
||||
print DIGEST $V{'NAME'},$center,$PDATE,$center,$volstr,"\n\n";
|
||||
|
||||
foreach (split(/\n/,$HEADER)) {
|
||||
if (/_SUBJECTS_/) {
|
||||
$pre = $`;
|
||||
foreach $subj (@subj) {
|
||||
print DIGEST $pre,$subj,"\n";
|
||||
}
|
||||
}else{
|
||||
print DIGEST "$_\n";
|
||||
}
|
||||
}
|
||||
print DIGEST "\n";
|
||||
print DIGEST "-" x 70,"\n\n";
|
||||
|
||||
open(TEMP);
|
||||
print DIGEST <TEMP>;
|
||||
close(TEMP);
|
||||
unlink($TEMP);
|
||||
|
||||
$end = sprintf("End of %s V%d #%d", $V{'NAME'}, $VOLUME, $NUMBER);
|
||||
print DIGEST $end, "\n";
|
||||
print DIGEST "*" x length($end), "\n";
|
||||
print DIGEST "\n";
|
||||
print DIGEST $TRAILER;
|
||||
|
||||
close(DIGEST);
|
||||
|
||||
if ($opt_d) {
|
||||
warn "digest output in $TMPDIR/testdigest.$NUMBER\n";
|
||||
} else {
|
||||
$sender = $V{'ERRORS-TO'};
|
||||
$mailcmd = eval qq/"$mailer"/;
|
||||
system("$mailcmd $V{'REALLY-TO'} < $DIGEST");
|
||||
foreach $file (@processed) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
undef @subj;
|
||||
undef @processed;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub init {
|
||||
$HOME = $ENV{"HOME"} || (getpwuid($>))[7];
|
||||
chdir($HOME);
|
||||
&getopt("drRmpc:Cl:z") ||
|
||||
&abort("Usage: digest {-r|-R|-m|-p} [-c config|(-C -l list)]\nStopped");
|
||||
$config = $opt_c || "$HOME/.digestrc";
|
||||
$SIG{'INT'} = 'cleanup';
|
||||
@MONTHS = ("January","February","March","April","May","June","July",
|
||||
"August","September","October","November","December");
|
||||
@DAYS = ("Sunday","Monday","Tuesday","Wednesday","Thursday",
|
||||
"Friday","Saturday");
|
||||
$EB = "-" x 30;
|
||||
}
|
||||
|
||||
sub readconfig {
|
||||
if (defined($opt_C)) {
|
||||
if (!defined($opt_l)) {
|
||||
&abort("-C used without -l");
|
||||
} else {
|
||||
# Read and execute the .cf file
|
||||
$cf = $opt_c || $ENV{"MAJORDOMO_CF"} ||
|
||||
"/etc/majordomo.cf";
|
||||
require "$cf";
|
||||
|
||||
chdir($homedir);
|
||||
|
||||
$opt_l =~ tr/A-Z/a-z/;
|
||||
|
||||
require "config_parse.pl";
|
||||
|
||||
# Define all of the mailer properties:
|
||||
# It is possible that one or both of $sendmail_command and $bounce_mailer
|
||||
# are not defined, so we provide reasonable defaults.
|
||||
$sendmail_command = "/usr/lib/sendmail"
|
||||
unless defined $sendmail_command;
|
||||
$mailer = "$sendmail_command -oi -oee -f\$sender"
|
||||
unless defined $mailer;
|
||||
$bounce_mailer = "$sendmail_command -f\$sender -t"
|
||||
unless defined $bounce_mailer;
|
||||
&set_abort_addr($whoami_owner);
|
||||
&set_mail_from($whoami);
|
||||
&set_mail_sender($whoami_owner);
|
||||
&set_mailer($bounce_mailer);
|
||||
|
||||
# get the digest config file
|
||||
# Let's hope that nobody ever invokes us both with and
|
||||
# without -C, since these locks don't interact
|
||||
$lockfile = "$listdir/$opt_l.config.LOCK";
|
||||
&set_lock($lockfile) ||
|
||||
&abort("$program_name: can't get lock '$lockfile'\n");
|
||||
$lock_set = 1;
|
||||
&get_config($listdir, $opt_l, "locked");
|
||||
|
||||
# get details of parent list footers and headers
|
||||
if ($config_opts{$opt_l,"digest_rm_fronter"}) {
|
||||
&get_config($listdir, $config_opts{$opt_l,"digest_rm_fronter"});
|
||||
$RMHEADER = $config_opts{$config_opts{$opt_l,"digest_rm_fronter"},
|
||||
"message_fronter"};
|
||||
$RMHEADER =~ s/([^A-Za-z0-9 \001])/\\\1/g;
|
||||
$RMHEADER =~ s/\\\$(SENDER|VERSION|LIST)/\[\^\\n\]\*/g;
|
||||
$RMHEADER =~ s/\001/\\n/g;
|
||||
}
|
||||
if ($config_opts{$opt_l,"digest_rm_footer"}) {
|
||||
if ($config_opts{$opt_l,"digest_rm_footer"} ne
|
||||
$config_opts{$opt_l,"digest_rm_fronter"}) {
|
||||
&get_config($listdir, $config_opts{$opt_l,"digest_rm_footer"});
|
||||
}
|
||||
$RMTRAILER = $config_opts{$config_opts{$opt_l,"digest_rm_footer"},
|
||||
"message_footer"};
|
||||
$RMTRAILER =~ s/([^A-Za-z0-9 \001])/\\\1/g;
|
||||
$RMTRAILER =~ s/\\\$(SENDER|VERSION|LIST)/\[\^\\n\]\*/g;
|
||||
$RMTRAILER =~ s/\001/\\n/g;
|
||||
}
|
||||
|
||||
# map config opts to internal variables and $V array
|
||||
$HEADER = $config_opts{$opt_l,"message_fronter"};
|
||||
$HEADER =~ s/\001/\n/g;
|
||||
$TRAILER = $config_opts{$opt_l,"message_footer"};
|
||||
$TRAILER =~ s/\001/\n/g;
|
||||
$VOLUME = $config_opts{$opt_l,"digest_volume"};
|
||||
$NUMBER = $config_opts{$opt_l,"digest_issue"};
|
||||
$Precedence = $config_opts{$opt_l,"precedence"};
|
||||
$Precedence = "bulk" if ($Precedence eq "");
|
||||
$V{'ARCHIVE'} = "$filedir/$opt_l$filedir_suffix";
|
||||
$V{'DIGEST_SIZE'} = $config_opts{$opt_l, "maxlength"};
|
||||
$V{'DIGEST_LINES'} = $config_opts{$opt_l, "digest_maxlines"};
|
||||
$V{'MAX_AGE'} = $config_opts{$opt_l, "digest_maxdays"};
|
||||
$V{'ERRORS-TO'} = $config_opts{$opt_l,"sender"} . "@" .
|
||||
($config_opts{$opt_l,"resend_host"}
|
||||
||$whereami);
|
||||
$V{'FROM'} = $config_opts{$opt_l, "sender"}. "@" .
|
||||
($config_opts{$opt_l,"resend_host"}
|
||||
||$whereami);
|
||||
$V{'INCOMING'} = "$digest_work_dir/$opt_l";
|
||||
$V{'NAME'} = $config_opts{$opt_l,"digest_name"};
|
||||
$V{'REALLY-TO'} = $ARGV[0]."@".${whereami};
|
||||
$V{'REPLY-TO'} = $config_opts{$opt_l,"reply_to"};
|
||||
$V{'TO'} = "$opt_l\@$whereami";
|
||||
|
||||
# make the headers keyword work
|
||||
if ( $config_opts{$opt_l,"message_headers"} ne '' ) {
|
||||
$from = $V{'FROM'};
|
||||
$HEADERS = &config'substitute_values (
|
||||
$config_opts{$opt_l,"message_headers"}, $opt_l);
|
||||
$HEADERS =~ s/\001/\n/g;
|
||||
}
|
||||
} # list is defined
|
||||
} else { # not using -C
|
||||
require "config_parse.pl";
|
||||
|
||||
# Define all of the mailer properties:
|
||||
# The majordomo.cf file isn't used in this option, so fake everything.
|
||||
$sendmail_command = "/usr/lib/sendmail"
|
||||
unless defined $sendmail_command;
|
||||
$mailer = "$sendmail_command -oi -oee -f\$sender"
|
||||
unless defined $mailer;
|
||||
$bounce_mailer = "$sendmail_command -fmajordomo-owner -t"
|
||||
unless defined $bounce_mailer;
|
||||
&set_abort_addr("majordomo-owner");
|
||||
&set_mail_from("majordomo-owner");
|
||||
&set_mail_sender("majordomo-owner");
|
||||
&set_mailer($bounce_mailer);
|
||||
|
||||
open(config) || &abort("$config: $!\n");
|
||||
while (<config>) {
|
||||
next if /^\s*$|^\s*#/;
|
||||
chop;
|
||||
($key,$value) = split(/\s*=\s*/,$_,2);
|
||||
$V{$key} = $value;
|
||||
}
|
||||
close(config);
|
||||
|
||||
# Let's hope that nobody ever invokes us both with and
|
||||
# without -C, since these locks don't interact
|
||||
$lockfile = "$V{'INCOMING'}/.LOCK";
|
||||
&set_lock($lockfile) ||
|
||||
&abort("$program_name: can't get lock '$lockfile'\n");
|
||||
$lock_set = 1;
|
||||
|
||||
open(header,$V{'HEADER'}) || &abort("$V{'HEADER'}: $!\n");
|
||||
$HEADER = join("",<header>);
|
||||
close(header);
|
||||
|
||||
open(trailer,$V{'TRAILER'}) || &abort("$V{'TRAILER'}: $!\n");
|
||||
$TRAILER = join("",<trailer>);
|
||||
close(trailer);
|
||||
|
||||
open(VOL_FILE,$V{'VOL_FILE'}) || &abort("$V{'VOL_FILE'}: $!\n");
|
||||
$VOLUME = join("",<VOL_FILE>);
|
||||
chop($VOLUME);
|
||||
close(VOL_FILE);
|
||||
|
||||
open(NUM_FILE,$V{'NUM_FILE'}) || &abort("$V{'NUM_FILE'}: $!\n");
|
||||
$NUMBER = join("",<NUM_FILE>);
|
||||
chop($NUMBER);
|
||||
close(NUM_FILE);
|
||||
|
||||
} # end not using -C
|
||||
}
|
||||
|
||||
#my favorite of the existing getopt routines; twisted
|
||||
#
|
||||
sub getopt {
|
||||
local($_,%opt,$rest) = (split(/([^:])/,$_[0]),'');
|
||||
while ($_ = $ARGV[0], /^-(.)/ && shift(@ARGV)) {
|
||||
$rest = $';
|
||||
last if $1 eq '-';
|
||||
if (!defined $opt{$1}) {
|
||||
warn "Unrecognized switch \"-$1\".\n";
|
||||
return 0;
|
||||
}elsif ($opt{$1}) {
|
||||
$rest = shift(@ARGV) if $rest eq '';
|
||||
eval "\$opt_$1 = \$rest";
|
||||
}else{
|
||||
eval "\$opt_$1 = 1";
|
||||
$rest =~ /^(.)/;
|
||||
redo if $rest ne '';
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub cleanup {
|
||||
unlink($TEMP);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sub getdate {
|
||||
local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
||||
$year += 1900;
|
||||
return("$DAYS[$wday], $MONTHS[$mon] $mday $year");
|
||||
}
|
||||
|
||||
sub abort {
|
||||
local($msg) = shift;
|
||||
|
||||
&free_lock($lockfile) if $lock_set;
|
||||
die($msg);
|
||||
}
|
||||
Reference in New Issue
Block a user