#!/usr/bin/perl

use strict;
use Net::Ping;
use File::Basename;

# if $debug is not 0, will work without changing anything
my($debug) = 0;

$debug && print <<EOF;
******************************************
*** DEBUGING MODE NO PERMANENT CHANGES ***
******************************************
EOF

# First read the existing settings
my $IFCFG_ETH0="/etc/sysconfig/network-scripts/ifcfg-eth0";
my $RESOLV_CONF="/etc/resolv.conf";

my %ifcfgeth0 = ();
my %resolvconf = ();



open(FILE, "$IFCFG_ETH0") || die "Unable to open file $IFCFG_ETH0: $!";
while (<FILE>) {
  chop;
  next if (/^[;#]/); # Skip comment line
  my ($param, $value) = /(\w+)\s*=\s*(.*)/;

  next if ($param eq "");

  $ifcfgeth0{$param} = $value;

}

open(FILE, "$RESOLV_CONF") || die "Unable to open file $RESOLV_CONF: $!";
while (<FILE>) {
  chop;
  next if (/^[;#]/); # Skip comment line
  my ($param, $value) = /(\w+)\s+(.*)/;

  next if ($param eq "");
  print "$param=$value\n";
  $resolvconf{$param} = $value;

}

# Display current settings

print "***************************************************\n";
print "******** CURRENT NETWORK CONFIGURATION ************\n";
print "***************************************************\n";
if ($ifcfgeth0{'BOOTPROTO'} eq "dhcp") {
  print "DHCP IP Address: ";
  system("/sbin/ifconfig eth0 | grep -w inet");
}
else {
  print "IP ADDRESS: " . $ifcfgeth0{'IPADDR'} . "\n";
  print "NETMASK   : " . $ifcfgeth0{'NETMASK'} . "\n";
  print "GATEWAY   : " . $ifcfgeth0{'GATEWAY'} . "\n";
  print "NAMESERVER: " . $resolvconf{'nameserver'} . "\n";
  print "DOMAIN    : " . $resolvconf{'domain'} . "\n";
}

print "\n";

print "***************************************************\n";
print "**** ASSIGN STATIC IP ADDRESS TO THE APPLIANCE ****\n";
print "***************************************************\n";
print "\n";
print "Continue ? [yes/no] : ";
my $choice = <>;
chop $choice;

if ($choice ne "yes") {
  print "Bye!\n";
  exit;
}

my $ip;
my $netmask;
my $gateway;

while (1) {
  $ip = takeInput("IP Address", 0);
  ($ip =~ /^\d+\.\d+\.\d+\.\d+$/) && last;
  print "invalid syntax '$ip'\nneed dotted quad like 192.168.123.17\n";
}


while (1) {
  $netmask = takeInput("Netmask", 0);
  ($netmask =~ /^\d+\.\d+\.\d+\.\d+$/) && last;
  print "invalid syntax '$netmask'\nneed dotted quad like 255.255.255.0\n";
}


while (1) {
  $gateway = takeInput("Gateway", 0);
  ($gateway =~ /^\d+\.\d+\.\d+\.\d+$/) && last;
  print "invalid syntax '$gateway'\nneed dotted quad like 192.168.123.1\n";
}

my $domainName = takeInput("Domain Name (Optional)", 1);
my $nameServer = takeInput("Name Server(Optional)", 1);

print "Apply changes? [yes/no]:  ";

$choice = <>;
chop $choice;

if ($choice eq "yes") {
  print "Applying changes ...\n";

  $ifcfgeth0{'IPADDR'} = $ip;
  $ifcfgeth0{'NETMASK'} = $netmask;
  $ifcfgeth0{'GATEWAY'} = $gateway;

  $ifcfgeth0{'BOOTPROTO'} = "STATIC";

  $resolvconf{'nameserver'} = $nameServer if ($nameServer ne "");
  $resolvconf{'domain'} = $domainName if ($domainName ne "");

  saveFile("=", $IFCFG_ETH0, %ifcfgeth0);
  saveFile(" ", $RESOLV_CONF, %resolvconf);

  print "Restarting network to apply changes ...\n";
  if ($debug) {
    print "*** DEBUG MODE NO CHANGES ***\n";
  } else {
    system("/etc/init.d/network restart");
  }

  # Now test if we can ping the gateway
  print "Testing if the gateway can be reached ...\n";

  my $p = Net::Ping->new( "icmp", 1, 64 );
  if ( $p->ping($gateway) ) {
    print "$gateway answered\n";
    print "Done!\n";
  } else {
    print "$gateway did not answer\n";
    print "Revert back to previous configuration? [yes/no]: ";
    my $choice = <>;
    chop $choice;

    if ($choice eq "yes") {
      if ($debug) {
	print "*** DEBUG MODE NO CHANGES ***\n";
      } else {
	system("cp /tmp/" . basename($IFCFG_ETH0) . ".$$ $IFCFG_ETH0");
	system("cp /tmp/" . basename($RESOLV_CONF) . ".$$ $RESOLV_CONF");
	system("/etc/init.d/network restart");
	print "Reverted back!\n";
      }
    }
  }
}
else {
  print "Changes not applied.\n";
}

print "Press Enter to quit this session";
my $choice = <>;


# Safely, via temp file and rename, save data to file, saving original
# to a backup copy. On success, return empty string.  On error, return
# error message.

sub saveFile {
  my ($separator, $fileName, %paramHash) = @_;

  if ($debug) {
    print "*** DEBUG MODE NO CHANGES to $fileName ***\n";
  }

  # Make a backup
  system("cp $fileName /tmp/" . basename($fileName) . ".$$");
  # save in temp file

  # note no pid in this filename,
  # assume one script runs at a time
  my($t) = "$fileName.tmp";

  open(FILE, ">$t") || return "can't write $t to $fileName: $!";

  print FILE "#Auto generated  by config-network.pl\n";

  foreach my $key (keys(%paramHash)) {
    print FILE "$key".$separator. $paramHash{$key} . "\n";
  }
  if (close(FILE)) {
    $debug && return '';
    rename($t, $fileName) && return '';
    return "can't rename $t to $fileName: $!";
  }
  return "can't write $t to $fileName: $!";
}

sub takeInput {
  my ($text, $optional) = @_;
  my ($input);

  while (1) {
    print "Enter $text: ";
    $input = <>;
    chop $input;
    next if (!$optional && $input eq "");
    last;
  }
  return $input;
}


