diff options
Diffstat (limited to 'debian/local/update_mk')
-rw-r--r-- | debian/local/update_mk | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/debian/local/update_mk b/debian/local/update_mk new file mode 100644 index 0000000..92d7731 --- /dev/null +++ b/debian/local/update_mk @@ -0,0 +1,765 @@ +#!/usr/bin/perl -w +#------------------------------------------------------------------------ +# +# $Sendmail: update_mk,v 8.14.3 2009-02-28 22:32:11 cowboy Exp $ +# +# Create /etc/mail/Makefile for Debian Sendmail databases +# +# Copyright 1998-2009 Richard Nelson. All Rights Reserved. +# +# Notes (to all): +# * +# +# Notes (to self): +# * Should actually put data in some files (local-host-names, etc) +# +#------------------------------------------------------------------------ +# +# Initialization of the perl environment +use strict; # be kosher +use Cwd; # provide cwd() +use Env; # A few environmental references +use integer; # Peformance +use Sys::Hostname; # make sure we have a valid hostname +use Getopt::Long; # parameter handling + +# Local libraries - for Debian Sendmail Perl helper functions +# BEGIN { $main::my_path = substr($0,$[,rindex($0,'/')) }; +use lib ('.', substr($0,$[,rindex($0,'/')), "/usr/share/sendmail"); +require Parse_mc; +require Parse_conf; + +# Version of this program +#($main::MYNAME = $main::0) =~ s|.*/||; +#$main::Author = "Richard Nelson"; +#$main::AuthorMail = "cowboy\@debian.org"; +#$main::Version = '$Revision: 2.00 $ '; +$main::program_name = $0; +$main::program_version = '8.14.3'; +$main::program_date = '2009-02-28 22:32:11 cowboy'; +$main::debug = 0; + +my $interp_pgm = "$^X"; +my $interp_vrm = $]; +$interp_vrm = ("$^V" | '000') if (defined $^V); +my $current_time = scalar localtime; +my $user = getlogin || (getpwuid($<))[0] || "Unknown!!"; +my $hostname = hostname(); +my $directory = getcwd(); + +my $Makefile_def = "/etc/mail/Makefile"; +my $Conffile = "/etc/mail/sendmail.conf"; +# List of database entries that will be created if not found +my %created_dbs; +my @created_dbs; +# A few files (like exposed-users) can be listed >1 times ! +my %created_files = (); +my $reload_stamp = "/var/run/sendmail/stampdir/reload"; + +# +#------------------------------------------------------------------------------ +# Finally, some code (almost) +#------------------------------------------------------------------------------ +# +# Argument handling... +$main::opt_help=''; +$main::opt_output_file=''; +$main::opt_input_file=''; +$main::opt_debug=''; +my @options = qw( + help|h + output-file|output_file|o:s + input-file|input_file|i:s + debug! + ); +my $result = GetOptions(@options); +if ( ! $result ) { + die "Terminating due to parameter error"; + }; +if ( $main::opt_help ) { + warn "$main::program_name $main::program_version $main::program_date\n"; + warn "$0 \n"; + warn " -help\n" if $main::opt_help; + warn " -debug\n" if $main::opt_debug; + warn " -o $main::opt_output_file\n" if $main::opt_output_file; + warn " -i $main::opt_input_file\n" if $main::opt_input_file; + exit 0; + }; + +my $Makefile = $main::opt_output_file || $Makefile_def; +${Parse_mc::database_file} = $main::opt_input_file + if $main::opt_input_file; +# $main::debug is used in Parse_mc ! +$main::debug = $main::opt_debug || $main::debug; + +# Pull in some configuration data +&Parse_conf::read_conf("$Conffile"); +my ($ok, $value) = &Parse_conf::get_value('HANDS_OFF'); +if ($value ne '0') { + exit; + }; + +# Let them know wtf is going on... +print STDOUT "Creating ${Makefile}...\n"; + +# Read the mc/m4 files +&Parse_mc::read_dbs($Parse_mc::database_file, ''); + +# Determine names with which we shall work +my @databases = &get_names(); + +# Write out the textual representation +&write_make; + +# +#------------------------------------------------------------------------------ +# Obtain list of candidate databases from sendmail.mc +#------------------------------------------------------------------------------ +sub get_names { + my @names; + + # Database types we know how to handle + my %make_types = ( + 'btree' => 1 + ,'dbm' => 1 + ,'hash' => 1 + ,'m4' => 1 + ,'newaliases' => 1 + ,'parse_mc' => 1 + ,'update_conf' => 1 + ,'update_mk' => 1 + ,'update_auth' => 1 + ,'update_tls' => 1 + ,'QUEUE_GROUP' => 1 + ,'include' => 1 + ); + + # Add any qualified databases to the list + foreach my $entry (&Parse_mc::names_dbs()) { + my ($class, $flags, $files, $options) = + &Parse_mc::entry_dbs($entry); + if ( (exists($make_types{$entry}) or + exists($make_types{$class})) + and @{$files}[0] ne '-' + and ! exists($created_dbs{$entry})) { + push @names, $entry; + push @created_dbs, $entry; + $created_dbs{$entry} = ''; + }; + }; + + return @names; + }; + +# +#------------------------------------------------------------------------------ +# Create Makefile +#------------------------------------------------------------------------------ +sub write_make { + my $ofh = new FileHandle; + + $Makefile = '&STDOUT' if ($Makefile eq '-'); + unless ( open($ofh, ">$Makefile") ) { + warn("Could not open $Makefile($!), using STDOUT.\n"); + open($ofh, ">&STDOUT"); + }; + $Makefile = '-' if ($Makefile eq '&STDOUT'); + + &write_header($ofh); + &write_target_clean($ofh); + &write_target_restart($ofh); + &write_target_sendmail($ofh); + &write_targets($ofh); + &write_files($ofh); + &write_footer($ofh); + + close $ofh; + if ($Makefile eq $Makefile_def) { + my $gid = getgrnam('smmsp'); + chown '0', $gid, $Makefile; + chmod 0754, $Makefile; + }; + }; + +# +#------------------------------------------------------------------------------ +# Write Makefile header +#------------------------------------------------------------------------------ +sub write_header { + my ($ofh) = @_; + + print $ofh <<"EOT"; +#!/usr/bin/make -f +#################################################################### +##### This file is automagically generated -- edit at your own risk +##### +##### Copyright (c) 1998-2009 Richard Nelson. All Rights Reserved. +##### +##### file: ${Makefile} Makefile for Sendmail databases +##### generated via: (${interp_pgm} ${interp_vrm}) +##### ${main::program_name} +##### version: ${main::program_version} ${main::program_date} +##### by: ${user}\@${hostname} +##### on: ${current_time} +##### in: ${directory} +##### input files: ${Parse_mc::database_file} +##### +##### Usage: +##### 1) Make all targets upto date - use one of the following: +##### A) \`(cd /etc/mail && make)\` +##### B) \`make -f ${Makefile}\` +##### C) \`${Makefile}\` +##### 2) Force update of <target> - Add <target> to one of the +##### prior commands ie, \`${Makefile} access\`. Most +##### any reasonable <target> value is accepted. +##### +#################################################################### +SHELL=/bin/sh + +# +# targets that will be routed to the /etc/init.d/sendmail script +# NOTE: newaliases and clean removed due to extant rules +# +INIT = start stop restart restart-if-running \\ + reload-if-running reload force-reload \\ + hoststat purgestat mailstats mailq runq control \\ + status debug + +.SUFFIXES: +.PRECIOUS: $Makefile + +# +# all, the default target, will update everything +# +.PHONY: all +all: sendmail $reload_stamp + +# +# route to the /etc/init.d/sendmail script +# +.PHONY: \$(INIT) +\$(INIT): FORCE + /etc/init.d/sendmail \$\@ + +EOT + }; + +# +#------------------------------------------------------------------------------ +# Write Makefile 'CLEAN' target +#------------------------------------------------------------------------------ +sub write_target_clean { + my ($ofh) = @_; + my @names; + + %created_files = (); + foreach my $entry (@databases) { + next if ($entry eq 'QUEUE_GROUP' + or $entry eq 'Makefile' + or $entry eq 'auth' + or $entry eq 'tls' + or $entry eq 'include' + ); + my ($class, $flags, $files, $options) = + &Parse_mc::entry_dbs($entry); + foreach my $file (@{$files}) { + next if ( $file eq '-' + or exists($created_files{$file}) ); + $created_files{$file} = ''; + my $dbname; + if ($class eq 'parse_mc' + or $class eq 'update_mk' + or $class eq 'm4') { + $dbname = "/etc/mail/$entry"; + } + elsif ($class eq 'update_conf') { + $dbname = "/etc/cron.d/sendmail"; + } + elsif ($class eq 'btree' + or $class eq 'hash' + or $class eq 'newaliases') { + $dbname = "$file.db"; + } + else { + $dbname = $file; + }; + push @names, $dbname; + }; + }; + + print $ofh <<"EOT"; + +# +# clean target, remove {sendmail,submit}.cf and generated databases +# +EOT + print $ofh + ".PHONY: clean\n", + "clean: FORCE\n", + "\trm -f ",join(";\n\trm -f ", @names),";\n"; + }; + +# +#------------------------------------------------------------------------------ +# Write Makefile 'RESTART' target +#------------------------------------------------------------------------------ +sub write_target_restart { + my ($ofh) = @_; + my $file; + + print $ofh <<"EOT"; + +# +# restart target, check to see if sendmail needs to be restarted +# +.PHONY: noreload norestart +noreload norestart: FORCE + \@touch $reload_stamp; + +.PHONY: should_reload should_restart +should_reload should_restart: FORCE + \@rm -f $reload_stamp; + \@\$(MAKE) -sf $Makefile $reload_stamp; + +EOT + + # Spew secondary target of actual restart + %created_files = (); + my @right; + foreach my $entry (sort &Parse_mc::restart_dbs()) { + if (! exists($created_dbs{$entry})) { + push @created_dbs, $entry; + $created_dbs{$entry} = ''; + }; + my ($class, $flags, $files, $options) = + &Parse_mc::entry_dbs($entry); + foreach my $file (@{$files}) { + next if ( $file eq '-' + or exists($created_files{$file}) ); + $created_files{$file} = ''; + my $dbname = $file; + $dbname =~ s/\.mc$/\.cf/; + push @right, "$dbname"; + }; + }; + + print $ofh "$reload_stamp: \\\n\t", + join(" \\\n\t", @right), "\n", + "\t\@if [ ! -f \$\@ ]; then \\\n", + "\t\techo 'A forced reload...'; \\\n", + "\telse \\\n", + "\t\techo 'The following file(s) have changed:'; \\\n", + "\t\techo ' \$?'; \\\n", + "\t\tfi;\n", + "\t\@echo '** ** You should issue ", + "\`/etc/init.d/sendmail reload\` ** **';\n"; + }; + +# +#------------------------------------------------------------------------------ +# Write Sendmail dependancies +#------------------------------------------------------------------------------ +sub write_target_sendmail { + my ($ofh) = @_; + + print $ofh <<"EOT"; + +# +# sendmail targets, depend upon *ALL* relevant files/databases +# +.PHONY: sendmail +sendmail: sendmail_files sendmail_dbs + +EOT + my (@smfiles, @smdbs); + + %created_files = (); + foreach my $entry (@created_dbs) { + my ($class, $flags, $files, $options) = + &Parse_mc::entry_dbs($entry); + foreach my $file (@{$files}) { + next if $file eq '-'; + next if $file eq 'ldap'; # ALIAS hack + if ($class eq 'parse_mc' or $class eq 'update_mk' + or $class eq 'm4') { + push @smfiles, "$file" + if (!exists($created_files{$file})); + $created_files{$file} = ''; + push @smdbs, "/etc/mail/$entry"; + } + elsif ($class eq 'update_conf') { + push @smdbs, "/etc/cron.d/sendmail"; + } + elsif ($class eq 'btree' or $class eq 'hash' + or $class eq 'newaliases') { + push @smfiles, "$file" + if (!exists($created_files{$file})); + $created_files{$file} = ''; + push @smdbs, "$file.db"; + } + else { + push @smfiles, "$file" + if (!exists($created_files{$file})); + $created_files{$file} = ''; + }; + }; + }; + + print $ofh ".PHONY: sendmail_files\n", + "sendmail_files: \\\n\t", + join(" \\\n\t", @smfiles), "\n\n"; + print $ofh ".PHONY: sendmail_dbs\n", + "sendmail_dbs: \\\n\t", + join(" \\\n\t", @smdbs), "\n"; + }; + +# +#------------------------------------------------------------------------------ +# Write Makefile individual targets +#------------------------------------------------------------------------------ +sub write_targets { + my ($ofh) = @_; + my $file; + + print $ofh <<"EOT"; + +# +# Individual database targets +# + +# +# Default db type is hash (Must be in /etc/mail, or +# fully qualify the dataset for this target to work) +# +%.db: % FORCE + \@echo 'Updating \$\@...'; + \@if [ -x /usr/sbin/makemap ]; then \\ + /usr/sbin/makemap hash \$\@.new.db < \$<; \\ + chown root:smmsp \$\@.new.db; \\ + chmod 0640 \$\@.new.db; \\ + mv -f \$\@.new.db \$\@; \\ + fi; +EOT + + # Spew primary target of <target> + foreach my $entry (@databases) { + my ($class, $flags, $files, $options) = + &Parse_mc::entry_dbs($entry); + my @names; + my $left = ''; + my $right = ''; + my $sleft = ''; + my $dbname = ''; + print $ofh "\n"; + + # Create short name(s) for database entries + $sleft .= "$entry "; + if ($class eq 'newaliases' + or $class eq 'parse_mc' + or $class eq 'update_mk' + or $class eq 'update_conf' + or $class eq 'update_auth' + or $class eq 'update_tls' + ) { + $sleft = 'makefile make ' if ($class eq 'update_mk'); + $sleft .= 'cron ' if ($class eq 'update_conf'); + $sleft .= "$class "; + }; + + foreach my $file (@{$files}) { + next if $file eq '-'; + next if $file eq 'ldap'; # ALIAS hack + if ($entry eq 'QUEUE_GROUP' or $entry eq 'include') { + $dbname = ''; + $sleft = lc "${entry}s"; + $left = lc "${entry}s"; + } + elsif ($class eq 'parse_mc' or $class eq 'update_mk' + or $class eq 'm4') { + $dbname = "/etc/mail/$entry"; + } + elsif ($class eq 'update_conf') { + $dbname = "/etc/cron.d/sendmail"; + } + elsif ($class eq 'btree' or $class eq 'hash' + or $class eq 'newaliases') { + $dbname = "$file.db"; + } + else { + $dbname = $file; + $file = "" + if ($class eq 'update_tls' + or $class eq 'update_auth'); + }; + $left .= "$dbname "; + $right .= " $file"; + + # Create short name(s) for database entries + if ($class ne 'parse_mc' + and $class ne 'update_mk' + and $class ne 'update_conf' + and $class ne 'update_auth' + and $class ne 'update_tls' + and $entry ne 'QUEUE_GROUP' + and $entry ne 'include' + ) { + my $dbsname = "$dbname"; + $dbsname =~ s/\/etc\/mail\///; + $sleft .= "$dbsname " if ($entry ne $dbsname); + if ($file ne $dbname) { + $dbsname =~ s/\.db//; + $sleft .= "$dbsname " if ($entry ne $dbsname); + }; + }; + }; + + # Spew out a phony entry suitable for FORCE + print $ofh '.PHONY: ', $sleft, "\n"; + print $ofh $sleft,": FORCE\n" + if ($entry ne 'QUEUE_GROUP' and $entry ne 'include'); + if ($class eq 'update_mk') { + print $ofh "\t\@touch $right;\n", + "\t\@\$(MAKE) -sf $Makefile $left;\n"; + } + elsif ($entry ne 'QUEUE_GROUP' and $entry ne 'include') { + print $ofh "\t\@rm -f $left;\n", + "\t\@\$(MAKE) -sf $Makefile $left;\n"; + }; + + # + # Spew out the whole enchilada for this database + if ($entry eq 'sendmail.cf' or $entry eq 'databases') { + my ($iclass, $iflags, $ifiles, $ioptions) = + &Parse_mc::entry_dbs('include'); + $right .= ' '; + $right .= join(' ', @{$ifiles}); + }; + print $ofh $left, ':', $right, "\n"; + next if ($entry eq 'QUEUE_GROUP' or $entry eq 'include'); + print $ofh "\t\@echo 'Updating $entry ...';\n"; + if ($class eq 'newaliases') { + print $ofh "\t\@if [ -x /usr/sbin/sendmail ]; then \\\n"; + print $ofh "\t\t/usr/sbin/sendmail -bi || true; \\\n"; + } + elsif ($class eq 'parse_mc' + or $class eq 'update_conf' + or $class eq 'update_mk' + or $class eq 'update_auth' + or $class eq 'update_tls' + ) { + print $ofh "\t\@if [ -x /usr/share/sendmail/${class} ]; then \\\n"; + print $ofh "\t\t/usr/share/sendmail/${class} || true; \\\n" + } + elsif ($class eq 'btree' or $class eq 'hash') { + print $ofh "\t\@if [ -x /usr/sbin/makemap ]; then \\\n"; + }; + foreach my $file (@{$files}) { + next if ( $file eq 'ldap' ); # ALIAS hack + my $dbname = $file; + my $newname = $file; + my $uid = 'root'; + $uid = 'smmta' if ($entry eq 'authinfo' + or $entry eq 'access_db' + or $entry eq 'QUEUE_GROUP' + or $class eq 'newaliases'); + my $mode = '0644'; + $mode = '0640' if ($entry eq 'authinfo' + or $entry eq 'access_db'); + $mode = '0640' if ($class eq 'btree' or $class eq 'hash'); + $mode = '0644' if ($class eq 'm4'); + $mode = '0754' if ($class eq 'update_mk'); + $mode = '02750' if ($entry eq 'QUEUE_GROUP'); + if ($class eq 'btree' or $class eq 'hash') { + $dbname .= '.db'; + $newname .= '.new.db'; + if (index($flags, '-o') == -1) { + print $ofh "\t\t/usr/sbin/makemap $class $newname \\\n", + "\t\t\t< $file; \\\n", + "\t\tchown $uid:smmsp $newname; \\\n", + "\t\tchmod $mode $newname; \\\n", + "\t\tmv -f $newname $dbname; \\\n"; + } + else { + print $ofh + "\t\tif [ -s $file ]; then \\\n", + "\t\t/usr/sbin/makemap $class $newname \\\n", + "\t\t\t< $file; \\\n", + "\t\tchown $uid:smmsp $newname; \\\n", + "\t\tchmod $mode $newname; \\\n", + "\t\tmv -f $newname $dbname; \\\n", + "\t\tfi; \\\n"; + }; + } + elsif ($class eq 'newaliases') { + $newname .= '.db'; + print $ofh "\t\tif [ -f $newname ]; then \\\n", + "\t\t\tchown $uid:smmsp $newname; \\\n", + "\t\t\tchmod $mode $newname; \\\n", + "\t\t\tfi; \\\n"; + } + elsif ($class eq 'parse_mc' or $class eq 'update_mk') { + $newname = "/etc/mail/$entry"; + print $ofh "\t\tchown $uid:smmsp $newname; \\\n", + "\t\tchmod $mode $newname; \\\n"; + } + elsif ($class eq 'm4') { + my $oldname = $dbname; + $dbname =~ s/\.mc$/\.cf/; + $newname =~ s/\.mc$/\.cf\.new/; + my $lead = "\t"; + my $leadh = "\t\@"; + my $lead2 = "\t\t"; + my $trail = ""; + if ($entry eq 'submit.cf') { + $lead = "\t\t"; + $leadh = "\t\t"; + $lead2 = "\t\t\t"; + $trail = "\\"; + }; + print $ofh + "\t\@rm -f ${dbname}.errors\n"; + print $ofh + "\t\@if [ -f /usr/share/sendmail/cf/feature/msp.m4 ]; ", + "then \\\n" if ($entry eq 'submit.cf'); + print $ofh + "${leadh}m4 $file > $newname \\\n", + "${lead2}2> ${dbname}.errors || true; $trail\n", + "${leadh}echo \"### ${oldname} ###\" \\\n", + "${lead2}>> $newname; $trail\n", + "${leadh}sed -e 's/^/# /' $file \\\n", + "${lead2}>> $newname; $trail\n", + "${leadh}chown $uid:smmsp $newname; $trail\n", + "${leadh}chmod $mode $newname; $trail\n", + "${leadh}mv -f $newname $dbname; $trail\n", + "${leadh}if [ -s ${dbname}.errors ]; then \\\n", + "${lead2}chown $uid:smmsp ${dbname}.errors; \\\n", + "${lead2}cat ${dbname}.errors; \\\n", + "${lead}else \\\n", + "${lead2}rm -f ${dbname}.errors; \\\n", + "${lead2}fi; $trail\n"; + print $ofh + "${lead}fi;\n" if ($entry eq 'submit.cf'); + }; + }; + if ($class eq 'newaliases' + or $class eq 'parse_mc' + or $class eq 'update_conf' + or $class eq 'update_mk' + or $class eq 'update_auth' + or $class eq 'update_tls' + or $class eq 'btree' or $class eq 'hash' + ) { + print $ofh "\t\tfi;\n"; + }; + }; + }; + +# +#------------------------------------------------------------------------------ +# Write Makefile file targets (create any missing files) +#------------------------------------------------------------------------------ +sub write_files { + my ($ofh) = @_; + + print $ofh <<"EOT"; + +# +# Individual file targets - create any requisite files +# +EOT + + %created_files = (); + foreach my $entry (@created_dbs) { + my ($class, $flags, $files, $options) = + &Parse_mc::entry_dbs($entry); + + # These are done above... + next if ($entry eq 'databases' + or $entry eq 'auth' + or $entry eq 'tls' + or $entry eq 'Makefile' + or $entry eq 'include' + ); + + foreach my $file (@{$files}) { + next if ( $file eq '-' + or exists($created_files{$file}) ); + $created_files{$file} = ''; + my $uid = 'root'; + $uid = 'smmta' if ($entry eq 'authinfo' + or $entry eq 'access_db' + or $entry eq 'QUEUE_GROUP' + or $class eq 'newaliases'); + my $mode = '0644'; + $mode = '0640' if ($entry eq 'authinfo' + or $entry eq 'access_db'); + $mode = '0640' if ($class eq 'btree' or $class eq 'hash'); + $mode = '0644' if ($class eq 'm4'); + $mode = '0754' if ($class eq 'update_mk'); + $mode = '02750' if ($entry eq 'QUEUE_GROUP'); + print $ofh "\n$file:\n", + "\t\@echo 'Creating $file';\n"; + if ($entry eq 'QUEUE_GROUP') { + print $ofh "\t\@install -d", + " -o $uid -g smmsp -m $mode $file;\n", + "\t\@chown $uid:smmsp $file;\n", + "\t\@chmod $mode $file;\n"; + } + elsif ($entry eq 'sendmail.cf') { + print $ofh "\t\@/usr/sbin/sendmailconfig", + " --no-reload;\n"; + } + elsif ($entry eq 'submit.cf') { + print $ofh "\t\@cp /usr/share/sendmail/", + "cf/debian/submit.mc \\\n", + "\t\t$file;\n", + "\t\@chown $uid:smmsp $file;\n", + "\t\@chmod $mode $file;\n"; + } + elsif ($entry eq 'access_db') { + print $ofh "\t\@cp /usr/share/sendmail/", + "examples/db/access \\\n", + "\t\t$file;\n", + "\t\@chown $uid:smmsp $file;\n", + "\t\@chmod $mode $file;\n"; + } + elsif ($file eq '/etc/mail/aliases') { + print $ofh "\t\@ln -s ../aliases /etc/mail/aliases\n"; + } + elsif ($class eq 'update_conf' + or $class eq 'update_auth' + or $class eq 'update_tls') { + print $ofh "\t\@/usr/share/sendmail/${class};\n"; + } + # FIXME: come back and create real data + # where needed (local-host-names, etc) + elsif (index($flags, '-o') == -1) { + print $ofh "\t\@touch $file;\n", + "\t\@chown $uid:smmsp $file;\n", + "\t\@chmod $mode $file;\n"; + } + elsif (index($flags, '-o') != -1) { + print $ofh "\t# Optional file...\n"; + }; + }; + }; + }; + +# +#------------------------------------------------------------------------------ +# Write Makefile footer +#------------------------------------------------------------------------------ +sub write_footer { + my ($ofh) = @_; + +print $ofh <<"EOT"; + +# +# FORCE target, allow one to override dependancies +# +.PHONY: FORCE +FORCE: ; + +EOT + }; + |