Imported both gpgdir and gpgwrap projects.
[pgp-tools.git] / gpgdir / install.pl
diff --git a/gpgdir/install.pl b/gpgdir/install.pl
new file mode 100755 (executable)
index 0000000..95def39
--- /dev/null
@@ -0,0 +1,450 @@
+#!/usr/bin/perl -w
+#
+####################################################################
+#
+# File: install.pl
+#
+# Purpose: To install gpgdir on a Linux system.
+#
+# Author: Michael Rash (mbr@cipherdyne.org)
+#
+# Copyright (C) 2002-2008 Michael Rash (mbr@cipherdyne.org)
+#
+# License (GNU Public License):
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program; if not, write to the Free Software
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+#    USA
+#
+####################################################################
+#
+# $Id: install.pl 311 2008-08-31 23:11:12Z mbr $
+#
+
+use Cwd;
+use File::Copy;
+use Getopt::Long;
+use strict;
+
+#======================= config =======================
+my $install_dir = '/usr/bin';
+my $libdir      = '/usr/lib/gpgdir';
+my $manpage     = 'gpgdir.1';
+
+### only used it $ENV{'HOME'} is not set for some reason
+my $config_homedir = '';
+
+### system binaries
+my $gzipCmd = '/usr/bin/gzip';
+my $perlCmd = '/usr/bin/perl';
+my $makeCmd = '/usr/bin/make';
+#===================== end config =====================
+
+my $print_help = 0;
+my $uninstall  = 0;
+my $force_mod_re  = '';
+my $exclude_mod_re  = '';
+my $skip_module_install   = 0;
+my $cmdline_force_install = 0;
+my $locale = 'C';  ### default LC_ALL env variable
+my $no_locale = 0;
+my $deps_dir  = 'deps';
+
+my %cmds = (
+    'gzip' => $gzipCmd,
+    'perl' => $perlCmd,
+    'make' => $makeCmd
+);
+
+### map perl modules to versions
+my %required_perl_modules = (
+    'Class::MethodMaker' => {
+        'force-install' => 0,
+        'mod-dir' => 'Class-MethodMaker'
+    },
+    'GnuPG::Interface' => {
+        'force-install' => 0,
+        'mod-dir' => 'GnuPG-Interface'
+    },
+    'Term::ReadKey' => {
+        'force-install' => 0,
+        'mod-dir' => 'TermReadKey'
+    }
+);
+
+### make Getopts case sensitive
+Getopt::Long::Configure('no_ignore_case');
+
+&usage(1) unless (GetOptions(
+    'force-mod-install' => \$cmdline_force_install,  ### force install of all modules
+    'Force-mod-regex=s' => \$force_mod_re,  ### force specific mod install with regex
+    'Exclude-mod-regex=s' => \$exclude_mod_re, ### exclude a particular perl module
+    'Skip-mod-install'  => \$skip_module_install,
+    'home-dir=s'        => \$config_homedir, ### force a specific home dir
+    'LC_ALL=s'          => \$locale,
+    'locale=s'          => \$locale,
+    'no-LC_ALL'         => \$no_locale,
+    'no-locale'         => \$no_locale,  ### synonym
+    'uninstall' => \$uninstall,      # Uninstall gpgdir.
+    'help'      => \$print_help      # Display help.
+));
+&usage(0) if $print_help;
+
+### set LC_ALL env variable
+$ENV{'LC_ALL'} = $locale unless $no_locale;
+
+$force_mod_re = qr|$force_mod_re| if $force_mod_re;
+$exclude_mod_re = qr|$exclude_mod_re| if $exclude_mod_re;
+
+### check to see if we are installing in a Cygwin environment
+my $non_root_user = 0;
+if (&is_cygwin()) {
+
+    print
+"[+] It looks like you are installing gpgdir in a Cygwin environment.\n";
+    $non_root_user = 1;
+
+} else {
+
+    unless ($< == 0 && $> == 0) {
+        print
+"[+] It looks like you are installing gpgdir as a non-root user, so gpgdir\n",
+"    will be installed in your local home directory.\n\n";
+
+        $non_root_user = 1;
+    }
+}
+
+if ($non_root_user) {
+
+    ### we are installing as a normal user instead of root, so see
+    ### if it is ok to install within the user's home directory
+    my $homedir = '';
+    if ($config_homedir) {
+        $homedir = $config_homedir;
+    } else {
+        $homedir = $ENV{'HOME'} or die '[*] Could not get home ',
+            "directory, set the $config_homedir var.";
+    }
+
+    print
+"    gpgdir will be installed at $homedir/bin/gpgdir, and a few\n",
+"    perl modules needed by gpgdir will be installed in $homedir/lib/gpgdir/.\n\n",
+
+    mkdir "$homedir/lib" unless -d "$homedir/lib";
+    $libdir = "$homedir/lib/gpgdir";
+    $install_dir = "$homedir/bin";
+}
+
+### make sure we can find the system binaries
+### in the expected locations.
+&check_commands();
+
+my $src_dir = getcwd() or die "[*] Could not get current working directory.";
+
+### create directories, make sure executables exist, etc.
+&setup();
+
+print "[+] Installing gpgdir in $install_dir\n";
+&install_gpgdir();
+
+### install perl modules
+unless ($skip_module_install) {
+    for my $module (keys %required_perl_modules) {
+        &install_perl_module($module);
+    }
+}
+chdir $src_dir or die "[*] Could not chdir $src_dir: $!";
+
+print "[+] Installing man page.\n";
+&install_manpage();
+
+print "\n    It is highly recommended to run the test suite in the test/\n",
+    "    directory to ensure proper gpgdir operation.\n",
+    "\n[+] gpgdir has been installed!\n";
+
+exit 0;
+#===================== end main =======================
+
+sub install_gpgdir() {
+    die "[*] gpgdir does not exist.  Download gpgdir from " .
+        "http://www.cipherdyne.org/gpgdir" unless -e 'gpgdir';
+    copy 'gpgdir', "${install_dir}/gpgdir" or die "[*] Could not copy " .
+        "gpgdir to $install_dir: $!";
+
+    if ($non_root_user) {
+        open F, "< ${install_dir}/gpgdir" or die "[*] Could not open ",
+            "${install_dir}/gpgdir: $!";
+        my @lines = <F>;
+        close F;
+        open P, "> ${install_dir}/gpgdir.tmp" or die "[*] Could not open ",
+            "${install_dir}/gpgdir.tmp: $!";
+        for my $line (@lines) {
+            ### change the lib dir to new homedir path
+            if ($line =~ m|^\s*use\s+lib\s+\'/usr/lib/gpgdir\';|) {
+                print P "use lib '", $libdir, "';\n";
+            } else {
+                print P $line;
+            }
+        }
+        close P;
+        move "${install_dir}/gpgdir.tmp", "${install_dir}/gpgdir" or
+            die "[*] Could not move ${install_dir}/gpgdir.tmp -> ",
+                "${install_dir}/gpgdir: $!";
+
+        chmod 0700, "${install_dir}/gpgdir" or die "[*] Could not set " .
+            "permissions on gpgdir to 0755";
+    } else {
+        chmod 0755, "${install_dir}/gpgdir" or die "[*] Could not set " .
+            "permissions on gpgdir to 0755";
+        chown 0, 0, "${install_dir}/gpgdir" or
+            die "[*] Could not chown 0,0,${install_dir}/gpgdir: $!";
+    }
+    return;
+}
+
+sub install_perl_module() {
+    my $mod_name = shift;
+
+    chdir $src_dir or die "[*] Could not chdir $src_dir: $!";
+    chdir $deps_dir or die "[*] Could not chdir($deps_dir): $!";
+
+    die '[*] Missing force-install key in required_perl_modules hash.'
+        unless defined $required_perl_modules{$mod_name}{'force-install'};
+    die '[*] Missing mod-dir key in required_perl_modules hash.'
+        unless defined $required_perl_modules{$mod_name}{'mod-dir'};
+
+    if ($exclude_mod_re and $exclude_mod_re =~ /$mod_name/) {
+        print "[+] Excluding installation of $mod_name module.\n";
+        return;
+    }
+
+    my $version = '(NA)';
+
+    my $mod_dir = $required_perl_modules{$mod_name}{'mod-dir'};
+
+    if (-e "$mod_dir/VERSION") {
+        open F, "< $mod_dir/VERSION" or
+            die "[*] Could not open $mod_dir/VERSION: $!";
+        $version = <F>;
+        close F;
+        chomp $version;
+    } else {
+        print "[-] Warning: VERSION file does not exist in $mod_dir\n";
+    }
+
+    my $install_module = 0;
+
+    if ($required_perl_modules{$mod_name}{'force-install'}
+            or $cmdline_force_install) {
+        ### install regardless of whether the module may already be
+        ### installed
+        $install_module = 1;
+    } elsif ($force_mod_re and $force_mod_re =~ /$mod_name/) {
+        print "[+] Forcing installation of $mod_name module.\n";
+        $install_module = 1;
+    } else {
+        if (has_perl_module($mod_name)) {
+            print "[+] Module $mod_name is already installed in the ",
+                "system perl tree, skipping.\n";
+        } else {
+            ### install the module in the /usr/lib/gpgdir directory because
+            ### it is not already installed.
+            $install_module = 1;
+        }
+    }
+
+    if ($install_module) {
+        unless (-d $libdir) {
+            print "[+] Creating $libdir\n";
+            mkdir $libdir, 0755 or die "[*] Could not mkdir $libdir: $!";
+        }
+        print "[+] Installing the $mod_name $version perl " .
+            "module in $libdir/\n";
+        my $mod_dir = $required_perl_modules{$mod_name}{'mod-dir'};
+        chdir $mod_dir or die "[*] Could not chdir to ",
+            "$mod_dir: $!";
+        unless (-e 'Makefile.PL') {
+            die "[*] Your $mod_name source directory appears to be incomplete!\n",
+                "    Download the latest sources from ",
+                "http://www.cipherdyne.org/\n";
+        }
+        system "$cmds{'make'} clean" if -e 'Makefile';
+        system "$cmds{'perl'} Makefile.PL PREFIX=$libdir LIB=$libdir";
+        system $cmds{'make'};
+#        system "$cmds{'make'} test";
+        system "$cmds{'make'} install";
+        chdir $src_dir or die "[*] Could not chdir $src_dir: $!";
+
+        print "\n\n";
+    }
+    chdir $src_dir or die "[*] Could not chdir $src_dir: $!";
+    return;
+}
+
+sub has_perl_module() {
+    my $module = shift;
+
+    # 5.8.0 has a bug with require Foo::Bar alone in an eval, so an
+    # extra statement is a workaround.
+    my $file = "$module.pm";
+    $file =~ s{::}{/}g;
+    eval { require $file };
+
+    return $@ ? 0 : 1;
+}
+
+sub install_manpage() {
+
+    if ($non_root_user) {
+        print
+"[+] Because this is a non-root install, the man page will not be installed\n",
+"    but you can download it here:  http://www.cipherdyne.org/gpgdir\n\n";
+        return;
+    }
+
+    die "[*] man page: $manpage does not exist.  Download gpgdir " .
+        "from http://www.cipherdyne.org/gpgdir" unless -e $manpage;
+    ### default location to put the gpgdir man page, but check with
+    ### /etc/man.config
+    my $mpath = '/usr/share/man/man1';
+    if (-e '/etc/man.config') {
+        ### prefer to install $manpage in /usr/local/man/man1 if
+        ### this directory is configured in /etc/man.config
+        open M, '< /etc/man.config' or
+            die "[*] Could not open /etc/man.config: $!";
+        my @lines = <M>;
+        close M;
+        ### prefer the path "/usr/share/man"
+        my $found = 0;
+        for my $line (@lines) {
+            chomp $line;
+            if ($line =~ m|^MANPATH\s+/usr/share/man|) {
+                $found = 1;
+                last;
+            }
+        }
+        ### try to find "/usr/local/man" if we didn't find /usr/share/man
+        unless ($found) {
+            for my $line (@lines) {
+                chomp $line;
+                if ($line =~ m|^MANPATH\s+/usr/local/man|) {
+                    $mpath = '/usr/local/man/man1';
+                    $found = 1;
+                    last;
+                }
+            }
+        }
+        ### if we still have not found one of the above man paths,
+        ### just select the first one out of /etc/man.config
+        unless ($found) {
+            for my $line (@lines) {
+                chomp $line;
+                if ($line =~ m|^MANPATH\s+(\S+)|) {
+                    $mpath = $1;
+                    last;
+                }
+            }
+        }
+    }
+    mkdir $mpath, 0755 unless -d $mpath;
+    my $mfile = "${mpath}/${manpage}";
+    print "[+] Installing $manpage man page as: $mfile\n";
+    copy $manpage, $mfile or die "[*] Could not copy $manpage to " .
+        "$mfile: $!";
+    chmod 0644, $mfile or die "[*] Could not set permissions on ".
+        "$mfile to 0644";
+    chown 0, 0, $mfile or
+        die "[*] Could not chown 0,0,$mfile: $!";
+    print "[+] Compressing man page: $mfile\n";
+    ### remove the old one so gzip doesn't prompt us
+    unlink "${mfile}.gz" if -e "${mfile}.gz";
+    system "$cmds{'gzip'} $mfile";
+    return;
+}
+
+### check paths to commands and attempt to correct if any are wrong.
+sub check_commands() {
+    my @path = qw(
+        /bin
+        /sbin
+        /usr/bin
+        /usr/sbin
+        /usr/local/bin
+        /usr/local/sbin
+    );
+    CMD: for my $cmd (keys %cmds) {
+        unless (-x $cmds{$cmd}) {
+            my $found = 0;
+            PATH: for my $dir (@path) {
+                if (-x "${dir}/${cmd}") {
+                    $cmds{$cmd} = "${dir}/${cmd}";
+                    $found = 1;
+                    last PATH;
+                }
+            }
+            unless ($found) {
+                die "[*] Could not find $cmd anywhere!!!  ",
+                    "Please edit the config section to include the path to ",
+                    "$cmd.\n";
+            }
+        }
+        unless (-x $cmds{$cmd}) {
+            die "[*] $cmd is located at ",
+                "$cmds{$cmd} but is not executable by uid: $<\n";
+        }
+    }
+    return;
+}
+
+sub is_cygwin() {
+
+    my $rv = 0;
+
+    ### get OS output from uname
+    open UNAME, "uname -o |" or return $rv;
+    while (<UNAME>) {
+        $rv = 1 if /Cygwin/;
+    }
+    close UNAME;
+
+    return $rv;
+}
+
+
+sub setup() {
+    unless (-d $libdir) {
+        mkdir $libdir, 0755 or die "[*] Could not create $libdir: $!"
+    }
+    return;
+}
+
+sub usage() {
+    my $exit_status = shift;
+    print <<_HELP_;
+
+Usage: install.pl [options]
+
+    -u,  --uninstall             - Uninstall gpgdir.
+    -f, --force-mod-install      - Force all perl modules to be installed
+                                   even if some already exist in the system
+                                   /usr/lib/perl5 tree.
+    -F, --Force-mod-regex <re>   - Specify a regex to match a module name
+                                   and force the installation of such modules.
+    -E, --Exclude-mod-regex <re> - Exclude a perl module that matches this
+                                   regular expression.
+    -S, --Skip-mod-install       - Do not install any perl modules.
+
+    -L, --LANG <locale>          - Specify LANG env variable (actually the
+                                   LC_ALL variable).
+    -h  --help                   - Prints this help message.
+
+_HELP_
+    exit $exit_status;
+}