#!/usr/bin/perl -X
#
# Copyright (C) 2002-2003 by NCHC, Steven Shiau, K. L. Huang
# (steven@nchc.org.tw, c00hkl00@nchc.org.tw)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# 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.
#
# Version 0.1, by K. L. Huang, c00hkl00@nchc.org.tw, especially for Debian
# Modified by Steven Shiau, steven@nchc.org.tw DRBL for Redhat

# setting 
# timed login to GDM default time (seconds)
our $TIMED_GDM_TIME_DEFAULT="30";

# Swap size for client to open
our $MAXSWAPSIZE_DEFAULT="128";

# user with UID greater than $uid_del_begin will be deleted in templates,
# so we will use YP in the clients, not any local account.
# This one only works for RedHat
# you can run "id -u" as a normal user to get this value, for RH9, it's 500 
our $UID_DEL_BEGIN_DEFAULT="500";

# file name to record the auto login ID and passwd
our $AUTO_LOGIN_ID_PASSWD="auto_login_id_passwd.txt";

# default autologin or timed login account password length
our $ACCOUNT_PASSWD_LENGTH_DEFAULT="8";

# default ratio for nfsd and total client number, i.e. the nfs daemon number
# (RPCNFSDCOUNT) running in server = $NFSD_RATIO * total_client_no.
our $NFSD_RATIO="2.5";

# default client no connected to some ethernet port
our $DEFAULT_CLIENT_NO_EACH_PORT="12";

# default boot prompt timeout for PXE client 
our $DEFAULT_CLIENT_SYSTEM_BOOT_TIMEOUT="70";

#
our $DRBL_SCRIPT_PATH="/opt/drbl";
our $drbl_setup_path="$DRBL_SCRIPT_PATH/setup";
our $drbl_syscfg="/etc/sysconfig/drbl";

# the craeted config filename
our $DRBLPUSH_CONF="drblpush.conf";
# file to record the hosts
our $hosts_list="hosts_list.drbl";
# file to record the public IP for clients
our $public_ip_list="public_ip.drbl";

our $purge_client;

# use some perl modules
use Term::ANSIColor;
use File::Path;
# Import locale-handling tool set from POSIX module.
use POSIX qw(locale_h);
# set the locale to C
setlocale(LC_ALL, "C");

#
# ------------------------------------------------------------------------
# Begin of the program
# subroutines
require "$DRBL_SCRIPT_PATH/sbin/drbl-perl-functions";

chomp($orig_wd=`LC_ALL=C pwd`);
chomp($drblpush_wd=`LC_ALL=C mktemp -d /tmp/drblpush_wd.tmp.XXXXXX`);
# before changing to working directory, we copy the macadr-eth* into working dir
system("cp -f macadr-eth*.txt $drblpush_wd &> /dev/null");
chdir ($drblpush_wd) || die ("Could not change to new working directory!!!");

