#!/usr/bin/perl
#
# $Revision: 1.31.2.2 $
# Copyright Teleflora 2010
#
# Install OSTools onto a Teleflora POS Linux machine.
#
use strict;
use warnings;
use POSIX;
use Getopt::Long;
use File::Basename;
use English;

my $CVS_REVISION = '$Revision: 1.31.2.2 $';
my $TIMESTAMP = strftime("%Y%m%d%H%M%S", localtime());
my $PROGNAME = basename($0);

my $OS = "";
my $TOOLSDIR = "";
my $VERSION = 0;
my $HELP = 0;
my $RTI_PATCHES = 0;
my $DAISY_PATCHES = 0;
my $UPDATE = 0;
my $TFSERVER = "rtihardware.homelinux.com";
my $PACKAGE = "http://$TFSERVER/ostools/ostools-latest.tar.gz";
my $MSG_PREFIX = "OSTools v1.12.3";


GetOptions(
	"help" => \$HELP,
	"version" => \$VERSION,
	"rti_patches" => \$RTI_PATCHES,
	"daisy_patches" => \$DAISY_PATCHES,
	"update" => \$UPDATE,
) or exit(1);


# --version
if ($VERSION) {
	print("OSTools Version: 1.12.3\n");
	print("$PROGNAME $CVS_REVISION\n");
	exit(0);
}


# --help
if ($HELP) {
	print << "EOF";
Usage:
$PROGNAME --help
$PROGNAME --version
$PROGNAME --rti_patches
$PROGNAME --daisy_patches
$PROGNAME --update [ostools_pkg_file]
EOF

	exit(0);
}


# Are we running as root?
if($UID != 0) {
	print("Error: Must run via sudo.\n");
	exit(1);
}


# Allow user to specify where to pull ostools 'package' from.
# otherwise, we will default to the 'latest'.
if (defined($ARGV[0])) {
	if ($ARGV[0] ne "") {
		$PACKAGE = $ARGV[0];
	}
}

determine_os();

loginfo("Installation of OSTools 1.12.3");

#
# Which POS are we using? 
# Where is the root directory of said POS ?
# Ultimately, our ostools should reside under either:
# /d/ostools/bin/ /usr2/ostools/bin/ or /teleflora/ostools/bin/
#
if (-d "/d") {
	$TOOLSDIR="/d/ostools";
} elsif (-d "/usr2") {
	$TOOLSDIR="/usr2/ostools";
} elsif (-d "/teleflora") {
	$TOOLSDIR="/teleflora/ostools";
} else {
	# At this point, none of the expected dirs exist, so use the default.
	$TOOLSDIR="/teleflora/ostools";
}

# make the bin directory for the ostools scripts if necessary
unless (-d "$TOOLSDIR/bin") {
	loginfo("making directory \"$TOOLSDIR/bin\" for OSTools installation");
	system("mkdir -p $TOOLSDIR/bin");
	system("chown root:root $TOOLSDIR");
	system("chmod 775 $TOOLSDIR");
	system("chown root:root $TOOLSDIR/bin");
	system("chmod 775 $TOOLSDIR/bin");
}

# At this point, the install dir must exist, or we can't continue.
unless (-d "$TOOLSDIR/bin") {
	logerror("$TOOLSDIR/bin: directory does not exist... exiting");
	exit(1);
}

#
# If explicitly specified on the command line, just do the POS patches.
#
if ($RTI_PATCHES) {
	exit(install_rti_patches());
}

if ($DAISY_PATCHES) {
	exit(install_daisy_patches());
}


print("\n");
print("\n");
print("\n");
print("$PROGNAME $CVS_REVISION\n");
print("\n");
print("\n");
print("\n");
sleep(3);


# Either download the package or use a local package and
# install the various files.
if ($PACKAGE =~ /http/) {
	system("cd $TOOLSDIR && wget -O - $PACKAGE | tar -xzf -");
	if($? != 0) {
		logerror("download error of OSTools package: $PACKAGE");
		exit(1);
	}
} else {
	system("cat $PACKAGE | tar -C $TOOLSDIR -xzf -");
	if($? != 0) {
		logerror("install error of local OSTools package file: $PACKAGE");
		exit(1);
	}
}


loginfo("Installing OSTools Scripts...");

# install on all system other than RH72
if ($OS ne "RH72") {
	system("$TOOLSDIR/bin/tfremote.pl --install");
	system("$TOOLSDIR/bin/rtibackup.pl --install");
}

# install on daisy systems only
if (-f "/d/daisy") {
	system("perl $TOOLSDIR/bin/dsyperms.pl --install");
}

# for this release of OSTools, do not install the harden script on RTI systems.
if (-d "/usr2/bbx") {
    loginfo("$MSG_PREFIX: will not run \"harden_linux.pl --install\" on RTI system");
}
else {
    system("$TOOLSDIR/bin/harden_linux.pl --install");
}

