#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html

BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; }

use Getopt::Long;

use lib "$::XCATROOT/lib/perl";
use Cwd;
use File::Basename;
use xCAT::Client;
use xCAT::MsgUtils;
use xCAT::Usage;
use strict;

sub updatenode_usage
{
    my $usage_string = xCAT::Usage->getUsage("updatenode");
    print "$usage_string\n";
}

my $bname = basename($0);
my $cmdref;
$cmdref->{command}->[0] = $bname;
$cmdref->{cwd}->[0]     = cwd();
my $data;

# allows our plugins to get the stdin of the cmd that invoked the plugin
if ((($^O =~ /^linux/i) && ($ENV{'SHELL'} =~ /\/ksh$/)) || !defined($ENV{'TERM'}))
{
    my $rin = "";
    my $rout;
    vec($rin, fileno(STDIN), 1) = 1;
    my $nfound = select($rout = $rin, "", "", 1);
    if ($nfound)
    {
        while (<STDIN>) { $data .= $_; }
        $cmdref->{stdin}->[0] = $data;
    }
}
else
{
    if (-p STDIN) {
        while (<STDIN>) { $data .= $_; }
        $cmdref->{stdin}->[0] = $data;
    }
}


Getopt::Long::Configure("posix_default");
Getopt::Long::Configure("no_gnu_compat");
Getopt::Long::Configure("bundling");

my $tmp = " " . join(' ', @ARGV);
if (!($tmp =~ / (--help|-h|-v|--version)/)) {
    my $arg = shift(@ARGV);

    # Set the noderange
    if ($arg !~ /^-/) {
        my @tempnr = ();
        foreach my $nr (split(/,/, $arg)) {
            if ($nr =~ /^\^(.*)$/) {
                my $nrf = $1;
                if ($nrf !~ /^\//) {    #relative path
                    $nrf = Cwd::abs_path($nrf);
                }
                $nrf = "\^" . $nrf;
                push @tempnr, $nrf;
            } else {
                push @tempnr, $nr;
            }
        }
        $arg = join(',', @tempnr);
        $cmdref->{noderange}->[0] = $arg;
    } else {
        &updatenode_usage();
        print "The noderange should be the first argument.\n";
        exit 1;
    }
}

push(@{ $cmdref->{arg} }, @ARGV);

# check the syntax
my ($ALLSW, $CMDLINE, $ALTSRC, $HELP, $VERSION, $VERBOSE, $FILESYNC, $GENMYPOST, $USER, $SNFILESYNC, $SWMAINTENANCE, $SETSERVER, $RERUNPS, $SECURITY, $OS, $fanout, $timeout, $NOVERIFY);
if (
    !GetOptions(
        'A|updateallsw' => \$ALLSW,
        'c|cmdlineonly' => \$CMDLINE,
        'd=s'           => \$ALTSRC,
        'h|help'        => \$HELP,
        'v|version'     => \$VERSION,
        'V|verbose'     => \$VERBOSE,
        'F|sync'        => \$FILESYNC,
        'g|genmypost'   => \$GENMYPOST,
        'f|snsync'      => \$SNFILESYNC,
        'l|user=s'      => \$USER,
        'S|sw'          => \$SWMAINTENANCE,
        's|sn'          => \$SETSERVER,
        'P|scripts:s'   => \$RERUNPS,
        'k|security'    => \$SECURITY,
        'o|os=s'        => \$OS,
        'fanout=i'      => \$fanout,
        't|timetout=i'  => \$timeout,
        'n|noverify'    => \$NOVERIFY,
    )
  ) {
    &updatenode_usage();
    exit 1;
}

if ($HELP)
{
    &updatenode_usage();
    exit 0;
}
if (($USER) && ($SECURITY))
{
    my $msg = "-l option is not allowed with -k option.";
    xCAT::MsgUtils->message("E", $msg);
    exit 1;
}
if (($USER) && ($SNFILESYNC))
{
    my $msg = "-l option is not allowed with -f options.";
    xCAT::MsgUtils->message("E", $msg);
    exit 1;
}

# display the version statement if -v or --verison is specified
if ($VERSION)
{
    my $version = xCAT::Utils->Version();
    print "$version\n";
    exit 0;
}
if (($FILESYNC) && ($SNFILESYNC)) {    # only one
    my $msg = "Choose either -f to sync the service nodes, or -F  to sync the nodes not both.";
    xCAT::MsgUtils->message("E", $msg);
    exit 1;
}
if (($SECURITY) && (($SWMAINTENANCE) || defined($RERUNPS) || ($FILESYNC) || ($SNFILESYNC))) {
    my $msg = "If you use the -k flag, you cannot specify the -S,-P,-f or -F flags.";
    xCAT::MsgUtils->message("E", $msg);
    exit 1;
}

if ($SNFILESYNC && ($SWMAINTENANCE || defined($RERUNPS) || $SECURITY || $FILESYNC)) {
    my $msg = "If you specify the -f flag you must not specify either the -S or -k or -P or -F flags";
    xCAT::MsgUtils->message("E", $msg);
    exit 1;
}

# determine who is running the command on the client and who we will run as
# on the node
my $current_userid = getpwuid($>);
$ENV{DSH_FROM_USERID} = $current_userid;
my $to_userid;
if ($USER)    # entered -l
{
    $to_userid = $USER;
}
else
{
    $to_userid = $current_userid;
}
$ENV{DSH_TO_USERID} = $to_userid;

# if -k then we have to get the password
if ($SECURITY) {
    my $msg;
    if (!($ENV{'DSH_REMOTE_PASSWORD'}))
    {    # if not already set
         # prompt for the password for the userid on the node that will be setup
        my $userpw;
        $msg =
"The ssh keys will be updated for '$to_userid' on the node(s).\nPassword:";
        xCAT::MsgUtils->message("I", $msg);
        system("stty -echo");    # turn off keyboard
        chop($userpw = <STDIN>);
        system("stty echo");     # turn on keyboard

        if ($userpw eq "")
        {                        # did not enter a password
            $msg = "Did not enter a password will abort the security update.";
            xCAT::MsgUtils->message("E", $msg);
            exit 2;
        }
        else
        {                        # password entered pass to the server
            $ENV{DSH_REMOTE_PASSWORD} = $userpw;

        }
    }
}

foreach (keys %ENV) {
    if (/^DSH_/ || /^XCAT/) {
        push @{ $cmdref->{environment} }, "$_=$ENV{$_}";
    }
}

# Allow to print server information when -V/--verbose
foreach (reverse(@ARGV)) {
    if ($_ eq '-V' || $_ eq '--verbose') {
        $ENV{'XCATSHOWSVR'} = 1;
        last;
    }
}

xCAT::Client::submit_request($cmdref, \&xCAT::Client::handle_response);
exit $xCAT::Client::EXITCODE;