sub set_client_public_ip {
  # $_[0]: file to input containing client IPs (input)
  # $_[1]: file to output containing client public IPs parameters (return)
  my @drbl_ip=`cat $_[0]`;
  my $public_ip_file="$_[1]";
  
  my $saved_ip="";
  my $saved_gw="";
  my $saved_netmask="255.255.255.0";
  my $public_ip;
  my $public_gw;
  my $public_netmask;
  my @public_network_param;
  my $first_saved_ip;

sub check_net_digit {
    my $check_ip="$_[0]";
    my $check_type="$_[1]"; # 2 values: IP or NETMASK
    my @check_ip_each=split(/\./,$check_ip);
    if (@check_ip_each != "4") {
       return "failed";
    }
    if ($check_type eq "IP") {
      # check the first and last digit, it can not be 255 or 0. 
      if ($check_ip_each[$#$check_ip_each] eq "0" || $check_ip_each[$#$check_ip_each] eq "255" ) {
         print "$check_ip_each[$#$check_ip_each] $lang_deploy{\"can_not_be_the_last_IP\"}!!!\n";
         return "failed";
      }
      if ($check_ip_each[0] eq "0" || $check_ip_each[0] eq "255" ) {
         print "$check_ip_each[0] $lang_deploy{\"can_not_be_the_first_IP\"}!!!\n";
         return "failed";
      }
    }

    foreach $DIG (@check_ip_each) {
      if ($check_type eq "IP") {
        if ($DIG > "255" || $DIG < "0") {
          return "failed";
        }
      }elsif ($check_type eq "NETMASK"){
        if ($DIG >= "256") {
          return "failed";
        }
      }
    }
} # end of sub check_net_digit

sub get_network_param {
    $IP="$_[0]";
    $saved_ip="$_[1]";
    $saved_gw="$_[2]";
    $saved_netmask="$_[3]";
    print "$lang_deploy{\"enter_public_IP_for_the_client\"} ($lang_deploy{\"its_IP_in_DRBL_is\"} $IP)\n[$saved_ip] ";
    chomp($public_ip=<STDIN>);
    if ($public_ip eq ""){
      $public_ip=$saved_ip;
    }
    my $chk_rlt=check_net_digit($public_ip,"IP");
    while ($chk_rlt eq "failed") {
       print "$lang_deploy{\"wrong_entered_IP\"}\n";
       chomp($public_ip=<STDIN>);
       $chk_rlt=check_net_digit($public_ip,"IP");
    }
    print "public_ip $public_ip\n" if $verbosity >=2;
    
    @networkIp=split(/\./,$public_ip);
    my $IP_PREFIX=$networkIp[0].".".$networkIp[1].".".$networkIp[2];
    $saved_ip=$IP_PREFIX.".".++$networkIp[3];
    print "network $IP_PREFIX.0\n" if $verbosity >=2;
    print "saved_ip $saved_ip\n" if $verbosity >=2;
    $saved_gw=$IP_PREFIX.".".254;
    
    # public ip gateway
    print "$lang_deploy{\"enter_gateway_for_client\"} ($lang_deploy{\"its_IP_in_DRBL_is\"} $IP) \n[$saved_gw] ";
    chomp($public_gw=<STDIN>);
    if ($public_gw eq "") {
      $public_gw=$saved_gw;
    }
    my $chk_rlt=check_net_digit($public_gw,"IP");
    while ($chk_rlt eq "failed") {
       print "$lang_deploy{\"wrong_entered_IP\"}\n";
       chomp($public_gw=<STDIN>);
       $chk_rlt=check_net_digit($public_gw,"IP");
    }
    $saved_gw=$public_gw;
    print "public_gw is $public_gw\n" if $verbosity >=2;
    print "saved_gw is $saved_gw\n" if $verbosity >=2;
    
    
    # public ip netmask
    print "$lang_deploy{\"enter_netmask_for_client\"} ($lang_deploy{\"its_IP_in_DRBL_is\"} $IP) \n[$saved_netmask] ";
    chomp($public_netmask=<STDIN>);
    if ($public_netmask eq "") {
      $public_netmask="$saved_netmask"
    }
    my $chk_rlt=check_net_digit($public_netmask,"NETMASK");
    while ($chk_rlt eq "failed") {
       print "$lang_deploy{\"wrong_entered_netmask\"}\n";
       chomp($public_netmask=<STDIN>);
       $chk_rlt=check_net_digit($public_netmask,"NETMASK");
    }
    $saved_netmask=$public_netmask;
    print "public_netmask is $public_netmask\n" if $verbosity >=2;
    print "saved_netmask is $saved_netmask\n" if $verbosity >=2;
    
    return $saved_ip, $saved_gw, $saved_netmask, $public_ip, $public_gw, $public_netmask;
}
#end of sub get_network_param
  
  chomp($public_ip_tmp=`LC_ALL=C mktemp /tmp/public_ip_tmp.XXXXXX`);
  chomp($public_ip_guess=`LC_ALL=C mktemp /tmp/public_ip_guess.XXXXXX`);
  open(PUBLIC_IP_FILE,">$public_ip_tmp") or die "$lang_deploy{\"failed_to_open_file\"}  \"$public_ip_tmp\"\n";
  open(PUBLIC_IP_GUESS_FILE,">$public_ip_guess") or die "$lang_deploy{\"failed_to_open_file\"}  \"$public_ip_guess\"\n";
  print "Clients' IPs: @drbl_ip\n" if $verbosity >=2;
  
# prepare the public ip file, one for guessed from first input, the other for
# entering one by one.
  print PUBLIC_IP_FILE <<END_PUBLIC_IP;
# The private IP is for the client connected to DRBL server.
# The public IP is for the client connected to WAN.
#------------------------------------------------------------
#private IP \t public IP \t netmask \t gateway
END_PUBLIC_IP

  print PUBLIC_IP_GUESS_FILE <<END_PUBLIC_IP_GUESS;
# The private IP is for the client connected to DRBL server.
# The public IP is for the client connected to WAN.
#------------------------------------------------------------
#private IP \t public IP \t netmask \t gateway
END_PUBLIC_IP_GUESS
  
  chomp($IP=@drbl_ip[0]);
  # get first public ip for client
  get_network_param($IP, $saved_ip, $saved_gw, $saved_netmask);
  $first_saved_ip=$saved_ip;
  
  print PUBLIC_IP_FILE <<END_PUBLIC_IP;
$IP \t $public_ip \t $public_netmask \t $public_gw
END_PUBLIC_IP

  print PUBLIC_IP_GUESS_FILE <<END_PUBLIC_IP_GUESS;
$IP \t $public_ip \t $public_netmask \t $public_gw
END_PUBLIC_IP_GUESS
  
  foreach $IP (@drbl_ip[1..$#drbl_ip]) {
    chomp($IP);
    $public_ip=$saved_ip;
    @networkIp=split(/\./,$public_ip);
    my $IP_PREFIX=$networkIp[0].".".$networkIp[1].".".$networkIp[2];
    $saved_ip=$IP_PREFIX.".".++$networkIp[3];
   
    $public_netmask=$saved_netmask;
    $public_gw=$saved_gw;
    print PUBLIC_IP_GUESS_FILE <<END_PUBLIC_IP_GUESS;
$IP \t $public_ip \t $public_netmask \t $public_gw
END_PUBLIC_IP_GUESS
  }
  
  print "#$delimiter{\"dash_line\"}\n";
  print "$lang_deploy{\"set_client_public_IP_as\"}\n";
  print "#$delimiter{\"dash_line\"}\n";
  system("LC_ALL=C cat $public_ip_guess");
  print "#$delimiter{\"dash_line\"}\n";
  print "$lang_text{\"Accept\"} ? [Y/n] ";
  chomp($value=<STDIN>);
  SWITCH: for ($value) {
	  /^n$|^no$/i && do {
            # Enter each one by one
            foreach $IP (@drbl_ip[1..$#drbl_ip]) {
              chomp($IP);
              # use the first one saved for initial prompt value to user
              $saved_ip=$first_saved_ip;
              get_network_param($IP, $saved_ip, $saved_gw, $saved_netmask);
              print PUBLIC_IP_FILE <<END_PUBLIC_IP;
$IP \t $public_ip \t $public_netmask \t $public_gw
END_PUBLIC_IP
            }
            close(PUBLIC_IP_FILE);
            # put the result file to working directory
            system("LC_ALL=C cp -f $public_ip_tmp $public_ip_file");
            last SWITCH;
	  };
	  /.*/ && do {
            # accept the guess one, output the result
            close(PUBLIC_IP_GUESS_FILE);
            # put the result file to working directory
            system("LC_ALL=C cp -f $public_ip_guess $public_ip_file");
            last SWITCH;
	  };
  }
  
  unlink ($public_ip_tmp) if -f $public_ip_tmp;
  unlink ($public_ip_guess) if -f $public_ip_guess;
} #end of sub set_client_public_ip

#
sub interactive_mode {
        my $NIC_prefix="/etc/sysconfig/network-scripts/ifcfg-";
        my $NET_sys="/etc/sysconfig/network";
	#we will scan the ethernet from $ethernet_list[0]... (eth0-eth5 here),
	#use public IP in alias interface, private IP in real interface, 
	#Ex: eth0: 192.168.0.254, eth0:1 61.216.116.23
	my @ethernet_list= sort(0..5, "0:1", "1:1", "2:1", "3:1", "4:1", "5:1") ;
	my @ethernet_sys; # the private ethernet we found and useful, ex:"eth1"
	my @range_start;
	my @range_end;
	my @MAC_file;
	our @ip_sys_prefix;
	our @ip_sys;

        # Try to get setting from system 
        my $rNET = read_config("$NET_sys");
        my $domain_sys=$rNET->{"general"}{"DOMAINNAME"};
        my $nisdomain_sys=$rNET->{"general"}{"NISDOMAIN"};
        my $hostname_sys=$rNET->{"general"}{"HOSTNAME"};
        my @client_hostname_prefix_default=split(/\./,$hostname_sys);
        print "DOMAIN in system is $domain_sys\n" if $verbosity >= 2;
        print "NISDOMAIN in system is $nisdomain_sys\n" if $verbosity >= 2;
        print "Client hostname prefix default is $client_hostname_prefix_default[0]\n" if $verbosity >= 2;

        unlink ($DRBLPUSH_CONF) if -f $DRBLPUSH_CONF;
	open(CONFIG_FILE,">$DRBLPUSH_CONF") or die "$lang_deploy{\"failed_to_open_file\"} \"$DRBLPUSH_CONF\"\n";

        unless ( $domain_sys ) {
           print "$delimiter{\"dash_line\"}\n".
                 "$lang_deploy{\"domain_unset_prompt\"}\n".
	         "[drbl.sf.net] ";
           while (<STDIN>) {
              chomp;
              $domain_sys=$_;
	      if ( "$domain_sys" =~ / |\/|\\/ ) {
  	        print "\" \" ($lang_text{\"space\"}), \"/\", $lang_text{\"or\"} \"\\\" $lang_deploy{\"not_allowed_domainname\"}\n";
              } else {
	        # if empty, use default name
                if ($domain_sys eq "") {
                  $domain_sys="drbl.sf.net";
                }
	        print "$lang_deploy{\"set_domain_as\"} $domain_sys\n";
                last;
              }
           }
        }
        unless ( $nisdomain_sys ) {
           print "$delimiter{\"dash_line\"}\n".
                 "$lang_deploy{\"nisdomain_unset_prompt\"}\n".
	         "[penguinzilla] ";
           while (<STDIN>) {
              chomp;
              $nisdomain_sys=$_;
	      if ( "$nisdomain_sys" =~ / |\/|\\|\.|^[0-9]/ ) {
  	        print "\" \" ($lang_text{\"space\"}), \"/\", \".\", \"\\\" $lang_text{\"or\"} \"$lang_word{\"initial_digit\"}\" $lang_deploy{\"not_allowed_nisdomain_sys\"}\n";
              } else {
	        # if empty, use default name
                if ($nisdomain_sys eq "") {
                  $nisdomain_sys="penguinzilla";
                }
	        print "$lang_deploy{\"set_domain_as\"} $nisdomain_sys\n";
                last;
              }
           }
        }
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"enter_client_hostname_prefix\"}\n".
	      "[$client_hostname_prefix_default[0]] ";
           while (<STDIN>) {
              chomp;
              $client_hostname_prefix=$_;
	      if ( "$client_hostname_prefix" =~ / |\/|\\|\.|^[0-9]/ ) {
		# "-" should be ok, but we need to parse the /etc/dhcpd.conf
		# then if make it like fc1-1=00:2A:00:AB:CD:EF, run 
		#  fc1-1=00:2A:00:AB:CD:EF in shell will fail. So we skip
		#  "-"
  	        print "\" \" ($lang_text{\"space\"}), \"/\", \".\", \"\\\" $lang_text{\"or\"} \"$lang_word{\"initial_digit\"}\" $lang_deploy{\"not_allowed_hostname\"}\n";
              } else {
	        # if empty, use default name
                if ($client_hostname_prefix eq "") {
                  $client_hostname_prefix="$client_hostname_prefix_default[0]";
                }
                print "$lang_deploy{\"set_client_hostname_prefix\"} $client_hostname_prefix\n".
                "$delimiter{\"dash_line\"}\n";
                last;
              }
           }
        # try to find all the NIC for clients, i.e. eth1, eth2...
        for($i=0;$i<=$#ethernet_list;$i++) {
	 $ethx="eth"."$ethernet_list[$i]";
   	 if ( -f "$NIC_prefix"."$ethx" ) {
	   # orig script: `/sbin/ifconfig | grep -A1 $ethx | grep -v $ethx | sed 's/^.*inet addr:\([0-9\.]\+\).*$/\1/'`;
	   # Specially, we do not want the alias interface, such as:eth0:1
           my $IP=`LC_ALL=C /sbin/ifconfig $ethx | grep -A1 $ethx | grep -v $ethx | grep \"inet addr\" | sed 's/^.*inet addr:\\([0-9\\.]\\+\\).*\$\/\\1\/'`;
	   chomp($IP);
	   if ( "$IP" =~ /^192.168.*/ ) {
  	     print "Found private IP \"$IP\" in $ethx on your system!\n";
  	     push @ethernet_sys, $ethx;
           } else {
             print "Found $ethx IP ($IP) in your system, $lang_deploy{\"but_not_private_IP_or_configured\"}\n".
	           "$lang_deploy{\"we_will_skip\"} $ethx!\n";
           }

         }
        }
	if ( @ethernet_sys <= 0 ) {
 	  print "$lang_deploy{\"no_NIC_setup\"}\n".
	        "$lang_deploy{\"we_can_NOT_continue\"}\n";
	  exit;
	} else { 
       	  print "$lang_deploy{\"configured_nic\"} ". 
	         colored ("@ethernet_sys \n", 'red');
          print "$delimiter{\"dash_line\"}\n";
	  # find those private IP in same eth, 
	  # ex, eth0: 192.168.1.1, eth0:1 192.168.101.1
	  # orig script: ifconfig |grep -B1 "inet addr:192.168" |grep "^eth" |cut -d" " -f1 | sed -e "s/:.//g" |uniq -d
          $dup_eth=`LC_ALL=C /sbin/ifconfig |grep -B1 \"inet addr:192.168\" |grep \"^eth\" |cut -d\" \" -f1 | sed -e \"s\/:.\/\/g\" |uniq -d`;
	  chomp($dup_eth);
	  if ($dup_eth) {
            print "Both $dup_eth and $dup_eth:1 have private IP addresses.\n".
                  "$lang_deploy{\"for_internet_access_prompt\"}\n".
		  "$lang_deploy{\"drbl_website_prompt\"}\n".
                  "0-> $dup_eth, 1-> $dup_eth:1\n".
                  "[0] ";
            chomp($del_ans=<STDIN>);
            if ( "$del_ans" eq "1" ) {
                $del = "$dup_eth:1";
            }else{
                $del = "$dup_eth";
            }
            print "$lang_deploy{\"ethernet_port_for_internet\"} $del\n";
            @ethernet_sys = grep { $_ ne "$del" } @ethernet_sys;
            print "$lang_deploy{\"ethernet_port_for_DRBL\"} ".
	          colored ("@ethernet_sys \n", 'red');

          }else{
            print "$lang_deploy{\"only_1_IP_for_eth0\"}\n";
            @ethernet_sys = grep { $_ ne "eth0" } @ethernet_sys;
            print "$lang_deploy{\"ethernet_port_for_DRBL\"} ".
	          colored ("@ethernet_sys \n", 'red');
          }
	  # if not ethernet port is available for DRBL, quit.
	  if ( @ethernet_sys <= 0 ) {
	    print colored ("$lang_deploy{\"no_DRBL_port\"}\n", 'red').
	          colored ("$lang_deploy{\"we_can_NOT_continue\"}\n", 'red');
	    exit;
	  }
	  print "$delimiter{\"star_line\"}\n";
        }

# detect the mac address
    print "$delimiter{\"star_line\"}\n".
          "$lang_deploy{\"collect_MAC_prompt\"}\n".
	  "[y/N] ";
    chomp($line=<STDIN>);
    SWITCH: for ($line) {
	    /^y$|^yes$/i && do {
		  $collect_mac="yes";
                  print "$delimiter{\"star_line\"}\n".
                        "$lang_deploy{\"ok_let_do_it\"}\n";
                  my $whoiam = `LC_ALL=C id -nu`;
                  chomp($whoiam);
                  if ("$whoiam" eq "root") { 
                    system("LC_ALL=C $DRBL_SCRIPT_PATH/sbin/drbl-collect-mac @ethernet_sys");
                  }else{
                     print "$lang_deploy{\"you_are_not_root\"},\n". 
                           "$lang_word{\"please_enter\"} ". colored("$lang_word{\"root_passwd\"} ",'red'). "to collect those MAC addresses...\n"; 
                     my $su_rlt=system("LC_ALL=C su -c \"$DRBL_SCRIPT_PATH/sbin/drbl-collect-mac @ethernet_sys\" root");
                     while ($su_rlt == 256) { 
                            $su_rlt=system("LC_ALL=C su -c \"$DRBL_SCRIPT_PATH/sbin/drbl-collect-mac @ethernet_sys\" root");
                     }
                  }
		  last SWITCH;
	    };
	    /.*/ && do {
		  $collect_mac="no";
		  last SWITCH;
	    };
    }

    print "$delimiter{\"star_line\"}\n".
          "$lang_deploy{\"ok_let_continue\"}\n".
          "$delimiter{\"star_line\"}\n";

# ask user to input client no.
        for($i=0;$i<=$#ethernet_sys;$i++) {
	 $ethx="$ethernet_sys[$i]";
          my $NIC_sys="/etc/sysconfig/network-scripts/ifcfg-$ethx";
          # Try to get setting from system also
          my $rNIC = read_config("$NIC_sys");
          # get the ipaddress of NIC "eth1, eth2..." 
          my $ip_sys_tmp=$rNIC->{"general"}{"IPADDR"};
	  # We must get the static IP for this NIC, NO DHCP...
          if ( "$ip_sys_tmp" eq "" ) {
	    print "$delimiter{\"star_line\"}\n".
  	          "$lang_deploy{\"unable_to_get_ethx_IP\"} ".
	           colored("$ethx \n",'red').
            	  "$lang_deploy{\"program_stop\"}\n";
            exit (1);
          };
          my @ip_sys_sp=split(/\./,$ip_sys_tmp);
          $ip_sys[$i]=$ip_sys_tmp;
          $ip_sys_prefix[$i]="$ip_sys_sp[0].$ip_sys_sp[1].$ip_sys_sp[2]";

  	  print "$lang_deploy{\"fix_eth_IP_prompt\"} ".
	         colored("$ethx",'red').
		 " ?\n".
	  "[y/N] ";
	  chomp($MAC=<STDIN>);
	  if ($MAC eq "y" || $MAC eq "Y" || $MAC eq "yes" || $MAC eq "YES") {
            # user want to fix the IP address for DRBL client 
	    print "$delimiter{\"star_line\"}\n".
	          "$lang_deploy{\"MAC_file_prompt\"} $ethx.\n".
		  "[macadr-$ethx.txt] ";
            while (<STDIN>) {
	      chomp;
	      if ( $_ eq "" ) {
	        $MAC_file[$i]="macadr-$ethx.txt";
	      }else{
	        $MAC_file[$i]=$_;
	      }

              # copy the entered file from orig_wd if they exist
              system("[ -f $orig_wd/$MAC_file[$i] ] && cp -f $orig_wd/$MAC_file[$i] ./");
              # check MAC address files
              check_MAC_file(".","$MAC_file[$i]");

              # get the client no from user input
	      # 1st, get the initial value of the last set of digits in the IP address in this subnet
	      print "$delimiter{\"star_line\"}\n".
	            "$lang_deploy{\"IP_start_prompt\"} $ethx.\n",
		    "[1] ";

              unless ( $range_start[$i] ) {
                 while (<STDIN>) {
                   chomp;
	           my $start_input=$_;
                   if ($start_input eq "") {
                     $range_start[$i]=1;
	             last;
	           } elsif ( $start_input =~ /[^0-9]/ ) {
	               print "$lang_deploy{\"not_initial_value\"}\n";
                   } else {
	               $range_start[$i]=$start_input;
	               last;
                   }
                 }
              }
	      # use wc -l to count the lines of file user input
              $line=`LC_ALL=C cat $MAC_file[$i] 2>/dev/null| wc -l |tr -d \" \" `;
	      chomp($line);
	      if ($line >= 254) {
	       print "The file \"$MAC_file[$i]\" you set for the clients connected to $ethx is empty or invalid, $lang_word{\"please_enter\"} the filename again, or press \"ctrl-c\" to quit!\n";
              } else {
               $range_end[$i]=$range_start[$i] + $line - 1;
	       last;
              }
	    }
	  } else {
            # user does NOT want to fix the IP address for DRBL client 
            # get the client no from user input
	    print "$delimiter{\"star_line\"}\n".
	          "$lang_deploy{\"IP_start_prompt\"} $ethx.\n",
		  "[1] ";
            unless ( $range_start[$i] ) {
               while (<STDIN>) {
                 chomp;
	         my $start_input=$_;
                 if ($start_input eq "") {
                   $range_start[$i]=1;
	           last;
	         } elsif ( $start_input =~ /[^0-9]/ ) {
	             print "$lang_deploy{\"not_initial_value\"}\n";
                 } else {
	             $range_start[$i]=$start_input;
	             last;
                 }
               }
            }
            # count the clients no which already exist to prompt user
            my $client_no=`LC_ALL=C unalias ls 2> /dev/null; ls -d /tftpboot/nodes/$ip_sys_prefix[$i].* 2>/dev/null |wc -w|sed -e "s/ //g"`;
            chomp($client_no);
            # if 0, set the default no for user
	    if ($client_no eq "0") { $client_no="$DEFAULT_CLIENT_NO_EACH_PORT";}
            print "client_no:$client_no\n" if $verbosity >=2;
	    print "$delimiter{\"star_line\"}\n".
	          "$lang_deploy{\"range_prompt\"}\n";
  	    print "$lang_deploy{\"client_number_connected_to_eth\"} $ethx ?\n";
            print "$lang_deploy{\"enter_the_no\"} \n".
                  "[$client_no] ";
            while (<STDIN>) {
	      chomp;
	      my $line=$_;
	      if ($line eq "") { $line=$client_no;}
	      if ($line >= 254) {
	       print "The value \"$line\" you input for the number of clients connected to $ethx is INVALID, $lang_word{\"please_enter\"} again!\n";
	      }
	      else {
               $range_end[$i]=$range_start[$i] + $line - 1;
	       last;
              }
	    }
	  }

          if ( ! $MAC_file[$i] ){ 
            # use the range for clients.
	    print "$delimiter{\"star_line\"}\n".
	          "$lang_deploy{\"the_value_you_set\"} \"$range_end[$i]\".\n".
  	          "$lang_deploy{\"set_the_IP_connected_to_eth\"} ".
                  colored ("$ethx $lang_text{\"as\"}: $ip_sys_prefix[$i].$range_start[$i] - $ip_sys_prefix[$i].$range_end[$i]\n",'red').
                  "$lang_text{\"Accept\"} ? [Y/n] ";
	  }else{
            # use the fixed IP address for clients.
	    print "$delimiter{\"star_line\"}\n".
	          "$lang_deploy{\"filename_you_set\"} \"$MAC_file[$i]\".\n".
		  "$lang_deploy{\"client_no_in_MAC_file\"} $line.\n".
  	          "$lang_deploy{\"set_the_IP_connected_to_eth\"} $ethx $lang_deploy{\"by_MAC_file\"} ".
                  colored ("$ethx $lang_text{\"as\"}: $ip_sys_prefix[$i].$range_start[$i] - $ip_sys_prefix[$i].$range_end[$i]\n",'red').
                  "$lang_text{\"Accept\"} ? [Y/n] ";
          }

	  chomp($line=<STDIN>);
	  if ($line eq "n" || $line eq "N" || $line eq "no" || $line eq "NO") {
	   print "$delimiter{\"exclamation_line\"}\n".
	         "$lang_deploy{\"let_restart_it_again\"}\n";
	   redo;
	  }
	  else {
	   print "$delimiter{\"star_line\"}\n".
	         "$lang_deploy{\"ok_let_continue\"}\n";
          }
  
	}
	# Find the public IP, we assume now only eth0 have public IP
        my $NIC_eth0;
	$NIC_eth0="/etc/sysconfig/network-scripts/ifcfg-eth0";
	$PUB_NIC="eth0";
        # Try to get eth0 IP from system also, just for output
	# We need the public IP.
        my $rNIC = read_config("$NIC_eth0");
        my $ip_eth0=$rNIC->{"general"}{"IPADDR"};
        # Only if eth0:1 and eth0 are configured for DRBL environment,
        # and we found IP addresss for eth0 is 192.168.*
        # Oetherwise, only eth0 is for public Internet access, even it's 
        # IP address is 192.168.*, we will not try to search eth0:1
	if ( "$ip_eth0" =~ /^192.168.*/ && @ethernet_sys =~ /eth0/) {
          # It's private IP, public IP must be in eth0:1
	  $PUB_NIC="eth0:1";
          $NIC_eth0="/etc/sysconfig/network-scripts/ifcfg-eth0:1";
          $rNIC = read_config("$NIC_eth0");
          $ip_eth0=$rNIC->{"general"}{"IPADDR"};
        }

	print "$delimiter{\"star_line\"}\n".
       	      "$lang_deploy{\"layout_for_DRBL\"} \n".
  	      "$delimiter{\"star_line\"}\n";
        print color 'bold red';
        print
"          NIC    NIC IP                    Clients\n".
"+-----------------------------+\n".
"|         DRBL SERVER         |\n".
"|                             |\n".
"|    +-- [$PUB_NIC] $ip_eth0 +- to WAN\n".
"|                             |\n";
	  my @grp_no;
          my $total_client_no=0;
          for($i=0;$i<=$#ethernet_sys;$i++) {
	   $ethx="$ethernet_sys[$i]";
	   my $grp=$ethx;
	   # extract group for ethx, i.e. group 1 for eth1, group 3 for eth3... 
	   $grp=~ s/eth//;
	   # calculate the clients number
	   $grp_no[$i] = $range_end[$i]-$range_start[$i]+1;
	   # get the total client number
           $total_client_no += $grp_no[$i];
	   #
           print 
"|    +-- [$ethx] $ip_sys[$i] +- to clients group $grp [ $grp_no[$i] clients, their IP \n".
"|                             |            from $ip_sys_prefix[$i].$range_start[$i] - $ip_sys_prefix[$i].$range_end[$i]]\n";
          }
  
	  print
"+-----------------------------+\n";
          print color 'reset';
          print
		"$delimiter{\"star_line\"}\n";

        print "Total clients: ". 
	      colored ("$total_client_no\n", 'red');

        # ask if use need local HD space as swap file ?
	print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"swap_prompt\"}\n".
	      "[Y/n] ";
	
        chomp($mkswap_ans=<STDIN>);
        if ($mkswap_ans eq "n" || $mkswap_ans eq "N" || $mkswap_ans eq "no" || $mkswap_ans eq "NO") {
          $localswapfile="no";
	}else{
	  print "$delimiter{\"star_line\"}\n".
                "$lang_deploy{\"try_to_create_swap\"}\n".
                "$delimiter{\"dash_line\"}\n";
          $localswapfile="yes";
	  print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"max_swap_size\"}\n".
	        "[$MAXSWAPSIZE_DEFAULT] ";
          chomp($maxswapsize=<STDIN>);
	  if ( "$maxswapsize" eq "" ) {
		$maxswapsize="$MAXSWAPSIZE_DEFAULT";
		print colored ("maxswapsize=$maxswapsize\n", 'red');
          }
        }

	# Ask which mode is preferred for clients
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"mode_for_client_init\"}\n".
	      "[1] ";
        chomp($client_startup_mode=<STDIN>);
        if ($client_startup_mode eq "2" || $client_startup_mode eq "2") {
            $CLIENT_INIT="3";
            print "$lang_deploy{\"client_text_mode\"}\n".
                  "$delimiter{\"star_line\"}\n";
	}else{
            $CLIENT_INIT="5";
            print "$lang_deploy{\"client_graphic_mode\"}\n".
                  "$delimiter{\"star_line\"}\n";
            print "$delimiter{\"dash_line\"}\n".
                  "$lang_deploy{\"login_mode_for_client\"}\n".
	          "[0] ";
            chomp($login_gdm_opt=<STDIN>);
            if ($login_gdm_opt eq "1") {
                $LOGIN_GDM_OPT="auto_login";
                print "$lang_deploy{\"auto_login\"}\n".
                      "$delimiter{\"star_line\"}\n";
                print "[$total_client_no] $lang_deploy{\"created_account_for_auto_login\"}".
                      " \"$AUTO_LOGIN_ID_PASSWD\"\n";
            } elsif ($login_gdm_opt eq "2") {
                $LOGIN_GDM_OPT="timed_login";
                print "$delimiter{\"dash_line\"}\n".
                      "$lang_deploy{\"time_for_countdown\"}\n".
	              "[$TIMED_GDM_TIME_DEFAULT] ";
                chomp($timed_time=<STDIN>);
                if ($timed_time eq "") {
                   $TIMED_LOGIN_TIME = "$TIMED_GDM_TIME_DEFAULT";
                }else{
                   $TIMED_LOGIN_TIME = $timed_time;
                }
                print "$lang_deploy{\"timed_login_prompt\"} $TIMED_LOGIN_TIME $lang_text{\"seconds\"}.\n".
                      "$delimiter{\"star_line\"}\n";
                print "[$total_client_no] $lang_deploy{\"created_account_for_auto_login\"}".
                      " \"$AUTO_LOGIN_ID_PASSWD\"\n";
            } else {
                $LOGIN_GDM_OPT="login";
                print "$lang_deploy{\"normal_login_prompt\"}\n".
                      "$delimiter{\"star_line\"}\n";
            }
        }
	# Ask if user want to set the root password of clients
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"set_client_root_passwd\"}\n".
	      "[y/N] ";
        chomp($set_client_root_passwd=<STDIN>);
        if ($set_client_root_passwd eq "y" || $set_client_root_passwd eq "y" || $set_client_root_passwd eq "yes" || $set_client_root_passwd eq "yes") {
            $set_client_root_passwd="yes";
	    # we set 2 different passwords to make while loop works.
	    $client_root_passwd_1="init1";
	    $client_root_passwd_2="init2";
	    while ($client_root_passwd_1 ne $client_root_passwd_2 || ($client_root_passwd_1 eq "" && $client_root_passwd_2 eq "" )) { 
                 print "$lang_deploy{\"whats_client_root_passwd\"}\n";
		 # turn off echo
                 system "LC_ALL=C stty -echo";
                 chomp($client_root_passwd_1=<STDIN>);
		 # turn on echo
                 system "LC_ALL=C stty echo";
                 print "$lang_deploy{\"retype_root_passwd\"}\n";
                 system "LC_ALL=C stty -echo";
                 chomp($client_root_passwd_2=<STDIN>);
                 system "LC_ALL=C stty echo";
	      if ($client_root_passwd_1 ne $client_root_passwd_2) { 
		  print colored ("$lang_deploy{\"sorry_passwd_not_match\"}\n", 'red');
	      }elsif ($client_root_passwd_1 eq "" && $client_root_passwd_2 eq "" ){ 
		  print colored ("$lang_deploy{\"sorry_passwd_can_not_empty\"}\n", 'red');
	      }
	    }
	    $client_root_passwd=$client_root_passwd_1;
	}else{
            $set_client_root_passwd="no";
            print "$lang_deploy{\"ok_let_continue\"}\n";
        }

	# Ask if user want to set the boot prompt for clients
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"set_client_system_select\"}\n".
	      "[Y/n] ";
        chomp($set_client_system_select=<STDIN>);
        if ($set_client_system_select eq "n" || $set_client_system_select eq "N" || $set_client_system_select eq "no" || $set_client_system_select eq "NO") {
            $set_client_system_select="no";
	}else{
            $set_client_system_select="yes";
	    while ($client_system_boot_timeout eq "") { 
                 print "$lang_deploy{\"whats_client_system_boot_timeout\"}\n".
                       "[$DEFAULT_CLIENT_SYSTEM_BOOT_TIMEOUT] ";
                 chomp($client_system_boot_timeout_=<STDIN>);
	      if ( "$client_system_boot_timeout_" =~ /[^0-9]/ ) { 
		  print colored ("$lang_deploy{\"sorry_timeout_must_be_number\"}\n", 'red');
	      } else { 
	          # if empty, use default timeout
                  if ($client_system_boot_timeout_ eq "") {
                    $client_system_boot_timeout_="$DEFAULT_CLIENT_SYSTEM_BOOT_TIMEOUT";
                  }
                  $client_system_boot_timeout="$client_system_boot_timeout_";
	      }
	    }
            print "$lang_deploy{\"ok_let_continue\"}\n";
            print "$delimiter{\"dash_line\"}\n";
        }

        # Ask if user want to set the public IP for clients
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"set_client_alias_IP\"}\n".
              "[y/N] ";
        chomp($line=<STDIN>);
        SWITCH: for ($line) {
            /^y$|^yes$/i && do {
                $set_client_public_ip_opt="yes";
                last SWITCH;
        	};
        	/.*/ && do {
                $set_client_public_ip_opt="no";
                last SWITCH;
        	};
        }

	# Ask if user want to open the thin-client mode
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"open_thin_client_option\"}\n".
	      "[y/N] ";
        chomp($open_thin_client_option=<STDIN>);
        if ($open_thin_client_option eq "y" || $open_thin_client_option eq "Y" || $open_thin_client_option eq "yes" || $open_thin_client_option eq "YES") {
            $open_thin_client_option="yes";
	}else{
            $open_thin_client_option="no";
            print "$lang_deploy{\"ok_let_continue\"}\n";
            print "$delimiter{\"dash_line\"}\n";
        }

	# Ask if user want to purge client files if they exist
        my $client_exist=system("LC_ALL=C ls -d /tftpboot/nodes/* >/dev/null 2>&1");
        if ($client_exist ne 256) {
           print "$delimiter{\"dash_line\"}\n".
                 "$lang_deploy{\"keep_client_setting_question\"}\n".
	         "[Y/n] ";
           chomp($keep_client=<STDIN>);
           if ($keep_client eq "n" || $keep_client eq "N" || $keep_client eq "no" || $keep_client eq "no") {
               $purge_client="yes";
               print "$lang_deploy{\"remove_client_setting\"}\n".
                     "$delimiter{\"star_line\"}\n";
	   }else{
               $purge_client="no";
               print "$lang_deploy{\"keep_client_setting\"}\n".
                     "$delimiter{\"star_line\"}\n";
           }
        }

	#
        print "$delimiter{\"star_line\"}\n";

# output the config file
  	  print CONFIG_FILE <<END_CFG;
#Setup for general
[general]
domain=$domain_sys
nisdomain=$nisdomain_sys
localswapfile=$localswapfile
client_init=$CLIENT_INIT
login_gdm_opt=$LOGIN_GDM_OPT
timed_login_time=$TIMED_LOGIN_TIME
maxswapsize=$maxswapsize
total_client_no=$total_client_no
create_account=$create_account
account_passwd_length=$ACCOUNT_PASSWD_LENGTH_DEFAULT
ip_wan_eth0=$ip_eth0
hostname=$client_hostname_prefix
purge_client=$purge_client
client_root_passwd=$client_root_passwd
set_client_system_select=$set_client_system_select
open_thin_client_option=$open_thin_client_option
client_system_boot_timeout=$client_system_boot_timeout
language=$language
set_client_public_ip_opt=$set_client_public_ip_opt
config_file=$DRBLPUSH_CONF
collect_mac=$collect_mac

END_CFG


        for($i=0;$i<=$#ethernet_sys;$i++) {
          my $ethx=$ethernet_sys[$i];
          if ( ! $MAC_file[$i] ){ 
	  # output the range format
  	  print CONFIG_FILE <<END_CFG;
#Setup for $ethx
[$ethx]
interface=$ethx
range=$range_start[$i]-$range_end[$i]

END_CFG
  	  }else{
 	    # output the MAC format
  	    print CONFIG_FILE <<END_CFG;
#Setup for $ethx
[$ethx]
interface=$ethx
mac=$MAC_file[$i]
ip_start=$range_start[$i]

END_CFG
	  }
	}

        close(CONFIG_FILE);
	# set mode for more secure
	system("LC_ALL=C chmod 600 $DRBLPUSH_CONF");

}#end of interactive_mode

sub drbl_config_example {
        #our $cfg_example_details="config.example.details";
        #our $cfg_example_easy="config.example.easy";
        my $cfg_example_details="$_[0]";
        my $cfg_example_easy="$_[1]";
        unlink ("$cfg_example_details") if -f "$cfg_example_details";
        unlink ("$cfg_example_easy") if -f "$cfg_example_easy";
        open(CFG_EXAMPLE_DETAILS,">$cfg_example_details") or die "$lang_deploy{\"failed_to_open_file\"}  $cfg_example_details for writing\n";
        open(CFG_EXAMPLE_EASY,">$cfg_example_easy") or die "$lang_deploy{\"failed_to_open_file\"}  $cfg_example_easy for writing\n";
        print CFG_EXAMPLE_DETAILS q{
# DRBL environment layout for some classroom, say, 
# they have 1 server, and 40 clients (PC for students).
# The best layout for this classroom is:
#
#              NIC    NIC IP                    Clients
#    +-----------------------------+
#    |         DRBL SERVER         |
#    |                             |
#    |    +-- [eth0] public IP     +- to WAN
#    |        (ex. 61.216.116.23)  |
#    |                             |
#    |    +-- [eth1] 192.168.1.254 +- to clients group 1 [13 clients, their IP 
#    |                             |            from 192.168.1.1 - 192.168.1.13]
#    |    +-- [eth2] 192.168.2.254 +- to clients group 2 [13 clients, their IP
#    |                             |            from 192.168.2.1 - 192.168.2.13]
#    |    +-- [eth3] 192.168.3.254 +- to clients group 3 [14 clients, their IP
#    |                             |            from 192.168.3.1 - 192.168.3.14]
#    +-----------------------------+
# The line leading by "#" is just a comment. 
# If you do not set the following:
# nameserver, domain, nisdomain, network, nfsserver, bootserver, nisserver
# The program will try to extract them from DRBL server's system setting.

# General Setup
[general]
nameserver=168.95.1.1,140.113.17.5  #nameserver setting for DRBL clients 
domain=drbl.org             #Domain for DRBL clients
nisdomain=drbl              #NIS domain for DRBL clients
nbi=vmlinuz-rtl8139-nbi     #if you want to specify sepcial kernel file for DRBL clients, set here
localswapfile=yes           #The client will try to create local swapfile
CLIENT_INIT=3               #The client's will be 3 (text mode), 5 for graphic
maxswapsize=128             #If local HD exists, use 128 MB as swap file

# Setup for eth1
[eth1]                      #1st subnet for DRBL clients
interface=eth1              #the network interface card used by this subnet
network=192.168.1.0         #the network for eth1
nfsserver=192.168.1.254     #NFS Server for clients in this subnet (Usually it's the IP address of this network interface card)
bootserver=192.168.1.254    #if not set, same value as nfsserver will be used
nisserver=192.168.1.254     #if not set, same value as nfsserver will be used
mac=mac_1.txt               #We want to fix the IP of DRBL client when DHCP server provide IP to them, so use the file "mac_1.txt" to describe the MAC address of DRBL Clients, each one in one line.
#range=1-13                 #the DRBL clients IP will be 192.168.1.1,...192.168.1.13
hostname=G1_                #the hosstname of DRBL clients will be G1_001AG1_002 ... G1_013

# Setup for eth2
[eth2]
interface=eth2
network=192.168.2.0
nfsserver=192.168.2.254
bootserver=192.168.2.254
nisserver=192.168.2.254
nbi=vmlinuz-3c59x-nbi       #if you want to specify sepcial kernel file for DRBL clients
#mac=mac_2.txt              #We use the range to let DHCP provide the IP to clients randomly, so comment this.
range=1-13                  #the DRBL clients IP will be 192.168.1.1,...192.168.1.13
hostname=G2_

# Setup for eth3
[eth3]
interface=eth3
network=192.168.3.0
nfsserver=192.168.3.254
bootserver=192.168.3.254
nisserver=192.168.3.254
#mac=mac_3.txt              
range=1-14                  
hostname=G3_
};
        close(CFG_EXAMPLE_DETAILS);

        print CFG_EXAMPLE_EASY q{
# DRBL environment layout for some classroom, say, 
# they have 1 server, and 40 clients (PC for students).
# The best layout for this classroom is:
#
#              NIC    NIC IP                    Clients
#    +-----------------------------+
#    |         DRBL SERVER         |
#    |                             |
#    |    +-- [eth0] public IP     +- to WAN
#    |        (ex. 61.216.116.23)  |
#    |                             |
#    |    +-- [eth1] 192.168.1.254 +- to clients group 1 [13 clients, their IP 
#    |                             |            from 192.168.1.1 - 192.168.1.13]
#    |    +-- [eth2] 192.168.2.254 +- to clients group 2 [13 clients, their IP
#    |                             |            from 192.168.2.1 - 192.168.2.13]
#    |    +-- [eth3] 192.168.3.254 +- to clients group 3 [14 clients, their IP
#    |                             |            from 192.168.3.1 - 192.168.3.14]
#    +-----------------------------+
# The line leading by "#" is just a comment. 
# We do NOT set the following:
# nameserver, network, nfsserver, bootserver, nisserver.
# So the program will try to extract them from DRBL server's system setting.

# General Setup
[general]
domain=drbl.org  #Domain for DRBL clients
nisdomain=drbl   #NIS domain for DRBL clients
localswapfile=yes           #The client will try to create local swapfile
CLIENT_INIT=3               #The client's will be 3 (text mode), 5 for graphic
maxswapsize=128             #If local HD exists, use 128 MB as swap file

# Setup for eth1
[eth1]         #1st subnet for DRBL clients, give any name you can identify 
interface=eth1 #the network interface card used by this subnet
range=1-13     #the DRBL clients IP will be 192.168.1.1,...192.168.1.13
hostname=G1_   #the hosstname of DRBL clients will be G1_001AG1_002 ... G1_013

# Setup for eth2
[eth2]
interface=eth2
range=1-13     #the DRBL clients IP will be 192.168.2.1,...192.168.2.13
hostname=G2_

# Setup for eth3
[eth3]
interface=eth3
range=1-14     #the DRBL clients IP will be 192.168.3.1,...192.168.3.14
hostname=G3_
};
        close(CFG_EXAMPLE_EASY);

}


# subroutine to read file, parse them as parameters
# in: config_file
# out: hash of hash reference 
sub read_config {

  my %HoH = ();
  my $KoH="general";
  my $key="",$value="";

  open(CONFIG,$_[0]) or die "Can NOT find file \"$_[0]\"! \nPlease check your config file!\n";
  while(<CONFIG>) {
    if($_=~/^#.*/) {
      # ignore comment
      #print "ignore $_\n";
    }
    elsif($_=~/\[.*\]/) {
      # has key 
      chop;
      my $key_ = $_;
      # skip the comments
      $key_ =~ s/#.*//;
      # delete the spaces
      $key_ =~ s/ //g;
      $KoH=substr($key_,1,length($key_)-2); 
    }
    else { 
      # hash value
      chop;
      if( 0 == length($_) ) { next; }
      ($key,$value)=split(/=/);
      # Turn all the key to uppercase
      $key=uc($key);
      # skip the comments
      $value =~ s/#.*//;
      # delete the spaces
      $value =~ s/ //g;
      #print "KoH=$KoH, key=$key, value=$value\n";
      $HoH{ $KoH }{ $key }= $value;
    }
  }
  close(CONFIG);

  return( \%HoH );  
}

sub drbl_server_parse {

# user with UID greater than $uid_del_begin will be deleted in templates,
# so we will use YP in the clients, not any local account.
my $uid_del_begin="$UID_DEL_BEGIN_DEFAULT";

# Part 1,
# get enough information, setup the DRBL server
#
  my $DNS_sys="/etc/resolv.conf";
  my $NET_sys="/etc/sysconfig/network";
  my $rHoH = read_config($_[0]);

  my $nameserver=$rHoH->{"general"}{"NAMESERVER"};
  my $domain=$rHoH->{"general"}{"DOMAIN"};
  my $nisdomain=$rHoH->{"general"}{"NISDOMAIN"};
  my $nfsserver_default=$rHoH->{"general"}{"NFSSERVER_DEFAULT"};
  my $localswapfile=$rHoH->{"general"}{"LOCALSWAPFILE"};
  my $CLIENT_INIT=$rHoH->{"general"}{"CLIENT_INIT"};
  my $maxswapsize=$rHoH->{"general"}{"MAXSWAPSIZE"};
  my $ip_wan_eth0=$rHoH->{"general"}{"IP_WAN_ETH0"};
  my $purge_client=$rHoH->{"general"}{"PURGE_CLIENT"};
  my $language=$rHoH->{"general"}{"LANGUAGE"};
  my $set_client_system_select=$rHoH->{"general"}{"SET_CLIENT_SYSTEM_SELECT"};
  my $open_thin_client_option=$rHoH->{"general"}{"OPEN_THIN_CLIENT_OPTION"};
  my $client_system_boot_timeout=$rHoH->{"general"}{"CLIENT_SYSTEM_BOOT_TIMEOUT"};
  my $set_client_public_ip_opt=$rHoH->{"general"}{"SET_CLIENT_PUBLIC_IP_OPT"};
  my $config_file=$rHoH->{"general"}{"CONFIG_FILE"};
  my $collect_mac=$rHoH->{"general"}{"COLLECT_MAC"};
  
  # for login GDM
  my $login_gdm_opt=$rHoH->{"general"}{"LOGIN_GDM_OPT"};
  my $timed_login_time=$rHoH->{"general"}{"TIMED_LOGIN_TIME"};

  # for auto login or timed login account
  my $create_account=$rHoH->{"general"}{"CREATE_ACCOUNT"};
  my $account_prefix=$rHoH->{"general"}{"ACCOUNT_PREFIX"};
  my $total_client_no=$rHoH->{"general"}{"TOTAL_CLIENT_NO"};
  my $passwd_length=$rHoH->{"general"}{"ACCOUNT_PASSWD_LENGTH"};
  my $hostname_prefix=$rHoH->{"general"}{"HOSTNAME"};

  print "The GDM login option: $login_gdm_opt\n" if $verbosity >=2;
  print "timed_login_time: $timed_login_time\n" if $verbosity >=2;
  print "account_prefix: $account_prefix\n" if $verbosity >=2;
  print "total_client_no: $total_client_no\n" if $verbosity >=2;
  print "passwd_length: $passwd_length\n" if $verbosity >=2;
  print "maxswapsize in system is $maxswapsize\n" if $verbosity >= 2;
  print "WAN IP eth0 in system is $ip_wan_eth0\n" if $verbosity >= 2;
  print "The hostname_prefix from config file: \"$hostname_prefix\".\n" if $verbosity >= 2;

  # Try to get setting from system also
  my $nameserver_sys=`LC_ALL=C grep ^nameserver $DNS_sys | awk -F\" \" '{print \$2}'`;
  chomp $nameserver_sys;  # clean the last \n before substitute them as ","
  $nameserver_sys =~ s/\n/,/g;
  print "nameserver in system is $nameserver_sys\n" if $verbosity >= 2;

  my $rNET = read_config("$NET_sys");
  my $domain_sys=$rNET->{"general"}{"DOMAINNAME"};
  my $nisdomain_sys=$rNET->{"general"}{"NISDOMAIN"};
  print "DOMAIN in system is $domain_sys\n" if $verbosity >= 2;
  print "NISDOMAIN in system is $nisdomain_sys\n" if $verbosity >= 2;
  
  # set nameserver, domain, nisdomain, the priority: use the config file first, if unset, then use the value in system
  if ( ! $nameserver ) { 
   $nameserver = $nameserver_sys; 
   print "* nameserver is not set in config file, \nthe one \"$nameserver\" got from system will be used.\n" if $verbosity >= 2;   
  }
  if ( ! $nisdomain ) { 
   $nisdomain = $nisdomain_sys; 
   print "* nisdomain is not set in config file, \nthe one \"$nisdomain\" got from system will be used.\n" if $verbosity >= 2;   
  }
  if ( ! $domain ) { 
   $domain = $domain_sys; 
   print "* domain is not set in config file, \nthe one got \"$domain\" from system will be used.\n" if $verbosity >= 2;   
  }

  # check if the values are set in config file or system  
  if ( ! $nameserver ) {
     print "Error! NAMESERVER is unset!\n";
     print "Please set it in config file \"$_[0]\" or $DNS_sys.\n";
     exit;
  }

  if ( ! $nisdomain ) {
     print "Error! NISDOMAIN is unset!\n"; 
     print "Please set it in config file \"$_[0]\" or $NET_sys.\n";
     exit;
  }
  if ( ! $domain ) {
     print "Error! DOMAIN unset!\n"; 
     print "Please set it in config file \"$_[0]\" or $NET_sys.\n";
     exit;
  }

  if ("$mode" eq "load_config_file") {
    # check public IP setting
    if ("$set_client_public_ip_opt" eq "yes" && ! -f "$drbl_syscfg/$public_ip_list") {
        print "$delimiter{\"star_line\"}\n".
              colored ("Unable to find the $drbl_syscfg/$public_ip_list; If you want to create the $$drbl_syscfg/$public_ip_list, you must run \"drblpush\" in interactive mode (with -i option)!\n", 'red').
              "$lang_deploy{\"press_enter_to_continue\"}";
              chomp($line=<STDIN>);
        print "$delimiter{\"dash_line\"}\n";
    }
    # check MAC address files
    if ("$collect_mac" eq "yes" ){ check_MAC_file("$drbl_syscfg","macadr-eth"); }
  }

  #
  if ($localswapfile eq "y" || $localswapfile eq "Y" || $localswapfile eq "yes" || $localswapfile eq "YES") {
      $mkswapfile="mkswapfile";
  }else{
      $mkswapfile="";
  }

  if ( "$login_gdm_opt" eq "timed_login" && ! $timed_login_time ) {
     print "You set to timed login GDM, but there is no timed time!\n". 
           "We will set the timed time as $TIMED_GDM_TIME_DEFAULT seconds.\n";
  }

  my $nameserver_=$nameserver;
  $nameserver_=~ s/\,/ /g;

  # generate dhcpd.conf, hosts, $main_sh...

  $main_sh="drbl_deploy.sh";
  # delete the old files
  unlink ($main_sh) if -f $main_sh;
  unlink (dhcpd.conf) if -f dhcpd.conf;
  unlink (dhcpd) if -f dhcpd;
  unlink (hosts) if -f hosts;
  unlink (exports) if -f exports;
  unlink (nfsserver_all) if -f nfsserver_all;
  unlink (yp.conf) if -f yp.conf;
  unlink (securenets) if -f securenets;
  unlink ($hosts_list) if -f $hosts_list;
  unlink ($public_ip_list) if -f $public_ip_list;
  #unlink ($AUTO_LOGIN_ID_PASSWD) if -f $AUTO_LOGIN_ID_PASSWD;

  # open the config files for DRBL server
  open(DHCPD_OUT,">dhcpd.conf") or die "Can NOT write file \"dhcpd.conf\" \n";
  open(DHCPDITF_OUT,">dhcpd") or die "Can NOT write file \"dhcpd\"! \n";
  open(HOSTS_OUT,">hosts") or die "Can NOT write file \"hosts\"! \n";
  open(NETGROUP_OUT,">netgroup") or die "Can NOT write file \"netgroup\"! \n";
  open(DISKLESS_OUT,">$main_sh") or die "Can NOT write file \"$main_sh\" \n";
  open(EXPORTS_OUT,">exports") or die "Can NOT write file \"exports\" \n";
  open(NFSSERVER_OUT,">nfsserver_all") or die "Can NOT write file \"nfsserver_all\" \n";
  open(YPCONF_SERVER,">yp.conf") or die "Can NOT write file \"yp.conf\" \n";
  open(YP_SECURENETS,">securenets") or die "Can NOT write file \"securenets\" \n";
  open(HOSTS_LIST_OUT,">$hosts_list") or die "Can NOT write file \"$hosts_list\" \n";
  open(SWAPCONF_OUT,">mkswapfile") or die "Can NOT write file \"mkswapfile\" \n";
  # some general option in dhcpd.conf, hosts, $main_sh
  print DHCPD_OUT <<EOF;
default-lease-time			7776000;
max-lease-time				7776000;
option subnet-mask			255.255.255.0;
option domain-name-servers  $nameserver;
option domain-name			"$domain";	
ddns-update-style                       none;
server-name 				drbl;

include "/etc/dhcpd.conf.etherboot.include";
include "/etc/dhcpd.conf.pxe-etherboot.include";

# Keep the filename below and those two include above... Keep the position!!!
# The reason to keep the position (order) is that we can use the 
# last filename to overwrite the previous one if necessary.
# drbl-client-switch will try to uncomment this and change it's filename when
# necessary.
if substring ( option vendor-class-identifier, 0, 9 ) = "Etherboot" {
  #filename "your_nbi_here";
}



EOF


  # set the config file for mkswapfile
  print SWAPCONF_OUT <<SWAP_END;
maxswapsize=$maxswapsize
SWAP_END

  print DHCPDITF_OUT "DHCPDARGS=\"";

  print HOSTS_OUT <<EOF;
127.0.0.1 localhost localhost.localdomain
EOF

  print NETGROUP_OUT "# Added by DRBL, begin\n";

  print NETGROUP_OUT "nodes ";

# write the nis client config file for server, i.e. ypbind will also run in
# DRBL server, so that user can use yppasswd to change his passwd in server.
# The yp server is the DRBL server, too, so we use localhost.
  print YPCONF_SERVER <<YPCONF_SERVER_EOF;
domain $nisdomain server localhost
YPCONF_SERVER_EOF

#set the securenets to control which clients can request YP
  print YP_SECURENETS <<YPAUTH_SERVER_EOF;
255.0.0.0	127.0.0.0
255.255.0.0	192.168.0.0
255.255.255.255 $ip_wan_eth0
YPAUTH_SERVER_EOF

  print DISKLESS_OUT <<EOF;
#!/bin/sh

# **********************************************************************
# File automatically created by drbl.pl, 
# better not to modify this file manually.
# "drbl.pl" is written by K. L. Huang, c00hkl00\@nchc.org.tw,
# especially for Debian, then modified to use with Redhat by
# Steven Shiau, steven\@nchc.org.tw
# **********************************************************************

# Load DRBL setting and functions
if [ ! -f "/opt/drbl/sbin/drbl-conf-functions" ]; then
  echo "Unable to find /opt/drbl/sbin/drbl-conf-functions! Program terminated!" 
  exit 1
fi
. /opt/drbl/sbin/drbl-conf-functions

# get the l10n message
if [ -f "$drbl_setup_path/lang/bash/$language" ] ; then
 . $drbl_setup_path/lang/bash/$language
else
   echo "Not such language option!!!"
   exit 1
fi
 
# store the orig LC_ALL, then set it as C
LC_ALL_org=\$LC_ALL
export LC_ALL=C


# global setting
DRBL_SCRIPT_PATH="$DRBL_SCRIPT_PATH"
drbl_setup_path="$drbl_setup_path"
purge_client="$purge_client"
client_root_passwd="$client_root_passwd"
language="$language"
set_client_system_select="$set_client_system_select"
open_thin_client_option=$open_thin_client_option
client_system_boot_timeout="$client_system_boot_timeout"
collect_mac=$collect_mac
total_client_no=$total_client_no

# the directory with its content that will be copied to client's /var/lib
# Ugly here....
# lib to be copied due to those necessary files for some packages, 
# especially rpm database and alternatives
# Do NOT copy others if you are not sure, such as /var/lib/nfs will cause
# nfslock refuse to start...
# A. alternatives is imkportant for printer setup (printconf-gui in client),
#    without that, printconf-gui or redhat-config-printer won't work.
# NOTE!!! Do not append "/" in the end of the dir name
varlib_2_be_copied="rpm alternatives scrollkeeper slocate xdm xkb"

# If purge_client = no, we'd better to add "-u" for rsync
[ "\$purge_client" = "no" ] && RSYNC_OPT_EXTRA="-u"

# check if drbl-script is installed or not, which is necessary
if ! rpm -q --quiet drbl-script; then
  echo "You did NOT install drbl-script!!! Program terminated!"
  exit 1
fi

# backup the original setting files in DRBL server
[ -f /etc/dhcpd.conf ] && mv /etc/dhcpd.conf /etc/dhcpd.conf.orig
[ -f /etc/exports ] && mv /etc/exports /etc/exports.orig
[ -f /etc/hosts ] && mv /etc/hosts /etc/hosts.orig
[ -f /etc/netgroup ] && mv /etc/netgroup /etc/netgroup.orig
[ -f /var/yp/securenets ] && mv /var/yp/securenets /var/yp/securenets.orig


# copy some config files (dhcpd.conf, exports, yp.conf, hosts_skel...) created
# in the DRBL script files (drblcli_desktop.pl) to DRBL server.
# Note: the hosts_skel will also be created in DRBL perl script, but it will
# copied to /etc as hosts
for icfg in dhcpd.conf exports yp.conf netgroup; do
  cp -f \$icfg /etc/
done
for icfg in mkswapfile dhcpd; do
  cp -f \$icfg /etc/sysconfig/
done

cp -f hosts_skel /etc/hosts
cp -f securenets /var/yp/securenets

EOF

print DISKLESS_OUT q{
  # check if the space is enough to setup DRBL
  echo -n "Checking the necessary disk space..."
  space_check=$($DRBL_SCRIPT_PATH/sbin/check_drbl_setup_space -n $total_client_no)
  rc=$?
  if [ "$rc" -gt 0 ]; then
    total_avail_space=$(echo $space_check | awk '{print $1}')
    drbl_need_space=$(echo $space_check | awk '{print $2}')
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "$msg_total_avail_space: $total_avail_space (MB)"
    echo "$msg_necessary_space_setup_drbl: $drbl_need_space (MB)"
    echo "$msg_total_client_no: $total_client_no"
    echo "$msg_system_maybe_not_enough_space"
    echo "$msg_press_ctrl_c_stop!"
    echo "$msg_press_enter_to_continue"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    read
  fi
  echo "done!"
  echo -n "Cleaning the stale files of the diskless nodes if they exist..."
  # clean the config or setting files in /tftpboot/node_root/etc/diskless-image
  # and /tftpboot/nodes/*/etc/diskless-image.
  # This action is important, otherwise the stalled files will always exist.
  find $drbl_common_root/etc/diskless-image $drblroot/*/etc/diskless-image -name "config" -exec rm -f {} \; &> /dev/null
  find $drbl_common_root $drblroot -name "$public_ip_list" -exec rm -f {} \; &> /dev/null
  echo "done!"
  
  # backup the old MAC address files if the collect MAC is on
  if [ "$collect_mac" = "yes" ]; then
    echo -n "Backuping the old MAC address files..." 
    now=$(date +%F-%k-%M)
    find $drbl_syscfg -name "macadr-eth*.txt" -exec mv {} {}.saved_$now \;
    echo "done!"
  fi
};


#  print DISKLESS_OUT q{
## Reserve the original data in /etc/hosts of DRBL server
## Still have 1 problem, what if hostname is different, while ip is same ???
## -> Solved! in the end of main, use perl system call to replace them or 
## append them.
#hosts_tmp=`mktemp -q /tmp/hosts.XXXXXX || exit 1`
#diff -Nau hosts /etc/hosts |grep -e "^-[^-]" > $hosts_tmp
#cat $hosts_tmp  | sed -e "s/^-//" >> /etc/hosts
#
#};



# Part 2,
# generate DRBL file system for Redhat...
# same with Debian's diskless-newimage
#

print DISKLESS_OUT q{
# Setting
echo "$msg_delimiter_star_line"
# get the distribution name
OS_Version=`check_distribution_name`
echo "$msg_delimiter_star_line"
if [ -z "$OS_Version" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "$msg_not_determine_OS"
  echo "$msg_is_not_supported"
  echo "$msg_press_ctrl_c_stop!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  read
  exit 1 
fi
echo "The version number for your Linux: $OS_Version"

};

print DISKLESS_OUT <<EOF;

# First, common root files
[ ! -d /tftpboot ] && mkdir /tftpboot

case "\$purge_client" in
   [yY][eE][sS])
      echo -n "Completely cleaning old common root files if they exist... " 
      # Clean the stalled files...
      [ -d /tftpboot/node_root/etc ] && rm -rf /tftpboot/node_root/etc
      [ -d /tftpboot/node_root/var ] && rm -rf /tftpboot/node_root/var
      echo " done !"
      
      echo -n "Completely cleaning old nodes if they exist... " 
      # clean old nodes link
      for iclient_link in /tftpboot/192.168.*; do
        [ -L "\$iclient_link" ] && rm -f \$iclient_link
      done
      
      # then, clean old node's files
      for iclient in /tftpboot/nodes/192.168.*; do
        [ -d "\$iclient" ] && rm -rf \$iclient
      done
      echo " done !"
      ;;
   *)
      echo "Keeping the old common root files if they exist... " 
      echo "Keeping old nodes if they exist... " 
      ;;
esac

echo -n "Creating common root files... This might take several minutes..."
echo -n "."
for d in home mnt proc tmp usr opt root dev var lib initrd sys media; do
	mkdir -p /tftpboot/node_root/\$d
done

echo -n "."
for d in floppy cdrom loop disk usb; do
	mkdir -p /tftpboot/node_root/mnt/\$d
done

# copy /sbin, /bin to node_root
echo -n "."

# Note!!! For rsync, do NOT to append "/" in the /sbin, .i.e. NO /sbin/
rsync -a \$RSYNC_OPT_EXTRA /sbin /tftpboot/node_root/
# put the real init into common root as init.orig, DRBL client will have 
# an "init" to run before this init.orig
rsync -a \$RSYNC_OPT_EXTRA /sbin/init /tftpboot/node_root/sbin/init.orig

#
echo -n "."
rsync -a \$RSYNC_OPT_EXTRA /bin /tftpboot/node_root/

echo -n "."
# Creat a file /tftpboot/node_root/sbin/fsck.nfs to let rc.sysinit use 
# "fsck.nfs" always successfully
echo "#!/bin/sh
exit 0" > /tftpboot/node_root/sbin/fsck.nfs
chmod 755 /tftpboot/node_root/sbin/fsck.nfs

# copy /lib excluding /lib/modules
echo -n "."
#(cd /lib && tar cplf - . --exclude modules ) | ( cd /tftpboot/node_root/lib && tar xpfm -)

# Steven todo, make sure it's right ?
# /tftpboot/node_root/lib/security is important for PAM, if we remove/update it,
# clients have to reboot, otherwise user can not login in the client.
# So it's better to keep /tftpboot/node_root/lib/security/ without updating.
if [ -d /tftpboot/node_root/lib/security ]; then
  rsync -a \$RSYNC_OPT_EXTRA --exclude=modules/ --exclude=security/ /lib /tftpboot/node_root/
else
  rsync -a \$RSYNC_OPT_EXTRA --exclude=modules/ /lib /tftpboot/node_root/
fi

# For x86_64 (FC3)
# TODO: How about MDK ?
[ -d "/lib64" ] && rsync -a \$RSYNC_OPT_EXTRA /lib64 /tftpboot/node_root/

# then copy the modules for clients to /tftpboot/$ip/lib/modules
# Steven to do
# cp -r xxx/lib/modules/2.4.x /tftpboot/$ip/lib/modules
# chown -r root.root /tftpboot/lib/modules/2.4.x
#tar xzf files/modules.tgz -C /tftpboot/node_root/lib
# need to be modified... How to know the kernel version ? 
# so that we do not have to copy a lot of useless modules
echo -n "."
DRBL_KVER="`cat /tftpboot/nbi_img/kernel_version_in_initrd.txt`"

# from drbl-setup 1.2, the kernel image will be installed directly into
# /tftpboot/node_root/lib/modules/, so it's not necessary to copy them.
# However, if we can find drbl kernel modules in drbl server, just copy them...
# This intention is to backward compatable with drbl-setup 1.1 and 
# previous version
# For RedHat/Fedora, we can use the new method (install the kernel directory in
# to /tftpboot/node_root/lib/modules/ if no drbl kernel is available).
# For Mandrake, we must have a drbl kernel in apt repository to avoid 
# the devfs problem.

echo -n "The DRBL client will use kernel \$DRBL_KVER..."
if [ -n "\$DRBL_KVER" -a -d "/lib/modules/\$DRBL_KVER" -a -f "/lib/modules/\$DRBL_KVER/modules.dep" ] ; then 
  # check if -f "/lib/modules/\$DRBL_KVER/modules.dep is important.
  # this will avoid copying an empty kernel modules tree... just a better check.
  # it will happen if use compiled a module and install it, when he remove
  # the kernel by rpm -e ..., the /lib/modules/kernel-xxx will still exist.
  # Steven todo... How about adding rpm -q kernel$SMP_OPT#$DRBL_KVER checking ?
  echo -n "copying /lib/modules/\$DRBL_KVER to common root..."
  rsync -a \$RSYNC_OPT_EXTRA /lib/modules/\$DRBL_KVER /tftpboot/node_root/lib/modules/
fi

# copy /etc to template node
echo -n "."
# /etc/sysconfig/drbl/ is for server only.
rsync -a --exclude=/etc/sysconfig/drbl/ \$RSYNC_OPT_EXTRA /etc /tftpboot/node_root

# clean the ssh key, so that client will create its own. 
key_file="ssh_host_dsa_key ssh_host_dsa_key.pub ssh_host_key ssh_host_key.pub ssh_host_rsa_key ssh_host_rsa_key.pub"
for ik in \$key_file; do
  if diff /etc/ssh/\$ik /tftpboot/node_root/etc/ssh/\$ik >/dev/null 2>&1; then
     echo -n "Cleaning the ssh key file \$ik copied from server..."
     rm -f /tftpboot/node_root/etc/ssh/\$ik
     echo "done!"
  fi
done

# make sure the hostname of server in 127.0.0.1 in /etc/hosts 
# is not copied to clients.
# like
#-----------------------------------------------------------
#127.0.0.1               rh9 localhost.localdomain localhost
#-----------------------------------------------------------
# if it is copied to client, client will have some problem to connect to server
# such as yppasswd will complain the yppasswdd is NOT running on "rh9".
HOSTNAME_SRV=`/bin/hostname`
if [ -n "\$(grep \$HOSTNAME_SRV /tftpboot/node_root/etc/hosts |grep 127.0.0.1)" ]; then
 perl -p -i -e "s/127.0.0.1.*/127.0.0.1		localhost.localdomain localhost/g" /tftpboot/node_root/etc/hosts
fi

# create mkswapfile to /tftpboot/node_root/etc/init.d/
# This must before service to add
cp -f \$drbl_setup_path/files/mkswapfile \$drbl_setup_path/files/drblthincli /tftpboot/node_root/etc/init.d
chown root.root /tftpboot/node_root/etc/init.d/mkswapfile /tftpboot/node_root/etc/init.d/drblthincli

# If MDK, we put the firstboot.MDKXX.drbl to common root's /etc/init.d as
# firstboot.
case "\$OS_Version" in
    "MDK9.2"|"MDK10.0"|"MDK10.1")
      cp -f \$drbl_setup_path/files/firstboot.\$OS_Version.drbl /tftpboot/node_root/etc/init.d/firstboot
    ;;
esac


EOF

print DISKLESS_OUT q{

   
   # remove the unnecessary service, 
   # why chkconfig can not accept "chkconfig --del *" ???
   # First, remove all the service
   #service_del=$(cd /etc/init.d/; ls *)
   for i in /etc/init.d/*; do
    i="`basename $i`"
    # skip those do not support chkconfig, or actually, they are not services.
    if [ "$i" != "dualconf" -a "$i" != "functions" -a "$i" != "halt" -a "$i" != "killall" -a "$i" != "single" -a "$i" != "mandrake_consmap" -a "$i" != "mandrake_everytime" -a "$i" != "mandrake_firstime" -a "$i" != "usb" ]; then
      /usr/sbin/chroot /tftpboot/node_root/ /sbin/chkconfig --del $i
    fi
   done
};

print DISKLESS_OUT <<EOF;
   # 2nd, add the service which DRBL client need

   service_added=""
   case "\$OS_Version" in
     RH*|FC*)
       service_added_list="netfs portmap crond nfslock sshd crond xfs ypbind kudzu firstboot drblthincli $mkswapfile"
       ;;
     MDK*)
       service_added_list="netfs portmap crond nfslock sshd crond xfs ypbind firstboot harddrake dm alsa sound keytable drblthincli $mkswapfile"
       ;;
   esac
   for iser in \$service_added_list; do
      [ -e "/etc/init.d/\$iser" ] && service_added="\$service_added \$iser"
   done
EOF

print DISKLESS_OUT q{
   # For some distribution, add special service if DRBL is configured to run
   # some desktop application, such as iiimf, cups.

   # IIim in FC2, iiim in FC3, scim for MDK 10.1
   case "$OS_Version" in
     FC2)
        if [ -n $(LC_ALL=C chkconfig --list IIim 2>/dev/null | awk '/5:on/ {print $7}') -o -n $(LC_ALL=C chkconfig --list IIim 2>/dev/null | awk '/3:on/ {print $5}') ]; then
           service_added="$service_added IIim"
        fi
        ;;
     FC3)
        if [ -n $(LC_ALL=C chkconfig --list iiim 2>/dev/null | awk '/5:on/ {print $7}') -o -n $(LC_ALL=C chkconfig --list iiim 2>/dev/null | awk '/3:on/ {print $5}') ]; then
           service_added="$service_added iiim"
        fi
	# add this for USB automount...
        service_added="$service_added haldaemon messagebus"
        ;;
   esac

   # add the services specified by user
   if [ -f /etc/sysconfig/drbl/client-extra-service ]; then
     . /etc/sysconfig/drbl/client-extra-service
     service_added="$service_added $service_extra_added"
   fi
   echo "The startup services for DRBL client are:"
   echo "$service_added"

   #
   for i in $service_added; do
      /usr/sbin/chroot /tftpboot/node_root/ /sbin/chkconfig --add $i
   done

   vmware_as_server=$(grep "VMWare Inc" /proc/pci)
   # for VMWare, you'd better to install the VMWare tools, 

   # create an automatically X config program, if you like, but for Redhat 8.0,
   # better to use Redhat 8.0's /etc/init.d/firstboot

   # First, clean the XF86Config, 
   # let redhat-cfg-xfree86 in /etc/init.d/firstboot
   # to create the first one.

   if [ -n "$vmware_as_server" ]; then
     [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
     echo "It's VMWare as DRBL server ..., If you want to use X Window, make sure you already installed VMWare tools."
     [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
   fi
   # Remove XF86Config and xorg.conf in common root
   [ -f /tftpboot/node_root/etc/X11/XF86Config ] && rm -f /tftpboot/node_root/etc/X11/XF86Config*
   [ -f /tftpboot/node_root/etc/X11/xorg.conf ] && rm -f /tftpboot/node_root/etc/X11/xorg.conf*
   # remove the firstboot setting to aviod it say NO
   [ -f /tftpboot/node_root/etc/sysconfig/firstboot ] && rm -f /tftpboot/node_root/etc/sysconfig/firstboot 
   # disable the /usr/sbin/firstboot in the firstboot service, we should not
   # reconfig ntp, user accounts for clients...
   perl -p -i -e 's|^(\s*/usr/sbin/firstboot)$|#$1|g' /tftpboot/node_root/etc/init.d/firstboot
   
   RH_version=`grep 7.3 /etc/issue`
   # RH7.3 has no firstboot, so we add a service setupx to do that.
   if [ "$RH_version" != "" ]; then
     tar xzf $drbl_setup_path/files/setupx_redhat.tgz -C /tftpboot/node_root/etc/rc.d
     # enable the setupx for this template
     /usr/sbin/chroot /tftpboot/node_root /sbin/chkconfig --add setupx
   fi
   
   # remove the script in rc[0,6].d to let the client can halt and reboot
   drbl_client_must_remove="netfs network killall"
   for i in $drbl_client_must_remove; do 
      rm -f /tftpboot/node_root/etc/rc0.d/*$i*
      rm -f /tftpboot/node_root/etc/rc6.d/*$i*
   done
   
   # remove the etc/modules.conf in template so that the kudzu in the client can create their own hardware config file.
   find /tftpboot/node_root/etc/ -name "modules.conf*" -exec rm -f {} \;

   # remove the template's etc/sysconfig/hwconf which kudzu will log
   [ -f /tftpboot/node_root/etc/sysconfig/hwconf ] && rm -f /tftpboot/node_root/etc/sysconfig/hwconf
   
   # The root over NFS mount is done in sbin/init which Steven modified,
   # $nfsserver:/tftpboot/node_root
   # so remove this file
   [ -f /tftpboot/node_root/etc/fstab ] && rm -f /tftpboot/node_root/etc/fstab

   # clean the rhn config, client should not do that.
   [ -d /tftpboot/node_root/etc/sysconfig/rhn ] && rm -rf /tftpboot/node_root/etc/sysconfig/rhn 2> /dev/null
   
   # create new init to mount separate client's fstab and ...
   # Ref. Debian's diskless_newimage, /var/lib/diskless/default/root/sbin/init
   # The original init has already renamed as init.orig
   
   cp -f $drbl_setup_path/files/init.drbl /tftpboot/node_root/sbin/init
   chown root.root /tftpboot/node_root/sbin/init
   chown 755 /tftpboot/node_root/sbin/init

   # mkdir special directory etc/diskless-image for each diskless host to mount its fstab
   #
   mkdir -p /tftpboot/node_root/etc/diskless-image

   # copy dev tarball to /tftpboot/node_root/etc/diskless-image
   if [ -x "/tftpboot/node_root/sbin/udevstart" ]; then
     echo -n "Using udev for clients... " 
   elif [ -f "$drbl_pkgdir/dev.tgz" ]; then
     echo -n "Using old-style dev for clients... " 
     cp -f $drbl_pkgdir/dev.tgz /tftpboot/node_root/etc/diskless-image
   else
     [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
     echo "Can NOT find udev or the dev.tgz, did you already setup the DRBL server ?"
     echo "Please press Ctrl-C to stop the program!"
     [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
     read
     exit 1 
   fi
};

print DISKLESS_OUT <<EOF;
   # set the init to user specifies
   perl -p -i -e "s/^id:[1-5]:initdefault:/id:$CLIENT_INIT:initdefault:/g" /tftpboot/node_root/etc/inittab
EOF

print DISKLESS_OUT q{
   # set the tftp to on when xinetd start
   # backup it first
   #cp /etc/xinetd.d/tftp /etc/xinetd.d/tftp.drblsave
   perl -p -i -e "s/disable.*=.*/disable                 = no/g" /etc/xinetd.d/tftp 
   # set the tftp working directory to be /tftpboot/nbi_img 
   # to have higher security.
   perl -p -i -e "s/server_arg.*=.*/server_args		= -s \/tftpboot\/nbi_img/g"  /etc/xinetd.d/tftp
      
};

print DISKLESS_OUT <<EOF;
# create a config file for each diskless host to mount its fstab
# Steven to do, what's master ?
cat <<-CONFIG_END > /tftpboot/node_root/etc/diskless-image/config

#master=drblsrv
#nfsserver=$nfsserver_default
nfsserver_default=$nfsserver_default
nfsimagedir=/tftpboot/node_root
nfshostsdir=/tftpboot/nodes
#nfshomedir=/home
nameserver=$nameserver
#domain=$domain

CONFIG_END

# for clients' public IP 
# if the file $public_ip_list is created, copy it
[ -f "$public_ip_list" ] && cp -f $public_ip_list /tftpboot/node_root/etc/diskless-image/

# copy the collected MAC addresses to drbl sysconfig
if [ "$collect_mac" = "yes" ]; then
  cp -f macadr-eth*.txt $drbl_syscfg/ &> /dev/null
fi


# write the nis client config file for template
cat <<-YPCONF_ETH0 > /tftpboot/node_root/etc/yp.conf
domain $nisdomain server $nisserver
YPCONF_ETH0

# write the resolv.conf 
[ -f /tftpboot/node_root/etc/resolv.conf ] && rm -rf /tftpboot/node_root/etc/resolv.conf

for nameserver in $nameserver_
do 
  echo "nameserver \$nameserver" >> /tftpboot/node_root/etc/resolv.conf
done

# "ln -fs tmp/boot/ boot" in template 
# insert "mkdir tmp/boot" in rc.sysinit of other clients, because it's tmpfs
# so that /sbin/mkkerneldoth in rc.sysinit can creat file "/boot/boot.h"
# Steven to do
cp -rf \$drbl_setup_path/files/rc.sysinit.\$OS_Version.drbl /tftpboot/node_root/etc/rc.d/rc.sysinit
(cd /tftpboot/node_root; ln -fs tmp/boot boot)

# create the CLEAN rc.local to avoid some command copy from server
#  1st, clean rc.local 
[ -f /tftpboot/node_root/etc/rc.d/rc.local ] && rm -f /tftpboot/node_root/etc/rc.d/rc.local

#  2nd, create a clean rc.local 
cat <<-RC_LOCAL > /tftpboot/node_root/etc/rc.d/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

# For Mandrake, harddrake will not create cdrom link automatically... so
# detect it and create it.
# While for Redhat, kudzu will do that. Anyway, we just do it.
if [ ! -e "/dev/cdrom" ]; then
  cddev=\\\$\(\$DRBL_SCRIPT_PATH/bin/detect_cdrom\)
  [ -n "\\\$cddev" ] && ln -fs /dev/\\\$cddev /dev/cdrom
fi

# run the time sync when client boots.
[ -x "/etc/cron.daily/timesync" ] && /etc/cron.daily/timesync &

RC_LOCAL

#change its mode
chown root.root /tftpboot/node_root/etc/rc.d/rc.local
chmod 775 /tftpboot/node_root/etc/rc.d/rc.local

# modify the template's etc/init.d/halt, remove all the umount command
cp -rf \$drbl_setup_path/files/halt.\$OS_Version.drbl /tftpboot/node_root/etc/init.d/halt

# Force to use the /proc/mounts, not use the /etc/mtab, otherwise they will
# NOT sync to each other
[ -f /tftpboot/node_root/etc/mtab~ ] && rm -rf /tftpboot/node_root/etc/mtab~
ln -fs /proc/mounts /tftpboot/node_root/etc/mtab

EOF

# collect the account in server, remove them in the clients
# i.e. we will use the YP, not local account
open (PASSWD, "/etc/passwd") or die "Can NOT open file \/etc\/passwd";
my @user_now;
my @grp_now;
my @user_to_del;
#my $uid_del_begin="501";
while (<PASSWD>) {
  chomp;
  $line = $_;
  my @user_now = split (":", $line);
  #print "now it's $user_now[0] $user_now[2]\n";
  if ( $user_now[2] >= $uid_del_begin ) {
       push @user_to_del, $user_now[0];
  }
}
close(PASSWD);
print "user to del: @user_to_del\n" if $verbosity >= 2;

print DISKLESS_OUT <<EOF_ACNT;
# delete the users in template, i.e. we will use the YP, not local account 
# in clients
echo -n "Deleting the accounts (except root) in the DRBL common root template..."
newroot="/tftpboot/node_root/"
usrdel_file_need="/usr/sbin/userdel"
cp --parents \$usrdel_file_need \$newroot
usrdel_lib_need=\$(ldd /usr/sbin/userdel | cut -d" " -f3)
cp --parents \$usrdel_lib_need \$newroot
for u in @user_to_del; do
  if grep -q "^\$u:" \$newroot/etc/passwd; then
    /usr/sbin/chroot \$newroot /usr/sbin/userdel \$u
  fi
done
echo "done!"
EOF_ACNT

print DISKLESS_OUT q{
case "$OS_Version" in
     RH8.0|RH9|FC[1-3])
        # enable the NIS client for this template
        echo -n "Enabling the NIS client for this DRBL common root template..."
        newroot="/tftpboot/node_root/"
        file_need="/usr/sbin/authconfig /usr/sbin/pwconv /usr/sbin/grpconv"
        cp --parents $file_need $newroot
        lib_need=$(ldd /usr/sbin/authconfig | cut -d" " -f3)
        cp --parents $lib_need $newroot
        /usr/sbin/chroot $newroot /usr/sbin/authconfig --enablenis --kickstart --nostart 2>/dev/null
        echo "done!"
	;;
     MDK9.2|MDK10.0|MDK10.1)
      ## for Mandrake, there is no authconfig, use drakauth, but not interactive ?
      continue
esac

echo -n "Creating some necessary files in the DRBL common root template."
# Insert a line in /etc/sysconfig/mouse, set the DEVICE=/dev/psaux or /dev/mouse
# Steven to do
# autodetect the mouse, while we force to use "ln -fs /dev/mouse /dev/psaux" in 
# rc.sysinit, this should be the bug of Redhat 8.0, so we solve it temporarily.
#
#newroot="/tftpboot/node_root/"
#mcfg_file_need="/usr/sbin/mouseconfig"
#cp --parents $mcfg_file_need $newroot
#mcfg_lib_need=$(ldd /usr/sbin/mouseconfig | cut -d" " -f3)
#cp --parents $mcfg_lib_need $newroot
#/usr/sbin/chroot $newroot /usr/sbin/mouseconfig --kickstart --modifyx --device psaux generic3ps/2

echo -n "."
# set the arguments "-q" in kudzu to let system do configuration that
# doesn't require user input
newroot="/tftpboot/node_root/"
#perl -p -i -e "s/^KUDZU_ARGS=.*/KUDZU_ARGS=-q/" $newroot/etc/init.d/kudzu 
echo "KUDZU_ARGS=-q" >> $newroot/etc/sysconfig/kudzu

echo -n "."
# write the ntp server setting
if ! grep -q "^server pool.ntp.org" /etc/ntp.conf ; then
  echo "server pool.ntp.org" >> /etc/ntp.conf
fi
if ! grep -q "^server stdtime.sinica.edu.tw" /etc/ntp.conf ; then
  echo "server stdtime.sinica.edu.tw" >> /etc/ntp.conf
fi

# set the restrict for ntp clients
if ! grep -q "^restrict default ignore" /etc/ntp.conf ; then
  echo "restrict default ignore" >> /etc/ntp.conf
fi

if ! grep -q "^restrict 127.0.0.1" /etc/ntp.conf ; then
  echo "restrict 127.0.0.1" >> /etc/ntp.conf
fi

};

print DISKLESS_OUT q{
echo -n "."
# create the /var in template, only directory 
# Other directory in /var/lib/ is important for some applications.
# but /var/lib/rpm/* is necessary for rpm database,
# /var/spool/mail is necessary for each user.
# It's better to export /var/lib all.

# use rsync will be easier....Thanks to Wayne Davison wayned@samba.org
rsync -a $RSYNC_OPT_EXTRA --include="*/" --exclude="*" /var /tftpboot/node_root/

echo -n "."
# ugly here....
# copy those necessary files for some packages, especially rpm database.
# Do NOT copy others if you are not sure, such as /var/lib/nfs will cause
# nfslock refuse to start...
# A. alternatives is imkportant for printer setup (printconf-gui in client),
#    without that, printconf-gui or redhat-config-printer won't work.
for ilib in $varlib_2_be_copied; do
  [ -d "/var/lib/$ilib" ] && rsync -a $RSYNC_OPT_EXTRA /var/lib/$ilib /tftpboot/node_root/var/lib/
done

};

# print all the nfsserver to /tftpboot/node_root/etc/diskless-image/config
print NFSSERVER_OUT "NFSSERVER_LIST=\"";
foreach my $k1 ( sort(keys %$rHoH) ) {
  if( $k1=~/general/ ) { next; } # skip general block
  my $nfsserver=$rHoH->{$k1}{"NFSSERVER"};
  #---------------
  my $interface=$rHoH->{$k1}{"INTERFACE"};
  my $NIC_sys="/etc/sysconfig/network-scripts/ifcfg-$interface";
  # Try to get setting from system also
  
  my $rNIC = read_config("$NIC_sys");
  # use the NIC "eth1, eth2..." of DRBL server as default nfsserver_sys...
  my $nfsserver_sys=$rNIC->{"general"}{"IPADDR"};
  # set nfsserver, the priority: use the config file first, if unset, then use the value in system
  if ( ! $nfsserver ) { 
   $nfsserver = $nfsserver_sys; 
   print "* nfsserver is not set in config file, \nthe one \"$nfsserver\" got from system will be used.\n" if $verbosity >= 2;   
  }
  
  # check if the values are set in config file or system  
  unless ( $nfsserver ) {
     print "Error! NFSSERVER is unset!\n";
     print "Please set nfsserver in config file \"$_[0]\" or IPADDR in $NIC_sys.\n";
     exit;
  }
    #---------------
  #print "nfsserver: $nfsserver\n";
  print NFSSERVER_OUT "$nfsserver ";

    # next one
    $i++;
  };
print NFSSERVER_OUT "\"";

print DISKLESS_OUT q{
echo -n "."
# append all the nfsserver to /tftpboot/node_root/etc/diskless-image/config
cat nfsserver_all >> /tftpboot/node_root/etc/diskless-image/config

echo "done!"
};

print "$delimiter{\"star_line\"}\n".
      "$delimiter{\"dash_line\"}\n";
# try to get if the kernel running the server supports NFS over TCP, if not, ust NFS over UDP
$nfsd_tcp_rlt=system(". $DRBL_SCRIPT_PATH/sbin/drbl-functions; check_kernel_nfsd_tcp_config");
if ($nfsd_tcp_rlt == 256) { 
	# set the protocol as udp
        $nfs_protocol="udp";
}else{
	# set the protocol as tcp
        $nfs_protocol="tcp";
}
$nfs_protocol_uc=uc $nfs_protocol;
print "$lang_deploy{\"server_kernel_nfsd_support\"} ".
      colored ("NFS over $nfs_protocol_uc", 'red').
      "!\n".
      colored ("$lang_deploy{\"change_kernel_notes\"}\n", 'red').
      "$lang_deploy{\"press_enter_to_continue\"}";
      chomp($line=<STDIN>);
print "$delimiter{\"dash_line\"}\n";

# Part 3,
# create every client node, like Debian's diskless-newhost
#
  print DISKLESS_OUT <<EOF;
# create every client node, like Debian's diskless-newhost
EOF
  foreach my $k1 ( sort(keys %$rHoH) ) {
    if( $k1=~/general/ ) { next; } # skip general block
    my $interface=$rHoH->{$k1}{"INTERFACE"};
    my $network=$rHoH->{$k1}{"NETWORK"};
    my $nfsserver=$rHoH->{$k1}{"NFSSERVER"};
    my $bootserver=$rHoH->{$k1}{"BOOTSERVER"};
    my $nisserver=$rHoH->{$k1}{"NISSERVER"};
    my $nbi=$rHoH->{$k1}{"NBI"};
    my $mac=$rHoH->{$k1}{"MAC"};
    my $ip_start=$rHoH->{$k1}{"IP_START"};
    my $range=$rHoH->{$k1}{"RANGE"};

    if( length($bootserver)==0 ) { $bootserver=$nfsserver; }
    if( length($nisserver)==0 ) { $nisserver=$nfsserver; }
    if( length($nbi)==0 ) { $nbi=$rHoH->{"general"}{"NBI"}; }
    my $NET_sys="/etc/sysconfig/network";
    my $NIC_sys="/etc/sysconfig/network-scripts/ifcfg-$interface";
    #print "NIC_sys is $NIC_sys\n";
    #---------------
    # Try to get setting from system also
    
    my $rNET = read_config("$NET_sys");
    my $rNIC = read_config("$NIC_sys");
    # use the NIC "eth1, eth2..." of DRBL server as default nfsserver_sys...
    my $hostname_sys=$rNET->{"general"}{"HOSTNAME"};
    my $network_sys=$rNIC->{"general"}{"NETWORK"};
    my $ipaddr_sys=$rNIC->{"general"}{"IPADDR"};
    # the IP address for server is the NFS server for client
    my $nfsserver_sys=$rNIC->{"general"}{"IPADDR"};
    my $netmask_sys=$rNIC->{"general"}{"NETMASK"};
    my $bootserver_sys=$nfsserver_sys;
    my $nisserver_sys=$nfsserver_sys;
    #print "hostname, network, nfsserver, bootserver, nisserver got from system are \n$hostname_sys, $network_sys, $nfsserver_sys, $bootserver_sys, $nisserver_sys\n";
    # set nfsserver, bootserver, nisserver address, the priority: use the config file first, if unset, then use the value in system
   
    # If hostname_prefix unset, try to set it as that of server
    if ( ! $hostname_prefix ) { 
      @hostname_sp_sys=split(/\./,$hostname_sys);
      $hostname_prefix="$hostname_sp_sys[0]"; 
    }
    # Get the interface number (i.e eth1 -> extract "1")
    # and set it as a part of hostname, it will be like node-1...
    my $grp_no = $interface;
    $grp_no =~ s/eth//g;
    # If IP alias, eth0:1 will be 0:1, which is not a legal name in dhcpd.
    # so we change 0:1 to 0_1
    $grp_no =~ s/:/_/g;
    $hostname = "$hostname_prefix"."-$grp_no"; 
    print "The hostname set for client is: \"$hostname\".\n" if $verbosity >= 2;

    unless ( $netmask_sys ) {
       print "Error! NETMASK is unset!\n";
       print "Please set NETMASK in $NIC_sys\n";
       exit;
    }

    if ( ! $network ) { 
     # if NETWORK is not specified in DRBL config file, use the one from system
     if ( $network_sys ) { 
        $network = $network_sys; 
        print "* network is not set in config file, \nthe one \"$network\" got from system will be used.\n" if $verbosity >= 2;   
     } else {
       # if NETWORK is not specified in system config file, use calculated one
       $network = `LC_ALL=C /bin/ipcalc --network $ipaddr_sys $netmask_sys | cut -d"=" -f2`;
       chomp($network);
       print colored ("The NETWORK is NOT set in $NIC_sys, use the calculated NETWORK=$network.\n", 'red').
             "$delimiter{\"dash_line\"}\n";
     }
    }

    if ( ! $nfsserver ) { 
     $nfsserver = $nfsserver_sys; 
     print "* nfsserver is not set in config file, \nthe one \"$nfsserver\" got from system will be used.\n" if $verbosity >= 2;   
    }
    if ( ! $bootserver ) { 
     $bootserver = $bootserver_sys; 
     print "* bootserver is not set in config file, \nthe one \"$bootserver\" got from system will be used.\n" if $verbosity >= 2;   
     ot
    }
    if ( ! $nisserver ) { 
     $nisserver = $nisserver_sys; 
     print "* nisserver is not set in config file, \nthe one \"$nisserver\" got from system will be used.\n" if $verbosity >= 2;   
    }
    
    # Last check if the values are set in config file or system  
    unless ( $hostname ) {
       print "Error! HOSTNAME is unset!\n";
       print "Please set hostname in config file \"$_[0]\" or HOSTNAME in $NIC_sys.\n";
       exit;
    }
    unless ( $nfsserver ) {
       print "Error! NFSSERVER is unset!\n";
       print "Please set nfsserver in config file \"$_[0]\"\n";
       exit;
    }
    unless ( $bootserver ) {
       print "Error! BOOTSERVER is unset!\n";
       print "Please set bootserver in config file \"$_[0]\"\n";
       exit;
    }
    unless ( $nisserver ) {
       print "Error! NISSERVER is unset!\n";
       print "Please set nisserver in config file \"$_[0]\"\n";
       exit;
    }
    
    # go 
    @nfsserverIp=split(/\./,$nfsserver);
    @networkIp=split(/\./,$network);

    print DHCPD_OUT <<EOF;
subnet $network netmask 255.255.255.0 {
    option broadcast-address	$networkIp[0].$networkIp[1].$networkIp[2].255;
    option routers $bootserver;
    next-server $bootserver;

EOF
    # if the itnerface is alias, print the original interface
    # i.e. if eth0:1, we print eth0
    my $interface_real = $interface;
    $interface_real=~ s/:.*//g;
    print DHCPDITF_OUT "$interface_real ";

    # generate hosts
    $SERVER_HOSTNAME=readpipe("hostname");
    chop($SERVER_HOSTNAME);
    print HOSTS_OUT <<EOF;
$nfsserver nfsserver_$k1.$domain nfsserver_$k1 $SERVER_HOSTNAME
EOF

    # range option, we have to create the IP table file
    if( length($mac)==0 && length($range)!=0 ) {
      chomp ( $temprange = `LC_ALL=C mktemp /tmp/drbl_range.XXXXXX` );
      open(RANGE_OUT,">$temprange");
      my($rs,$re)=split(/-/,$range,2);
      # get the initial value in the last set of digits in the IP address 
      # from range starting no.
      $ip_start=$rs;
      for($i=$rs;$i<=$re;$i++) {
        my $rg_ip="$networkIp[0].$networkIp[1].$networkIp[2].$i";
	print "checking IP is same with nfsserver or not, nfsserver is $nfsserver, ip is $rg_ip!\n" if $verbosity >= 2;
	if ( "$rg_ip" ne "$nfsserver" ) {
          print RANGE_OUT "$networkIp[0].$networkIp[1].$networkIp[2].$i\n";
	}
	else {
	  # skip the IP same with nfsserver.
          my $next_ip=$i;
	  $next_ip++;
          $next_ip="$networkIp[0].$networkIp[1].$networkIp[2].$next_ip";
	  print "* The client IP address you assigned is same with nfsserver: $rg_ip, \n ---> the next IP address ($next_ip) will be used for that client!\n";
	  # increase the end of range by 1 
	  $re++;
	}
      }
      close(RANGE_OUT);
    }

    # open mac or range file
    # set the initial IP address in the subnet for fixed IP client (MAC) or range option
    #$i=1;
    $i=$ip_start;
    if( length($mac)!=0 ) { open(MAC_IN,$mac) or die "Can NOT find MAC address file \"$mac\"! \n"; }
    elsif( length($range)!= 0 ) { open(MAC_IN,"$temprange") or die "Can NOT find IP address range temp file \"$temprange\"! \n"; }
    else {}

    # MAC_IN is both for MAC and RANGE readin number
    while(<MAC_IN>) {
      chop;
      if($nfsserverIp[0]==$networkIp[0] &&
         $nfsserverIp[1]==$networkIp[1] &&
         $nfsserverIp[2]==$networkIp[2] &&
         $nfsserverIp[3]==$i) { 
         $i++; 
      }

      # hostname for client
      # the name will like fc2-101, fc2-201...,i.e. like
      # prefix-{ethx}{client no}, it's impossible we will have more than 100
      # DRBL clients connectted to each ethernet card of the server.
      # So forget about something like fc2-1-001, fc2-1-002...
      $label="";
      if($i<10) { $label=$hostname."0".$i; }
      elsif($i<100) { $label=$hostname.$i; }
      elsif($i>254) { last; } # minus 2 ip: $network.0 $network.255

      # ip
      if( length($mac)!=0 ) { 
	# mac 
        if($nfsserverIp[0]==$networkIp[0] &&
           $nfsserverIp[1]==$networkIp[1] &&
           $nfsserverIp[2]==$networkIp[2] &&
           $nfsserverIp[3]==$i) { 
           $i++; 
        }
        $ip="$networkIp[0].$networkIp[1].$networkIp[2].$i";

        # generate dhcpd.conf      
	if ( ! $nbi ) {
	  # without nbi set in config file
          print DHCPD_OUT <<EOF;
    host $label {
        hardware ethernet  $_;
        fixed-address $ip;
        option host-name "$label";
    }
EOF
	}else{
  	  # without nbi set in config file
          print DHCPD_OUT <<EOF;
    host $label {
        hardware ethernet  $_;
        fixed-address $ip;
        filename "$nbi";
    }
EOF
        }
      } elsif( length($range)!=0 ) { # range
        $ip=$_;
      }
      else {}
      
      # clean the temp range file
      unlink ($temprange) if -f $temprange;

      # generate hosts
      print HOSTS_OUT <<EOF;
$ip $label.$domain $label
EOF
      # generate netgroup
      print NETGROUP_OUT "($label,,) ";

      # append the hosts to hosts_list
      print HOSTS_LIST_OUT <<EOF;
$ip
EOF
      # generate exports
      print EXPORTS_OUT <<EOF;
/tftpboot/node_root $ip(ro,sync,async,no_root_squash)
/tftpboot/nodes/$ip/ $ip(rw,sync,async,no_root_squash)
/usr $ip(ro,sync,async,no_root_squash)
/opt $ip(ro,sync,async,no_root_squash)
/home $ip(rw,sync,async,no_root_squash)
/var/spool/mail $ip(rw,sync,async,root_squash)

EOF

#
        print DISKLESS_OUT <<EOF;
echo -n "Creating DRBL client: "
[ "\$BOOTUP" = "color" ] && \$SETCOLOR_SUCCESS
echo -n "$label $ip... "
[ "\$BOOTUP" = "color" ] && \$SETCOLOR_NORMAL
# Steven to do, like Debian's diskless-newhost
mkdir -p /tftpboot/nodes/$ip
mkdir -p /tftpboot/nodes/$ip/root
mkdir -p /tftpboot/nodes/$ip/dev
rsync -a \$RSYNC_OPT_EXTRA /tftpboot/node_root/etc /tftpboot/nodes/$ip/

# copy the node_root/var to client,
# we do not have to copy /tftproot/node_root/var/lib/rpm (big directory!), 
# it will be mounted. i.e. # we just share that for every client.
rsync -a \$RSYNC_OPT_EXTRA --exclude=rpm/ /tftpboot/node_root/var /tftpboot/nodes/$ip/

# Instead, we need mount point /tftpboot/nodes/$ip/var/lib/rpm 
# and /tftpboot/nodes/$ip/var/spool/mail
mkdir -p /tftpboot/nodes/$ip/var/lib/rpm /tftpboot/nodes/$ip/var/spool/mail

# comment this, now we use "mount -t tmpfs none /dev" in the beginning of 
# initrd, so we will use mknode to create console, null, tty[0-5] runtime
## must have some dev for initrd when boot
#cp -a /dev/console /dev/null /dev/tty[0-5] /tftpboot/nodes/$ip/dev

# output the file to $ip/etc/fstab

cat <<-FSTAB > /tftpboot/nodes/$ip/etc/fstab
$nfsserver:/tftpboot/node_root  /       nfs     ro,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
$nfsserver:/tftpboot/node_root/var/lib/rpm /var/lib/rpm       nfs     ro,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
$nfsserver:/tftpboot/nodes/$ip/etc      /etc    nfs     rw,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
$nfsserver:/tftpboot/nodes/$ip/var      /var    nfs     rw,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
$nfsserver:/tftpboot/nodes/$ip/root     /root   nfs     rw,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
none                    /dev/pts        devpts  gid=5,mode=620  0 0
$nfsserver:/usr             /usr        nfs    ro,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
$nfsserver:/opt             /opt        nfs    ro,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
$nfsserver:/home            /home       nfs    rw,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
$nfsserver:/var/spool/mail /var/spool/mail       nfs     rw,rsize=8192,wsize=8192,$nfs_protocol,defaults        0 0
none                    /proc           proc    defaults        0 0
tmpfs                   /tmp            tmpfs   defaults        0 0
tmpfs                   /media          tmpfs   defaults        0 0
/dev/fd0                /mnt/floppy     auto    noauto,owner,kudzu 0 0
#/dev/sr0          	/mnt/cdrom      iso9660 iocharset=cp950,noauto,owner,kudzu,ro 0 0
FSTAB

# output the file to etc/sysconfig/network
cat <<-HOSTNAME_END > /tftpboot/nodes/$ip/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=$label
DOMAINNAME=$nisdomain.org
GATEWAY=$nfsserver
NISDOMAIN=$nisdomain

HOSTNAME_END

# clean all ifcfg-ethx, we already set the network in init
rm -f /tftpboot/nodes/$ip/etc/sysconfig/network-scripts/ifcfg-eth* 

cat <<-YPCONF_ETH0 > /tftpboot/nodes/$ip/etc/yp.conf
domain $nisdomain server $nisserver
YPCONF_ETH0

# write the ntp time sync client to DRBL client
[ -f "/tftpboot/nodes/$ip/etc/cron.daily/timesync" ] && rm -f /tftpboot/nodes/$ip/etc/cron.daily/timesync
cat <<-NTPC_END > /tftpboot/nodes/$ip/etc/cron.daily/timesync
/usr/sbin/ntpdate -b -s $nfsserver pool.ntp.org
NTPC_END
chmod 755 /tftpboot/nodes/$ip/etc/cron.daily/timesync

[ -f "/tftpboot/nodes/$ip/etc/resolv.conf" ] && rm -f /tftpboot/nodes/$ip/etc/resolv.conf
for nameserver in $nameserver_
do 
  echo "nameserver \$nameserver" >> /tftpboot/nodes/$ip/etc/resolv.conf
done
EOF

print DISKLESS_OUT <<EOF;
ln -fs /tftpboot/node_root /tftpboot/$ip

#
#echo -n "."
# get the login_gdm_opt and TIMED_GDM_TIME_DEFAULT from perl, 
# you can not get it in q command, doing so we can continue...
login_gdm_opt="$login_gdm_opt"
timed_login_time="$TIMED_LOGIN_TIME"
#
# Steven todo.
# RedHat user GDM only,
# Mandrake use KDM, GDM...here only KDM now, will change, 
# set the login option for GDM
case "$login_gdm_opt" in
  "auto_login")
        $DRBL_SCRIPT_PATH/sbin/drbl-login-switch --auto --no_nis_update --host $ip
        ;;
  "timed_login")
        $DRBL_SCRIPT_PATH/sbin/drbl-login-switch --timed $timed_login_time --no_nis_update --host $ip
        ;;
  *)
        $DRBL_SCRIPT_PATH/sbin/drbl-login-switch --normal --no_nis_update --host $ip
esac

# set the root's passwd for clients if set
# client_root_passwd
[ -n "\$client_root_passwd" ] && $DRBL_SCRIPT_PATH/sbin/drbl-client-root-passwd --stdin \$client_root_passwd --host $ip

EOF

print DISKLESS_OUT <<EOF;
echo "done !!!"
EOF


      # next one
      $i++;
    }

    # generate dhcpd.conf 
    if( length($mac)!=0 ) 
    { # mac - just close it 
      print DHCPD_OUT <<EOF;
}

