Updates in preparation for 3.0.0beta2:
[BackupPC.git] / configure.pl
index bb86691..7cf5149 100755 (executable)
@@ -19,7 +19,7 @@
 #   Craig Barratt <cbarratt@users.sourceforge.net>
 #
 # COPYRIGHT
-#   Copyright (C) 2001-2004  Craig Barratt
+#   Copyright (C) 2001-2006  Craig Barratt
 #
 #   This program is free software; you can redistribute it and/or modify
 #   it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@
 #
 #========================================================================
 #
-# Version 2.1.0beta1, released 9 Apr 2004.
+# Version 3.0.0alpha, released 8 Jul 2006.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -49,7 +49,7 @@ use vars qw(%Conf %OrigConf);
 use lib "./lib";
 
 my @Packages = qw(File::Path File::Spec File::Copy DirHandle Digest::MD5
-                  Data::Dumper Getopt::Std Getopt::Long Pod::Usage
+                  Data::Dumper Getopt::Std Getopt::Long Encode Pod::Usage
                   BackupPC::Lib BackupPC::FileZIO);
 
 foreach my $pkg ( @Packages ) {
@@ -58,7 +58,8 @@ foreach my $pkg ( @Packages ) {
     if ( $pkg =~ /BackupPC/ ) {
         die <<EOF;
 
-BackupPC cannot find the package $pkg, which is included in the
+Error loading $pkg: $@
+BackupPC cannot load the package $pkg, which is included in the
 BackupPC distribution.  This probably means you did not cd to the
 unpacked BackupPC distribution before running configure.pl, eg:
 
@@ -77,22 +78,36 @@ before installing BackupPC.
 EOF
 }
 
+my $EncodeVersion = eval($Encode::VERSION);
+if ( $EncodeVersion < 1.99 ) {
+    print("\nError: you need to upgrade the Encode package;"
+        . " I found $EncodeVersion and BackupPC needs >= 1.99\n\n");
+    exit(1);
+}
+
 my %opts;
+$opts{"set-perms"} = 1;
 if ( !GetOptions(
             \%opts,
             "batch",
+            "backuppc-user=s",
             "bin-path=s%",
-            "config-path=s",
             "cgi-dir=s",
+            "compress-level=i",
+            "config-path=s",
+            "config-dir=s",
             "data-dir=s",
             "dest-dir=s",
+            "fhs!",
             "help|?",
             "hostname=s",
             "html-dir=s",
             "html-dir-url=s",
             "install-dir=s",
+            "log-dir=s",
             "man",
-            "uid-ignore",
+            "set-perms!",
+            "uid-ignore!",
         ) || @ARGV ) {
     pod2usage(2);
 }
@@ -100,8 +115,9 @@ pod2usage(1) if ( $opts{help} );
 pod2usage(-exitstatus => 0, -verbose => 2) if $opts{man};
 
 my $DestDir = $opts{"dest-dir"};
+$DestDir = "" if ( $DestDir eq "/" );
 
-if ( $< != 0 ) {
+if ( !$opts{"uid-ignore"} && $< != 0 ) {
     print <<EOF;
 
 This configure script should be run as root, rather than uid $<.
@@ -115,44 +131,86 @@ EOF
     exit(1) if ( $opts{batch} && !$opts{"uid-ignore"} );
 }
 
-print <<EOF;
-
-Is this a new installation or upgrade for BackupPC?  If this is
-an upgrade please tell me the full path of the existing BackupPC
-configuration file (eg: /xxxx/conf/config.pl).  Otherwise, just
-hit return.
-
-EOF
+#
+# Whether we use the file system hierarchy conventions or not.
+# Older versions did not.  BackupPC used to be installed in
+# two main directories (in addition to CGI and html pages)
+#
+#    TopDir       which includes subdirs conf, log, pc, pool, cpool
+#                
+#    InstallDir   which includes subdirs bin, lib, doc
+#
+# With FHS enabled (which is the default for new installations)
+# the config files move to /etc/BackupPC and log files to /var/log:
+#
+#    /etc/BackupPC/config.pl  main config file (was $TopDir/conf/config.pl)
+#    /etc/BackupPC/hosts      hosts file (was $TopDir/conf/hosts)
+#    /etc/BackupPC/pc/HOST.pl per-pc config file (was $TopDir/pc/HOST/config.pl)
+#    /var/log/BackupPC        log files (was $TopDir/log)
+#    /var/log/BackupPC        Pid, status and email info (was $TopDir/log)
+#
 
 #
 # Check if this is an upgrade, in which case read the existing
 # config file to get all the defaults.
 #
 my $ConfigPath = "";
+my $ConfigFileOK = 1;
 while ( 1 ) {
-    $ConfigPath = prompt("--> Full path to existing conf/config.pl",
-                         $ConfigPath,
-                         "config-path");
+    if ( $ConfigFileOK && -f "/etc/BackupPC/config.pl" ) {
+        $ConfigPath = "/etc/BackupPC/config.pl";
+        $opts{fhs} = 1 if ( !defined($opts{fhs}) );
+        print <<EOF;
+
+Found /etc/BackupPC/config.pl, so this is an upgrade of an
+existing BackupPC installation.  We will verify some existing
+information, but you will probably not need to make any
+changes - just hit ENTER to each question.
+EOF
+    } else {
+        print <<EOF;
+
+Is this a new installation or upgrade for BackupPC?  If this is
+an upgrade please tell me the full path of the existing BackupPC
+configuration file (eg: /etc/BackupPC/config.pl).  Otherwise, just
+hit return.
+
+EOF
+        $ConfigPath = prompt("--> Full path to existing main config.pl",
+                             $ConfigPath,
+                             "config-path");
+    }
     last if ( $ConfigPath eq ""
-            || ($ConfigPath =~ /^\// && -r $ConfigPath && -w $ConfigPath) );
+            || ($ConfigPath =~ /^\// && -f $ConfigPath && -w $ConfigPath) );
     my $problem = "is not an absolute path";
-    $problem = "is not writable" if ( !-w $ConfigPath );
-    $problem = "is not readable" if ( !-r $ConfigPath );
-    $problem = "doesn't exist"   if ( !-f $ConfigPath );
+    $problem = "is not writable"        if ( !-w $ConfigPath );
+    $problem = "is not readable"        if ( !-r $ConfigPath );
+    $problem = "is not a regular file"  if ( !-f $ConfigPath );
+    $problem = "doesn't exist"          if ( !-e $ConfigPath );
     print("The file '$ConfigPath' $problem.\n");
     if ( $opts{batch} ) {
         print("Need to specify a valid --config-path for upgrade\n");
         exit(1);
     }
+    $ConfigFileOK = 0;
 }
+$opts{fhs} = 1 if ( !defined($opts{fhs}) && $ConfigPath eq "" );
+$opts{fhs} = 0 if ( !defined($opts{fhs}) );
+
 my $bpc;
 if ( $ConfigPath ne "" && -r $ConfigPath ) {
-    (my $topDir = $ConfigPath) =~ s{/[^/]+/[^/]+$}{};
+    (my $confDir = $ConfigPath) =~ s{/[^/]+$}{};
     die("BackupPC::Lib->new failed\n")
-            if ( !($bpc = BackupPC::Lib->new($topDir, ".", 1)) );
+            if ( !($bpc = BackupPC::Lib->new(".", ".", $confDir, 1)) );
     %Conf = $bpc->Conf();
     %OrigConf = %Conf;
-    $Conf{TopDir} = $topDir;
+    if ( !$opts{fhs} ) {
+        ($Conf{TopDir} = $ConfigPath) =~ s{/[^/]+/[^/]+$}{}
+                    if ( $Conf{TopDir} eq '' );
+        $bpc->{LogDir} = $Conf{LogDir}  = "$Conf{TopDir}/log"
+                    if ( $Conf{LogDir} eq '' );
+    }
+    $bpc->{ConfDir} = $Conf{ConfDir} = $confDir;
     my $err = $bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort}, 1);
     if ( $err eq "" ) {
         print <<EOF;
@@ -166,6 +224,16 @@ EOF
     }
 }
 
+#
+# Create defaults for FHS setup
+#
+if ( $opts{fhs} ) {
+    $Conf{TopDir}       ||= "/data/BackupPC";
+    $Conf{ConfDir}      ||= $opts{"config-dir"} || "/etc/BackupPC";
+    $Conf{InstallDir}   ||= "/usr/local/BackupPC";
+    $Conf{LogDir}       ||= $opts{"log-dir"} || "/var/log/BackupPC";
+}
+
 #
 # These are the programs whose paths we need to find
 #
@@ -213,13 +281,13 @@ EOF
     }
 }
 
-my $Perl56 = system($Conf{PerlPath}
-                        . q{ -e 'exit($^V && $^V ge v5.6.0 ? 1 : 0);'});
+my $Perl58 = system($Conf{PerlPath}
+                        . q{ -e 'exit($^V && $^V ge v5.8.0 ? 1 : 0);'});
 
-if ( !$Perl56 ) {
+if ( !$Perl58 ) {
     print <<EOF;
 
-BackupPC needs perl version 5.6.0 or later.  $Conf{PerlPath} appears
+BackupPC needs perl version 5.8.0 or later.  $Conf{PerlPath} appears
 to be an older version.  Please upgrade to a newer version of perl
 and re-run this configure script.
 
@@ -246,25 +314,26 @@ the main data directory and read/execute permission on the install
 directory (these directories will be setup shortly).
 
 The primary group for this user should also be chosen carefully.
-By default the install directories will have group write permission.
-The data directories and files will have group read permission but
-no other permission.
+The data directories and files will have group read permission,
+so group members can access backup files.
 
 EOF
 my($name, $passwd, $Uid, $Gid);
 while ( 1 ) {
     $Conf{BackupPCUser} = prompt("--> BackupPC should run as user",
                                  $Conf{BackupPCUser} || "backuppc",
-                                 "username");
-    ($name, $passwd, $Uid, $Gid) = getpwnam($Conf{BackupPCUser});
-    last if ( $name ne "" );
-    print <<EOF;
+                                 "backuppc-user");
+    if ( $opts{"set-perms"} ) {
+        ($name, $passwd, $Uid, $Gid) = getpwnam($Conf{BackupPCUser});
+        last if ( $name ne "" );
+        print <<EOF;
 
-getpwnam() says that user $Conf{BackupPCUser} doesn't exist.  Please check the
-name and verify that this user is in the passwd file.
+getpwnam() says that user $Conf{BackupPCUser} doesn't exist.  Please
+check the name and verify that this user is in the passwd file.
 
 EOF
-    exit(1) if ( $opts{batch} );
+        exit(1) if ( $opts{batch} );
+    }
 }
 
 print <<EOF;
@@ -287,10 +356,10 @@ while ( 1 ) {
 
 print <<EOF;
 
-Please specify a data directory for BackupPC.  This is where the
-configuration files, LOG files and all the PC backups are stored.
-This file system needs to be big enough to accommodate all the
-PCs you expect to backup (eg: at least 1-2GB per machine).
+Please specify a data directory for BackupPC.  This is where all the
+PC backup data is stored.  This file system needs to be big enough to
+accommodate all the PCs you expect to backup (eg: at least several GB
+per machine).
 
 EOF
 
@@ -305,6 +374,9 @@ while ( 1 ) {
     }
 }
 
+$Conf{CompressLevel} = $opts{"compress-level"}
+                            if ( defined($opts{"compress-level"}) );
+
 if ( !defined($Conf{CompressLevel}) ) {
     $Conf{CompressLevel} = BackupPC::FileZIO->compOk ? 3 : 0;
     if ( $ConfigPath eq "" && $Conf{CompressLevel} ) {
@@ -435,7 +507,7 @@ Ok, we're about to:
 
   - install the binaries, lib and docs in $Conf{InstallDir},
   - create the data directory $Conf{TopDir},
-  - create/update the config.pl file $Conf{TopDir}/conf,
+  - create/update the config.pl file $Conf{ConfDir}/config.pl,
   - optionally install the cgi-bin interface.
 
 EOF
@@ -454,9 +526,9 @@ foreach my $dir ( qw(bin doc
                     lib/BackupPC/Zip
                 ) ) {
     next if ( -d "$DestDir$Conf{InstallDir}/$dir" );
-    mkpath("$DestDir$Conf{InstallDir}/$dir", 0, 0775);
+    mkpath("$DestDir$Conf{InstallDir}/$dir", 0, 0755);
     if ( !-d "$DestDir$Conf{InstallDir}/$dir"
-            || !chown($Uid, $Gid, "$DestDir$Conf{InstallDir}/$dir") ) {
+            || !my_chown($Uid, $Gid, "$DestDir$Conf{InstallDir}/$dir") ) {
         die("Failed to create or chown $DestDir$Conf{InstallDir}/$dir\n");
     } else {
         print("Created $DestDir$Conf{InstallDir}/$dir\n");
@@ -468,8 +540,8 @@ foreach my $dir ( qw(bin doc
 #
 foreach my $dir ( ($Conf{CgiImageDir}) ) {
     next if ( $dir eq "" || -d $dir );
-    mkpath("$DestDir$dir", 0, 0775);
-    if ( !-d "$DestDir$dir" || !chown($Uid, $Gid, "$DestDir$dir") ) {
+    mkpath("$DestDir$dir", 0, 0755);
+    if ( !-d "$DestDir$dir" || !my_chown($Uid, $Gid, "$DestDir$dir") ) {
         die("Failed to create or chown $DestDir$dir");
     } else {
         print("Created $DestDir$dir\n");
@@ -477,74 +549,38 @@ foreach my $dir ( ($Conf{CgiImageDir}) ) {
 }
 
 #
-# Create $TopDir's top-level directories
+# Create other directories
 #
-foreach my $dir ( qw(. conf pool cpool pc trash log) ) {
-    mkpath("$DestDir$Conf{TopDir}/$dir", 0, 0750) if ( !-d "$DestDir$Conf{TopDir}/$dir" );
-    if ( !-d "$DestDir$Conf{TopDir}/$dir"
-            || !chown($Uid, $Gid, "$DestDir$Conf{TopDir}/$dir") ) {
-        die("Failed to create or chown $DestDir$Conf{TopDir}/$dir\n");
+foreach my $dir ( (
+            "$Conf{TopDir}",
+            "$Conf{TopDir}/pool",
+            "$Conf{TopDir}/cpool",
+            "$Conf{TopDir}/pc",
+            "$Conf{TopDir}/trash",
+            "$Conf{ConfDir}",
+            "$Conf{LogDir}",
+        ) ) {
+    mkpath("$DestDir$dir", 0, 0750) if ( !-d "$DestDir$dir" );
+    if ( !-d "$DestDir$dir"
+            || !my_chown($Uid, $Gid, "$DestDir$dir") ) {
+        die("Failed to create or chown $DestDir$dir\n");
     } else {
-        print("Created $DestDir$Conf{TopDir}/$dir\n");
+        print("Created $DestDir$dir\n");
     }
 }
 
 printf("Installing binaries in $DestDir$Conf{InstallDir}/bin\n");
-foreach my $prog ( qw(BackupPC BackupPC_dump BackupPC_link BackupPC_nightly
-        BackupPC_sendEmail BackupPC_tarCreate BackupPC_trashClean
-        BackupPC_tarExtract BackupPC_compressPool BackupPC_zcat
-        BackupPC_archive BackupPC_archiveHost
-        BackupPC_restore BackupPC_serverMesg BackupPC_zipCreate ) ) {
-    InstallFile("bin/$prog", "$DestDir$Conf{InstallDir}/bin/$prog", 0555);
+foreach my $prog ( qw(
+        __CONFIGURE_BIN_LIST__
+    ) ) {
+    InstallFile($prog, "$DestDir$Conf{InstallDir}/$prog", 0555);
 }
 
 printf("Installing library in $DestDir$Conf{InstallDir}/lib\n");
 foreach my $lib ( qw(
-       BackupPC/Lib.pm
-       BackupPC/Attrib.pm
-       BackupPC/FileZIO.pm
-        BackupPC/Config.pm
-        BackupPC/PoolWrite.pm
-        BackupPC/Storage.pm
-       BackupPC/View.pm
-        BackupPC/CGI/AdminOptions.pm
-       BackupPC/CGI/Archive.pm
-       BackupPC/CGI/ArchiveInfo.pm
-       BackupPC/CGI/Browse.pm
-       BackupPC/CGI/DirHistory.pm
-       BackupPC/CGI/EmailSummary.pm
-       BackupPC/CGI/GeneralInfo.pm
-       BackupPC/CGI/HostInfo.pm
-       BackupPC/CGI/Lib.pm
-       BackupPC/CGI/LOGlist.pm
-       BackupPC/CGI/Queue.pm
-        BackupPC/CGI/ReloadServer.pm
-       BackupPC/CGI/RestoreFile.pm
-       BackupPC/CGI/RestoreInfo.pm
-       BackupPC/CGI/Restore.pm
-        BackupPC/CGI/StartServer.pm
-       BackupPC/CGI/StartStopBackup.pm
-        BackupPC/CGI/StopServer.pm
-       BackupPC/CGI/Summary.pm
-       BackupPC/CGI/View.pm
-       BackupPC/Config/Meta.pm
-        BackupPC/Lang/en.pm
-       BackupPC/Lang/fr.pm
-       BackupPC/Lang/es.pm
-        BackupPC/Lang/de.pm
-        BackupPC/Lang/it.pm
-        BackupPC/Lang/nl.pm
-       BackupPC/Lang/pt_br.pm
-       BackupPC/Storage/Text.pm
-       BackupPC/Xfer/Archive.pm
-       BackupPC/Xfer/Tar.pm
-        BackupPC/Xfer/Smb.pm
-       BackupPC/Xfer/Rsync.pm
-       BackupPC/Xfer/RsyncDigest.pm
-        BackupPC/Xfer/RsyncFileIO.pm
-       BackupPC/Zip/FileMember.pm
+        __CONFIGURE_LIB_LIST__
     ) ) {
-    InstallFile("lib/$lib", "$DestDir$Conf{InstallDir}/lib/$lib", 0444);
+    InstallFile($lib, "$DestDir$Conf{InstallDir}/$lib", 0444);
 }
 
 if ( $Conf{CgiImageDir} ne "" ) {
@@ -563,6 +599,8 @@ if ( $Conf{CgiImageDir} ne "" ) {
     }
     InstallFile("conf/BackupPC_stnd.css",
                "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css", 0444, 0);
+    InstallFile("conf/BackupPC_stnd_orig.css",
+               "$DestDir$Conf{CgiImageDir}/BackupPC_stnd_orig.css", 0444, 0);
 }
 
 printf("Making init.d scripts\n");
@@ -577,28 +615,30 @@ foreach my $doc ( qw(BackupPC.pod BackupPC.html) ) {
     InstallFile("doc/$doc", "$DestDir$Conf{InstallDir}/doc/$doc", 0444);
 }
 
-printf("Installing config.pl and hosts in $DestDir$Conf{TopDir}/conf\n");
-InstallFile("conf/hosts", "$DestDir$Conf{TopDir}/conf/hosts", 0644)
-                    if ( !-f "$DestDir$Conf{TopDir}/conf/hosts" );
+printf("Installing config.pl and hosts in $DestDir$Conf{ConfDir}\n");
+InstallFile("conf/hosts", "$DestDir$Conf{ConfDir}/hosts", 0644)
+                    if ( !-f "$DestDir$Conf{ConfDir}/hosts" );
 
 #
 # Now do the config file.  If there is an existing config file we
 # merge in the new config file, adding any new configuration
 # parameters and deleting ones that are no longer needed.
 #
-my $dest = "$DestDir$Conf{TopDir}/conf/config.pl";
-my ($newConf, $newVars) = ConfigParse("conf/config.pl");
+my $dest = "$DestDir$Conf{ConfDir}/config.pl";
+my ($distConf, $distVars) = ConfigParse("conf/config.pl");
 my ($oldConf, $oldVars);
+my ($newConf, $newVars) = ($distConf, $distVars);
 if ( -f $dest ) {
     ($oldConf, $oldVars) = ConfigParse($dest);
-    $newConf = ConfigMerge($oldConf, $oldVars, $newConf, $newVars);
+    ($newConf, $newVars) = ConfigMerge($oldConf, $oldVars, $distConf, $distVars);
 }
-$Conf{EMailFromUserName}  ||= $Conf{BackupPCUser};
-$Conf{EMailAdminUserName} ||= $Conf{BackupPCUser};
 
 #
-# Update various config parameters
+# Update various config parameters.  The old config is in Conf{}
+# and the new config is an array in text form in $newConf->[].
 #
+$Conf{EMailFromUserName}  ||= $Conf{BackupPCUser};
+$Conf{EMailAdminUserName} ||= $Conf{BackupPCUser};
 
 #
 # Guess $Conf{CgiURL}
@@ -701,6 +741,47 @@ if ( defined($Conf{SmbClientTimeout}) ) {
     delete($Conf{SmbClientTimeout});
 }
 
+#
+# Replace --devices with -D in RsyncArgs and RsyncRestoreArgs
+#
+foreach my $param ( qw(RsyncArgs RsyncRestoreArgs) ) {
+    next if ( !defined($newVars->{$param}) );
+    $newConf->[$newVars->{$param}]{text} =~ s/--devices/-D/g;
+}
+
+#
+# Merge any new user-editable parameters into CgiUserConfigEdit
+# by copying the old settings forward.
+#
+if ( defined($Conf{CgiUserConfigEdit}) ) {
+    #
+    # This is a real hack.  The config file merging is done in text
+    # form without actually instantiating the new conf structure.
+    # So we need to extract the new hash of settings, update it,
+    # and merge the text.  Ugh...
+    #
+    my $new;
+    my $str = $distConf->[$distVars->{CgiUserConfigEdit}]{text};
+
+    $str =~ s/^\s*\$Conf\{.*?\}\s*=\s*/\$new = /m;
+    eval($str);
+    foreach my $p ( keys(%$new) ) {
+        $new->{$p} = $Conf{CgiUserConfigEdit}{$p}
+                if ( defined($Conf{CgiUserConfigEdit}{$p}) );
+    }
+    $Conf{CgiUserConfigEdit} = $new;
+    my $d = Data::Dumper->new([$new], [*value]);
+    $d->Indent(1);
+    $d->Terse(1);
+    my $value = $d->Dump;
+    $value =~ s/(.*)\n/$1;\n/s;
+    $newConf->[$newVars->{CgiUserConfigEdit}]{text}
+            =~ s/(\s*\$Conf\{.*?\}\s*=\s*).*/$1$value/s;
+}
+
+#
+# Now backup and write the config file
+#
 my $confCopy = "$dest.pre-__VERSION__";
 if ( -f $dest && !-f $confCopy ) {
     #
@@ -711,10 +792,12 @@ if ( -f $dest && !-f $confCopy ) {
     my $mode = $stat[2];
     my $uid  = $stat[4];
     my $gid  = $stat[5];
-    die("can't copy($dest, $confCopy)\n")  unless copy($dest, $confCopy);
+    die("can't copy($dest, $confCopy)\n")
+                                unless copy($dest, $confCopy);
     die("can't chown $uid, $gid $confCopy\n")
-                                           unless chown($uid, $gid, $confCopy);
-    die("can't chmod $mode $confCopy\n")   unless chmod($mode, $confCopy);
+                                unless my_chown($uid, $gid, $confCopy);
+    die("can't chmod $mode $confCopy\n")
+                                unless my_chmod($mode, $confCopy);
 }
 open(OUT, ">", $dest) || die("can't open $dest for writing\n");
 binmode(OUT);
@@ -735,8 +818,8 @@ foreach my $var ( @$newConf ) {
 }
 close(OUT);
 if ( !defined($oldConf) ) {
-    die("can't chmod 0640 mode $dest\n")  unless chmod(0640, $dest);
-    die("can't chown $Uid, $Gid $dest\n") unless chown($Uid, $Gid, $dest);
+    die("can't chmod 0640 mode $dest\n")  unless my_chmod(0640, $dest);
+    die("can't chown $Uid, $Gid $dest\n") unless my_chown($Uid, $Gid, $dest);
 }
 
 if ( $Conf{CgiDir} ne "" ) {
@@ -751,12 +834,12 @@ print <<EOF;
 Ok, it looks like we are finished.  There are several more things you
 will need to do:
 
-  - Browse through the config file, $Conf{TopDir}/conf/config.pl,
-    and make sure all the settings are correct.  In particular, you
-    will need to set the smb share password and user name, backup
-    policies and check the email message headers and bodies.
+  - Browse through the config file, $Conf{ConfDir}/config.pl,
+    and make sure all the settings are correct.  In particular,
+    you will need to set \$Conf{CgiAdminUsers} so you have
+    administration privileges in the CGI interface.
 
-  - Edit the list of hosts to backup in $Conf{TopDir}/conf/hosts.
+  - Edit the list of hosts to backup in $Conf{ConfDir}/hosts.
 
   - Read the documentation in $Conf{InstallDir}/doc/BackupPC.html.
     Please pay special attention to the security section.
@@ -789,9 +872,9 @@ EOF
 }
 
 eval "use File::RsyncP;";
-if ( !$@ && $File::RsyncP::VERSION < 0.51 ) {
+if ( !$@ && $File::RsyncP::VERSION < 0.64 ) {
     print("\nWarning: you need to upgrade File::RsyncP;"
-        . " I found $File::RsyncP::VERSION and BackupPC needs 0.51\n");
+        . " I found $File::RsyncP::VERSION and BackupPC needs 0.64\n");
 }
 
 exit(0);
@@ -825,7 +908,11 @@ sub InstallFile
        binmode(OUT);
        while ( <PROG> ) {
            s/__INSTALLDIR__/$Conf{InstallDir}/g;
+           s/__LOGDIR__/$Conf{LogDir}/g;
+           s/__CONFDIR__/$Conf{ConfDir}/g;
            s/__TOPDIR__/$Conf{TopDir}/g;
+            s/^(\s*my \$useFHS\s*=\s*)\d;/${1}$opts{fhs};/
+                                    if ( $prog =~ /Lib.pm/ );
            s/__BACKUPPCUSER__/$Conf{BackupPCUser}/g;
            s/__CGIDIR__/$Conf{CgiDir}/g;
            if ( $first && /^#.*bin\/perl/ ) {
@@ -841,8 +928,8 @@ sub InstallFile
        close(PROG);
        close(OUT);
     }
-    die("can't chown $uid, $gid $dest") unless chown($uid, $gid, $dest);
-    die("can't chmod $mode $dest")      unless chmod($mode, $dest);
+    die("can't chown $uid, $gid $dest") unless my_chown($uid, $gid, $dest);
+    die("can't chmod $mode $dest")      unless my_chmod($mode, $dest);
 }
 
 sub FindProgram
@@ -919,7 +1006,7 @@ sub ConfigMerge
 {
     my($old, $oldVars, $new, $newVars) = @_;
     my $posn = 0;
-    my $res;
+    my($res, $resVars);
 
     #
     # Find which config parameters are not needed any longer
@@ -951,7 +1038,26 @@ sub ConfigMerge
             push(@$res, $new);
         }
     }
-    return $res;
+    for ( my $i = 0 ; $i < @$res ; $i++ ) {
+        $resVars->{$res->[$i]{var}} = $i;
+    }
+    return ($res, $resVars);
+}
+
+sub my_chown
+{
+    my($uid, $gid, $file) = @_;
+
+    return 1 if ( !$opts{"set-perms"} );
+    return chown($uid, $gid, $file);
+}
+
+sub my_chmod
+{
+    my ($mode, $file) = @_;
+
+    return 1 if ( !$opts{"set-perms"} );
+    return chmod($mode, $file);
 }
 
 sub prompt
@@ -998,6 +1104,11 @@ Run configure.pl in batch mode.  configure.pl will run without
 prompting the user.  The other command-line options are used
 to specify the settings that the user is usually prompted for.
 
+=item B<--backuppc-user=USER>
+
+Specify the BackupPC user name that owns all the BackupPC
+files and runs the BackupPC programs.  Default is backuppc.
+
 =item B<--bin-path PROG=PATH>
 
 Specify the path for various external programs that BackupPC
@@ -1015,6 +1126,17 @@ Examples
 
     --bin-path cat=/bin/cat --bin-path bzip2=/home/user/bzip2
 
+=item B<--compress-level=N>
+
+Set the configuration compression level to N.  Default is 3
+if Compress::Zlib is installed.
+
+=item B<--config-dir CONFIG_DIR>
+
+Configuration directory for new installations.  Defaults
+to /etc/BackupPC with FHS.  Automatically extracted
+from --config-path for existing installations.
+
 =item B<--config-path CONFIG_PATH>
 
 Path to the existing config.pl configuration file for BackupPC.
@@ -1050,6 +1172,13 @@ to run it from below the --dest-dir directory, since all the
 paths are set assuming BackupPC is installed in the intended
 final locations.
 
+=item B<--fhs>
+
+Use locations specified by the Filesystem Hierarchy Standard
+for installing BackupPC.  This is enabled by default for new
+installatios.  To use the pre-3.0 installation locations,
+specify --no-fhs.
+
 =item B<--help|?>
 
 Print a brief help message and exits.
@@ -1090,10 +1219,21 @@ Example:
 
     --install-dir /usr/local/BackupPC
 
+=item B<--log-dir LOG_DIR>
+
+Log directory.  Defaults to /var/log/BackupPC with FHS.
+
 =item B<--man>
 
 Prints the manual page and exits.
 
+=item B<--set-perms>
+
+When installing files and creating directories, chown them to
+the BackupPC user and chmod them too.  This is enabled by default.
+To disable (for example, if staging a destination directory)
+then specify --no-set-perms.
+
 =item B<--uid-ignore>
 
 configure.pl verifies that the script is being run as the super user
@@ -1131,7 +1271,7 @@ Craig Barratt <cbarratt@users.sourceforge.net>
 
 =head1 COPYRIGHT
 
-Copyright (C) 2001-2004  Craig Barratt.
+Copyright (C) 2001-2006  Craig Barratt.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by