#! /usr/bin/perl

#ident "$Id: prepare-master,v 1.83 2015/07/07 08:35:34 carsten.kuhl Exp $ Copyright (c) 2013 Bruker BioSpin GmbH";

use strict;
use English;
use Getopt::Long;
use Pod::Usage;
use File::Find ();
use File::Basename;
use File::Path;
use File::Copy;
use Sys::Syslog qw(:standard :macros);  # standard functions & macros
use IO::Socket::INET;

my $program = basename($0);

# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

###
# Function prototypes
sub get_os_version;
sub GetSmbiosSerialNumber;
sub EditIfcfgFiles();
sub get_local_ip_address;
sub remove_dot_topspin;
sub remove_broken_bruker_links;
sub all_ifcg_eth_files;
sub installed_program_versions(@);
sub search_user_history_files;
sub search_mozilla_history;
sub search_old_var_log_files;
sub search_user_mail;
sub mozilla_cache;

sub doexec ($@);
sub create_rpm_package;
sub clear_abrt_reports;
sub clear_dhcp_lease;
sub restore_ntp_conf;
sub clear_etc_host;
sub disable_bruker_repos;
sub enable_required_services;
sub disable_kudzu_service;

sub boolean($) {my $var=shift; return $var ? 'true' : 'false'; }


####
# Supported options
my $verbose = 0;
my $help = 0;
my $man = 0;
my $test = 0;
my $rpmpkg = 1;
my $sshkeys = 1;
my $archive = 1;
my $restore = 0;

GetOptions(
	   'help|?' => \$help,
	   'man'  => \$man,
	   'verbose+'  => \$verbose,
	   'test'  => \$test,
	   'rpmpkg!'  => \$rpmpkg,
	   'sshkeys!'  => \$sshkeys,
	   'archive!'  => \$archive,
	   'restore'  => \$restore,

	  ) || pod2usage(2);
pod2usage(1) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;


my $revision = '$Revision: 1.83 $';
my $version = $1 if $revision =~ /\s([\d\.]*)/;
my $dmi ='/usr/sbin/dmidecode';
####
# Backup Network files
my $archived_network_files = '/tmp/prepare_master_network_files.tar.bz2';

my $tar_c_options = '--create --bzip2 --selinux --absolute-names --ignore-failed-read --file';
my $tar_x_options = '--extract --bzip2 --preserve-permissions --absolute-names  --file';

my $OS_Version = get_os_version();

print "$program (version ",$version,")\n","Copyright (c) 2015 Bruker BioSpin GmbH\n";

if ($EUID != 0)
{
  $test = 1;
  $verbose = 1;
  print "\nStarted as non-root: verbose and testmode on!\n";

}
if ($verbose)
	    {
		print "\nFlags:\n";
		print '  $help    '," = ",boolean($help),"\n";
		print '  $man     '," = ",boolean($man),"\n";
		print '  $verbose '," = ",boolean($verbose),"\n";
		print '  $test    '," = ",boolean($test),"\n";
		print '  $rpmpkg  '," = ",boolean($rpmpkg),"\n";
		print '  $sshkeys '," = ",boolean($sshkeys),"\n";
		print '  $archive '," = ",boolean($archive),"\n";
		print '  $restore '," = ",boolean($restore),"\n";
		print "\n";
	    }

if ($restore)
{
    system("tar $tar_x_options $archived_network_files");
    exit 0;
}

###
# Use syslog for reports
openlog('bruker-setup', 'nofatal,pid', 'user');

syslog(LOG_INFO,"$program Version $version");


my @rwx = qw(--- --x -w- -wx r-- r-x rw- rwx);
my @moname = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my (%uid, %user);
while (my ($name, $pw, $uid) = getpwent) {
    $user{$uid} = $name unless exists $user{$uid};
}

my (%gid, %group);
while (my ($name, $pw, $gid) = getgrent) {
    $group{$gid} = $name unless exists $group{$gid};
}

my $SSH_DIR = '/etc/ssh';
my @SSH_FILES = (
	"$SSH_DIR/ssh_host_key",
	"$SSH_DIR/ssh_host_key.pub",
	"$SSH_DIR/ssh_host_rsa_key",
	"$SSH_DIR/ssh_host_rsa_key.pub",
	"$SSH_DIR/ssh_host_dsa_key",
	"$SSH_DIR/ssh_host_dsa_key.pub",
	"/root/.ssh/authorized_keys",
	"/root/.ssh/known_hosts",
	"/usr/NX/home/nx/.ssh/known_hosts",
	);

my $SSL_DIR = '/usr/share/ssl/certs';
my @SSL_FILES = (
	"$SSL_DIR/ipop3d.pem",
	"$SSL_DIR/imapd.pem",
	);

