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