system("$TOOLSDIR/bin/altiriscontrol.pl --install");


loginfo("Configuring CUPS...");

# RH72 does not use CUPS
if ($OS ne "RH72") {
	system("$TOOLSDIR/bin/updateos.pl --cupstmp");
	system("$TOOLSDIR/bin/updateos.pl --cupsconf");
}


# configure swap for all systems
loginfo("Configuring swap...");
system("$TOOLSDIR/bin/updateos.pl --swapon");


# make links from POS to OSTools if POS is installed
install_ostools_links();


loginfo("Setting permissions...");

# Run "perms" script to properly setup permissions on the script(s)
# which we just put into place.
if (-f "/usr2/bbx/bin/rtiperms.pl") {
	system("/usr2/bbx/bin/rtiperms.pl /usr2/bbx");

} elsif (-f "/d/daisy/bin/dsyperms.pl") {
	set_daisy_perms();
}

#
# This should not be necessary, but just to be sure...
#
# Check the owner of a representative file - if the file is not owned by
# "tfsupport", then either the POS *perms.pl script did not run or
# did not run correctly, so the perms must be set here.
#

my @stats = stat("$TOOLSDIR/bin/tfsupport.pl");
my $uid_fileowner = $stats[4];

my @pwent = getpwnam("tfsupport");
my $uid_tfsupport = (@pwent) ? $pwent[2] : -1;

if ( $uid_fileowner != $uid_tfsupport ) {

	system("chown root:root $TOOLSDIR/bin/*");
	system("chmod 775 $TOOLSDIR/bin/*");

	logwarning("perms set explicitly for scripts in $TOOLSDIR/bin");
}

#
# If on a daisy system, install any applicable patches.
#
if (-d "/d/daisy") {
	install_daisy_patches();
}

loginfo("Installation of OSTools 1.12.3 complete");

exit(0);

################################################################################

sub install_rti_patches
{
	return(0);
}

#
# Always remember - there can be multiple daisy db dirs!
#
sub install_ostools_links
{
	my $script_path;
	my $script_name;

	# Get a list of POS bin dirs, if any.
	my @dst_dirs = get_pos_bin_dirs();

	# If there are none, then nothing to do.
	unless (@dst_dirs) {
		return;
	}

	loginfo("Making symlinks from a POS to OSTools...");

	my @ostools_scripts = glob("$TOOLSDIR/bin/*.pl");
	foreach $script_path (@ostools_scripts) {

		$script_name = basename($script_path);

		foreach my $dst_dir (@dst_dirs) {

		    # for this release, don't install harden_linux.pl on a RTI system.
		    if ($dst_dir eq "/usr2/bbx/bin") {
			if ($script_name eq "harden_linux.pl") {
			    loginfo("$MSG_PREFIX: skipping symlink for harden_linux.pl");
			    next;
			}
		    }

		    system("rm -f $dst_dir/$script_name");
		    system("ln -sf $script_path $dst_dir");
		}
	}
}

sub get_pos_bin_dirs
{
	my @bin_dirs = ();

	# if RTI POS, then only one item in the list
	if (-d "/usr2/bbx/bin") {
		@bin_dirs = ("/usr2/bbx/bin");
		return(@bin_dirs);
	}

	# if not RIT or Daisy, then list is empty - should not happen
	unless (-d "/d/daisy/bin") {
		return(@bin_dirs);
	}

	# Daisy POS can have one or more bin dirs
	my @daisy_db_dirs = glob("/d/*");
	for my $daisy_db_dir (@daisy_db_dirs) {

		# must be a directory
		next unless (-d $daisy_db_dir);

		# skip old daisy dirs
		next if ($daisy_db_dir =~ /.+-\d{12}$/);

		# must contain the magic files
		next unless(-e "$daisy_db_dir/flordat.tel");
		next unless(-e "$daisy_db_dir/control.dsy");

		# must be daisy 8.0+
		next unless (-d "$daisy_db_dir/bin");

		push(@bin_dirs, "$daisy_db_dir/bin");
	}

	return(@bin_dirs);
}


#
# Run dsyperms.pl on all possible daisy database dirs... always remember
# that there can be multiple daisy database dirs!
#
# Look for all directories in "/d" that contain files named
# "flordat.tel" and "control.dsy".  Skip old dirs.
#
sub set_daisy_perms
{
	my $dsyperms_cmd = '/d/daisy/bin/dsyperms.pl';

	unless (-f $dsyperms_cmd) {
		logerror("expecting script to exist: $dsyperms_cmd");
		logerror("could not run: $dsyperms_cmd");
		return;
	}

	my @daisy_db_dirs = glob("/d/*");

	for my $daisy_db_dir (@daisy_db_dirs) {

		# must be a directory
		next unless (-d $daisy_db_dir);

		# skip old daisy dirs
		next if ($daisy_db_dir =~ /.+-\d{12}$/);

		# must contain the magic files
		next unless(-e "$daisy_db_dir/flordat.tel");
		next unless(-e "$daisy_db_dir/control.dsy");

		loginfo("Running $dsyperms_cmd $daisy_db_dir");
		system("perl $dsyperms_cmd $daisy_db_dir");
	}
}