my @TOPSPIN_FILES = (
	'/usr/local/flexlm/Bruker/licenses/license.dat',
		     '/etc/profile.d/flexlm_license.sh',
	);

my @NETWORK_FILES = (
	'/etc/resolv.conf',
        '/etc/dhclient-eth0.conf',
	'/etc/sysconfig/networking/profiles/default/network',
	'/etc/sysconfig/networking/profiles/default/resolv.conf',
	);

if ($OS_Version < 7)
{
    ####
    # append with all ifcfg-eth* files
    print "Search ifcg_eth? FILES\n" if  $verbose;
    File::Find::find({wanted => \&all_ifcg_eth_files},'/etc/sysconfig');
}
else
{
    EditIfcfgFiles();
}

####
# Files from bruker-setup services
my @BRUKER_FILES = (
		    '/.default-hostname',
		    '/root/bin/mk-changes',
		    '/root/bin/mount_pub',
		    '/etc/sysconfig/bruker-setup',
		    '/etc/sysconfig/hwconf',
  );

####
# and unwanted files in home directories
print "Search history FILES\n" if  $verbose;
my @HISTORY_FILES =();
File::Find::find({wanted => \&search_mozilla_history}, '/home','/root');
File::Find::find({wanted => \&search_user_history_files},'/home','/root');
print "@HISTORY_FILES\n" if  $verbose;

####
# and unwanted files in /var/log and subdirs
print "Search old  FILES\n" if  $verbose;
my @SYSTEM_FILES =();
File::Find::find({wanted => \&search_old_var_log_files},'/var/log');
my @USER_MAIL = search_user_mail();
push(@SYSTEM_FILES,@USER_MAIL) if @USER_MAIL;
print "@SYSTEM_FILES\n" if  $verbose;

####
# Find and remove mozilla cache
my @MOZCACHE;
File::Find::find({wanted => \&mozilla_cache}, '/home','/root');
doexec('rm','-rf',@MOZCACHE) if (@MOZCACHE);

my $file;
my @Files;
my @Directories;
my @REMOVE;

###
# update oui.txt for Vendor MAC List
###
updateOuiText() if ($OS_Version < 7);


###
# option 'nosshkeys' : emty @SSH_FILES and @SSL_FILES
if (not $sshkeys)
{
    @SSH_FILES = ();
    @SSL_FILES = ();
}


push (@REMOVE,@BRUKER_FILES,@HISTORY_FILES,@SYSTEM_FILES,@SSH_FILES,@SSL_FILES,@TOPSPIN_FILES,@NETWORK_FILES);
push (my @TARFILES,@BRUKER_FILES,@SSH_FILES,@SSL_FILES,@TOPSPIN_FILES,@NETWORK_FILES);

if ($verbose)
{
    print "Files to be removed:\n";
    foreach $file (@REMOVE)
    {
	ls($file) if -f $file;
    }
}

###
# create archive of all files to be removed
###
system("tar $tar_c_options $archived_network_files @TARFILES 2> /dev/null")if $archive;
print "Backup of network files created '$archived_network_files'\n" if ($archive and $verbose);

clear_abrt_reports();
clear_dhcp_lease();
restore_ntp_conf();
clear_etc_host;

enable_required_services();
disable_kudzu_service();
cleanEfiBootMBR();

print "Removing files to prepare Master image " .
  ($test ? ' == test only ==' : '') . "\n";

# Traverse desired filesystems
File::Find::find({wanted => \&remove_dot_topspin}, '/home');

File::Find::find({wanted => \&remove_dot_teamviewer}, '/home');

File::Find::find({wanted => \&remove_broken_bruker_links}, '/usr/share/applications');

create_rpm_package() if $rpmpkg;

foreach $file (@REMOVE)
{
    next unless -f $file;
    print " $file\n";
    unlink($file)  || warn "\t$file: $!\n" unless $test;
}

closelog();

####
# Disable Network on Next boot (wil be reenabled by bruker-setup service)
####
if ($OS_Version < 7)
{
    my $network = '/etc/sysconfig/network';
    open(NETWORK, ">$network") or die "Cannot open $network: $!";
    print NETWORK "NETWORKING=no\n";
    close(NETWORK) ;
}

if (open(FD,"rpm -q --queryformat='%{RELEASE}' bruker-setup-release|"))
{
    my $bim_bersion = <FD>;
    close FD;
    print "\nRelease of this Bruker Image is:\n\t$bim_bersion\n\n";
}

exit;

################
#              #
# Soubroutines #
#              #
################
sub cleanEfiBootMBR
{
    my $msg = "Clean efibootmbr of duplicate entries from bootorder";
    syslog(LOG_INFO,$msg);
    system("efibootmbr -D -q");
}

