1#!/usr/bin/env perl
2#============================================================= -*-perl-*-
3#
4# configure.pl: Configuration and installation program for BackupPC
5#
6# DESCRIPTION
7#
8#   This script should be run as root:
9#
10#        perl configure.pl
11#
12#   To read about the command-line options for this configure script:
13#
14#        perldoc configure.pl
15#
16#   The installation steps are described as the script runs.
17#
18# AUTHOR
19#   Craig Barratt <cbarratt@users.sourceforge.net>
20#
21# COPYRIGHT
22#   Copyright (C) 2001-2017  Craig Barratt
23#
24#   This program is free software: you can redistribute it and/or modify
25#   it under the terms of the GNU General Public License as published by
26#   the Free Software Foundation, either version 3 of the License, or
27#   (at your option) any later version.
28#
29#   This program is distributed in the hope that it will be useful,
30#   but WITHOUT ANY WARRANTY; without even the implied warranty of
31#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32#   GNU General Public License for more details.
33#
34#   You should have received a copy of the GNU General Public License
35#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
36#
37#========================================================================
38#
39# Version __VERSION__, released __RELEASEDATE__.
40#
41# See http://backuppc.sourceforge.net.
42#
43#========================================================================
44
45use strict;
46no  utf8;
47use vars qw(%Conf %OrigConf $Upgrade);
48use lib "./lib";
49
50#
51# The two strings below are replaced with the full list of BackupPC executables
52# and libraries by makeDist.
53#
54my @ConfigureBinList = qw(
55        __CONFIGURE_BIN_LIST__
56    );
57my @ConfigureLibList = qw(
58        __CONFIGURE_LIB_LIST__
59    );
60
61#
62# Check that makeDist has been run; need to avoid having the magic string
63# appear exactly (otherwise makeDist will replace it), so compute it instead
64#
65if ( $ConfigureBinList[0] eq "__" . "CONFIGURE_BIN_LIST__" ) {
66    die <<EOF;
67You need to run makeDist first to create a tarball release that includes an
68updated configure.pl.  After you unpack the tarball, run configure.pl from
69there.
70EOF
71}
72
73my @Packages = qw(version Encode Socket File::Path File::Spec File::Copy
74                  Digest::MD5 Data::Dumper Getopt::Std Getopt::Long Pod::Usage
75                  File::Listing CGI BackupPC::XS BackupPC::Lib);
76
77my $PackageVersion = {
78        "Encode"       => "1.99",
79        "BackupPC::XS" => "0.53",
80    };
81
82foreach my $pkg ( @Packages ) {
83    eval "use $pkg";
84    if ( !$@ ) {
85        next if ( !defined($PackageVersion->{$pkg}) );
86        my $ver = eval "\$${pkg}::VERSION";
87        next if ( version->parse($ver) >= version->parse($PackageVersion->{$pkg}) );
88        die <<EOF;
89
90Perl package $pkg needs to be at least version $PackageVersion->{$pkg}.
91The currently installed $pkg is version $ver.
92
93Please upgrade package $pkg to the latest version and then re-run
94this script.
95EOF
96    }
97    if ( $pkg =~ /BackupPC::Lib/ ) {
98        die <<EOF;
99
100Error loading $pkg: $@
101BackupPC cannot load the package $pkg, which is included in the
102BackupPC distribution.  This probably means you did not cd to the
103unpacked BackupPC distribution before running configure.pl, eg:
104
105    cd BackupPC-__VERSION__
106    ./configure.pl
107
108Please try again.
109
110EOF
111    }
112    die <<EOF;
113
114BackupPC needs the perl package "$pkg".  Please install "$pkg"
115(eg, using cpan) before installing BackupPC.
116
117EOF
118}
119
120my %opts;
121$opts{"set-perms"} = 1;
122if ( !GetOptions(
123            \%opts,
124            "batch",
125            "backuppc-user=s",
126            "bin-path=s%",
127            "cgi-dir=s",
128            "compress-level=i",
129            "config-path=s",
130            "config-override=s%",
131            "config-dir=s",
132            "config-only",
133            "data-dir=s",
134            "dest-dir=s",
135            "fhs!",
136            "help|?",
137            "hostname=s",
138            "html-dir=s",
139            "html-dir-url=s",
140            "install-dir=s",
141            "log-dir=s",
142            "man",
143            "run-dir=s",
144            "scgi-port=i",
145            "set-perms!",
146            "uid-ignore!",
147        ) || @ARGV ) {
148    pod2usage(2);
149}
150pod2usage(1) if ( $opts{help} );
151pod2usage(-exitstatus => 0, -verbose => 2) if $opts{man};
152
153my $DestDir = $opts{"dest-dir"};
154$DestDir = "" if ( $DestDir eq "/" );
155
156if ( !$opts{"uid-ignore"} && $< != 0 ) {
157    print <<EOF;
158
159This configure script should be run as root, rather than uid $<.
160Provided uid $< has sufficient permissions to create the data and
161install directories, then it should be ok to proceed.  Otherwise,
162please quit and restart as root.
163
164EOF
165    exit(1) if ( prompt("--> Do you want to continue?",
166                       "y") !~ /y/i );
167    exit(1) if ( $opts{batch} && !$opts{"uid-ignore"} );
168}
169
170#
171# Whether we use the file system hierarchy conventions or not.
172# Older versions did not.  BackupPC used to be installed in
173# two main directories (in addition to CGI and html pages)
174#
175#    TopDir       which includes subdirs conf, log, pc, pool, cpool
176#
177#    InstallDir   which includes subdirs bin, lib, share/doc/BackupPC
178#
179# With FHS enabled (which is the default for new installations)
180# the config files move to /etc/BackupPC and log files to /var/log:
181#
182#    /etc/BackupPC/config.pl  main config file (was $TopDir/conf/config.pl)
183#    /etc/BackupPC/hosts      hosts file (was $TopDir/conf/hosts)
184#    /etc/BackupPC/pc/HOST.pl per-pc config file (was $TopDir/pc/HOST/config.pl)
185#    /var/log/BackupPC        log files (was $TopDir/log)
186#    /var/log/BackupPC        Pid, status and email info (was $TopDir/log)
187#
188
189#
190# Check if this is an upgrade, in which case read the existing
191# config file to get all the defaults.
192#
193my $ConfigDir = $opts{"config-dir"} || "/etc/BackupPC";
194my $ConfigPath = "";
195my $ConfigFileOK = 1;
196while ( 1 ) {
197    if ( $ConfigFileOK && -f "$DestDir$ConfigDir/config.pl"
198            && (!defined($opts{fhs}) || $opts{fhs}) && !defined($opts{"config-path"}) ) {
199        $ConfigPath = "$ConfigDir/config.pl";
200        $opts{fhs} = 1 if ( !defined($opts{fhs}) );
201        print <<EOF;
202
203Found $DestDir$ConfigDir/config.pl, so this is an upgrade of an
204existing BackupPC installation.  We will verify some existing
205information, but you will probably not need to make any
206changes - just hit ENTER to each question.
207EOF
208    } else {
209        print <<EOF;
210
211Is this a new installation or upgrade for BackupPC?  If this is
212an upgrade please tell me the full path of the existing BackupPC
213configuration file (eg: $ConfigDir/config.pl).  Otherwise, just
214hit return.
215
216EOF
217        $ConfigPath = prompt("--> Full path to existing main config.pl",
218                             $ConfigPath,
219                             "config-path");
220    }
221    last if ( $ConfigPath eq ""
222            || ($ConfigPath =~ /^\// && -f "$DestDir$ConfigPath" && -w "$DestDir$ConfigPath") );
223    my $problem = "is not an absolute path";
224    $problem = "is not writable"        if ( !-w $ConfigPath );
225    $problem = "is not readable"        if ( !-r $ConfigPath );
226    $problem = "is not a regular file"  if ( !-f $ConfigPath );
227    $problem = "doesn't exist"          if ( !-e $ConfigPath );
228    print("The file '$DestDir$ConfigPath' $problem.\n");
229    if ( $opts{batch} ) {
230        print("Need to specify a valid --config-path for upgrade\n");
231        exit(1);
232    }
233    $ConfigFileOK = 0;
234}
235$opts{fhs} = 1 if ( !defined($opts{fhs}) && $ConfigPath eq "" );
236
237my $bpc;
238if ( $ConfigPath ne "" && -r "$DestDir$ConfigPath" ) {
239    ($ConfigDir = $ConfigPath) =~ s{/[^/]+$}{};
240
241    # In config-only mode use installed BackupPC if distribution files are not available.
242    my $libPath = ($opts{"config-only"} && ($INC{"BackupPC/Lib.pm"} ne "lib/BackupPC/Lib.pm"))
243                        ? "" : ".";
244
245    die("BackupPC::Lib->new failed\n")
246            if ( !($bpc = BackupPC::Lib->new(".", $libPath, "$DestDir$ConfigDir", 1)) );
247    %Conf = $bpc->Conf();
248    %OrigConf = %Conf;
249    $Upgrade = 1;
250    if ( !defined($opts{fhs}) ) {
251        if ( $ConfigPath eq "$Conf{TopDir}/conf/config.pl" ) {
252            $opts{fhs} = 0;
253        } else {
254            $opts{fhs} = 1;
255        }
256    }
257    if ( !$opts{fhs} ) {
258        ($Conf{TopDir} = $ConfigPath) =~ s{/[^/]+/[^/]+$}{}
259                    if ( $Conf{TopDir} eq '' );
260        $bpc->{LogDir} = $Conf{LogDir}  = "$Conf{TopDir}/log"
261                    if ( $Conf{LogDir} eq '' );
262        $bpc->{RunDir} = $Conf{RunDir}  = "$Conf{TopDir}/log"
263                    if ( $Conf{RunDir} eq '' );
264    }
265    $bpc->{ConfDir} = $Conf{ConfDir} = $ConfigDir;
266    if ( !length($DestDir) ) {
267        my $err = $bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort}, 1);
268        if ( $err eq "" ) {
269            print <<EOF;
270
271BackupPC is running on $Conf{ServerHost}.  You need to stop BackupPC before
272you can upgrade the code.  Depending upon your installation, you could
273run "systemctl stop backuppc.service" if you use systemd,
274or "/etc/init.d/backuppc stop" if you use init.d.
275
276EOF
277            exit(1);
278        }
279    }
280}
281
282#
283# Create filesystem hierarchy defaults
284#
285$Conf{TopDir}       ||= $opts{"data-dir"}    || "/data/BackupPC";
286$Conf{InstallDir}   ||= $opts{"install-dir"} || "/usr/local/BackupPC";
287
288#
289# These are the programs whose paths we need to find
290#
291my %Programs = (
292    perl           => "PerlPath",
293    rsync_bpc      => "RsyncBackupPCPath",
294    'gtar/tar'     => "TarClientPath",
295    smbclient      => "SmbClientPath",
296    nmblookup      => "NmbLookupPath",
297    rsync          => "RsyncClientPath",
298    ping           => "PingPath",
299    ping6          => "Ping6Path",
300    df             => "DfPath",
301    'ssh/ssh2'     => "SshPath",
302    sendmail       => "SendmailPath",
303    hostname       => "HostnamePath",
304    split          => "SplitPath",
305    par2           => "ParPath",
306    cat            => "CatPath",
307    gzip           => "GzipPath",
308    bzip2          => "Bzip2Path",
309    rrdtool        => "RrdToolPath",
310);
311
312foreach my $prog ( sort(keys(%Programs)) ) {
313    my $path;
314    foreach my $subProg ( split(/\//, $prog) ) {
315        $path = FindProgram("$ENV{PATH}:/usr/bin:/bin:/sbin:/usr/sbin:/usr/local/bin",
316                            $subProg) if ( !length($path) );
317    }
318    $Conf{$Programs{$prog}} = $path if ( !length($Conf{$Programs{$prog}}) );
319}
320
321while ( 1 ) {
322    print <<EOF;
323
324I found the following locations for these programs:
325
326EOF
327    foreach my $prog ( sort(keys(%Programs)) ) {
328        printf("    %-12s => %s\n", $prog, $Conf{$Programs{$prog}});
329    }
330    print "\n";
331    last if (prompt('--> Are these paths correct?', 'y') =~ /^y/i);
332    foreach my $prog ( sort(keys(%Programs)) ) {
333        $Conf{$Programs{$prog}} = prompt("--> $prog path",
334                                         $Conf{$Programs{$prog}});
335    }
336}
337
338my $Perl58 = system($Conf{PerlPath}
339                        . q{ -e 'exit($^V && $^V ge v5.8.0 ? 1 : 0);'});
340
341if ( !$Perl58 ) {
342    print <<EOF;
343
344BackupPC needs perl version 5.8.0 or later.  $Conf{PerlPath} appears
345to be an older version.  Please upgrade to a newer version of perl
346and re-run this configure script.
347
348EOF
349    exit(1);
350}
351
352print <<EOF;
353
354Please tell me the hostname of the machine that BackupPC will run on.
355
356EOF
357chomp($Conf{ServerHost} = `$Conf{HostnamePath}`)
358        if ( defined($Conf{HostnamePath}) && !defined($Conf{ServerHost}) );
359$Conf{ServerHost} = prompt("--> BackupPC will run on host",
360                           $Conf{ServerHost},
361                           "hostname");
362
363print <<EOF;
364
365BackupPC should run as a dedicated user with limited privileges.  You
366need to create a user.  This user will need read/write permission on
367the main data directory and read/execute permission on the install
368directory (these directories will be setup shortly).
369
370The primary group for this user should also be chosen carefully.
371The data directories and files will have group read permission,
372so group members can access backup files.
373
374EOF
375my($name, $passwd, $Uid, $Gid);
376while ( 1 ) {
377    $Conf{BackupPCUser} = prompt("--> BackupPC should run as user",
378                                 $Conf{BackupPCUser} || "backuppc",
379                                 "backuppc-user");
380    if ( $opts{"set-perms"} ) {
381        ($name, $passwd, $Uid, $Gid) = getpwnam($Conf{BackupPCUser});
382        last if ( $name ne "" );
383        print <<EOF;
384
385getpwnam() says that user $Conf{BackupPCUser} doesn't exist.  Please
386check the name and verify that this user is in the passwd file.
387
388EOF
389        exit(1) if ( $opts{batch} );
390    } else {
391        last;
392    }
393}
394
395print <<EOF;
396
397Please specify an install directory for BackupPC.  This is where the
398BackupPC scripts, library and documentation will be installed.
399
400EOF
401
402while ( 1 ) {
403    $Conf{InstallDir} = prompt("--> Install directory (full path)",
404                               $Conf{InstallDir},
405                               "install-dir");
406    last if ( $Conf{InstallDir} =~ /^\// );
407    if ( $opts{batch} ) {
408        print("Need to specify --install-dir for new installation\n");
409        exit(1);
410    }
411}
412
413print <<EOF;
414
415Please specify a data directory for BackupPC.  This is where all the
416PC backup data is stored.  This file system needs to be big enough to
417accommodate all the PCs you expect to backup (eg: at least several GB
418per machine).
419
420EOF
421
422while ( 1 ) {
423    $Conf{TopDir} = prompt("--> Data directory (full path)",
424                           $Conf{TopDir},
425                           "data-dir");
426    last if ( $Conf{TopDir} =~ /^\// );
427    if ( $opts{batch} ) {
428        print("Need to specify --data-dir for new installation\n");
429        exit(1);
430    }
431}
432
433if ( $opts{fhs} ) {
434    $Conf{ConfDir}      ||= $ConfigDir           || "/etc/BackupPC";
435    $Conf{LogDir}       ||= $opts{"log-dir"}     || "/var/log/BackupPC";
436    $Conf{RunDir}       ||= $opts{"run-dir"}     || "/var/run/BackupPC";
437} else {
438    $Conf{ConfDir}      ||= $ConfigDir           || "$Conf{TopDir}/conf";
439    $Conf{LogDir}       ||= $opts{"log-dir"}     || "$Conf{TopDir}/log";
440    $Conf{RunDir}       ||= $opts{"run-dir"}     || "$Conf{TopDir}/log";
441}
442
443$Conf{CompressLevel} = $opts{"compress-level"}
444                            if ( defined($opts{"compress-level"}) );
445
446print <<EOF;
447
448BackupPC has SCGI and CGI perl interfaces that run under Apache.  You need
449to pick which one to run.
450
451For SCGI, Apache uses the scgi_mod module to communicate with BackupPC_Admin_SCGI,
452which handles the requests.  This allows Apache to run as a different user as
453$Conf{BackupPCUser}.  To use SCGI you need to set SCGIServerPort to any spare
454non-privileged TCP port number.  A negative value disables SCGI.
455
456Important security warning!!  The SCGIServerPort must not be accessible by
457anyone untrusted.  That means you can't allow untrusted users access to the
458BackupPC server, and you should block the SCGIServerPort TCP port from
459network access.
460
461The traditional alternative is to use CGI.  In this case, an executable needs
462to be installed Apache's cgi-bin directory.  This executable needs to run as
463set-uid $Conf{BackupPCUser}, or it can be run under mod_perl with Apache
464running as user $Conf{BackupPCUser}.
465
466EOF
467
468$Conf{SCGIServerPort} = prompt("--> SCGI port (-1 to disable)",
469                               $Conf{SCGIServerPort} || -1,
470                               "scgi-port");
471
472if ( $Conf{SCGIServerPort} < 0 ) {
473    while ( 1 ) {
474        $Conf{CgiDir} = prompt("--> CGI bin directory (full path, or empty for no CGI)",
475                               $Conf{CgiDir},
476                               "cgi-dir");
477        last if ( $Conf{CgiDir} =~ /^\// || $Conf{CgiDir} eq "" );
478        if ( $opts{batch} ) {
479            print("Need to specify --cgi-dir for new installation\n");
480            exit(1);
481        }
482    }
483}
484
485if ( $Conf{SCGIServerPort} > 0 || $Conf{CgiDir} ne "" ) {
486    print <<EOF;
487
488BackupPC's CGI and SCGI script need to display various PNG/GIF
489images that should be stored where Apache can serve them.  They
490should be placed somewhere under Apache's DocumentRoot.  BackupPC
491also needs to know the URL to access these images.  Example:
492
493    Apache image directory:  /var/www/htdocs/BackupPC
494    URL for image directory: /BackupPC
495
496The URL for the image directory should start with a slash.
497
498EOF
499    while ( 1 ) {
500        $Conf{CgiImageDir} = prompt("--> Apache image directory (full path, or empty for no S/CGI)",
501                                    $Conf{CgiImageDir},
502                                    "html-dir");
503        last if ( $Conf{CgiImageDir} =~ /^\// || $Conf{CgiImageDir} eq "" );
504        if ( $opts{batch} ) {
505            print("Need to specify --html-dir for new installation\n");
506            exit(1);
507        }
508    }
509    while ( 1 ) {
510        $Conf{CgiImageDirURL} = prompt("--> URL for image directory (omit http://host; starts with '/', or empty for no S/CGI)",
511                                        $Conf{CgiImageDirURL},
512                                        "html-dir-url");
513        last if ( $Conf{CgiImageDirURL} =~ /^\// || $Conf{CgiImageDirURL} eq "" );
514        if ( $opts{batch} ) {
515            print("Need to specify --html-dir-url for new installation\n");
516            exit(1);
517        }
518    }
519}
520
521print <<EOF;
522
523Ok, we're about to:
524
525EOF
526
527print <<EOF if ( !$opts{"config-only"} );
528  - install the binaries, lib and docs in $DestDir$Conf{InstallDir}
529  - create the data directory $DestDir$Conf{TopDir}
530  - optionally install the cgi-bin interface
531EOF
532
533print <<EOF;
534  - create/update the config.pl file $DestDir$Conf{ConfDir}/config.pl
535
536EOF
537
538exit unless prompt("--> Do you want to continue?", "y") =~ /y/i;
539
540CleanPidSock();
541
542DoInstall() if ( !$opts{"config-only"} );
543
544print("Installing config.pl and hosts in $DestDir$Conf{ConfDir}\n");
545InstallFile("conf/hosts", "$DestDir$Conf{ConfDir}/hosts.sample", 0644)
546                    if ( !$opts{"config-only"} );
547my $hostsSample = $opts{"config-only"} ? "$DestDir$Conf{ConfDir}/hosts.sample" : "conf/hosts";
548InstallFile($hostsSample, "$DestDir$Conf{ConfDir}/hosts", 0644)
549                    if ( !-f "$DestDir$Conf{ConfDir}/hosts" );
550
551#
552# Now do the config file.  If there is an existing config file we
553# merge in the new config file, adding any new configuration
554# parameters and deleting ones that are no longer needed.
555#
556my $dest = "$DestDir$Conf{ConfDir}/config.pl";
557my $configSample = $opts{"config-only"} ? "$DestDir$Conf{ConfDir}/config.pl.sample" : "conf/config.pl";
558my ($distConf, $distVars) = ConfigParse($configSample);
559my ($oldConf, $oldVars);
560my ($newConf, $newVars) = ($distConf, $distVars);
561if ( -f $dest ) {
562    ($oldConf, $oldVars) = ConfigParse($dest);
563    ($newConf, $newVars) = ConfigMerge($oldConf, $oldVars, $distConf, $distVars);
564}
565
566#
567# Update various config parameters.  The old config is in Conf{}
568# and the new config is an array in text form in $newConf->[].
569#
570$Conf{EMailFromUserName}  ||= $Conf{BackupPCUser};
571$Conf{EMailAdminUserName} ||= $Conf{BackupPCUser};
572
573#
574# Guess $Conf{CgiURL}
575#
576if ( $Conf{CgiURL} eq '' ) {
577    if ( $Conf{CgiDir} =~ m{cgi-bin(/.*)} ) {
578        $Conf{CgiURL} = "http://$Conf{ServerHost}/cgi-bin$1/BackupPC_Admin";
579    } else {
580        $Conf{CgiURL} = "http://$Conf{ServerHost}/cgi-bin/BackupPC_Admin";
581    }
582}
583
584#
585# The smbclient commands have moved from hard-coded to the config file.
586# $Conf{SmbClientArgs} no longer exists, so merge it into the new
587# commands if it still exists.
588#
589if ( defined($Conf{SmbClientArgs}) ) {
590    if ( $Conf{SmbClientArgs} ne "" ) {
591        foreach my $param ( qw(SmbClientRestoreCmd SmbClientFullCmd
592                                SmbClientIncrCmd) ) {
593            $newConf->[$newVars->{$param}]{text}
594                            =~ s/(-E\s+-N)/$1 $Conf{SmbClientArgs}/;
595        }
596    }
597    delete($Conf{SmbClientArgs});
598}
599
600#
601# CSS is now stored in a file rather than a big config variable.
602#
603delete($Conf{CSSstylesheet});
604
605#
606# The blackout timing settings are now stored in a list of hashes, rather
607# than three scalar parameters.
608#
609if ( defined($Conf{BlackoutHourBegin}) ) {
610    $Conf{BlackoutPeriods} = [
611	 {
612	     hourBegin => $Conf{BlackoutHourBegin},
613	     hourEnd   => $Conf{BlackoutHourEnd},
614	     weekDays  => $Conf{BlackoutWeekDays},
615	 }
616    ];
617    delete($Conf{BlackoutHourBegin});
618    delete($Conf{BlackoutHourEnd});
619    delete($Conf{BlackoutWeekDays});
620}
621
622#
623# $Conf{RsyncLogLevel} has been replaced by $Conf{XferLogLevel}
624#
625if ( defined($Conf{RsyncLogLevel}) ) {
626    $Conf{XferLogLevel} = $Conf{RsyncLogLevel};
627    delete($Conf{RsyncLogLevel});
628}
629
630#
631# Since 2.1.0 the default for $Conf{CgiNavBarAdminAllHosts} is now 1
632#
633$Conf{CgiNavBarAdminAllHosts} = 1;
634
635#
636# Empty $Conf{ParPath} if it isn't a valid executable
637# (pre-3.0.0 configure.pl incorrectly set it to a
638# hardcoded value).
639#
640$Conf{ParPath} = '' if ( $Conf{ParPath} ne '' && !-x $Conf{ParPath} );
641
642#
643# Figure out sensible arguments for the ping command
644#
645if ( defined($Conf{PingArgs}) ) {
646    $Conf{PingCmd} = '$pingPath ' . $Conf{PingArgs};
647    delete($Conf{PingArgs});
648} elsif ( $Upgrade && !defined($Conf{PingCmd}) ) {
649    if ( $^O eq "solaris" || $^O eq "sunos" ) {
650	$Conf{PingCmd} = '$pingPath -s $host 56 1';
651    } elsif ( ($^O eq "linux" || $^O eq "openbsd" || $^O eq "netbsd")
652	    && !system("$Conf{PingPath} -c 1 -w 3 localhost") ) {
653	$Conf{PingCmd} = '$pingPath -c 1 -w 3 $host';
654    } else {
655	$Conf{PingCmd} = '$pingPath -c 1 $host';
656    }
657}
658
659#
660# Figure out sensible arguments for the df command
661#
662if ( !defined($Conf{DfCmd}) ) {
663    if ( $^O eq "solaris" || $^O eq "sunos" ) {
664	$Conf{DfCmd} = '$dfPath -k $topDir';
665    }
666}
667
668#
669# $Conf{SmbClientTimeout} is now $Conf{ClientTimeout}
670#
671if ( defined($Conf{SmbClientTimeout}) ) {
672    $Conf{ClientTimeout} = $Conf{SmbClientTimeout};
673    delete($Conf{SmbClientTimeout});
674}
675
676#
677# Replace --devices with -D in RsyncArgs and RsyncRestoreArgs
678#
679foreach my $param ( qw(RsyncArgs RsyncRestoreArgs) ) {
680    next if ( !defined($newVars->{$param}) );
681    $newConf->[$newVars->{$param}]{text} =~ s/--devices/-D/g;
682}
683
684#
685# Merge any new user-editable parameters into CgiUserConfigEdit
686# by copying the old settings forward.
687#
688if ( defined($Conf{CgiUserConfigEdit}) ) {
689    #
690    # This is a real hack.  The config file merging is done in text
691    # form without actually instantiating the new conf structure.
692    # So we need to extract the new hash of settings, update it,
693    # and merge the text.  Ugh...
694    #
695    my $new;
696    my $str = $distConf->[$distVars->{CgiUserConfigEdit}]{text};
697
698    $str =~ s/^\s*\$Conf\{.*?\}\s*=\s*/\$new = /m;
699    eval($str);
700    foreach my $p ( keys(%$new) ) {
701        $new->{$p} = $Conf{CgiUserConfigEdit}{$p}
702                if ( defined($Conf{CgiUserConfigEdit}{$p}) );
703    }
704    $Conf{CgiUserConfigEdit} = $new;
705    my $d = Data::Dumper->new([$new], [*value]);
706    $d->Indent(1);
707    $d->Terse(1);
708    $d->Sortkeys(1);
709    my $value = $d->Dump;
710    $value =~ s/(.*)\n/$1;\n/s;
711    $newConf->[$newVars->{CgiUserConfigEdit}]{text}
712            =~ s/^(\s*\$Conf\{.*?\}\s*=\s*).*/$1$value/ms;
713}
714
715#
716# If this is an upgrade from V3, then set $Conf{PoolV3Enabled}
717# and update $Conf{RsyncArgs} and $Conf{RsyncRestoreArgs}.
718#
719if ( $Upgrade && !defined($Conf{PoolV3Enabled}) ) {
720    $Conf{PoolV3Enabled} = 1;
721    #
722    # for an upgrade, remove the new --one-file-system flag if it wasn't there before
723    #
724    if ( $oldConf->[$oldVars->{RsyncArgs}]{text} !~ /--one-file-system/ ) {
725        $distConf->[$distVars->{RsyncArgs}]{text} =~ s/\n\s*'--one-file-system',\n/\n/;
726    }
727    $newConf->[$newVars->{RsyncArgs}]{text}        = $distConf->[$distVars->{RsyncArgs}]{text};
728    $newConf->[$newVars->{RsyncRestoreArgs}]{text} = $distConf->[$distVars->{RsyncRestoreArgs}]{text};
729    #
730    # If it exists, use $Conf{RsyncClientCmd} to create the default $Conf{RsyncSshArgs}.
731    #
732    if ( $Conf{RsyncClientCmd} =~ /(\$sshPath.* +-l +\S+)/ && defined($newVars->{RsyncSshArgs}) ) {
733        my $value = "[\n    '-e', '$1',\n];\n\n";
734        $newConf->[$newVars->{RsyncSshArgs}]{text}
735                =~ s/^(\s*\$Conf\{RsyncSshArgs}\s*=\s*).*/$1$value/ms;
736    }
737}
738
739#
740# Update $Conf{CgiNavBarLinks} with github URLs
741#
742$newConf->[$newVars->{CgiNavBarLinks}]{text} =~ s{http://backuppc.wiki.sourceforge.net}{https://github.com/backuppc/backuppc/wiki}g;
743$newConf->[$newVars->{CgiNavBarLinks}]{text} =~ s{http://backuppc.sourceforge.net}{https://backuppc.github.io/backuppc}g;
744$newConf->[$newVars->{CgiNavBarLinks}]{text} =~ s{SourceForge}{Homepage}g;
745
746#
747# Apply any command-line configuration parameter settings
748#
749foreach my $param ( keys(%{$opts{"config-override"}}) ) {
750    my $value = $opts{"config-override"}{$param};
751    my $val = eval { $value };
752    if ( @$ ) {
753        printf("Can't eval --config-override setting %s=%s\n",
754                        $param, $opts{"config-override"}{$param});
755        exit(1);
756    }
757    if ( !defined($newVars->{$param}) ) {
758        printf("Unkown config parameter %s in --config-override\n", $param);
759        exit(1);
760    }
761    $value .= ";\n\n";
762    $newConf->[$newVars->{$param}]{text}
763            =~ s/^(\s*\$Conf\{$param}\s*=\s*).*/$1$value/ms;
764}
765
766#
767# Now backup and write the config file
768#
769my $confCopy = "$dest.pre-__VERSION__";
770if ( -f $dest && !-f $confCopy ) {
771    #
772    # Make copy of config file, preserving ownership and modes
773    #
774    print("Making backup copy of $dest -> $confCopy\n");
775    my @stat = stat($dest);
776    my $mode = $stat[2];
777    my $uid  = $stat[4];
778    my $gid  = $stat[5];
779    die("can't copy($dest, $confCopy)\n")
780                                unless copy($dest, $confCopy);
781    die("can't chown $uid, $gid $confCopy\n")
782                                unless my_chown($uid, $gid, $confCopy);
783    die("can't chmod $mode $confCopy\n")
784                                unless my_chmod($mode, $confCopy);
785}
786open(OUT, ">", $dest) || die("can't open $dest for writing\n");
787binmode(OUT);
788my $blockComment;
789foreach my $var ( @$newConf ) {
790    if ( length($blockComment)
791          && substr($var->{text}, 0, length($blockComment)) eq $blockComment ) {
792        $var->{text} = substr($var->{text}, length($blockComment));
793        $blockComment = undef;
794    }
795    $blockComment = $1 if ( $var->{text} =~ /^([\s\n]*#{70}.*#{70}[\s\n]+)/s );
796    $var->{text} =~ s/^\s*\$Conf\{(.*?)\}(\s*=\s*['"]?)(.*?)(['"]?\s*;)/
797                my $varName  = $1;
798                my $a        = $2;
799                my $varValue = $3;
800                my $b        = $4;
801                # Get quotes from default config to avoid missing or extra quotes
802                # when replacing misused undef or empty string values
803                ($a, $b) = GetQuotes($varName)
804                              if ( (!defined($OrigConf{$varName}) || $OrigConf{$varName} eq "")
805                                   && $Conf{$varName} ne $OrigConf{$varName} );
806
807                defined($Conf{$varName}) && ref($Conf{$varName}) eq ""
808                                   && !defined($opts{"config-override"}{$varName})
809                                   && $Conf{$varName} ne $OrigConf{$varName}
810                                   ? "\$Conf{$varName}$a$Conf{$varName}$b"
811                                   : "\$Conf{$varName}$a$varValue$b"/emg;
812    print OUT $var->{text};
813}
814close(OUT);
815if ( !defined($oldConf) ) {
816    die("can't chmod 0640 mode $dest\n")  unless my_chmod(0640, $dest);
817    die("can't chown $Uid, $Gid $dest\n") unless my_chown($Uid, $Gid, $dest);
818}
819
820InstallFile($dest, "$DestDir$Conf{ConfDir}/config.pl.sample", 0644)
821            if ( !$opts{"config-only"} );
822
823print <<EOF;
824
825Ok, it looks like we are finished.  There are several more things you
826will need to do:
827
828  - Browse through the config file, $Conf{ConfDir}/config.pl,
829    and make sure all the settings are correct.  In particular,
830    you will need to set \$Conf{CgiAdminUsers} so you have
831    administration privileges in the CGI interface.
832
833  - Edit the list of hosts to backup in $Conf{ConfDir}/hosts.
834
835  - Read the documentation in $Conf{InstallDir}/doc/BackupPC.html.
836    Please pay special attention to the security section.
837
838  - Verify that the CGI script BackupPC_Admin runs correctly.  You might
839    need to change the permissions or group ownership of BackupPC_Admin.
840    If this is an upgrade and you are using mod_perl, you will need
841    to restart Apache.  Otherwise it will have stale code.
842
843  - BackupPC should be ready to start.  Don't forget to run it
844    as user $Conf{BackupPCUser}!  The installation also contains
845    a systemd/backuppc.service script that can be installed so
846    that BackupPC can auto-start on boot.  This will also enable
847    administrative users to start the server from the CGI interface.
848    See systemd/README.
849
850Enjoy!
851EOF
852
853if ( `$Conf{PerlPath} -V` =~ /uselargefiles=undef/ ) {
854    print <<EOF;
855
856Warning: your perl, $Conf{PerlPath}, does not support large files.
857This means BackupPC won't be able to backup files larger than 2GB.
858To solve this problem you should build/install a new version of perl
859with large file support enabled.  Use
860
861    $Conf{PerlPath} -V | egrep uselargefiles
862
863to check if perl has large file support (undef means no support).
864EOF
865}
866
867exit(0);
868
869###########################################################################
870# Subroutines
871###########################################################################
872
873sub DoInstall
874{
875    #
876    # Create install directories
877    #
878    foreach my $dir ( qw(bin
879                         share share/doc share/doc/BackupPC
880                         lib lib/BackupPC
881                         lib/BackupPC/CGI
882                         lib/BackupPC/Config
883                         lib/BackupPC/Lang
884                         lib/BackupPC/Storage
885                         lib/BackupPC/Xfer
886                         lib/BackupPC/Zip
887                         lib/Net lib/Net/FTP
888                     ) ) {
889        next if ( -d "$DestDir$Conf{InstallDir}/$dir" );
890        mkpath("$DestDir$Conf{InstallDir}/$dir", 0, 0755);
891        if ( !-d "$DestDir$Conf{InstallDir}/$dir"
892                || !my_chown($Uid, $Gid, "$DestDir$Conf{InstallDir}/$dir") ) {
893            die("Failed to create or chown $DestDir$Conf{InstallDir}/$dir\n");
894        } else {
895            print("Created $DestDir$Conf{InstallDir}/$dir\n");
896        }
897    }
898
899    #
900    # Create CGI image directory
901    #
902    foreach my $dir ( ($Conf{CgiImageDir}) ) {
903        next if ( $dir eq "" || -d "$DestDir$dir" );
904        mkpath("$DestDir$dir", 0, 0755);
905        if ( !-d "$DestDir$dir" || !my_chown($Uid, $Gid, "$DestDir$dir") ) {
906            die("Failed to create or chown $DestDir$dir");
907        } else {
908            print("Created $DestDir$dir\n");
909        }
910    }
911
912    #
913    # Create other directories
914    #
915    foreach my $dir ( (
916                "$Conf{TopDir}",
917                "$Conf{TopDir}/pool",
918                "$Conf{TopDir}/cpool",
919                "$Conf{TopDir}/pc",
920                "$Conf{ConfDir}",
921                "$Conf{LogDir}",
922                "$Conf{RunDir}",
923            ) ) {
924        eval { mkpath("$DestDir$dir", 0, 0750) } if ( !-d "$DestDir$dir" );
925        if ( $@ || !-d "$DestDir$dir"
926                || !my_chown($Uid, $Gid, "$DestDir$dir") ) {
927            if ( $dir eq $Conf{RunDir} ) {
928                print("Failed to create or chown $DestDir$dir... continuing\n");
929            } else {
930                die("Failed to create or chown $DestDir$dir\n");
931            }
932        } else {
933            print("Created $DestDir$dir\n");
934        }
935    }
936
937    print("Installing binaries in $DestDir$Conf{InstallDir}/bin\n");
938    foreach my $prog ( @ConfigureBinList ) {
939        InstallFile($prog, "$DestDir$Conf{InstallDir}/$prog", 0555);
940    }
941
942    #
943    # remove old pre-v4 programs
944    #
945    foreach my $prog ( qw(
946            bin/BackupPC_link
947            bin/BackupPC_tarPCCopy
948            bin/BackupPC_trashClean
949            bin/BackupPC_compressPool
950        ) ) {
951        unlink("$DestDir$Conf{InstallDir}/$prog");
952    }
953
954    print("Installing library in $DestDir$Conf{InstallDir}/lib\n");
955    foreach my $lib ( @ConfigureLibList ) {
956        InstallFile($lib, "$DestDir$Conf{InstallDir}/$lib", 0444);
957    }
958
959    #
960    # remove old pre-v4 libraries
961    #
962    foreach my $lib ( qw(
963            lib/BackupPC/Attrib.pm
964            lib/BackupPC/Config.pm
965            lib/BackupPC/FileZIO.pm
966            lib/BackupPC/PoolWrite.pm
967            lib/BackupPC/Xfer/RsyncDigest.pm
968            lib/BackupPC/Xfer/RsyncFileIO.pm
969        ) ) {
970        unlink("$DestDir$Conf{InstallDir}/$lib");
971    }
972
973    if ( $Conf{CgiImageDir} ne "" ) {
974        print("Installing images in $DestDir$Conf{CgiImageDir}\n");
975        foreach my $img ( <images/*> ) {
976            (my $destImg = $img) =~ s{^images/}{};
977            InstallFile($img, "$DestDir$Conf{CgiImageDir}/$destImg", 0444, 1);
978        }
979
980        #
981        # Install new CSS file, making a backup copy if necessary
982        #
983        my $cssBackup = "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css.pre-__VERSION__";
984        if ( -f "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css" && !-f $cssBackup ) {
985            rename("$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css", $cssBackup);
986        }
987        InstallFile("conf/BackupPC_stnd.css",
988                    "$DestDir$Conf{CgiImageDir}/BackupPC_stnd.css", 0444, 0);
989        InstallFile("conf/BackupPC_retro_v2.css",
990                    "$DestDir$Conf{CgiImageDir}/BackupPC_retro_v2.css", 0444, 0);
991        InstallFile("conf/BackupPC_retro_v3.css",
992                    "$DestDir$Conf{CgiImageDir}/BackupPC_retro_v3.css", 0444, 0);
993        InstallFile("conf/sorttable.js",
994                    "$DestDir$Conf{CgiImageDir}/sorttable.js", 0444, 0);
995    }
996
997    print("Making systemd and init.d scripts\n");
998    foreach my $dir ( qw(systemd systemd/init.d) ) {
999        mkpath($dir, 0, 0755);
1000        if ( !-d $dir || !my_chown($Uid, $Gid, $dir) ) {
1001            die("Failed to create or chown $dir\n");
1002        }
1003    }
1004    InstallFile("systemd/src/backuppc.service", "systemd/backuppc.service", 0644);
1005    foreach my $init ( qw(init.d/gentoo-backuppc init.d/gentoo-backuppc.conf
1006                          init.d/linux-backuppc init.d/solaris-backuppc init.d/debian-backuppc
1007                          init.d/freebsd-backuppc init.d/freebsd-backuppc2 init.d/suse-backuppc
1008                          init.d/slackware-backuppc init.d/ubuntu-backuppc ) ) {
1009        InstallFile("systemd/src/$init", "systemd/$init", 0755);
1010    }
1011
1012    print("Making Apache configuration file for suid-perl\n");
1013    InstallFile("httpd/src/BackupPC.conf", "httpd/BackupPC.conf", 0644);
1014
1015    print("Installing docs in $DestDir$Conf{InstallDir}/share/doc/BackupPC\n");
1016    foreach my $doc ( qw(BackupPC.pod BackupPC.html) ) {
1017        InstallFile("doc/$doc", "$DestDir$Conf{InstallDir}/share/doc/BackupPC/$doc", 0444);
1018        #
1019        # clean up files from old directory
1020        #
1021        unlink("$DestDir$Conf{InstallDir}/doc/$doc") if ( -f "$DestDir$Conf{InstallDir}/doc/$doc" );
1022    }
1023    #
1024    # clean up old directory (ok if it quietly fails if there are other files in that directory)
1025    #
1026    rmdir("$DestDir$Conf{InstallDir}/doc") if ( -d "$DestDir$Conf{InstallDir}/doc" );
1027
1028    if ( $Conf{CgiDir} ne "" ) {
1029        print("Installing cgi script BackupPC_Admin in $DestDir$Conf{CgiDir}\n");
1030        mkpath("$DestDir$Conf{CgiDir}", 0, 0755);
1031        InstallFile("cgi-bin/BackupPC_Admin", "$DestDir$Conf{CgiDir}/BackupPC_Admin",
1032                    04554);
1033    }
1034}
1035
1036sub CleanPidSock
1037{
1038    #
1039    # clean pid and sock files from old location (they are now in $Conf{RunDir}, and they
1040    # get re-created each time BackupPC starts, so it's ok if RunDir eq LogDir).
1041    #
1042    unlink("$DestDir$Conf{LogDir}/BackupPC.pid")  if ( -f "$DestDir$Conf{LogDir}/BackupPC.pid" );
1043    unlink("$DestDir$Conf{LogDir}/BackupPC.sock") if ( -e "$DestDir$Conf{LogDir}/BackupPC.sock" );
1044}
1045
1046sub InstallFile
1047{
1048    my($prog, $dest, $mode, $binary) = @_;
1049    my $first = 1;
1050    my($uid, $gid) = ($Uid, $Gid);
1051
1052    if ( -f $dest ) {
1053        #
1054        # preserve ownership and modes of files that already exist
1055        #
1056        my @stat = stat($dest);
1057        $mode = $stat[2];
1058        $uid  = $stat[4];
1059        $gid  = $stat[5];
1060    }
1061    unlink($dest) if ( -f $dest );
1062    if ( $binary ) {
1063	die("can't copy($prog, $dest)\n") unless copy($prog, $dest);
1064    } else {
1065	open(PROG, $prog)     || die("can't open $prog for reading\n");
1066	open(OUT, ">", $dest) || die("can't open $dest for writing\n");
1067	binmode(PROG);
1068	binmode(OUT);
1069	while ( <PROG> ) {
1070	    s/__INSTALLDIR__/$Conf{InstallDir}/g;
1071	    s/__LOGDIR__/$Conf{LogDir}/g;
1072	    s/__RUNDIR__/$Conf{RunDir}/g;
1073	    s/__CONFDIR__/$Conf{ConfDir}/g;
1074	    s/__TOPDIR__/$Conf{TopDir}/g;
1075            s/^(\s*my \$useFHS\s*=\s*)\d;/${1}$opts{fhs};/
1076                                    if ( $prog =~ /Lib.pm/ );
1077	    s/__BACKUPPCUSER__/$Conf{BackupPCUser}/g;
1078	    s/__CGIDIR__/$Conf{CgiDir}/g;
1079            s/__IMAGEDIR__/$Conf{CgiImageDir}/g;
1080            s/__IMAGEDIRURL__/$Conf{CgiImageDirURL}/g;
1081	    if ( $first && /^#.*bin\/perl/ ) {
1082		#
1083		# Fill in correct path to perl (no taint for >= 2.0.1).
1084		#
1085		print OUT "#!$Conf{PerlPath}\n";
1086	    } else {
1087		print OUT;
1088	    }
1089	    $first = 0;
1090	}
1091	close(PROG);
1092	close(OUT);
1093    }
1094    die("can't chown $uid, $gid $dest") unless my_chown($uid, $gid, $dest);
1095    die("can't chmod $mode $dest")      unless my_chmod($mode, $dest);
1096}
1097
1098sub FindProgram
1099{
1100    my($path, $prog) = @_;
1101
1102    if ( defined($opts{"bin-path"}{$prog}) ) {
1103        return $opts{"bin-path"}{$prog};
1104    }
1105    foreach my $dir ( split(/:/, $path) ) {
1106        my $file = File::Spec->catfile($dir, $prog);
1107        return $file if ( -x $file );
1108    }
1109    return;
1110}
1111
1112sub ConfigParse
1113{
1114    my($file) = @_;
1115    open(C, $file) || die("can't open $file");
1116    binmode(C);
1117    my($out, @conf, $var);
1118    my $comment = 1;
1119    my $allVars = {};
1120    my $endLine = undef;
1121    while ( <C> ) {
1122        if ( /^#/ && !defined($endLine) ) {
1123            if ( $comment ) {
1124                $out .= $_;
1125            } else {
1126                if ( $out ne "" ) {
1127                    $allVars->{$var} = @conf if ( defined($var) );
1128                    push(@conf, {
1129                        text => $out,
1130                        var => $var,
1131                    });
1132                }
1133                $var = undef;
1134                $comment = 1;
1135                $out = $_;
1136            }
1137        } elsif ( /^\s*\$Conf\{([^}]*)/ ) {
1138            $comment = 0;
1139            if ( defined($var) ) {
1140                $allVars->{$var} = @conf if ( defined($var) );
1141                push(@conf, {
1142                    text => $out,
1143                    var => $var,
1144                });
1145                $out = $_;
1146            } else {
1147                $out .= $_;
1148            }
1149            $var = $1;
1150	    $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<(.*);/ );
1151	    $endLine = $1 if ( /^\s*\$Conf\{[^}]*} *= *<<'(.*)';/ );
1152        } else {
1153	    $endLine = undef if ( defined($endLine) && /^\Q$endLine\E[\n\r]*$/ );
1154            $out .= $_;
1155        }
1156    }
1157    if ( $out ne "" ) {
1158        $allVars->{$var} = @conf if ( defined($var) );
1159        push(@conf, {
1160            text => $out,
1161            var  => $var,
1162        });
1163    }
1164    close(C);
1165    return (\@conf, $allVars);
1166}
1167
1168sub ConfigMerge
1169{
1170    my($old, $oldVars, $new, $newVars) = @_;
1171    my $posn = 0;
1172    my($res, $resVars);
1173
1174    #
1175    # Find which config parameters are not needed any longer
1176    #
1177    foreach my $var ( @$old ) {
1178        next if ( !defined($var->{var}) || defined($newVars->{$var->{var}}) );
1179        #print(STDERR "Deleting old config parameter $var->{var}\n");
1180        $var->{delete} = 1;
1181    }
1182    #
1183    # Find which config parameters are new
1184    #
1185    foreach my $var ( @$new ) {
1186        next if ( !defined($var->{var}) );
1187        if ( defined($oldVars->{$var->{var}}) ) {
1188            $posn = $oldVars->{$var->{var}};
1189        } else {
1190            #print(STDERR "New config parameter $var->{var}: $var->{text}\n");
1191            push(@{$old->[$posn]{new}}, $var);
1192        }
1193    }
1194    #
1195    # Create merged config file
1196    #
1197    foreach my $var ( @$old ) {
1198        next if ( $var->{delete} );
1199        push(@$res, $var);
1200        foreach my $new ( @{$var->{new}} ) {
1201            push(@$res, $new);
1202        }
1203    }
1204    for ( my $i = 0 ; $i < @$res ; $i++ ) {
1205        $resVars->{$res->[$i]{var}} = $i;
1206    }
1207    return ($res, $resVars);
1208}
1209
1210sub GetQuotes
1211{
1212    my($varName) = @_;
1213
1214    my $posn = $distVars->{$varName};
1215    $distConf->[$posn]->{text} =~ /^\s*\$Conf\{.*?\}(\s*=\s*['"]?).*?(['"]?\s*;)/mg;
1216    return ($1, $2);
1217}
1218
1219sub my_chown
1220{
1221    my($uid, $gid, $file) = @_;
1222
1223    return 1 if ( !$opts{"set-perms"} );
1224    return chown($uid, $gid, $file);
1225}
1226
1227sub my_chmod
1228{
1229    my ($mode, $file) = @_;
1230
1231    return 1 if ( !$opts{"set-perms"} );
1232    return chmod($mode, $file);
1233}
1234
1235sub prompt
1236{
1237    my($question, $default, $option) = @_;
1238
1239    $default = $opts{$option} if ( defined($opts{$option}) );
1240    if ( $opts{batch} ) {
1241        print("$question [$default]\n");
1242        return $default;
1243    }
1244    print("$question [$default]? ");
1245    my $reply = <STDIN>;
1246    $reply =~ s/[\n\r]*//g;
1247    return $reply if ( $reply !~ /^$/ );
1248    return $default;
1249}
1250
1251__END__
1252
1253=head1 SYNOPSIS
1254
1255configure.pl [options]
1256
1257=head1 DESCRIPTION
1258
1259configure.pl is a script that is used to install or upgrade a BackupPC
1260installation.  It is usually run interactively without arguments.  It
1261also supports a batch mode where all the options can be specified
1262via the command-line.
1263
1264For upgrading BackupPC you need to make sure that BackupPC is not
1265running prior to running BackupPC.
1266
1267Typically configure.pl needs to run as the super user (root).
1268
1269=head1 OPTIONS
1270
1271=over 8
1272
1273=item B<--batch>
1274
1275Run configure.pl in batch mode.  configure.pl will run without
1276prompting the user.  The other command-line options are used
1277to specify the settings that the user is usually prompted for.
1278
1279=item B<--backuppc-user=USER>
1280
1281Specify the BackupPC user name that owns all the BackupPC
1282files and runs the BackupPC programs.  Default is backuppc.
1283
1284=item B<--bin-path PROG=PATH>
1285
1286Specify the path for various external programs that BackupPC
1287uses.  Several --bin-path options may be specified.  configure.pl
1288usually finds sensible defaults based on searching the PATH.
1289The format is:
1290
1291    --bin-path PROG=PATH
1292
1293where PROG is one of perl, tar, smbclient, nmblookup, rsync, rsync_bpc,
1294ping, df, ssh, sendmail, hostname, split, par2, cat, gzip, bzip2 and
1295PATH is that full path to that program.
1296
1297Examples
1298
1299    --bin-path cat=/bin/cat --bin-path bzip2=/home/user/bzip2
1300
1301=item B<--compress-level=N>
1302
1303Set the configuration compression level to N.  Default is 3.
1304
1305=item B<--config-dir CONFIG_DIR>
1306
1307Configuration directory.  Defaults to /etc/BackupPC with FHS.
1308Automatically extracted from --config-path for existing installations.
1309
1310=item B<--config-override name=value>
1311
1312Override a specific configuration parameter.  Can be specified multiple
1313times.  "Name" is the parameter name and "value" is the exact text that
1314is inserted in the config.pl file (so you will need to escape quotes etc).
1315For example, to override $Conf{ServerHost} you would specify:
1316
1317    --config-override ServerHost=\"myhost\"
1318
1319=item B<--config-only>
1320
1321Do not install anything else, just create or update the config.pl and hosts
1322configuration files. This option can be used for automatic update of the
1323configuration after upgrading BackupPC using a package. With this option enabled
1324the configure.pl can be used separately from the rest of BackupPC distribution
1325files. In this case you should tell it where to look for installed BackupPC
1326files.
1327
1328So you will need to define the PERL5LIB environmental variable, for example for
1329Bourne shell:
1330
1331    PERL5LIB=/usr/local/lib; export PERL5LIB
1332    configure.pl --config-only
1333
1334or specify the path via Perl -I flag:
1335
1336    perl -I /usr/local/lib configure.pl
1337
1338=item B<--config-path CONFIG_PATH>
1339
1340Path to the existing config.pl configuration file for BackupPC.
1341This option should be specified for batch upgrades to an
1342existing installation.  The option should be omitted when
1343doing a batch new install.
1344
1345=item B<--cgi-dir CGI_DIR>
1346
1347Path to Apache's cgi-bin directory where the BackupPC_Admin
1348script will be installed.  This option only needs to be
1349specified for a batch new install.
1350
1351=item B<--scgi-port N>
1352
1353Numeric TCP port that is used for communication between Apache
1354and BackupPC_Admin_SCGI.  A negative value disables SCGI.
1355
1356=item B<--data-dir DATA_DIR>
1357
1358Path to the BackupPC data directory.  This is where all the backup
1359data is stored, and it should be on a large file system. This option
1360only needs to be specified for a batch new install.
1361
1362Example:
1363
1364    --data-dir /data/BackupPC
1365
1366=item B<--dest-dir DEST_DIR>
1367
1368An optional prefix to apply to all installation directories.  Usually this
1369is not needed, but is used by package creators, or certain auto-installers
1370that like to stage an install in a temporary directory, and then copy
1371the files to their real destination.  This option can be used to specify
1372the target directory prefix.  If you specify this option any existing
1373installation should be ignored.  Note that BackupPC won't run correctly if
1374you try to run it from below the --dest-dir directory, since all the paths
1375are set assuming BackupPC is installed in the intended final locations.
1376
1377=item B<--fhs>
1378
1379Use locations specified by the Filesystem Hierarchy Standard
1380for installing BackupPC.  This is enabled by default for new
1381installations.  To use the pre-3.0 installation locations,
1382specify --no-fhs.
1383
1384=item B<--help|?>
1385
1386Print a brief help message and exits.
1387
1388=item B<--hostname HOSTNAME>
1389
1390Host name (this machine's name) on which BackupPC is being installed.
1391This option only needs to be specified for a batch new install.
1392
1393=item B<--html-dir HTML_DIR>
1394
1395Path to an Apache html directory where various BackupPC image files
1396and the CSS files will be installed.  This is typically a directory
1397below Apache's DocumentRoot directory.  This option only needs to be
1398specified for a batch new install.
1399
1400Example:
1401
1402    --html-dir /var/www/htdocs/BackupPC
1403
1404=item B<--html-dir-url URL>
1405
1406The URL (without http://hostname) required to access the BackupPC html
1407directory specified with the --html-dir option.  This option only needs
1408to be specified for a batch new install.
1409
1410Example:
1411
1412    --html-dir-url /BackupPC
1413
1414=item B<--install-dir INSTALL_DIR>
1415
1416Installation directory for BackupPC scripts, libraries, and
1417documentation.  This option only needs to be specified for a
1418batch new install.
1419
1420Example:
1421
1422    --install-dir /usr/local/BackupPC
1423
1424=item B<--log-dir LOG_DIR>
1425
1426Log directory.  Defaults to /var/log/BackupPC with FHS.
1427
1428=item B<--man>
1429
1430Prints the manual page and exits.
1431
1432=item B<--run-dir RUN_DIR>
1433
1434Run directory.  Defaults to /var/run/BackupPC with FHS.
1435
1436=item B<--set-perms>
1437
1438When installing files and creating directories, chown them to
1439the BackupPC user and chmod them too.  This is enabled by default.
1440To disable (for example, if staging a destination directory)
1441then specify --no-set-perms.
1442
1443=item B<--uid-ignore>
1444
1445configure.pl verifies that the script is being run as the super user
1446(root).  Without the --uid-ignore option, in batch mode the script will
1447exit with an error if not run as the super user, and in interactive mode
1448the user will be prompted.  Specifying this option will cause the script
1449to continue even if the user id is not root.
1450
1451=back
1452
1453=head1 EXAMPLES
1454
1455For a standard interactive install, run without arguments:
1456
1457    configure.pl
1458
1459For a batch new install you need to specify answers to all the
1460questions that are normally prompted:
1461
1462    configure.pl                                   \
1463        --batch                                    \
1464        --cgi-dir /var/www/cgi-bin/BackupPC        \
1465        --data-dir /data/BackupPC                  \
1466        --hostname myHost                          \
1467        --html-dir /var/www/html/BackupPC          \
1468        --html-dir-url /BackupPC                   \
1469        --install-dir /usr/local/BackupPC
1470
1471For a batch upgrade, you only need to specify the path to the
1472configuration file:
1473
1474    configure.pl --batch --config-path /data/BackupPC/conf/config.pl
1475
1476=head1 AUTHOR
1477
1478Craig Barratt <cbarratt@users.sourceforge.net>
1479
1480=head1 COPYRIGHT
1481
1482Copyright (C) 2001-2010  Craig Barratt.
1483
1484This program is free software; you can redistribute it and/or modify
1485it under the terms of the GNU General Public License as published by
1486the Free Software Foundation; either version 2 of the License, or
1487(at your option) any later version.
1488
1489=cut
1490