EOF
    } 
    elsif( length($range)!=0 ) { # range - generate range & filename
      if ( ! $nbi ) {
        # without nbi set in config file
        my($rs,$re)=split(/-/,$range,2);
        print DHCPD_OUT <<EOF;
    range $networkIp[0].$networkIp[1].$networkIp[2].$rs $networkIp[0].$networkIp[1].$networkIp[2].$re;
}

EOF
      }else{
        # with nbi set in config file
        my($rs,$re)=split(/-/,$range,2);
        print DHCPD_OUT <<EOF;
    range $networkIp[0].$networkIp[1].$networkIp[2].$rs $networkIp[0].$networkIp[1].$networkIp[2].$re;
    filename "$nbi";
}

EOF
      }
    }
    else {}
    close(MAC_IN);
  }

  # generate in $main_sh
  print DISKLESS_OUT <<EOF;
  # write the NISDOMAIN to system config file
  NET_sys="/etc/sysconfig/network"
  NIS_sys=\$(grep NISDOMAIN \$NET_sys)
  if [ "\$NIS_sys" = "" ]; then
    echo "NISDOMAIN=$nisdomain" >> $NET_sys
  else
    perl -p -i -e \"s/^NISDOMAIN=.*/NISDOMAIN=$nisdomain\/\" $NET_sys 
  fi
  # before restart NIS, force the variable NISDOMAIN now is that set in config file
  nisdomainname $nisdomain
