#!/usr/bin/perl -w # # update-qmail # John Simpson 2005-06-24 # # rebuilds qmail control files when/if needed. this command should be # called from some other script (like a "qmail-updater" service) whenever # a change is made in the appropriate files. # # 2006-04-11 jms1 - adding "auth.cdb" file. # # 2006-04-12 jms1 - adding "force" support. # # 2007-01-25 jms1 - adding the logic to call a "push" program, in case data # needs to be sent to other servers. thanks to Chad Berg for reminding me # that this wasn't in there yet. # # 2007-06-18 jms1 - mkvalidrcptto now supports a "-c" option which will build # the validrcptto.cdb file by itself, including the "diff" logic. changing # this script to use that. # # 2008-05-06 jms1 - mkauth also supports a "-c" option. i meant to add it # to this script at the time, but real life intruded... adding it now, # while setting up the script on a client's machine. # ############################################################################### # # Copyright (C) 2005,2006,2007,2008 John Simpson. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # or visit http://www.gnu.org/licenses/gpl.txt # ############################################################################### require 5.003 ; use strict ; ############################################################################### # # configuration my $vq = "/var/qmail" ; my $vqc = "$vq/control" ; my $vqu = "$vq/users" ; my $smtpd_user = "qmaild" ; # userid that qmail-smtpd runs as my $mkvalidrcptto = "/usr/local/bin/mkvalidrcptto" ; my $mkauth = "/usr/local/bin/mkauth" ; my $push_cmd = "" ; ############################################################################### # # global variables my ( @pw , $smtp_uid , $smtp_gid , @s ) ; my $force = 0 ; my $restart = 0 ; my $do_push = 0 ; ############################################################################### sub mtime($) { my @s = stat ( $_[0] ) ; return ( ( $#s > -1 ) ? $s[9] : -1 ) ; } ############################################################################### ############################################################################### ############################################################################### print "Starting\n" ; if ( ( $ARGV[0] || "" ) eq "force" ) { print "Running in FORCE mode\n" ; $force = 1 ; $do_push = 1 ; } @pw = getpwnam ( $smtpd_user ) ; $smtp_uid = ( $pw[2] || die "Can\'t find uid for \"$smtpd_user\"\n" ) ; $smtp_gid = ( $pw[3] || die "Can\'t find gid for \"$smtpd_user\"\n" ) ; umask 022 ; ######################################## # work-around for vpopmail bug (vdeldomain sometimes leaves # the "rcpthosts" file with bad permissions) @s = stat ( "$vqc/rcpthosts" ) ; if ( $#s < 0 ) { print "Creating non-existent $vqc/rcpthosts\n" ; open ( O , ">$vqc/rcpthosts" ) ; close O ; $do_push = 1 ; } if ( ( ( $s[2] || 0 ) & 0777 ) != 0644 ) { print "chmod 0644 $vqc/rcpthosts\n" ; chmod ( 0644 , "$vqc/rcpthosts" ) ; } ######################################## # build vqu/cdb from vqu/assign print "Checking users/assign and users/cdb\n" ; if ( -f "$vqu/assign" ) { if ( $force || ( mtime ( "$vqu/assign" ) > mtime ( "$vqu/cdb" ) ) ) { print " Running qmail-newu\n" ; system "$vq/bin/qmail-newu" ; } } elsif ( -f "$vqu/cdb" ) { print " Deleting $vqu/cdb" . " since $vqu/assign does not exist\n" ; unlink "$vqu/cdb" ; } ######################################## # build vqc/morercpthosts.cdb from vqc/morercpthosts print "Checking morercpthosts and morercpthosts.cdb\n" ; if ( -f "$vqc/morercpthosts" ) { if ( $force || ( mtime ( "$vqc/morercpthosts" ) > mtime ( "$vqc/morercpthosts.cdb" ) ) ) { print " Running qmail-newmrh\n" ; system "$vq/bin/qmail-newmrh" ; $do_push = 1 ; } } elsif ( -f "$vqc/morercpthosts.cdb" ) { print " Deleting morercpthosts.cdb" . " since morercpthosts does not exist\n" ; unlink "$vqc/morercpthosts.cdb" ; $do_push = 1 ; } ######################################## # if virtualdomains or locals has changed, # we will need to send a HUP to qmail-send $restart = 0 ; print "Checking virtualdomains\n" ; if ( -f "$vqc/virtualdomains" ) { if ( $force || ( mtime ( "$vqc/virtualdomains" ) > mtime ( "$vqc/virtualdomains.last" ) ) ) { print " virtualdomains has changed\n" ; unlink "$vqc/virtualdomains.last" ; open ( O , ">$vqc/virtualdomains.last" ) ; close O ; $restart = 1 ; $do_push = 1 ; } } print "Checking locals\n" ; if ( -f "$vqc/locals" ) { if ( $force || ( mtime ( "$vqc/locals" ) > mtime ( "$vqc/locals.last" ) ) ) { print " locals has changed\n" ; unlink "$vqc/locals.last" ; open ( O , ">$vqc/locals.last" ) ; close O ; $restart = 1 ; $do_push = 1 ; } } if ( $restart ) { print "Sending HUP to qmail-send\n" ; system "killall -HUP qmail-send" ; } ######################################## # build validrcptto.cdb if needed print "Checking validrcptto.cdb\n" ; if ( -f "$vqc/validrcptto.cdb" ) { umask 027 ; print " Running $mkvalidrcptto\n" ; my $ot = mtime ( "$vqc/validrcptto.cdb" ) ; system "$mkvalidrcptto -c $vqc/validrcptto.cdb" ; my $nt = mtime ( "$vqc/validrcptto.cdb" ) ; if ( $nt != $ot ) { print " Change detected\n" ; $do_push = 1 ; } else { print " No change detected\n" ; } } ######################################## # build auth.cdb if needed print "Checking auth.txt and auth.cdb\n" ; if ( -f "$vqc/auth.cdb" ) { umask 027 ; print " Running $mkauth\n" ; my $ot = mtime ( "$vqc/auth.cdb" ) ; system "$mkauth -c $vqc/auth.cdb" ; my $nt = mtime ( "$vqc/auth.cdb" ) ; if ( $nt != $ot ) { print " Change detected\n" ; $do_push = 1 ; } else { print " No change detected\n" ; } } ######################################## # handle push (if needed) if ( $do_push && $push_cmd && -e $push_cmd ) { print "Calling program to push data to external servers\n" ; print "/-----\n" ; open ( I , "$push_cmd |" ) or die "Cannot run \"$push_cmd\": $!\n" ; map { print "| $_" } ; close I ; print "\\-----\n" ; } ######################################## # outta here print "Done\n" ; exit 0 ;