sub get_os_version
{
    my $querycmd = 'rpm -qf --queryformat %{Name} /etc/redhat-release';
    my $redhat = `$querycmd`;
    chomp $redhat;
    $querycmd = 'rpm -q --queryformat %{version} ' . $redhat;
    my $redhat_release = `$querycmd`;
    my $rh_release  = (int $redhat_release);
    return $rh_release;
}

sub GetSmbiosSerialNumber
{
    open(DMI,"$dmi -t1|") || die "can't pipe to $dmi: $!\n";
    {
	my $ser_num;
	my $product;
	my $model;

	while (<DMI>)
	{
	    print STDERR if $verbose > 1;

	    if ( /Serial Number:\s(\w+)/ )
	    {
		$ser_num = $1;
		my $msg = '$'."ser_num = $ser_num";
		print STDERR $msg,"\n" if $verbose;
		syslog(LOG_INFO, $msg);
	    }
	    if ( /Serial Number: VMware-(.*)\n/ )
	    {
		$ser_num = 'VM' . substr(md5_hex($1),0,8);
		my $msg = '$'."ser_num = $ser_num";
		print STDERR $msg,"\n" if $verbose;
		syslog(LOG_INFO, $msg);
	    }

	    if ( /Product Name:\s(.*)/ )
	    {
		$product = $1;
		print STDERR '$',"product = $product\n" if $verbose;

		if ($product  =~ (/^hp workstation (xw4100|xw4200|xw5000)/))
		{
		    $model = $1;
		}
		if ($product  =~ (/^HP\s*(xw4300|xw4400|Z400|Z420)\s*Workstation/))
		{
		    $model = $1;
		}
		if ($product  =~ (/^VMware Virtual Platform/))
		{
		    use Digest::MD5 qw(md5_hex);
		    if ( /Serial Number: VMware-(.*)\n/ )
		    {
			$ser_num = 'VM' . substr(md5_hex($1),0,8);
		    }
		}
	    }
	    if ($product  =~ (/^VirtualBox/))
	    {
		if ( /UUID:\s*([\dA-Z]*)/ )
		{
		    $ser_num = 'VB' . $1;
		}
	    }
	}
	close(DMI);
	return $ser_num;
    }
    return;
}


# This idea was stolen from Net::Address::IP::Local::connected_to()
sub get_local_ip_address
{
    my $socket = IO::Socket::INET->new(
				       Proto       => 'udp',
				       PeerAddr    => '198.41.0.4', # a.root-servers.net
				       PeerPort    => '53', # DNS
				      );

    return '127.0.0.1' unless $socket;
    # A side-effect of making a socket connection is that our IP address
    # is available from the 'sockhost' method
    my $local_ip_address = $socket->sockhost;

    return $local_ip_address;
}

sub updateOuiText()
{
    my $local_ip_address = get_local_ip_address();

    return if $local_ip_address eq '127.0.0.1';

    my $silent = '-q';
    my $overwrite = '-N';
    my $bruker_oui_dir= '/usr/share/bruker-setup/';

    $silent = ''  if ($verbose);

    chdir $bruker_oui_dir;
    print "\nUpdate /usr/share/bruker-setup/oui.txt\n\n ... please wait ....\n";

    system("wget $silent $overwrite http://standards-oui.ieee.org/oui.txt");
}

sub EditIfcfgFiles()
{
    my $sysclass	= '/sys/class/net';
    opendir(NET,$sysclass) || die "can't open to $sysclass: $!\n";
    my @ethdevs = grep(!/^\./, readdir(NET));
    closedir(NET);

    print "Found Ether Devices: @ethdevs\n" if $verbose;

    my $netcfg	= '/etc/sysconfig/network-scripts/ifcfg';

    foreach my $dev (@ethdevs)
    {
	# check for physical devs
	my $linkname = readlink(join('/',$sysclass,$dev));
	next if ($linkname =~ /virtual\/net/); # skip virtual

	print "$linkname\n" if $verbose;
	my $addrpath = join('/',$sysclass,$dev, 'address');
	open(ADR,$addrpath) || die "can't open to $addrpath: $!\n";
	my $addr = <ADR>;
	close(ADR);
	chomp $addr;
	print "$addr\n" if $verbose;

	if ( $dev eq 'eno1')
	{
	    my $file = join('-',$netcfg,$dev);
	    open(CFG,"$file")  || die "$file: $!\n";
	    my @lines = <CFG>;
	    close(CFG);

	    my $netifnames = 0;
	    open(CFG,">$file")  || die "$file: $!\n";
	    foreach my $line (@lines)
	    {
		###
		# remove HWADDR if present
		next if ($line =~ /^HWADDR=/);

		if ($line =~ /^NAME=/)
		{
		    print CFG 'NAME="Spectrometer Network"'."\n";
		    print "\n" if $verbose;
		    next;
		}
		print CFG $line;
	    }
	    close(CFG);

	}
    }
    #manuel edit of ens1
    my $dev = "ens1";
    my $file = join('-',$netcfg,$dev);
    open(CFG,"$file")  || die "$file: $!\n";
    my @lines = <CFG>;
    close(CFG);

    open(CFG,">$file")  || die "$file: $!\n";
    foreach my $line (@lines)
    {
		###
		# remove HWADDR if present
		next if ($line =~ /^HWADDR=/);
		print CFG $line;
    }
    close(CFG);
}