EOF

$total_nfsd=int($total_client_no * $NFSD_RATIO);
print "$delimiter{\"star_line\"}\n".
      "The RPCNFSDCOUNT in /etc/sysconfig/nfs is set as ". 
      colored ("$total_nfsd ", 'red'). "($NFSD_RATIO*Total_Client_No).\n";

  print DISKLESS_OUT <<EOF;
# set the RPCNFSDCOUNT to $total_client_no*$NFSD_RATIO (say "40") 
# in /etc/sysconfig/nfs instead of 8 in /etc/init.d/nfs
# 
cat <<-NFSRPC_END > /etc/sysconfig/nfs
RPCNFSDCOUNT=$total_nfsd
NFSRPC_END

# copy the config files to \$drbl_syscfg...
echo -n "Copying the config file to \$drbl_syscfg..."
mkdir -m 700 -p \$drbl_syscfg
cp -f $config_file \$drbl_syscfg/
[ -f \$public_ip_list ] && cp -f \$public_ip_list \$drbl_syscfg/
echo "done!"
EOF

#
  #print DISKLESS_OUT <<EOF;
  print DISKLESS_OUT q{

# force to turn on portmap for rc3.d and rc5.d as default, without portmap
# nfs will go wrong...
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "Now set the services dhcp, xinetd, portmap, nis, nfs, iptables to be on when the machine start up."
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL

# set the restrict in ntp.conf, only the subnet of DRBL clients can access.
drbl_subnet=
for ihost in /tftpboot/nodes/*; do
  ip="`basename $ihost`"
  subnet=$(echo $ip | cut -d"." -f1-3)
  if [ -z "$(echo $drbl_subnet | grep $subnet 2> /dev/null)" ]; then
    drbl_subnet="$drbl_subnet $subnet"
  fi
done
for i_subnet in $drbl_subnet; do
  if ! grep -q "^restrict $i_subnet.*" /etc/ntp.conf ; then
    echo "restrict $i_subnet.0 mask 255.255.255.0 notrust nomodify notrap" >> /etc/ntp.conf
  fi
done

# set the iptables NAT
$DRBL_SCRIPT_PATH/sbin/drbl-nat start

server_to_on="dhcpd xinetd portmap iptables ypserv ypbind yppasswdd ypxfrd nfs nfslock ntpd" 

for serv in $server_to_on; do 
  /sbin/chkconfig $serv on
done

# flush the YP
echo "Update YP..."
make -C /var/yp 1>& /dev/null

# (re)start all the service which DRBL server need
$DRBL_SCRIPT_PATH/sbin/drbl-all-service start

# set the boot prompt for clients if set
case "$set_client_system_select" in
   y|Y|[yY][eE][sS])
     # process if we wan to turn on/off the thin client option in PXE boot menu
     case "$open_thin_client_option" in
         y|Y|[yY][eE][sS])
	    # set the option for processing PXE boot menu
	    client_select_opt="-e"
	    # Turn on the thin client server (gdm/kdm...)
	    $DRBL_SCRIPT_PATH/sbin/drbl-powerful-thin-client --thin -ln $language
	    ;;
         n|N|[nN][oO])
	    # set the option for processing PXE boot menu
	    client_select_opt="-d"
	    # Turn on the thin client server (gdm/kdm...)
	    $DRBL_SCRIPT_PATH/sbin/drbl-powerful-thin-client --powerful -ln $language
	    ;;
     esac
      $DRBL_SCRIPT_PATH/sbin/drbl-client-system-select $client_select_opt -t $client_system_boot_timeout on
      ;;
   n|N|[nN][oO])
      $DRBL_SCRIPT_PATH/sbin/drbl-client-system-select off
      ;;
esac


# echo warning message if TCPwrapper is set.
host_allow_set=$(grep -v "^[[:space:]]*#" /etc/hosts.allow)
host_deny_set=$(grep -v "^[[:space:]]*#" /etc/hosts.deny)
if [ -n "$host_allow_set" -o -n "$host_deny_set" ]; then
   [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
   echo "Warning! You already set the /etc/hosts.allow or /etc/hosts.deny!"
   echo "You must MAKE SURE the clients can access this DRBL server!"
   echo "If not, your client will fail to boot, and error messages will like:"
   [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
   echo "mount: RPC: Unable to receive; errno = Connection refused"
   [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fi

#restore the old LC_ALL
export LC_ALL=$LC_ALL_org

echo 
echo "******************************************************"
echo "Enjoy DRBL!!!"
echo "NCHC Free Software Labs, Taiwan"
echo "http://opensource.nchc.org.tw"
echo "http://drbl.nchc.org.tw; http://drbl.sf.net"
echo "******************************************************"
echo 

echo "******************************************************"
echo "Now syncing - flush filesystem buffers..." 
sync;sync;sync
# ask user to reboot after first time upgrade the nfs-utils in
# drblsrv_desktop.sh or get_drbl_kernel.sh
# if not, user will see a lot of 
# "kernel: lockd: rejected NSM callback from 7f000001:1027" 
# in the server console and /var/log/messages
echo "******************************************************"
echo "If you like, you can reboot the DRBL server now to make sure everything is ready...(This is not necessary, just an option.)" 
};

  print DHCPDITF_OUT "\"";
  print NETGROUP_OUT "\n";
  print NETGROUP_OUT "# Added by DRBL, end\n";

  close(DHCPD_OUT);
  close(DHCPITF_OUT);
  close(HOSTS_OUT);
  close(NETGROUP_OUT);
  close(DISKLESS_OUT);
  close(EXPORTS_OUT);
  close(NFSSERVER_OUT);
  close(HOSTS_LIST_OUT);
  close(SWAPCONF_OUT);
  #chnage its mode
  system("LC_ALL=C chmod 700 $main_sh");


  # to update the file /etc/hosts correctly, the hosts is already created by
  # parsing user config file
  $hosts_skel="hosts_skel";
  unlink $hosts_skel if -f $hosts_skel;
  if (-f "/etc/hosts") {
    system("LC_ALL=C cp -f /etc/hosts $hosts_skel");
  }
  else {
    system("LC_ALL=C touch $hosts_skel");
  }
  open (HOSTS_NEW, "<./hosts") or die "Can NOT open file \.\/hosts";
  
  my $line;
  my @host_new ;
  my $subst;
  while (<HOSTS_NEW>) {
    chomp;
    $line = $_;
    my @host_new = split /\s+/, $line;
    #print "now it's $host_new[0]\n";
    open (HOSTS_OLD, "</etc/hosts");
    $subst = "0";
    while (<HOSTS_OLD>) {
      chomp;
      $line_old = $_;
      my @host_old = split /\s+/, $line_old;
      if ( "$host_old[0]" eq "$host_new[0]" ) {
       #print "host_new[0]: $host_new[0]\n";
       #system ( "perl -p -i -e \"s/^$host_old[0] .*/@host_new/\" $hosts_skel" );
       # the space after ^$hosts_old[0] is important, it keeps hosts_old unique,
       # otherwise, 192.168.2.254 maybe replaced by 192.168.2.2 
       system ( "LC_ALL=C perl -p -i -e \"s/^@host_old/@host_new/\" $hosts_skel" );
       $subst = "1";
       last;
      }
      elsif ( "$host_old[1]" eq "$host_new[1]" ) {
       # the 2nd item must be replaced if it's same. 
       # i.e. the DNS forward lookup must match with reverse.
       # example: /etc/hosts can NOT have same G2-002.drbl.org for different IP
       # 192.168.2.2 G2-002.drbl.org G2-002
       # 192.168.2.97 G2-002.drbl.org G2-002
       # problem:
       # Feb  1 01:59:59 nfsserver_eth3 rpc.mountd: refused mount request from 192.168.2.97 (G2-002.drbl.org) for /tftpboot/node_root (/tftpboot/node_root): DNS forward lookup does't match with reverse 
       #print "host_new[1]: $host_new[1]\n";
       #system ( "perl -p -i -e \"s/^$host_old[0] $host_old[1] .*/@host_new/\" $hosts_skel" );
       # the space after ^$hosts_old[1] is important, it keeps hosts_old unique,
       # otherwise, 192.168.2.254 maybe replaced by 192.168.2.2 
       system ( "LC_ALL=C perl -p -i -e \"s/^@host_old/@host_new/\" $hosts_skel" );
       $subst = "1";
       last;
      }
    }
    if ( $subst eq "0" ) { 
        system ( "LC_ALL=C echo @host_new >> $hosts_skel" );
    }
    close(HOSTS_OLD);
  }
    close(HOSTS_NEW);

  # set public IP if options is yes
  if ("$set_client_public_ip_opt" eq "yes" && "$mode" eq "create_config_file"){
       # then user run drblpush with -i, create the $public_ip_list
       print "$delimiter{\"star_line\"}\n".
             "$lang_deploy{\"ok_let_do_it\"}\n".
             "$delimiter{\"dash_line\"}\n";
       # create the $public_ip_list file
       set_client_public_ip("$hosts_list","$public_ip_list");
  }

} # end of the drbl_server_parse

