#!/usr/bin/perl -w #------------------------------------------------------------------------ # # $Sendmail: Parse_conf.pm,v 8.14.3 2009-02-28 22:32:11 cowboy Exp $ # # Parse and update /etc/mail/sendmail.conf # # Copyright (c) 2001-2009 Richard Nelson. All Rights Reserved. # # Notes (to all): # # Notes (to self): # #------------------------------------------------------------------------ # # Package/Module declaration package Parse_conf; require Exporter; @ISA = qw(Exporter); #@EXPORT = qw(read_conf write_conf); @EXPORT_OK = qw(read_conf write_conf get_value); $VERSION = '2.0000'; # # Initialization of the perl environment use strict; # be kosher #use warnings; # Not needed here 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 use FileHandle; # I/O # 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; # Version of this program #($main::MYNAME = $main::0) =~ s|.*/||; #$main::Author = "Richard Nelson"; #$main::AuthorMail = "cowboy\@debian.org"; #$main::Version = '$Revision: 1.00 $ '; $Parse_conf::program_name = 'Parse_conf.pm'; $Parse_conf::program_version = '8.14.3'; $Parse_conf::program_date = '2009-02-28 22:32:11 cowboy'; $Parse_conf::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(); $Parse_conf::Conffile = "/etc/mail/sendmail.conf"; my $debug; # #------------------------------------------------------------------------------ # Global variables #------------------------------------------------------------------------------ my %parm_def = ( 'DAEMON_NETMODE' => 'Static' ,'DAEMON_NETIF' => 'eth0' ,'DAEMON_MODE' => 'Daemon' ,'DAEMON_RUNASUSER' => 'No' ,'DAEMON_PARMS' => '' ,'DAEMON_HOSTSTATS' => 'No' ,'DAEMON_MAILSTATS' => 'No' ,'QUEUE_MODE' => '${DAEMON_MODE}' ,'QUEUE_INTERVAL' => '10m' ,'QUEUE_PARMS' => '' ,'MSP_MODE' => 'Cron' ,'MSP_INTERVAL' => '20m' ,'MSP_PARMS' => '' ,'MSP_MAILSTATS' => '${DAEMON_MAILSTATS}' ,'MISC_PARMS' => '' ,'CRON_MAILTO' => 'root' ,'CRON_PARMS' => '' ,'HANDS_OFF' => 'No' ,'LOG_CMDS' => 'No' ,'AGE_DATA' => '' ); my %parameter = %parm_def; my %parm_kw = ( 'DAEMON_NETMODE' => ['static', 'dynamic'] ,'DAEMON_MODE' => ['daemon', 'inetd','none'] ,'QUEUE_MODE' => ['daemon', 'cron', 'none'] ,'MSP_MODE' => ['daemon', 'cron', 'none'] ); my %parm_bool = ( 'HANDS_OFF' => 1 ,'DAEMON_RUNASUSER' => 1 ,'DAEMON_HOSTSTATS' => 1 ,'DAEMON_MAILSTATS' => 1 ,'MSP_MAILSTATS' => 1 ,'LOG_CMDS' => 1 ); my %parm_dependant = ( ); my %parm_deprecated = ( 'DAEMON_STATS' => 'DAEMON_MAILSTATS' ,'MSP_STATS' => 'MSP_MAILSTATS' ); my %parm_hidden = ( 'DAEMON_RUNASUSER' => 1 ,'prefix' => 1 ,'exec_prefix' => 1 ,'bindir' => 1 ,'sbindir' => 1 ,'libexecdir' => 1 ,'datadir' => 1 ,'sysconfdir' => 1 ,'sharedstatedir' => 1 ,'localstatedir' => 1 ,'libdir' => 1 ,'MTA_DAEMON' => 1 ,'MTA_COMMAND' => 1 ,'MTA_L' => 1 ,'MTA_L_QUEUE' => 1 ,'MTA_ROOT' => 1 ,'MTA_PIDFILE' => 1 ,'MSP_DAEMON' => 1 ,'MSP_COMMAND' => 1 ,'MSP_L' => 1 ,'MSP_L_QUEUE' => 1 ,'MSP_ROOT' => 1 ,'MSP_PIDFILE' => 1 ); # #------------------------------------------------------------------------------ # Finally, some code (almost) #------------------------------------------------------------------------------ 1; # return (true); # #------------------------------------------------------------------------------ # Read /etc/mail/sendmail.conf #------------------------------------------------------------------------------ sub read_conf { my ($input_file) = @_; $input_file ||= $Parse_conf::Conffile; $debug = $main::debug || $Parse_conf::debug; # Update defaults according to current environment &update_defaults; # Read /etc/mail/sendmail.conf (if extant) &read_config($input_file); # Update old values to new format &update_values; # Make sure things are kosher my $ok = &validate_config; if (! $ok) { die "Terminating due to configuration error."; }; }; # #------------------------------------------------------------------------------ # [Re]write /etc/mail/sendmail.conf #------------------------------------------------------------------------------ sub write_conf { my ($output_file) = @_; $debug = $main::debug || $Parse_conf::debug; &write_config($output_file); }; # #------------------------------------------------------------------------ # Update default settings according to current environment #------------------------------------------------------------------------ sub update_defaults { my ($class, $flags, $files, $options); my ($ok, $stats); my $file; # Read the mc/m4 files &Parse_mc::read_dbs('', ''); # Obtain entry for HOST_STATUS_DIRECTORY ($class, $flags, $files, $options) = &Parse_mc::entry_dbs('confHOST_STATUS_DIRECTORY'); $file = @{$files}[0]; if ( $file ne '-' and -d $file ) { $parameter{'DAEMON_HOSTSTATS'} = 'Yes'; } else { $parameter{'DAEMON_HOSTSTATS'} = 'No'; }; # Obtain entry for STATUS_FILE ($class, $flags, $files, $options) = &Parse_mc::entry_dbs('STATUS_FILE'); $file = @{$files}[0]; if ( $file ne '-' and -e $file ) { $parameter{'DAEMON_MAILSTATS'} = 'Yes'; } else { $parameter{'DAEMON_MAILSTATS'} = 'No'; }; # Obtain entry for MSP_STATUS_FILE ($class, $flags, $files, $options) = &Parse_mc::entry_dbs('MSP_STATUS_FILE'); $file = @{$files}[0]; if ( $file ne '-' and -e $file ) { $parameter{'MSP_MAILSTATS'} = 'Yes'; } else { $parameter{'MSP_MAILSTATS'} = 'No'; }; }; # #------------------------------------------------------------------------ # Update old settings according to current format #------------------------------------------------------------------------ sub update_values { my ($ok, $var); # Add m(inutes) to {queue,msp}_interval if needed $parameter{'QUEUE_INTERVAL'} =~ s/^(p?\d+)$/$1m/; $parameter{'MSP_INTERVAL'} =~ s/^(p?\d+)$/$1m/; # Also update the queue aging data ($ok, $var) = &get_value('AGE_DATA'); my $tmpval = eval $var; if ($@) { warn $@; } else { $var = $tmpval; }; if (not defined $var) { $tmpval = '""'; } elsif (not ref $var) { $tmpval = "$var"; } elsif (@{$var} == 0) { $tmpval = '""'; } else { $tmpval = '['; foreach my $entry (@{$var}) { foreach my $ndx ($[ .. $#{$entry}) { @{$entry}[$ndx] =~ s/'/\\'/g; }; @{$entry}[0] =~ s/^(\d+)$/$1m/; $tmpval .= "['" . join("', '", @{$entry}) . "'],"; }; $tmpval .= ']'; $parameter{'AGE_DATA'} = $tmpval; }; # Set any dependant fields here... }; # #------------------------------------------------------------------------ # Obtain parameter name #------------------------------------------------------------------------ sub get_name { my ($name, $quiet) = @_; # Handle deprecated/renamed variables if ( exists($parm_deprecated{$name}) ) { print STDERR "$name is deprecated." if ($debug and ! $quiet); if ( $parm_deprecated{$name} ) { print STDERR " Please use $parm_deprecated{$name} instead.\n" if ($debug and ! $quiet); $name = $parm_deprecated{$name}; } else { print STDERR " It will be ignored.\n" if ($debug and ! $quiet); }; }; return $name; }; # #------------------------------------------------------------------------ # Obtain value directly, or indirectly #------------------------------------------------------------------------ sub get_value { my ($name) = @_; my $ok = 1; my $value = ''; if ( ! exists($parameter{$name}) ) { print STDERR "Variable $name not defined...\n"; return ($ok, $value); }; $name = get_name($name, ''); $value = $parameter{$name}; my $tval = $value; $tval =~ s/^\s*//; my $default = 0; # Dereference loop... keep original value if we get any errors... Dereference:; if ($tval =~ /^\$/) { my @ref_stack = ($name); my %ref_hash = ($name => 1); while ($tval =~ /^\$/ and $ok) { my $start = 1; my $del = 1; my $char = substr($tval, 1, 1); if ( $char eq '{' or $char eq '(' ) { $start += 1; $del += 2; }; my $ref = get_name(substr($tval, $start, length($tval)-$del), ''); push @ref_stack, $ref; if (exists($ref_hash{$ref})) { print STDERR "Go directly to jail; do not pass go, ", "do not collect \$200\n"; print STDERR " Reference loop: ", join('->', @ref_stack, '...'),"\n"; $ok = 0; } else { $ref_hash{$ref} = 1; if (lc $ref eq 'default') { $tval = $parm_def{$name}; print STDERR "Setting $name to default value: ", "$parm_def{$name}.\n" if ($debug); } elsif (exists($parameter{$ref})) { $tval = $parameter{$ref}; print STDERR "Setting $name to value of $ref: $tval.\n" if ($debug); } else { print STDERR "Can not deference $ref, it doesn't exist.\n"; $ok = 0; }; }; }; }; if ( $ok ) { # Check keyword parms for valid values if (exists $parm_kw{$name}) { my @ltval = split(/\s/,$tval); my $ltval = lc(@ltval[$[]); my $found = ""; foreach my $value (@{$parm_kw{$name}}) { if ($value eq $ltval) { $found = 1; $tval = ucfirst($ltval); }; }; if ( ! $found ) { $default += 1; if ( $default > 1 ) { print STDERR "Can not resolve $name, value=$value.\n"; $ok = 0; } else { print STDERR "Illegal value($tval) for $name.\n", " Valid values are: ", join(', ', @{$parm_kw{$name}}), "\n", " Set to default: $parm_def{$name}.\n"; $tval = $parm_def{$name}; goto Dereference; }; }; } # Check boolean parms for valid values elsif (exists $parm_bool{$name}) { my @ltval = split(/\s/,$tval); my $ltval = lc(@ltval[$[]); $ltval =~ s/^[ty1].*/1/; $ltval =~ s/^[fn0].*/0/; if ($ltval eq '0' or $ltval eq '1') { $tval = ucfirst($ltval); } else { $default += 1; if ( $default > 1 ) { print STDERR "Can not resolve $name, value=$value.\n"; $ok = 0; } else { print STDERR "Illegal value($tval) for $name.\n", " Valid values are: T[rue],Y[es],1,", " F[alse],N[o],0\n", " Set to default: $parm_def{$name}.\n"; $tval = $parm_def{$name}; goto Dereference; }; }; }; }; $value = $tval if $ok; print STDERR "get_value : $name => $value\n" if ($debug); return ($ok, $value); }; # #------------------------------------------------------------------------ # Read input configuration file (if no input, just use defaults) #------------------------------------------------------------------------ sub read_config { my ($input_file) = @_; @ARGV = split(' ', $input_file); return if (! -r $input_file); my $savename = ''; my $parmname = ''; my $parmval = ''; my $parmref = ''; my $defname = ''; my $defval = ''; my $tmpval = ''; print STDOUT "Reading configuration from ", join(',',@ARGV), ".\n"; line: while () { next line if /^$/; # skip empty lines chomp; # drop tailing \n if (s/\\$//) { $_ .= <>; redo unless eof(); }; # check commented lines for default parameter values # a bit of a kluge, but it works out nicely if (/^#\s*([\w_]+)="([^"]*)"/) { $defname = get_name($1, 1); $defval = $2; print STDERR "Default: $defname => $defval.\n" if ($debug); next line; }; # Skip any comments next line if /^#/; # skip comments # Process assignment statements if (/^\s*([\w_]+)="([^"]*)"/) { $savename = $1; $parmname = get_name($savename, ''); $parmval = $2; print STDERR "Value : $savename => $parmval.\n" if ($debug); # Do we know about this parameter? # NOTE: keep, even if we don't know about it to prevent # problems with up/down grades (not loose anything) if ( ! exists($parm_def{$parmname}) and ! exists($parm_hidden{$parmname}) ) { print STDERR "$parmname is a user defined parameter.\n" if ($debug); }; # Note if value is default, if so, we'll change it to # the current default - maybe counterintuitive, oh well # it does help with migration if ($parmname eq $defname and $parmval eq $defval) { print STDERR "$parmname is the default value: $defval.\n" if ($debug); $parmval = $parm_def{$parmname}; }; # Finally, assign value if (exists $parm_kw{$savename} or exists $parm_bool{$savename}) { $parmval = ucfirst($parmval); }; if ($savename eq $parmname) { $parameter{$parmname} = $parmval; } else { $parameter{$savename} = $parmval; }; }; }; }; # #------------------------------------------------------------------------ # Validate current configuration #------------------------------------------------------------------------ sub validate_config { my $valid = 1; print STDOUT "Validating configuration.\n"; # Really, we only care about the some of the variables - those # that have defaults... the rest, well, so what ! foreach my $val (sort keys %parm_def) { my ($ok, $value) = &get_value($val, 1); if (! $ok) { $valid = 0; }; }; if (! $valid ) { print STDERR "\nOne or more errors were encountered!\n\n"; }; return ($valid); }; # #------------------------------------------------------------------------ # Write updated configuration file #------------------------------------------------------------------------ sub write_config { my ($database_file) = @_; my $ofh = new FileHandle; # Make sure things are kosher my $result = &validate_config; if (! $result) { die "Terminating due to configuration error."; }; $database_file = $database_file || $Parse_conf::Conffile; my $caller = "$main::program_name" if ($main::program_name); $caller .= " $main::program_version" if ($main::program_version); $caller .= " $main::program_date" if ($main::program_date); print STDOUT "Writing configuration to $database_file.\n"; $database_file = '&STDOUT' if ($database_file eq '-'); unless ( open($ofh, ">$database_file") ) { warn("Could not open $database_file($!), using STDOUT\n"); open($ofh, ">&STDOUT"); }; $database_file = '-' if ($database_file eq '&STDOUT'); # print $ofh <<"EOT"; #################################################################### ##### This file is automagically generated -- edit at your own risk ##### ##### file: ${database_file} ##### generated via: (${interp_pgm} ${interp_vrm}) ##### ${caller} ##### ${Parse_conf::program_name} ${Parse_conf::program_version} ${Parse_conf::program_date} ##### by: ${user}\@${hostname} ##### on: ${current_time} ##### in: ${directory} ##### input files: #EOT # foreach my $file ( split(' ', $input_file) ) { # print $ofh <<"EOT"; ##### ${file} #EOT # }; # print $ofh <<"EOT"; ##### #################################################################### print $ofh <<"EOT"; #------------------------------------------------------------------------------ # # $database_file # # Copyright (c) 2001-2009 Richard Nelson. All Rights Reserved. # Version: ${main::program_version} # Time-stamp: <${main::program_date}> # # Parameter file for sendmail (sourced by /usr/share/sendmail/sendmail) # Make all changes herein, instead of altering /etc/init.d/sendmail. # # After making changes here, you'll need to run /usr/sbin/sendmailconfig # or ${main::program_name} to have the changes take effect - # If you change DAEMON_MODE, QUEUE_MODE, or QUEUE_INTERVAL, you'll also # need to run /etc/init.d/sendmail restart. # # Changes made herein will be kept across upgrades - except for comments! # Some comment lines have special significance ... # # **** **** **** **** DO NOT EDIT THE COMMENTS **** **** **** **** # # Supported parameters (and defaults) are listed herein. # # Notes: # * This setup allows sendmail to run in several modes: # - listener and queue runner..DAEMON_MODE="daemon".QUEUE_MODE="daemon" # - listener only..............DAEMON_MODE="daemon".QUEUE_MODE="none" # - queue runner only..........DAEMON_MODE="none"...QUEUE_MODE="daemon" # - *NOTHING* ?!?..............DAEMON_MODE="none"...QUEUE_MODE="none" # # * You can also run the listener from inetd: # - listener and queue runner..DAEMON_MODE="inetd"..QUEUE_MODE="daemon" # - listener only..............DAEMON_MODE="inetd"..QUEUE_MODE="none" # # * You can also run the queue runner from cron: # - listener and queue runner..DAEMON_MODE="....."..QUEUE_MODE="cron" # - queue runner only..........DAEMON_MODE="none"...QUEUE_MODE="cron" # # * _PARMS entries herein are shown in precedence order, any later _PARMS # field will, if applicable, override any previous _PARMS fields. # # * Values *MUST* be surrounded with double quotes ("), single quotes # will *NOT* work ! # #------------------------------------------------------------------------------ # SMTP Listener Configuration # # DAEMON_NETMODE="$parm_def{'DAEMON_NETMODE'}"; Keyword SMTP network mode # static: Do not monitor any network interfaces for changes # dynamic: Monitor one or more interfaces for changes # DAEMON_NETMODE="$parameter{'DAEMON_NETMODE'}"; # # DAEMON_NETIF="$parm_def{'DAEMON_NETIF'}"; string SMTP interface(s) # This parameter defines the network interface(s) that the daemon # will monitor for status changes (via ppp, dhcp, ifup/down hooks). # # NOTES: # 1) Only list more than one interfaces if they only used for fallback, # otherwise the daemon will wind up ping-ponging between interfaces. # 2) Do not use 'lo' unless your daemon only listens on the localhost. # DAEMON_NETIF="$parameter{'DAEMON_NETIF'}"; # # DAEMON_MODE="$parm_def{'DAEMON_MODE'}"; Keyword SMTP listener # daemon: Run as standalone daemon # inetd: Run from inet supervisor (forks for each mail) # none: No listener (ie, nullclient/smarthost) # # NOTE: If you choose "none", mail will build up in the MSP queues # and you will not receive any mail from external sites. # DAEMON_MODE="$parameter{'DAEMON_MODE'}"; # # DAEMON_PARMS="$parm_def{'DAEMON_PARMS'}"; String Listener parms # Any parameters here will be ignored when run from cron. # Note that {QUEUE,MISC,CRON}_PARMS, if applicable, will override # anything declared herein. # DAEMON_PARMS="$parameter{'DAEMON_PARMS'}"; # # DAEMON_HOSTSTATS="$parm_def{'DAEMON_HOSTSTATS'}"; Boolean Listener stats # This parameter determines whether or not host stats are collected # and available for the \`hoststat\` command to display. There will # be a (minor) performance hit, as files will be created/updated for each # sendmail delivery attempt. The files are fixed in size, and small, # but there can be many of them. # DAEMON_HOSTSTATS="$parameter{'DAEMON_HOSTSTATS'}"; # # DAEMON_MAILSTATS="$parm_def{'DAEMON_MAILSTATS'}"; Boolean Listener stats # This parameter determines whether or not mailer stats are collected # and available for the \`mailstats\` command to display. There will # be a (minor) performance hit, as this file will be updated for each # item coming into, or out of, sendmail. The file is fixed in size, # and small, so there's no need to rotate it. # DAEMON_MAILSTATS="$parameter{'DAEMON_MAILSTATS'}"; # #------------------------------------------------------------------------------ # SMTP MTA Queue Runner Configuration # # QUEUE_MODE="$parm_def{'QUEUE_MODE'}"; Keyword SMTP queue runner # daemon: Run as standalone daemon # cron: Run from crontab # none: No queue runner (ie, nullclient/smarthost) # QUEUE_MODE="$parameter{'QUEUE_MODE'}"; # # QUEUE_INTERVAL="$parm_def{'QUEUE_INTERVAL'}"; Timespec (p?digits+w|d|h|m|s) # Interval at which to run the MTA queues. What interval should you use? # The amount of time that is acceptable before retrying delivery on # mail that couldn't be delivered in one run, or how long an item can # set in the queue before having the first delivery attempt done. # # NOTE: To use persistent queue-runners use this form: p120m # # NOTE: If you leave this field blank, You get *NO* queue runners !!! # QUEUE_INTERVAL="$parameter{'QUEUE_INTERVAL'}"; # # QUEUE_PARMS="$parm_def{'QUEUE_PARMS'}"; String queue parameters # Any parameters here are also used when run from cron. # Note that MISC_PARMS and CRON_PARMS, if applicable, will override # anything declared herein. # QUEUE_PARMS="$parameter{'QUEUE_PARMS'}"; # #------------------------------------------------------------------------------ # SMTP - MSP Queue Runner Configuration # # MSP_MODE="$parm_def{'MSP_MODE'}"; Keyword MSP queue runner mode # daemon: Run as standalone daemon # cron: Run from crontab # none: No queue runner (ie, nullclient/smarthost) # # NOTE: If QUEUE_MODE="cron" & MSP_MODE="none", the MSP queue will # be run as part of the MTA queue running process. # MSP_MODE="$parameter{'MSP_MODE'}"; # # MSP_INTERVAL="$parm_def{'MSP_INTERVAL'}"; Timespec (digits+w|d|h|m|s) # Interval at which to run the MSP queues. What interval should you use? # The amount of time that is acceptable before retrying delivery on # mail that couldn't be accepted by the MTA, and was therefore left # in the message submission queue. The MTA shouldn't be down that often # so this can be larger than QUEUE_INTERVAL. # # NOTE: If you leave this field blank, The MSP queue will *NOT* be run !!! # MSP_INTERVAL="$parameter{'MSP_INTERVAL'}"; # # MSP_PARMS="$parm_def{'MSP_PARMS'}"; String queue parameters # Any parameters here are also used when run from cron. # Note that MISC_PARMS and CRON_PARMS, if applicable, will override # anything declared herein. # MSP_PARMS="$parameter{'MSP_PARMS'}"; # # MSP_MAILSTATS="$parm_def{'MSP_MAILSTATS'}"; Boolean Listener stats # This parameter determines whether or not mailer stats are collected # and available for the \`mailstats\` command to display. There will # be a (minor) performance hit, as this file will be updated for each # item coming into, or out of, sendmail. The file is fixed in size, # and small, so there's no need to rotate it. # MSP_MAILSTATS="$parameter{'MSP_MAILSTATS'}"; # #------------------------------------------------------------------------------ # Miscellaneous Confguration # # MISC_PARMS="$parm_def{'MISC_PARMS'}"; String miscellaneous parameters # Miscellaneous parameters - applied to any sendmail invocation. # Any parameters here are also used when run from cron. # Applied after {DAEMON,QUEUE}_PARMS, and can therefore override them # if need be (in which case why did use them?) # Note that CRON_PARMS, if applicable, will override anything # declared herein. # # Here is where'd you setup and debugging or special parms that you # want shared betwixt the possibly separate listener/queue-runner # processes. # MISC_PARMS="$parameter{'MISC_PARMS'}"; # #------------------------------------------------------------------------------ # Cron Job Configuration # # CRON_MAILTO="$parm_def{'CRON_MAILTO'}"; String cronjob output # Recipient of *rare* cronjob output. Some cronjobs will be running # under user `mail`, so any problems encountered would probably be missed # so define a user who actually (hopefully) checks email now and again. # CRON_MAILTO="$parameter{'CRON_MAILTO'}"; # # CRON_PARMS="$parm_def{'CRON_PARMS'}"; String cron specific parmeters # Cron parameters - applied *only* when sendmail queue running is done # via a cronjob. Applied after QUEUE_PARMS and MISC_PARMS, and can # therefore override them if need be. # CRON_PARMS="$parameter{'CRON_PARMS'}"; # #------------------------------------------------------------------------------ # Other stuff # LOG_CMDS="$parm_def{'LOG_CMDS'}"; Binary command logging flag # Will cause syslog entries for many of the sendmail related commands # like runq, mailq, etc - you'll also see cron jobs (if enabled). # LOG_CMDS="$parameter{'LOG_CMDS'}"; # # HANDS_OFF="$parm_def{'HANDS_OFF'}"; Binary Do *NOT* touch the configuration # Set this *ONLY* if you are going to be fully responsible for the entire # setup of sendmail - the directories, permissions, databases, etc. With # this variable set to "Yes", nothing will be done for you during updates. # # In other words, "The blood be upon your hands" if you set this... # My ability to help with problems will be greatly reduced ! # # "Well, a pet peeve of mine is people who directly edit the # .cf file instead of using the m4 configuration files. # Don't do it! [laughs] I treat the .cf file as a binary # file - you should too." # -- Eric Allman 1999/10/18 # http://www.dotcomeon.com/allman_sendmail_qa.html # HANDS_OFF="$parameter{'HANDS_OFF'}"; # #------------------------------------------------------------------------------ # Queue Aging Configuration # # Why would you want to age your queues? On every queue-run interval, # sendmail will try *every* file in the queue... If a site is down # for a while, considerable time can be wasted each interval in retrying # it. The scheme supported allows aging by time, and can move the older # files to another (less frequently run queue), thereby reducing overal # system impact - and providing better mail throughput. # # Note that this support is completely separate from QUEUE_MODE=cron, # you can age queues even if you're running QUEUE_MODE=daemon. # # There are four parts to the queue aging support, and these parts # may be repeated, to operate on multiple queues. # # 1. Interval at which to age the queues (in minutes). # What interval should you use? Roughly twice the normal queue # interval, so that messages are tried twice in each successively # slower queue. # # NOTE: some values just wont work, due to crontab pecularities # a value of 90 minutes will actually be run at every x:30 ! # Please check /etc/cron.d/sendmail to make sure it is doing what # you thought it should ! # # 2. Criteria (optional and defaults to interval). This is the # specification of which files to move. It defaults moving # files whose age in the queues exceeds the interval. # This field, if specified can be very complex - supporting # aging by just about anything! see qtool(8) for details. # # 3. To queue. This is the queue to which files will be moved. # It may be fully qualified, or relative to /var/spool/mqueue. # # 4. From queue. This is the queue from which files will be moved. # It may be fully qualified, or relative to /var/spool/mqueue. # # Samples: # AGE_DATA="[['25m', '', 'hourly', 'main']]"; # Every 25 minutes, move any file older than 25 minutes from # /var/spool/mqueue/main to /var/spool/mqueue/hourly # # AGE_DATA="[['25m', '', 'hourly', 'main'],\\ # ['120m', '', 'daily', 'hourly']]"; # Same as the above, but also move files from the hourly queue # to the daily queue after 120 minutes in the hourly queue. # # AGE_DATA="[['25m',\\ # '-e \\'\$msg{message}[0] == /Deferred: 452 4.2.2 Over quota/\\'',\\ # 'overquota', 'main']]"; # Every 25 minutes, move all files deferred because of quota # violations from /var/spool/mqueue/main to # /var/spool/mqueue/overquota where they can be processed on # a different interval, or by some other means. # # If the above samples suggest Perl arrays, well, they are... # # AGE_DATA="$parm_def{'AGE_DATA'}"; Perl array Queue aging data # EOT my ($ok, $var) = &get_value('AGE_DATA'); my $tmpval = eval $var; if ($@) { warn $@; } else { $var = $tmpval; }; if (not defined $var) { print $ofh 'AGE_DATA="";',"\n"; } elsif (not ref $var) { print $ofh 'AGE_DATA="',$var,'";',"\n"; } elsif (@{$var} == 0) { print $ofh 'AGE_DATA="";',"\n"; } else { print $ofh 'AGE_DATA="[\\',"\n"; foreach my $entry (@{$var}) { foreach my $ndx ($[ .. $#{$entry}) { @{$entry}[$ndx] =~ s/'/\\'/g; }; print $ofh "['",join("', '",@{$entry}),"'],\\\n"; }; print $ofh ']";',"\n"; }; print $ofh <<"EOT"; # #------------------------------------------------------------------------------ # Dependant variables (set according to other variables) # EOT foreach my $key (sort keys %parm_dependant) { my ($ok, $value); # Don't evaluate value, just stuff it... next if ( ! $parameter{$key} ); ($ok, $value) = (1, $parameter{$key}); print $ofh "$key=",'"',$value,'";',"\n"; }; print $ofh <<"EOT"; # #------------------------------------------------------------------------------ # Hidden variables (the blood be upon your hands) # EOT foreach my $key (sort keys %parm_hidden) { my ($ok, $value); # Don't evaluate value, just stuff it... next if ( ! $parameter{$key} ); ($ok, $value) = (1, $parameter{$key}); print $ofh "$key=",'"',$value,'";',"\n"; }; print $ofh <<"EOT"; # #------------------------------------------------------------------------------ # Deprecated variables (kept for reference) # EOT foreach my $key (sort keys %parm_deprecated) { my ($ok, $value); # Don't evaluate value, just stuff it... if ( $parm_deprecated{$key} ) { ($ok, $value) = (1, join('','${', $parm_deprecated{$key}, '}')); } elsif ( $parameter{$key} ) { ($ok, $value) = (1, $parameter{$key}); }; print $ofh "$key=",'"',$value,'";',"\n"; }; print $ofh <<"EOT"; # #------------------------------------------------------------------------------ # Unknown variables (kept for reference) # EOT foreach my $key (sort keys %parameter) { if (! exists($parm_def{$key}) and ! exists($parm_deprecated{$key})) { # Don't evaluate value, just stuff it... my ($ok, $value) = (1, $parameter{$key}); print $ofh "$key=",'"',$value,'";',"\n"; }; }; print $ofh <<"EOT"; #------------------------------------------------------------------------------ # EOT close($ofh); if ( $database_file eq $Parse_conf::Conffile ) { chown '0', '0', "$database_file"; chmod 0644, "$database_file"; }; }; __END__