sub remove_dot_topspin {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);
    my $search = '\.topspin-.*\z';
    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    -d _ &&
    /^$search/s &&
    doexec('rm','-rf','{}');

}

sub remove_dot_teamviewer {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);
    my $search = '\.teamviewer';
    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    -d _ &&
    /^$search/s &&
    doexec('rm','-rf','{}');

}

sub remove_broken_bruker_links {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    /^bruker-.*\z/s &&
    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    -l _
    && ! -f readlink($name) 
       && unlink($name) && syslog(LOG_INFO,"broken link $name removed");
}

sub all_ifcg_eth_files {
    /^ifcfg-eth.*\z/s
    && push(@NETWORK_FILES,$name);

}

sub installed_program_versions(@)
{
    print "@_\n";
    my $BAS_DIR = shift;
    my $prog = shift;

    opendir(DIR,$BAS_DIR) || return;
    my @subdir = grep(/^$prog/, readdir(DIR));
    closedir(DIR);
    my @PROGRAM =();
    foreach (@subdir)
    {
	push(@PROGRAM,join('/',$BAS_DIR,$_));
    }
    return @PROGRAM;
}

sub doexec ($@) {
    my @command = @_; # copy so we don't try to s/// aliases to constants
    for my $word (@command)
    {
	$word =~ s#{}#$name#g;
    }

    if ($verbose)
    {
	print "=> system(@command)\n"
    }
    else
    {
	print " $name\n";
    }
    return 1 if $test;
    system @command;
    return !$?;
}

sub search_user_history_files {
    /^\.recently-used.*\z/s
    && push(@HISTORY_FILES,$name);
    /^\.bash_history\z/s
    && push(@HISTORY_FILES,$name);
    /^known_hosts\z/s
    && push(@HISTORY_FILES,$name);
    /^nedit\.history\z/s
    && push(@HISTORY_FILES,$name);
    /^konq_history\z/s 
    && push(@HISTORY_FILES,$name);
}

sub search_mozilla_history {
    /^sessionstore\..*\z/s
        && push(@HISTORY_FILES,$name);

    /^places\.sqlite.*\z/s
        &&    push(@HISTORY_FILES,$name);

    /^downloads\.sqlite\z/s
        &&    push(@HISTORY_FILES,$name);

    /^cookies\.sqlite.*\z/s
        &&    push(@HISTORY_FILES,$name);

    /^formhistory\.sqlite\z/s
        &&    push(@HISTORY_FILES,$name);
}

sub search_old_var_log_files {
    /^boot\.log\..*\z/s && push(@SYSTEM_FILES,$name);

    /^cron\..*\z/s && push(@SYSTEM_FILES,$name);
    /^cron-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^maillog\..*\z/s && push(@SYSTEM_FILES,$name);
    /^maillog-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^messages\..*\z/s && push(@SYSTEM_FILES,$name);
    /^messages-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^rpmpkgs\..*\z/s && push(@SYSTEM_FILES,$name);
    /^rpmpkgs-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^secure\..*\z/s && push(@SYSTEM_FILES,$name);
    /^secure-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^spooler\..*\z/s && push(@SYSTEM_FILES,$name);
    /^spooler-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^wtmp\..*\z/s && push(@SYSTEM_FILES,$name);

    /^Xorg\..*\.log.*\z/s  && push(@SYSTEM_FILES,$name);

    /^yum\.log\..*\z/s && push(@SYSTEM_FILES,$name);

    ### cups log files
    /^access_log\..*\z/s && push(@SYSTEM_FILES,$name);
    /^access_log-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^error_log\..*\z/s && push(@SYSTEM_FILES,$name);
    /^error_log-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^page_log\..*\z/s && push(@SYSTEM_FILES,$name);
    /^page_log-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    /^cups-pdf_log\..*\z/s && push(@SYSTEM_FILES,$name);
    /^cups-pdf_log-\d{8}\z/s && push(@SYSTEM_FILES,$name);

    ### gdm log files
    /^:[0-9]\.log\.[0-9]\z/s && push(@SYSTEM_FILES,$name);
    /^:[0-9]\.log\z/s &&push(@SYSTEM_FILES,$name);

    ### sysstat log files
    /^sa[0-9][0-9]\z/s && push(@SYSTEM_FILES,$name);
    /^sar[0-9][0-9]\z/s && push(@SYSTEM_FILES,$name);

}