#
sub usage_details{
    die "$usage\n".
        "  -c, --config      The DRBL config file, text format\n".
	"  -e, --example     DRBL config file example\n".
	"  -n, --no_deploy   Just create files, do NOT deploy the files into system after all files created\n".
	"  -i, --interactive Interactive mode, let you supply the information interactive.\n".
        "  -l, --language    Set the language to be shown".
        "                  [0]: English, [1]: Chinese Traditional (Big5) - Taiwan, [2] Chinese Traditional (UTF-8, Unicode) - Taiwan".
	"  -q, --quiet       Be less verbose\n".
	"  -v, --verbose     Be more verbose\n".
	"  -w, --website     Browse the NCHC DRBL website\n";
} # end of usage_details

sub check_MAC_file{
  my $macfile_dir="$_[0]";
  my $macfile_prefix="$_[1]";
  # note! maybe there are multiple MAC files when run drblpush with "-c"
  my $macfile_exist=system("LC_ALL=C ls $macfile_dir/$macfile_prefix* &>/dev/null");
  if ($macfile_exist == 256) {
    # unable to find the $macfile_prefix*
    print "$delimiter{\"star_line\"}\n".
          colored ("$lang_word{\"unable_to_find_the\"} $macfile_dir/$macfile_prefix; $lang_deploy{\"hint_for_detect_MAC\"} $macfile_prefix\n", 'red').
          "$lang_deploy{\"press_enter_to_continue\"}";
          chomp($line=<STDIN>);
    print "$delimiter{\"dash_line\"}\n";
  }else{
   # MAC file exists, check if it contains illeagle character.
   # empty those comment line, and delete the empty line and those comment line
   system("perl -p -i -e \"s/^[[:space:]]*#.*\$//g\" $macfile_dir/$macfile_prefix*");
   system("perl -p -i -e \"s/^[[:space:]]*\$//g\" $macfile_dir/$macfile_prefix*");
   my $macfile_check=`for ifile in $macfile_dir/$macfile_prefix*; do grep -v -E '([[:alnum:]]|:|^[[:space:]]*\$)' \$ifile; done`;
   chomp($macfile_check);
   if ( $macfile_check ) {
      print "$lang_deploy{\"illeagle_char_in_MAC\"},". 
            colored ("\"$macfile_check\"\n", 'red').
            "$lang_deploy{\"fix_wrong_MAC_file\"} \n".
            "$lang_word{\"program_stop\"}!!!\n";
      exit(1);
   }
  }
} # end of check_MAC_file