sub install_daisy_patches
{
	my $daisy_version = "";

	# new version of dsyshell

	# get daisy version
	open(PIPE, "/d/daisy/bin/identify_daisy_distro.pl /d/daisy |");
	while(<PIPE>) {
		chomp;
		my @daisy_info = split(/ /);
		if (@daisy_info) {
			$daisy_version = $daisy_info[3];
			$daisy_version =~ s/[a-z]$//;
			my @build_nrs = split(/\./, $daisy_version);
			if ( ($build_nrs[0] > 8) ||
			     ($build_nrs[0] == 8 && $build_nrs[1] > 0) ||
			     ($build_nrs[0] == 8 && $build_nrs[1] == 0 && $build_nrs[2] > 24) ) {
				return;
			}

		} else {
			return;
		}
	}
	close(PIPE);

	my $platform = $OS;
	$platform = "RHEL5" if ($platform eq "RHWS5");
	my $url = "http://$TFSERVER/ostools/patches/dsyshell-$platform";
	my $dl_file_path = '/tmp/dsyshell';
	system("curl -o $dl_file_path $url");
	if ($? != 0) {
		logerror("download error of dsyshell for $platform: curl error");
		return;
	}
	system("grep \"404 Not Found\" $dl_file_path");
	if ($? == 0) {
		logerror("download error of $dl_file_path: file not found");
		return;
	}

	system("cp /d/daisy/bin/dsyshell /d/daisy/bin/dsyshell-$daisy_version");
	system("cp $dl_file_path /d/daisy/bin/dsyshell");
	system("chown tfsupport:daisy /d/daisy/bin/dsyshell");
	system("chmod 550 /d/daisy/bin/dsyshell");

	loginfo("dsyshell patched for daisy v$daisy_version for platform $platform");

	return;
}


#
# Sets global variable $OS to one of:
#	RH72  - Redhat Linux 7.2
#	FC3   - Fedora Core 3
#	FC4   - Fedora Core 4
#	FC5   - Fedora Core 5
#	RHEL4 - Redhat Enterprise Server 4
#	RHEL5 - Redhat Enterprise Server 5
#	RHWS5 - Redhat Enterprise Client Workstation 5

sub determine_os
{
	$OS = "";

	# We could also use /usr/bin/lsb-release
	open(FILE, "< /etc/redhat-release");
	while(<FILE>) {

		# Fedora Core 3
		if(/(Fedora)(\s+)(Core)(\s+)(release)(\s+)(3)/) {
			$OS = "FC3";
			last;
		}

		# Fedora Core 4
		if(/(Fedora)(\s+)(Core)(\s+)(release)(\s+)(4)/) {
			$OS = "FC4";
			last;
		}

		# Fedora Core 5
		if(/(Fedora)(\s+)(Core)(\s+)(release)(\s+)(5)/) {
			$OS = "FC5";
			last;
		}

		# ES 6
		# Redhat Enterprise Linux Server 6
		if( /(release)(\s+)(6)/ ) {
			$OS = "RHEL6";
			last;
		}

		# RHEL 5 Server
		if( (/(Server release)(\s+)(5)/)
		||  (/(CentOS)([[:print:]]+)(\s)(5)/) ) {
			$OS = "RHEL5";
			last;
		}

		# RHEL 5 Client Workstation
		if ( /(Client release)(\s+)(5)/ ) {
			$OS = "RHWS5";
			last;
		}

		# RHEL 4 Server
		if( (/(release)(\s+)(4)/) 
		||  (/(CentOS)([[:print:]]+)(\s)(4)/) ) {
			$OS = "RHEL4";
			last;
		}

		# Redhat 7.2
		if(/(release)(\s+)(7\.2)/) {
			$OS = "RH72";
			last;
		}
	}
	close(FILE);
}

sub loginfo
{
	my $msg = $_[0];

	print("$msg.\n");
	logit($msg, 'I');
}

sub logwarning
{
	my $msg = $_[0];

	print("Warning: $msg.\n");
	logit($msg, 'W');
}

sub logerror
{
	my $msg = $_[0];

	print("Error: $msg.\n");
	logit($msg, 'E');
}

sub logit
{
        my $msg = $_[0];
        my $msg_type = $_[1];
        my $tag = "$PROGNAME";

        system("/usr/bin/logger -i -t $tag -- \"$UID: <$msg_type> $msg\"");
}