sub mozilla_cache {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    -d _ &&
    /^Cache\z/s &&
      push(@MOZCACHE,$name . '/*');
}

sub search_user_mail {
    my $MAIL_DIR = '/var/spool/mail';
    opendir(DIR,$MAIL_DIR) || return undef;
    
    my @subdir = grep( !/^\./, readdir(DIR));
    closedir(DIR);

    my @user_mail = ();
    foreach my $name (@subdir)
    {
	push(@user_mail,join('/',$MAIL_DIR,$name));
    }
    return @user_mail;
}


sub create_rpm_package
{
    chdir $ENV{'HOME'};

    my $local_ip_address = get_local_ip_address();

    print "My-IP $local_ip_address\n" if $verbose;

    unless ($local_ip_address =~ /^149.236.\d*.\d*$/)
    {
	my $msg = "My-IP " . $local_ip_address . 
	    " is outside of Bruker.DE domain: no access to viola - " .
		" NO bruker-setup-release RPM created.";
	warn "$msg\n";
	return;
    }

    my $release_time = time();


    die "Missing $dmi\n" unless -x $dmi;


    ###
    # set some variables from hardware and current time
    #
    # Needed release string is: "bim_xw4200_L_1105678666")
    ###

    my @dmi_info;
    my $product;
    my $model;

    open(DMI,"$dmi -t1|") || die "can't pipe to $dmi: $!\n";
    while (<DMI>)
    {
	push(@dmi_info,$_);
	if ( /Product Name:\s(.*)/ )
	{
	    $product = $1;
	    print '$product =',"$product\n" if $verbose;


	    if ($product  =~ (/^hp workstation (xw\d+)/))
	    {
		$model = $1;
	    }
	    if ($product  =~ (/^HP\s*(\w*\d+)\s*Workstation/))
	    {
		$model = $1;
	    }
	    if ($product  =~ (/^VMware Virtual Platform/))
	    {
		$model = 'VMware';
	    }
	    if ($product  =~ (/^VirtualBox/))
	    {
		$model = 'VirtualBox';
	    }
	}
    }
    close(DMI);



    unless ($model)
    {
	print "***************************************************\n";
	print "*                                                 *\n";
	print '* Please notify gsc@bruker.de to fix this script  *',"\n";
	print "*                                                 *\n";
	print "***************************************************\n";

	print "The Workstation Model is not detected!\n\n";
	print "and send her the following text:\n\n\n", @dmi_info ,"\n";
	die "\n";
    }

    my $rpmmacros = $ENV{'HOME'} . '/.rpmmacros';
    my $specfile = 'bruker-setup-release.spec';
    my $bimcmd = 'bruker-image-info';
    my $macros = '--macros='. $rpmmacros;

    my $querycmd = 'rpm -qf --queryformat %{Name} /etc/redhat-release';
    my $redhat = `$querycmd`;

    chomp $redhat;
    $querycmd = 'rpm -q --queryformat %{version} ' . $redhat;

    my $redhat_release = `$querycmd`;

    my $rh_release  = (int $redhat_release);

    my $version = $revision;
    $version =~ s/[\$:a-zA-Z ]//g;
    my $package = 'bruker-setup-release'. '-' . $version ;
    my $release = 'bim_' . $model . '_L_' . $release_time;

    my $RPMtopdir = $ENV{'HOME'} . '/rpmbuild';

    my $RPM_File = $RPMtopdir . "/RPMS/noarch/$package-$release.noarch.rpm";
    my $SRPM_File = $RPMtopdir . "/SRPMS/$package-$release.src.rpm";

    open(FD,">$rpmmacros") || die;
    print FD '%_topdir',"\t$RPMtopdir","\n";
    print FD '%_target        linux',"\n";
    print FD '%packager       Bruker BioSpin GmbH <nmr-software-support@bruker.de>',"\n";
    print FD '%version',"\t",$version,"\n";
    print FD '%release',"\t$release","\n";
    print FD '%distro',"\t\t",'rhel'. $rh_release,"\n" if ($redhat eq 'redhat-release');
    print FD '%distro'."\t\t".'centos'. $rh_release,"\n" if ($redhat eq 'centos-release');
    print FD '%debug_package %{nil}',"\n";
    print FD '',"\n";
    close FD;
    unlink $specfile unless $test;

    my @subdirs = qw(BUILD RPMS SOURCES SPECS SRPMS);
    my @rpm_build_tree;
    foreach my$dir (@subdirs)
    {
	push(@rpm_build_tree,join('/',$RPMtopdir,$dir));
    }

    mkpath([@rpm_build_tree],0,0711);
    use Net::FTP;

    my $host = "viola.software.bruker.de";
    my $FtpPath = "/pub/Bruker-Workstation-Releases/$rh_release";

    my $debug_mode = 0;
    $debug_mode = 1 if ($verbose);

    my $ftp = Net::FTP->new($host,
			    Debug => $debug_mode,
			    Passive => 1) or die "Cannot connect to $host: $@";

    $ftp->login("anonymous") or die "Cannot login ", $ftp->message;
    my $subDir = $FtpPath . "/SPECS";
    $ftp->cwd($subDir) or die "cwd $subDir ", $ftp->message;

    $ftp->binary;

    print "fetch $specfile from\n  $host:", $ftp->pwd(),"\n" if $verbose;

    $ftp->get($specfile) or die "get $specfile failed ", $ftp->message;

    $ftp->cwd("../SOURCES") or die "cwd ../SOURCES ",$ftp->message;
    $ftp->get($bimcmd) or die "get $bimcmd failed ", $ftp->message;

    my $build =  $RPMtopdir . '/BUILD/' . $package;
    mkdir $build;
    my $srctgz=  $RPMtopdir . '/SOURCES/'. $package . '.tar.gz' ;


    my $quiet = '--quiet';
    my $devnull = '2>/dev/null';

    print "\nCreating $package RPM package.\n\n ... please wait ....\n";

    if ($verbose)
    {
	$quiet = '-v';
	$devnull = '';
	print "\nCreate $RPM_File \n";
    }

    system "rpm -qa | sort > $build/InstalledRPMs";
    system "dmidecode  > $build/BuildHost";
    system "mv bruker-image-info $build/";
    my @topspin_versions = installed_topspin_versions();
    my @TopspinInfo = '';
    foreach my $tsvers (@topspin_versions)
    {
	system "$tsvers -e showconf >/dev/null";
	open(FD,$ENV{HOME}."/confspec") || next;
	my @lines =<FD>;
	close(FD);
	push(@TopspinInfo,@lines);
	push(@TopspinInfo,"\n\n************ EOF $tsvers -e showconf *******************\n\n\n");
    }
    open(FD,">$build/TopspinInfo") || die;
    print FD @TopspinInfo;
    close(FD);

    my @RepoList = repository_sorted_list();
    open(FD,">$build/DistributionSortedRPMS") || die;
    print FD @RepoList;
    close(FD);
    
    system "tar -czf $srctgz -C $RPMtopdir/BUILD $package";

    system "rm -rf $build/$package/";

    my $cmd = "rpmbuild -ba --rmsource --rmspec --clean $quiet $specfile $devnull";

    print "$cmd \n" if $verbose;


    open(FD,"$cmd|") || die;
    my @LOG = <FD>;
    close(FD);

    unlink $rpmmacros unless $verbose;


    if (-f $RPM_File )
    {
	print "\nInstalling bruker-setup-release RPM File\n";
	system "rpm -U $RPM_File";

	$subDir = $FtpPath . "/RPMS";

	$ftp->cwd($subDir) or die "cwd $subDir ", $ftp->message;
	$ftp->binary;

	$ftp->put($RPM_File)or die "put $RPM_File failed ", $ftp->message;

	unlink $RPM_File;
    }

    chdir $RPMtopdir .'/SRPMS/';

    $subDir = $FtpPath . "/SRPMS";

    $ftp->cwd($subDir) or die "cwd $subDir ", $ftp->message;
    my $SRPM_File = "$package-$release.src.rpm";
    $ftp->binary;
    $ftp->put("$SRPM_File")or die "put $SRPM_File failed ", $ftp->message;
    $ftp->quit;
    
    unlink("$SRPM_File");
    my $bruker_setup_release = basename($RPM_File);
    syslog(LOG_INFO,"$bruker_setup_release installed");
}