sub cfg_example{
        my $cfg_example_details="config.example.details";
        my $cfg_example_easy="config.example.easy";
        drbl_config_example("$cfg_example_details","$cfg_example_easy");
        print "$delimiter{\"dash_line\"}\n".
	      "* Two example files of config, \"$cfg_example_details\" and \"$cfg_example_easy\", are created!\n".
	      "* \"$cfg_example_details\" is the config file you want to set most of parameters instead of letting them extracted from DRBL server.\n".
	      "* \"$cfg_example_easy\" is the config file which most of the parameters are extracetd from DRBL server. (Highly recommended!!!) \n".
              "$delimiter{\"dash_line\"}\n".
	      "press \"d\" to see the file \"$cfg_example_details\"\n".
	      "press \"e\" to see the file \"$cfg_example_easy\"\n".
	      "press \"q\" to exit \n";
	while (<STDIN>) {
	  chomp;
	  if ( "$_" eq "d" ){
	    system("LC_ALL=C less $cfg_example_details");
	    last;
	  }
	  elsif ("$_" eq "e"){
	    system("LC_ALL=C less $cfg_example_easy");
	    last;
	  }
	  elsif ("$_" eq "q"){
	    last;
	  }
	  else{
	    next;
	  }
	}
        exit(0);
} # end of config example

