#!/usr/bin/perl -w # # qmail-updater # John Simpson 2005-06-24 # # watches certain qmail control files and automatically runs commands to # update them when needed. # # 2006-01-13 jms1 - adding support for an external script to be run # whenever the validrcptto.cdb file is changed, to allow for pushing # the new data to other servers. See this web page for more info: # http://qmail.jms1.net/scripts/mkvalidrcptto.html # # 2006-02-15 jms1 - expanded the idea of what the external script will # be doing. it will now be run whenever any of (validrcptto.cdb, # rcpthosts, morercpthosts.cdb, smtproutes) changes, since these # four files are needed by a "mailhub" machine. also changed copyright # notice from "GPL v2 or later" to "GPL v2 only". # ############################################################################### # # Copyright (C) 2005-2006 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 $mkvalidrcptto = "/usr/local/bin/mkvalidrcptto" ; my $push_cmd = "" ; ############################################################################### # # return the time when a file was last modified, or -1 on error sub mtime($) { my @s = stat ( $_[0] ) ; return ( ( $#s > -1 ) ? $s[9] : -1 ) ; } ############################################################################### ############################################################################### ############################################################################### print "Starting\n" ; umask 022 ; while ( 1 ) { my $do_push = 0 ; ######################################## # work-around for vpopmail bug (vdeldomain sometimes leaves # the "rcpthosts" file with bad permissions) my @s = stat ( "$vqc/rcpthosts" ) ; if ( $#s < 0 ) { print "Creating non-existent $vqc/rcpthosts\n" ; open ( O , ">$vqc/rcpthosts" ) ; close O ; @s = stat ( "$vqc/rcpthosts" ) ; $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 if ( -f "$vqu/assign" ) { if ( 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 if ( -f "$vqc/morercpthosts" ) { if ( 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 ; } ######################################## # build validrcptto.cdb if needed if ( ( -f "$vqc/validrcptto.cdb" ) || ( -f "$vqc/validrcptto.txt" ) ) { unless ( -f "$vqc/validrcptto.txt" ) { open ( O , ">$vqc/validrcptto.txt" ) ; close O ; } system "$mkvalidrcptto > $vqc/validrcptto.new" ; my $diff = 0 ; if ( -s "$vqc/validrcptto.new" ) { open ( D , "diff $vqc/validrcptto.txt" . " $vqc/validrcptto.new |" ) or die "diff: $!\n" ; while ( my $line = ) { print $line ; $diff = 1 ; } close D ; } else { print "mkvalidrcptto returned no output\n" ; } if ( $diff ) { print "Building new validrcptto.cdb\n" ; system "cdbmake-12 $vqc/validrcptto.cdb" . " $vqc/validrcptto.tmp" . " < $vqc/validrcptto.new" ; chmod ( 0644 , "$vqc/validrcptto.cdb" , "$vqc/validrcptto.new" ) ; $do_push = 1 ; } rename ( "$vqc/validrcptto.new" , "$vqc/validrcptto.txt" ) ; } ######################################## # if we have a push command, and if smtproutes, virtualdomains, # or locals has changed more recently than the last time # smtproutes was sent, we need to push data. if ( $push_cmd ) { my $ss = mtime ( "$vqc/smtproutes.last" ) ; if ( ( mtime ( "$vqc/smtproutes" ) > $ss ) || ( mtime ( "$vqc/virtualdomains" ) > $ss ) || ( mtime ( "$vqc/locals" ) > $ss ) ) { print "smtproutes needs to be sent\n" ; unlink "$vqc/smtproutes.last" ; open ( O , ">$vqc/smtproutes.last" ) ; close O ; $do_push = 1 ; } } ######################################## # if virtualdomains or locals has changed, # we need to send a HUP to qmail-send my $restart = 0 ; if ( ( -f "$vqc/virtualdomains" ) && ( 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 ; } if ( ( -f "$vqc/locals" ) && ( 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 ; } if ( $restart ) { print "Sending HUP to qmail-send\n" ; system "killall -HUP qmail-send" ; } ######################################## # if any data-pushing needs to be done, # now is the time to do it if ( $do_push && $push_cmd && -e $push_cmd ) { print "Running $push_cmd\n" ; system $push_cmd ; } sleep 15 ; }