sub installed_topspin_versions
{
    my $OPT_DIR = '/opt';
    opendir(DIR,$OPT_DIR) || return;
    
    my @subdir = grep( !/^\./, readdir(DIR));
    closedir(DIR);

    my @TOPSPIN = ();
    foreach my $name (@subdir)
    {
	my $topspin = join('/',$OPT_DIR,$name,'topspin');
	if (-x $topspin)
	{
	    push(@TOPSPIN,$topspin);
	}
    }

    return @TOPSPIN;
}

sub repository_sorted_list
{
    ##
    # query RPM database
    my $cmd = 'rpm -qa --queryformat "%{N}-%{V}-%{R} %{DISTRIBUTION}\n"';

    my %Repo = ();

    print "Execute $cmd\n" if $verbose;

    ###
    # Build several lists
    open (FD,"$cmd|") || die "$!\n";
    while (<FD>)
    {
	chomp;
	my ($rpm,$repo) = split(/ /,$_,2);
	if ($Repo{$repo})
	{
	    $Repo{$repo} .= ' ' . $rpm;
	}
	else
	{
	    $Repo{$repo} = $rpm ;
	}
    }
    close(FD);

    my @REPOLIST = ();

    while (my($key,$val) = each(%Repo))
    {
	my @rpms = sort(split(/ /,$val));
	push(@REPOLIST,"\n$key\n");
	foreach my $pkg (@rpms)
	{
	     push(@REPOLIST,"\t$pkg\n");
	}
    }
    return @REPOLIST
}