#########################################
# Main program
my $no_deploy = 0;
my $config_file = "";
our $verbosity = 1;
my $usage="Usage: $0 [-e|--example] [-i|--interactive] [-n|--no_deploy] [-q|--quiet] [-v|--verbose] [-w|--website] [-h|--help] [-c|--config config_file]";

# must have argument
die "$usage\n" if $#ARGV<0;

# Parse command-line options
while ($#ARGV != -1) {
   my $arg;
   $arg = shift(@ARGV);
   if (lc($arg) =~ /^(-)?(-)?l(anguage)?$/) {
     $lang_opt = shift(@ARGV);
   } elsif (lc($arg) =~ /^(-)?(-)?n(o_deploy)?$/) {
     $no_deploy = 1; 
   } elsif (lc($arg) =~ /^(-)?(-)?c(config)?$/) {
     $config_file = shift(@ARGV);
     $mode="load_config_file";
   } elsif (lc($arg) =~ /^(-)?(-)?v(erbose)?$/) {
     $verbosity++;
   } elsif (lc($arg) =~ /^(-)?(-)?q(uiet)?$/) {
     $verbosity--;
   } elsif (lc($arg) =~ /^(-)?(-)?w(ebsite)?$/) {
     system("LC_ALL=C mozilla http://drbl.nchc.org.tw");
   } elsif (lc($arg) =~ /^(-)?(-)?h(elp)?$/) {
     usage_details();
   } elsif (lc($arg) =~ /^(-)?(-)?e(xample)?$/) {
     cfg_example();
   } elsif (lc($arg) =~ /^(-)?(-)?i(nteractive)?$/) {
     $mode = "create_config_file";
   } else {
     usage_details();
   }
}

# get the language
$language=lang_set($lang_opt);
require "$drbl_setup_path/lang/perl/$language";

# hint for user to answer y/n
print "$delimiter{\"star_line\"}\n".
      colored ("$lang_deploy{\"hint_for_answer\"}\n", 'yellow');

if ("$mode" eq "create_config_file") {
        print "$delimiter{\"dash_line\"}\n".
	      "$lang_deploy{\"interactive_mode_prompt\"}\n".
              "$delimiter{\"dash_line\"}\n";
        interactive_mode;
	$config_file=$DRBLPUSH_CONF;
} elsif ("$mode" eq "load_config_file") {
       # copy the pre-saved setting file to this working directory
       # config_file
       system("[ -f $config_file ] && cp -f $config_file .");
       # public IP setting
       system("[ -f $drbl_syscfg/$public_ip_list ] && cp -f $drbl_syscfg/$public_ip_list $public_ip_list");
       # MAC address files
       system("cp -f $drbl_syscfg/macadr-eth*.txt . &> /dev/null");

}
unless ( $config_file ) { die "$usage\n"; }

# parse the config file, then create the exe script file $main.sh
drbl_server_parse($config_file);

# check if drbl server package is installed or not
print "$delimiter{\"star_line\"}\n";
print "$lang_deploy{\"searching_installed_drbl_packages\"}\n";
# just pick drbl-script to test
my $drbl = system("LC_ALL=C rpm -qa | grep drbl-script > /dev/null");
if ($drbl eq 256) {
	print "$delimiter{\"star_line\"}\n".
	      "$delimiter{\"warning_line\"}\n".
	      "$lang_deploy{\"no_drbl_server_package_found\"}\n".
	      "[y/N] ";
	chomp($line=<STDIN>);
	SWITCH: for ($line) {
		/"^y"|"^yes"/i && do {
	          print "$delimiter{\"star_line\"}\n".
                        "$lang_deploy{\"ok_let_continue\"}\n".
                        "$lang_deploy{\"but_you_will_see_errors\"}\n";
                  last SWITCH;
                };
		/.*/ && do {
	          print "!!!!!!!!!!!!!!!!!!!!!!!!!\n".
                        "$lang_deploy{\"smart_decision\"}\n";
	          exit(1);
                  last SWITCH;
                };
        }
}else{
        print "$lang_deploy{\"finished_searching_installed_drbl_packages\"}\n";
	print "$delimiter{\"star_line\"}\n";
}

print "purge_client: $purge_client\n" if $verbosity >=2;
if ( $purge_client eq "no" ) { 
   print colored ("$lang_deploy{\"note_for_keep_client_setting\"}\n", 'red').
         "$lang_deploy{\"press_enter_to_continue\"}";
         chomp($line=<STDIN>);
}

# ready to go
if ( $no_deploy ) { 
	print "$delimiter{\"warning_line\"}\n".
	      "$lang_deploy{\"no_deploy_prompt\"}\n";
}
else {
	print "$delimiter{\"star_line\"}\n".
	      "$lang_deploy{\"ready_to_deploy\"}\n".
	      colored ("$lang_deploy{\"overwrite_firewall_rule\"}\n", 'red').
	      colored ("$lang_deploy{\"backup_firewall_rule\"}\n", 'red').
	      "[Y/n] ";
	chomp($line=<STDIN>);
	if ($line eq "n" || $line eq "N" || $line eq "no" || $line eq "NO") {
	 print "$delimiter{\"exclamation_line\"}\n".
	       "$lang_deploy{\"oh_quit_now\"}\n";
         unlink ($main_sh) if -f $main_sh;
	} else {
	 print "$delimiter{\"star_line\"}\n".
               "$lang_deploy{\"ok_let_do_it\"}\n".
               "$delimiter{\"dash_line\"}\n";
         my $whoiam = `LC_ALL=C id -nu`;
	 chomp($whoiam);
         # Also copy the $DRBLPUSH_CONF to system so that we can re-run the
         # program by "drblpush -c $drbl_syscfg/$DRBLPUSH_CONF"
         my $run_main="LC_ALL=C ./$main_sh";
	 if ("$whoiam" eq "root") { 
	     system("$run_main");
         }else{
             print "$lang_deploy{\"you_are_not_root\"},\n". 
	           "$lang_word{\"please_enter\"} ". colored("$lang_word{\"root_passwd\"} ",'red') ."$lang_word{\"to_deploy_them\"}...\n"; 
	     my $su_rlt=system("su -c '$run_main' root");
	     while ($su_rlt == 256) { 
	            $su_rlt=system("su -c '$run_main' root");
	     }
	     # copy the config file to DRBL server
         } 
        }
}
# clean the temp working directory
rmtree ($drblpush_wd) if -d $drblpush_wd;

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