sub restore_ntp_conf
{
    my $ntp_conf = '/etc/ntp.conf';
    my $ntp_conf_pool = '/usr/share/bruker-setup/ntp.conf.centos.pool';
    copy($ntp_conf_pool,$ntp_conf) or warn "Copy $ntp_conf_pool to $ntp_conf failed: $!";
}

sub clear_abrt_reports
{
    print "clear_abrt_reports:\n" if $verbose;
    my $cmd = 'abrt-cli';
    my @reports;
    open(FD,"$cmd list|") || die "can't execute $cmd: $!\n";
    {
	while (<FD>)
	{
	    chomp;
	    push(@reports,$1) if  /^Directory:\s*(.*)$/;
	}
	close(FD);
    }
    print "$cmd rm @reports\n" if $verbose;
    system($cmd,'rm',@reports);
}

sub  clear_dhcp_lease
{
    print "clear_dhcp_lease:\n" if $verbose;

    my $cmd = 'rpm -ql dhcp';
    my $dhcpd_lease;
    my $leasefile = 'dhcpd.leases';
    my @lease_cmnt = ();

    open(FD,"$cmd|") || die "can't execute $cmd: $!\n";
    {
	while (<FD>)
	{
	    chomp;
	    $dhcpd_lease = $_ if /.*\/$leasefile$/;
	}
	close(FD);
    }

    print "\t$dhcpd_lease\n" if $verbose;
    return unless $dhcpd_lease;
    open(FD,$dhcpd_lease)  || die "can't open $dhcpd_lease: $!\n";
    {
	while (<FD>)
	{
	    push(@lease_cmnt,$_) if /^#/;
	}
	close(FD);
    }

    open(FD,">$dhcpd_lease")  || die "can't open $dhcpd_lease: $!\n";
    {
	print FD @lease_cmnt;
	close(FD);
	print "written:\n@lease_cmnt\n"  if $verbose;
    }
}

sub clear_etc_host
{
    print "clear_dhcp_lease:\n" if $verbose;
    my $etchosts = '/etc/hosts';
    my $serial_number = GetSmbiosSerialNumber();

    if (open(FDI,$etchosts))
    {
	my $newhosts = $etchosts . '.new';
	if (open(FDO,">$newhosts"))
	{
	    while (<FDI>)
	    {
		if (/^(127.0.0.1)\s*(localhost.localdomain)\s*($serial_number)\s*(localhost)/)
		{
		    print FDO "$1\t$2  $4\n";
		}
		else
		{
		    print FDO $_;
		}
	    }
	    close(FDO);
	    rename($newhosts,$etchosts);
	}
	close(FDI);
    }
}

sub disable_bruker_repos
{
    print "disable_bruker_repos()\n" if $verbose;
    if ($OS_Version == 5)
    {
	my $repo = '/etc/yum.repos.d/Bruker-Addon.repo';
	open(my $fd,$repo) or return;
	my @lines = <$fd>;
	close($fd);
	my $curRepo ='undef';
	foreach (@lines)
	{
	    $curRepo = $1  if ( $_ =~ /^[\[](.*)[\]]/);
	    if ( $_ =~ /^enabled=(\d*)/)
	    {
		my $status = $1;
		printf "$curRepo is %s\n",$status ? 'enabled':'disabled'  if $verbose;
		if ($status)
		{
		        $_ = "enabled=0\n";
		}
	    }
	}
	print @lines   if $verbose;
	open($fd,'>',$repo) or die "can't open $repo: $!\n";
	print $fd @lines;
	close($fd);
    }
    else
    {
	doexec('yum-config-manager','--disable',"bruker*") && syslog(LOG_INFO,"bruker* repos disabled");
    }
}

sub disable_kudzu_service
{
    my $kudzu = '/etc/init.d/kudzu';
    my $hwconf	= '/etc/sysconfig/hwconf';

    if (-x $kudzu)
    {
	  system('/sbin/chkconfig kudzu off');
	  unlink($hwconf) if -e $hwconf;
    }
}

sub enable_required_services
{
    enable_required_services_C5() if $OS_Version == 5;
    enable_required_services_C5() if $OS_Version == 6;
    enable_required_services_C7() if $OS_Version == 7;
}

sub enable_required_services_C5
{
    print "enable_required_services($OS_Version):\n" if $verbose;

    my $cmd = 'rpm -ql bruker-setup';
    my $rc_init = '/etc/rc.d/init.d';

    open(FD,"$cmd|") || die "can't execute $cmd: $!\n";
    {
	while (<FD>)
	{
	    chomp;
	    if ( /^$rc_init/)
	    {
		my $service = basename($_);
		doexec('chkconfig','--add',$service);
		doexec('chkconfig', $service,'on') && syslog(LOG_INFO,"service $service enabled");
	    }
	}
	close(FD);
    }
}

sub enable_required_services_C7
{
    print "enable_required_services($OS_Version):\n" if $verbose;
    my @service = qw(assign-network.service assign-hostname.service);
    doexec('systemctl','enable',@service) && syslog(LOG_INFO,"service @service enabled");
}

sub sizemm {
    my $rdev = shift;
    sprintf("%3d, %3d", ($rdev >> 8) & 0xff, $rdev & 0xff);
}

sub ls () {
    my $name = shift;

    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
        $atime,$mtime,$ctime,$blksize,$blocks) = lstat($name);
    my $pname = $name;

    $blocks
        or $blocks = int(($size + 1023) / 1024);

    my $perms = $rwx[$mode & 7];
    $mode >>= 3;
    $perms = $rwx[$mode & 7] . $perms;
    $mode >>= 3;
    $perms = $rwx[$mode & 7] . $perms;
    substr($perms, 2, 1) =~ tr/-x/Ss/ if -u _;
    substr($perms, 5, 1) =~ tr/-x/Ss/ if -g _;
    substr($perms, 8, 1) =~ tr/-x/Tt/ if -k _;
    if    (-f _) { $perms = '-' . $perms; }
    elsif (-d _) { $perms = 'd' . $perms; }
    elsif (-l _) { $perms = 'l' . $perms; $pname .= ' -> ' . readlink($_); }
    elsif (-c _) { $perms = 'c' . $perms; $size = sizemm($rdev); }
    elsif (-b _) { $perms = 'b' . $perms; $size = sizemm($rdev); }
    elsif (-p _) { $perms = 'p' . $perms; }
    elsif (-S _) { $perms = 's' . $perms; }
    else         { $perms = '?' . $perms; }

    my $user = $user{$uid} || $uid;
    my $group = $group{$gid} || $gid;

    my ($sec,$min,$hour,$mday,$mon,$timeyear) = localtime($mtime);
    if (-M _ > 365.25 / 2) {
        $timeyear += 1900;
    } else {
        $timeyear = sprintf("%02d:%02d", $hour, $min);
    }

    printf "%5lu %-10s %3d %-8s %-8s %8s %s %2d %5s %s\n",
            $ino,
                      $perms,
                            $nlink,
                                $user,
                                     $group,
                                          $size,
                                              $moname[$mon],
                                                 $mday,
                                                     $timeyear,
                                                         $pname;

    push(@Directories,$name) if -d $name;
    push(@Files,$name) if -f $name;

    1;
}


__END__

=head1 NAME

prepare-master - Assign 'Hewlett Packard' Vendors  OUI to eth1

=head1 SYNOPSIS

prepare-master [options]

Options:

     -help            brief help message
     -man             prints the manual page
     -verbose         create verbose output
     -test            run script but do no changes
     -[no]rpmpkg      enable/disable build of bruker-setup-release rpm package
     -[no]sshkeys     enable/disable removal of  'ssh' related files
     -[no]archive     enable/disable backup creation of deleted network files
     -restore         restore network files from backup file


=head1 OPTIONS

=over 8

=item B<-help>

    Print a brief help message and exits.

=item B<-man>

    Prints the manual page and exits.


=item B<-verbose>

    Print additional debug information

=item B<-test>

    Run prepare-master script but show only files that would be removed

=item B<-rpmpkg>

    Build only the bruker-setup-release package and send the files to
    ftp://viola.software.bruker.de/pub/Bruker-Workstation-Releases/[56]

=item B<-nosshkeys>

    Run prepare-master script but disable removing of ssh key files

=item B<-noarchive>

    Disable backup creation of deleted network files

=item B<-restore>

    Restore network files from backup file

=back


=head1 DESCRIPTION

prepare-master - This script is required to remove all personalized information
before a master image is created.

=cut

