#!/usr/bin/perl -X
#
# Copyright (C) 2002-2003 by NCHC, Steven Shiau, K. L. Huang
# (steven _at nchc org tw, klhaung _at_ gmail com)
#
# 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, klhaung _at_ gmail com, especially for Debian
# Modified by Steven Shiau, steven _at_ 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";

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

# default client no connected to some ethernet port
our $DEFAULT_CLIENT_NO_EACH_PORT="12";
# $assign_client_no_each_port is assign by -p or --port_client_no
our $assign_client_no_each_port;

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

#
our $DEFAULT_NISDOMAINNAME="penguinzilla";
our $DEFAULT_DOMAINNAME="drbl.org";

# flag to turn on/off NAT service in drbl server
our $drbl_server_as_NAT_server;

# This parameters are defined in drbl.conf or environment variables (e.g. DRBL_SCRIPT_PATH).
our $DRBL_SCRIPT_PATH;
our $drbl_setup_path;
our $drbl_syscfg;
# file name to record the auto login ID and passwd
our $AUTO_LOGIN_ID_PASSWD;
# file to record the IP and hostname for clients
our $IP_HOST_TABLE;
our $CLIENT_IP_HOSTNAME_LIST;
our $drblroot;
our $drbl_common_root;
our $query_pkglist_cmd;
our $DHCPD_DEFAULT_LEASE_TIME;
our $DHCPD_MAX_LEASE_TIME;
our $pxecfg_pd;

# First we need to get DRBL_SCRIPT_PATH.
chomp($DRBL_SCRIPT_PATH=`LC_ALL=C get-drbl-conf-param DRBL_SCRIPT_PATH`);
$ENV{'PATH'} = "$ENV{'PATH'}:$DRBL_SCRIPT_PATH/sbin:$DRBL_SCRIPT_PATH/bin:";

# Get them from drbl.conf
chomp($drbl_setup_path=`LC_ALL=C get-drbl-conf-param drbl_setup_path`);
chomp($drbl_syscfg=`LC_ALL=C get-drbl-conf-param drbl_syscfg`);
chomp($AUTO_LOGIN_ID_PASSWD=`LC_ALL=C get-drbl-conf-param AUTO_LOGIN_ID_PASSWD`);
# We use $CLIENT_IP_HOSTNAME_LIST (IP_HOST_TABLE) as the temp file in drblpush working dir.
chomp($IP_HOST_TABLE=`LC_ALL=C get-drbl-conf-param IP_HOST_TABLE`);
chomp($CLIENT_IP_HOSTNAME_LIST=`LC_ALL=C basename $IP_HOST_TABLE`);
chomp($drblroot=`LC_ALL=C get-drbl-conf-param drblroot`);
chomp($drbl_common_root=`LC_ALL=C get-drbl-conf-param drbl_common_root`);
chomp($query_pkglist_cmd=`LC_ALL=C get-drbl-conf-param query_pkglist_cmd`);
chomp($DHCPD_DEFAULT_LEASE_TIME=`LC_ALL=C get-drbl-conf-param DHCPD_DEFAULT_LEASE_TIME`);
chomp($DHCPD_MAX_LEASE_TIME=`LC_ALL=C get-drbl-conf-param DHCPD_MAX_LEASE_TIME`);
chomp($pxecfg_pd=`LC_ALL=C get-drbl-conf-param pxecfg_pd`);
chomp($ocs_img_repo_dir_default=`LC_ALL=C get-drbl-conf-param ocsroot`);

# 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 @ip_sys_prefix;
our @ip_sys;
our $public_ip_port;
our $public_ip_addr;
# $pub_port_NAT is when there is no public IP in this drbl server, one of those
# private IPs which is connected to NAT server.
our $pub_port_NAT;

our $purge_client;
our $keep_client;
our $client_startup_mode;
# DRBL SSI (Single System Image) MODE: clients use the tarball template in $drbl_common_root/drbl_ssi for etc, var. There is a program "drbl-ssi-client-prepare" will be run in init.drbl to modify the necessary config of etc when client boots.
# Clonezilla box mode = DRBL SSI mode + runlevel 1 in client
our $drbl_mode;
our $drbl_ssi_mode;
our $clonezilla_mode;
our $clonezilla_box_mode;
our $run_drbl_ocs_live_prep="yes";
our $drbl_ocs_live_server;
our $live_client_cpu_mode;
our $ocs_img_repo_dir;
our $ocs_img_repo_dir_default;
# switch for local swap in client
our $swap_create;
our $client_exist_flag;
# default color for warning and error
#our $color_warn="yellow";
our $color_warn="Bold Yellow";
our $color_fail="red";
our $add_start_drbl_services_after_cfg="yes";
our $continue_with_one_port;

# 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 2>&1");
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 set_autologin_passwd{
  print "$lang_deploy{\"use_random_password\"}\n".
        "[Y/n] ";
  chomp($auto_login_random_passwd=<STDIN>);
  if ($auto_login_random_passwd eq "n" || $auto_login_random_passwd eq "N" || $auto_login_random_passwd eq "no" || $auto_login_random_passwd eq "NO") {
      # input password for client auto-login account
      print "$lang_deploy{\"enter_password_for_autologin_accounts\"}\n";
      # we set 2 different passwords to make while loop works.
      $client_autologin_passwd1="init1";
      $client_autologin_passwd2="init2";
      while ($client_autologin_passwd1 ne $client_autologin_passwd2 || ($client_autologin_passwd1 eq "" && $client_autologin_passwd2 eq "" )) { 
           print "$lang_deploy{\"whats_client_autologin_passwd\"}\n";
  	 # turn off echo
           system "LC_ALL=C stty -echo";
           chomp($client_autologin_passwd1=<STDIN>);
  	 # turn on echo
           system "LC_ALL=C stty echo";
           print "$lang_deploy{\"retype_autologin_passwd\"}\n";
           system "LC_ALL=C stty -echo";
           chomp($client_autologin_passwd2=<STDIN>);
           system "LC_ALL=C stty echo";
        if ($client_autologin_passwd1 ne $client_autologin_passwd2) { 
  	  print colored ("$lang_deploy{\"sorry_passwd_not_match\"}\n", "$color_warn");
        }elsif ($client_autologin_passwd1 eq "" && $client_autologin_passwd2 eq "" ){ 
  	  print colored ("$lang_deploy{\"sorry_passwd_can_not_empty\"}\n", "$color_warn");
        }
      }
      $client_autologin_passwd=$client_autologin_passwd1;
  }else{
      # Random password for client auto-login account
      $client_autologin_passwd="$ACCOUNT_PASSWD_LENGTH_DEFAULT";
      print "$lang_deploy{\"ok_let_continue\"}\n";
  }
} # end of set_autologin_passwd

#
sub interactive_mode {
        my $dnsdomain_sys, $nisdomain_sys, $hostname_sys;
	#we will scan the ethernet from $ethernet_list[0]...
	#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_;
	print "Finding the available ethernet ports...\n" if $verbosity >=2;
	chomp($ethernet_list_=`get-all-nic-ip -d`);
	my @ethernet_list=split(/ /,$ethernet_list_);
	my @ethernet_sys; # the private ethernet we found and useful, ex:"eth1"
	my @range_start;
	my @range_end;
	my @MAC_file;

        # Try to get setting from system 
        chomp($dnsdomain_sys=`dnsdomainname`);
        chomp($nisdomain_sys=`nisdomainname`);
	chomp($hostname_sys=`hostname`);
        my @client_hostname_prefix_default=split(/\./,$hostname_sys);
        print "DNSDOMAIN in system is $dnsdomain_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";

	# get domain name
	# If we can find the one in system, use it as the default one
	if ( $dnsdomain_sys && "$dnsdomain_sys" ne "localdomain" ) {
	  $DEFAULT_DOMAINNAME="$dnsdomain_sys";
        }
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"domain_prompt\"}\n".
	      "[$DEFAULT_DOMAINNAME] ";
        while (<STDIN>) {
           chomp;
           $dnsdomain_sys=$_;
	   if ( "$dnsdomain_sys" =~ / |\/|\\/ ) {
  	     print "\" \" ($lang_text{\"space\"}), \"/\", $lang_text{\"or\"} \"\\\" $lang_deploy{\"not_allowed_domainname\"} $lang_deploy{\"enter_it_again\"}!\n".
	           "[$DEFAULT_DOMAINNAME] ";
           } else {
	     # if empty, use default name
             if ($dnsdomain_sys eq "") { $dnsdomain_sys="$DEFAULT_DOMAINNAME"; }
	     print "$lang_deploy{\"set_domain_as\"} $dnsdomain_sys\n";
             last;
           }
        }

	# get nis domain name
	# If we can find the one in system, use it as the default one.
	# We will not use "localdomain" "nisdomainname: Local domain name not set" (on Fedora 13, when nisdomainname is not set, it is shown as that) and "(none)"
	if ( $nisdomain_sys && "$nisdomain_sys" !~ /^(localdomain|nisdomainname: Local domain name not set|\(none\))$/i ) {
	  $DEFAULT_NISDOMAINNAME="$nisdomain_sys";
        }
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"nisdomain_prompt\"}\n".
	      "[$DEFAULT_NISDOMAINNAME] ";
        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\"} $lang_deploy{\"enter_it_again\"}!\n".
	           "[$DEFAULT_NISDOMAINNAME] ";
           } else {
	     # if empty, use default name
             if ($nisdomain_sys eq "") { $nisdomain_sys="$DEFAULT_NISDOMAINNAME"; }
	     print "$lang_deploy{\"set_domain_as\"} $nisdomain_sys\n";
             last;
           }
        }

	# get client hostname prefix
        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" =~ / |\/|\\|\./ ) {
		# "-" 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\"} $lang_deploy{\"enter_it_again\"}!\n".
	              "[$client_hostname_prefix_default[0]] ";
              } 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...
        foreach my $ethx (@ethernet_list) {
	 print "Finding the IP address for $ethx...\n" if $verbosity >=2;
	 chomp($nic_ethx_ip=`drbl-get-ipadd $ethx`);
	 chomp($nic_ethx_netmask=`drbl-get-netmask $ethx`);
   	 if ( $nic_ethx_ip ) {
	   # Specially, we do not want the alias interface, such as:eth0:1
           my $IP=`drbl-get-ipadd $ethx`;
	   chomp($IP);
           if ( ! $IP ) {
             print "The IP address of $ethx was not found!\n".
	           "$lang_deploy{\"we_will_skip\"} $ethx!\n";
           } else {
  	     print "$ethx: IP address $IP, netmask $nic_ethx_netmask\n";
  	     push @ethernet_sys, $ethx;
           }

         }
        }
	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", "$color_warn");
          print "$delimiter{\"dash_line\"}\n";

	  # Find the ethernet port connected to WAN.
	  print "Finding the available public IP address...\n" if $verbosity >=2;
	  chomp($public_ip_addr=`get-all-nic-ip -a`);
	  chomp($public_ip_port=`get-all-nic-ip -p`);
	  if ($public_ip_port) {
            print "$lang_deploy{\"ethernet_port_for_internet\"} $public_ip_port\n";
            @ethernet_sys = grep { $_ ne "$public_ip_port" } @ethernet_sys;
            print "$lang_deploy{\"ethernet_port_for_DRBL\"} ".
	          colored ("@ethernet_sys \n", "$color_warn");

          }else{
            my $private_eth_ports_;
            chomp($private_eth_ports_=`get-all-nic-ip -t`);
            my @private_eth_ports=split(/ /,$private_eth_ports_);
	    my $guess_uplink_port;
	    # we just want one port, so use "head -n 1" to get the 1st one.
            chomp($guess_uplink_port=`PATH=$PATH:/sbin/:/usr/sbin route -n | awk '/^0.0.0.0/ {print \$8}' | sort | head -n 1`);
            print "$lang_deploy{\"unable_to_find_public_IP\"}\n".
                  "$lang_deploy{\"for_internet_access_prompt\"}\n".
		  "$lang_deploy{\"available_eth_ports\"}:\n";
            foreach my $ethx (@private_eth_ports){
                  my $IP=`drbl-get-ipadd $ethx`;
	          chomp($IP);
                  print "$ethx ($IP), ";
            }
	    print "\n";
            print "[$guess_uplink_port] ";
            while (<STDIN>) {
              chomp;
	      $pub_ans=$_;
              if ($pub_ans eq "") { $pub_ans="$guess_uplink_port"; }
	      foreach my $k (@private_eth_ports) {
	        if ( "$pub_ans" eq "$k" ) {
	          # if empty, use default name
	          $pub_port_NAT=$pub_ans;
                  last;
                } 
	      }
	      if ( $pub_port_NAT ) {
		 last;
              }else{
  	         print "\"$pub_ans\" $lang_deploy{\"is_not_in_the_lists\"} (@private_eth_ports). $lang_deploy{\"enter_it_again\"}!\n";
              }
            }
	    print "$lang_deploy{\"the_eth_port_you_choose_for_wan\"}: ".
	          colored ("$pub_port_NAT\n", "$color_warn");
            @ethernet_sys = grep { $_ ne "$pub_port_NAT" } @ethernet_sys;
	    if (@ethernet_sys) {
              print "$lang_deploy{\"ethernet_port_for_DRBL\"} ".
	          colored ("@ethernet_sys \n", "$color_warn");
            }
          }
	  # if not ethernet port is available for DRBL, use $pub_port_NAT.
	  if ( @ethernet_sys <= 0 ) {
	    # Since only one port is available, we will use this only one to provide services for client. Give WARNING!
	    if (!$continue_with_one_port) {
	      print colored ("$lang_deploy{\"only_one_network_card_in_system\"}\n", "$color_warn").
                    colored ("$lang_deploy{\"are_you_sure_you_want_to_continue\"}\n", "$color_warn").
	            "[y/N] ";
              chomp($continue_with_one_port=<STDIN>);
	    }
            SWITCH: for ($continue_with_one_port) {
              /^y$|^yes$/i && do {
	        # 2 cases: (1) only one public IP address port (public_ip_port) (2) only one private IP address port connected to WAN via NAT (pub_port_NAT)
		if ($pub_port_NAT) {
                  @ethernet_sys = ("$pub_port_NAT");
		} elsif ($public_ip_port) {
                  @ethernet_sys = ("$public_ip_port");
		}
                last SWITCH;
              };
              /.*/ && do {
	        print "$lang_deploy{\"program_stop\"}\n";
                exit (1);
                last SWITCH;
              };
            }
          }
	  # Final check before using ethernet port
	  if ( @ethernet_sys <= 0 ) {
 	    print "$lang_deploy{\"no_NIC_setup\"}\n".
	          "$lang_deploy{\"we_can_NOT_continue\"}\n";
	    exit;
	  }
	  # Checking if class A/B private IP ? If so, set warning about multicast clonezilla
          for($i=0;$i<=$#ethernet_sys;$i++) {
	    my $ethx="$ethernet_sys[$i]";
            my $IP=`drbl-get-ipadd $ethx`;
	    chomp($IP);
	    if ( "$IP" =~ /^(172\.(1[6-9]|2[0-9]|3[01])\..*|10\..*)/ ) {
              # Class A: 10.0.0.0 - 10.255.255.255
              # Class B: 172.16.0.0  - 172.31.255.255 
	      print "$delimiter{\"star_line\"}\n";
  	      print "Found class A or B private IP \"$IP\" in $ethx for your DRBL system! ".
              colored ("$lang_deploy{\"class_c_IP_for_multicast_clonezilla\"}\n", "$color_warn");
              print "$delimiter{\"star_line\"}\n".
                    "$lang_deploy{\"press_enter_to_continue\"}";
                    chomp($line=<STDIN>);
            }
	  };
	  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-collect-mac -n -l $language @ethernet_sys");
  	            print colored ("$lang_deploy{\"saved_mac_address_files_in_etc\"}\n", "$color_warn");
                  }else{
                     print "$lang_deploy{\"you_are_not_root\"},\n". 
                           "$lang_word{\"please_enter\"} ". colored("$lang_word{\"root_passwd\"} ","$color_warn"). "to collect those MAC addresses...\n"; 
                     my $su_rlt=system("LC_ALL=C su -c \"drbl-collect-mac @ethernet_sys\" root");
                     while ($su_rlt == 256) { 
                            $su_rlt=system("LC_ALL=C su -c \"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]";
          # Try to get setting from system also
          # get the ipaddress of NIC "eth1, eth2..." 
          my $ip_sys_tmp;
          my $netmask_sys_tmp;
          chomp($ip_sys_tmp=`drbl-get-ipadd $ethx`);
          chomp($netmask_sys_tmp=`drbl-get-netmask $ethx`);
	  # 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","$color_fail").
            	  "$lang_deploy{\"program_stop\"}\n";
            exit (1);
          };
          my $ip_hostmin = `drbl-ipcalc $ip_sys_tmp $netmask_sys_tmp | awk -F' ' '/^HostMin:/ {print \$2}'`;
	  chomp($ip_hostmin);
          my @ip_sys_sp=split(/\./,$ip_hostmin);
          $ip_sys_prefix[$i]="$ip_sys_sp[0].$ip_sys_sp[1].$ip_sys_sp[2]";
          $ip_sys[$i]=$ip_sys_tmp;

  	  print "$lang_deploy{\"fix_eth_IP_prompt\"} ".
	         colored("$ethx","$color_warn").
		 " ?\n".
	  "[y/N] ";
	  chomp($MAC=<STDIN>);
          my $mac_f_tmp="";
	  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_f_tmp="macadr-$ethx.txt";
	      }else{
	        $mac_f_tmp=$_;
	      }

              # 2 cases filename user entered (1) without path (2) with path
              # we will try both cases, and copy the file to working dir.
              $MAC_file[$i]=`basename $mac_f_tmp 2>/dev/null`;
              chomp($MAC_file[$i]);
              my $mac_dir=`dirname $mac_f_tmp 2>/dev/null`;
              chomp($mac_dir);
              # if user does not specify the path, then it is the original wd
              if ( $mac_dir eq "." ) { $mac_dir="$orig_wd"; }
              print "MAC_file[$i], mac_dir: $MAC_file[$i], $mac_dir\n" if $verbosity >= 2;

              # (1) w/o path: copy the entered file from orig_wd if they exist
              # this is the case if user specified file like "mac1.txt"
              # (2) whith path: copy the entered file if they exist
              # this is the case if user specified file like "/root/mac1.txt"
              system("[ -f $mac_dir/$MAC_file[$i] ] && cp -f $mac_dir/$MAC_file[$i] ./");

              # check MAC address files
              check_MAC_file(".","$MAC_file[$i]");

	      # Find the available start IP which will not conflict with the server
              my $ip_hostmin = `drbl-ipcalc $ip_sys_tmp $netmask_sys_tmp | awk -F' ' '/^HostMin:/ {print \$2}'`;
	      chomp($ip_hostmin);
	      print "Hostmin: $ip_hostmin\n";
              my $range_start_default = `echo $ip_hostmin | awk -F"." '{print \$4}'`;
	      chomp($range_start_default);

              # 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",
		    "[$range_start_default] ";

              unless ( $range_start[$i] ) {
                 while (<STDIN>) {
                   chomp;
	           my $start_input=$_;
                   if ($start_input eq "") {
                     $range_start[$i]=$range_start_default;
	             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
              # we use the MAC file in working dir ($MAC_file[$i]) so it been
              # processed by check_MAC_file. Ex. the space line is stripped.
              $line=`LC_ALL=C cat $MAC_file[$i] 2>/dev/null| wc -l |tr -d \" \" `;
	      chomp($line);
	      if ($line >= 254) {
	       print "The file \"$mac_dir/$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 {
	    print "$delimiter{\"star_line\"}\n".
	          "$lang_deploy{\"range_prompt\"}\n";
	    # Find the available start IP which will not conflict with the server
            my $ip_hostmin = `drbl-ipcalc $ip_sys_tmp $netmask_sys_tmp | awk -F' ' '/^HostMin:/ {print \$2}'`;
	    chomp($ip_hostmin);
	    print "Hostmin: $ip_hostmin\n";
            my $range_start_default = `echo $ip_hostmin | awk -F"." '{print \$4}'`;
	    chomp($range_start_default);

            # 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",
		  "[$range_start_default] ";
            unless ( $range_start[$i] ) {
               while (<STDIN>) {
                 chomp;
	         my $start_input=$_;
                 if ($start_input eq "") {
                   $range_start[$i]=$range_start_default;
	           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;
	    if ( ! $assign_client_no_each_port ) { 
              $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";}
            } else {
              $client_no=$assign_client_no_each_port;
            }
            print "client_no:$client_no\n" if $verbosity >=2;
	    print "$delimiter{\"star_line\"}\n".
  	          "$lang_deploy{\"client_number_connected_to_eth\"} $ethx ?\n".
                  "$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, please enter a number which is <= 253 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","$color_warn").
                  "$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","$color_warn").
                  "$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";
          }
  
	}

	# print the schematic network
        my $PUB_NIC;
        my $IP_PUB_NIC;
	if ( $public_ip_port ) {
          $PUB_NIC=$public_ip_port;
	  $IP_PUB_NIC=$public_ip_addr;
        }else{
          $PUB_NIC=$pub_port_NAT;
          chomp($IP_PUB_NIC=`drbl-get-ipadd $pub_port_NAT`);
	}
	print "$delimiter{\"star_line\"}\n".
       	      "$lang_deploy{\"layout_for_DRBL\"} \n".
  	      "$delimiter{\"star_line\"}\n";
        print color "$color_warn";
        print
"          NIC    NIC IP                    Clients\n".
"+-----------------------------+\n".
"|         DRBL SERVER         |\n".
"|                             |\n".
"|    +-- [$PUB_NIC] $IP_PUB_NIC +- 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... 
	   # For interface like vmnet1, we will not extract that so that the
	   # hostname will not conflict.
	   $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", "$color_warn").
              "$delimiter{\"star_line\"}\n".
              "$lang_deploy{\"press_enter_to_continue\"}";
              chomp($line=<STDIN>);

	# Ask user if DRBL SSI mode ?
	print "$delimiter{\"star_line\"}\n";
	if ( ! $drbl_mode ) {
          print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"which_drbl_mode_for_client\"}\n".
	        "[0] ";
          chomp($drbl_mode=<STDIN>);
        }
        SWITCH: for ($drbl_mode) {
          /^[[:space:]]*1[[:space:]]*$/ && do {
            $drbl_mode="drbl_ssi_mode";
            print "$lang_deploy{\"drbl_ssi_mode_is_set\"}\n".
                  "$delimiter{\"star_line\"}\n";
            last SWITCH;
	  };
          /^[[:space:]]*2[[:space:]]*$/ && do {
            $drbl_mode="none";
	    # since no diskless service for client in the system,
	    # set some default value to avoid asking laster.
	    $swap_create="no";
	    $client_startup_mode="2";  # text mode
            $set_client_root_passwd="no";
            $set_DBN_client_audio_plugdev="no";
            $set_client_alias_IP="no";
            $open_thin_client_option="no";
            print colored ("$lang_deploy{\"no_drbl_mode_in_system\"}\n", "$color_warn").
                  "$delimiter{\"star_line\"}\n";
            last SWITCH;
	  };
          /.*/ && do {
            $drbl_mode="full_drbl_mode";
            print "$lang_deploy{\"full_drbl_mode_is_set\"}\n".
                  "$delimiter{\"star_line\"}\n";
            last SWITCH;
          };
        }
	# Ask user if clonezilla box mode ?
	if ( ! $clonezilla_mode ) {
          print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"which_clonezilla_mode_for_client\"}\n".
	        "[0] ";
          chomp($clonezilla_mode=<STDIN>);
        }
        SWITCH: for ($clonezilla_mode) {
          /^[[:space:]]*1[[:space:]]*$/ && do {
            $clonezilla_mode="clonezilla_box_mode";
            print "$lang_deploy{\"clonezilla_box_mode_is_set\"}\n".
                  "$delimiter{\"star_line\"}\n";
            last SWITCH;
	  };
          /^[[:space:]]*2[[:space:]]*$/ && do {
            $clonezilla_mode="none";
	    # since no clonezilla in the system,
	    # set some default value to avoid asking laster.
            $ocs_img_repo_dir="$ocs_img_repo_dir_default";
            print  colored ("$lang_deploy{\"no_clonezilla_in_system\"}\n", "$color_warn").
                  "$delimiter{\"star_line\"}\n";
            last SWITCH;
	  };
          /^[[:space:]]*3[[:space:]]*$/ && do {
            $clonezilla_mode="clonezilla_live_mode";
            print "$lang_deploy{\"clonezilla_live_mode_is_set\"}\n".
                  "$delimiter{\"star_line\"}\n";
            last SWITCH;
	  };
          /.*/ && do {
            $clonezilla_mode="full_clonezilla_mode";
            print "$lang_deploy{\"full_clonezilla_mode_is_set\"}\n".
                  "$delimiter{\"star_line\"}\n";
            last SWITCH;
          };
        }
	# Ask client's CPU arch when running Clonezilla job with Clonezilla live
	if ( "$run_drbl_ocs_live_prep" eq "yes" ) {
          if ( "$clonezilla_mode" eq "clonezilla_live_mode" ) {
             if ( ! "$live_client_branch" ) {
  	     print "$delimiter{\"star_line\"}\n".
  	           "$lang_deploy{\"which_clonezilla_live_branch\"}\n".
  	           "[2] ";
  	     chomp($live_client_branch=<STDIN>);
             }
             if ( ! "$live_client_cpu_mode" ) {
               if ( "$live_client_branch" eq "0" || "$live_client_branch" eq "1" ) {
  	       print "$delimiter{\"star_line\"}\n".
  	             "$lang_deploy{\"which_live_client_cpu_mode\"}\n".
  	             "[0] ";
  	       chomp($live_client_cpu_mode=<STDIN>);
               }else{
                   # For Ubuntu-based Clonezilla live, only generic is available.
  	         $live_client_cpu_mode="generic";
  	     }
             }
  	}
  	# Format the input number as text
          SWITCH: for ($live_client_branch) {
            /^[[:space:]]*0[[:space:]]*$/ && do {
              $live_client_branch="stable";
              last SWITCH;
          };
            /^[[:space:]]*1[[:space:]]*$/ && do {
              $live_client_branch="testing";
              last SWITCH;
          };
            /^[[:space:]]*3[[:space:]]*$/ && do {
              $live_client_branch="alternative_testing";
              last SWITCH;
          };
            /.*/ && do {
              $live_client_branch="alternative";
              last SWITCH;
            };
          }
  	if ( $live_client_cpu_mode ) {
  	  print "$delimiter{\"star_line\"}\n";
  	  print "$lang_deploy{\"live_client_branch_set\"}: $live_client_branch\n";
  	}
  	# Format the input number as text
          SWITCH: for ($live_client_cpu_mode) {
            /^[[:space:]]*0[[:space:]]*$/ && do {
              $live_client_cpu_mode="i486";
              last SWITCH;
          };
            /^[[:space:]]*1[[:space:]]*$/ && do {
              $live_client_cpu_mode="i686";
              last SWITCH;
          };
            /^[[:space:]]*2[[:space:]]*$/ && do {
              $live_client_cpu_mode="amd64";
              last SWITCH;
          };
            /.*/ && do {
              $live_client_cpu_mode="generic";
              last SWITCH;
            };
          }
          if ( $live_client_cpu_mode ) {
            print "$delimiter{\"star_line\"}\n";
            print "$lang_deploy{\"live_client_cpu_arch_is_set\"}: $live_client_cpu_mode\n";
          }
        }

	if ( "$drbl_mode" eq "none" && "$clonezilla_mode" eq "none" ) {
  	  print colored ("$lang_deploy{\"both_drbl_clonezilla_are_none\"}\n", "$color_warn");}
	# Ask user what's clonezilla image's repository ?
	#
	if ( ! $ocs_img_repo_dir ) {
          print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"where_is_ocs_img_repo_dir\"}\n".
	        "[$ocs_img_repo_dir_default] ";
          while (<STDIN>) {
             chomp;
             $ocs_img_repo_dir=$_;
	     if ( "$ocs_img_repo_dir" =~ /\/mnt$|\/media$|\/tmp$/ ) {
	     print "$ocs_img_repo_dir $lang_deploy{\"not_allowed_ocs_img_repo_dir\"} $lang_deploy{\"enter_it_again\"}!\n".
	           "[$ocs_img_repo_dir_default] ";
             } else {
	       # if empty, use default name
               if ($ocs_img_repo_dir eq "") { $ocs_img_repo_dir="$ocs_img_repo_dir_default"; }
	       print colored ("Directory for clonezilla saved images: $ocs_img_repo_dir\n", "$color_warn");
               last;
             }
          }
        }

        # ask if use need local HD space as swap file ?
	if ( ! $swap_create ) {
	  print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"swap_prompt\"}\n".
	        "[Y/n] ";
          chomp($swap_create=<STDIN>);
	}
	SWITCH: for ($swap_create) {
	  /^n$|^no$/i && do {
            $localswapfile="no";
            last SWITCH;
	  };
	  /.*/ && do {
            $localswapfile="yes";
	    print "$delimiter{\"star_line\"}\n".
                  "$lang_deploy{\"try_to_create_swap\"}\n".
                  "$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", "$color_warn");
            }
            last SWITCH;
	  };
        }

	# Ask which mode is preferred for clients
	print "$delimiter{\"star_line\"}\n";
	if ( ! $client_startup_mode ) {
          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_INIT="text";
            print "$lang_deploy{\"client_text_mode\"}\n".
                  "$delimiter{\"star_line\"}\n";
	}else{
            $CLIENT_INIT="graphic";
            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";
		set_autologin_passwd;
                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
	if ( ! $set_client_root_passwd ){
          print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"set_client_root_passwd\"}\n".
	        "[y/N] ";
          chomp($set_client_root_passwd=<STDIN>);
	}
	SWITCH: for ($set_client_root_passwd) {
	  /^y$|^yes$/i && do {
            $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", "$color_warn");
	      }elsif ($client_root_passwd_1 eq "" && $client_root_passwd_2 eq "" ){ 
		  print colored ("$lang_deploy{\"sorry_passwd_can_not_empty\"}\n", "$color_warn");
	      }
	    }
	    $client_root_passwd=$client_root_passwd_1;
            last SWITCH;
	  };
          /.*/ && do {
            $set_client_root_passwd="no";
            print "$lang_deploy{\"ok_let_continue\"}\n";
            last SWITCH;
          };
	}

	# Ask if user want to set the pxelinux password of clients
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"set_client_pxelinux_passwd\"}\n".
	      "[y/N] ";
        chomp($set_client_pxelinux_passwd=<STDIN>);
	SWITCH: for ($set_client_pxelinux_passwd) {
	  /^y$|^yes$/i && do {
            $set_client_pxelinux_passwd="yes";
	    # we set 2 different passwords to make while loop works.
	    $client_pxelinux_passwd_1="pxeinit1";
	    $client_pxelinux_passwd_2="pxeinit2";
	    while ($client_pxelinux_passwd_1 ne $client_pxelinux_passwd_2 || ($client_pxelinux_passwd_1 eq "" && $client_pxelinux_passwd_2 eq "" )) { 
                 print "$lang_deploy{\"whats_client_pxelinux_passwd\"}\n";
		 # turn off echo
                 system "LC_ALL=C stty -echo";
                 chomp($client_pxelinux_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_pxelinux_passwd_2=<STDIN>);
                 system "LC_ALL=C stty echo";
	      if ($client_pxelinux_passwd_1 ne $client_pxelinux_passwd_2) { 
		  print colored ("$lang_deploy{\"sorry_passwd_not_match\"}\n", "$color_warn");
	      }elsif ($client_pxelinux_passwd_1 eq "" && $client_pxelinux_passwd_2 eq "" ){ 
		  print colored ("$lang_deploy{\"sorry_passwd_can_not_empty\"}\n", "$color_warn");
	      }
	    }
	    $client_pxelinux_passwd=$client_pxelinux_passwd_1;
            last SWITCH;
	  };
	  /.*/ && do {
            $set_client_pxelinux_passwd="no";
            print "$lang_deploy{\"ok_let_continue\"}\n";
            last SWITCH;
          };
        }

	# Ask if user want to set the boot prompt for clients
	if ( $set_client_pxelinux_passwd eq "no" ) {
          print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"set_client_system_select\"}\n".
	        "[Y/n] ";
          chomp($set_client_system_select=<STDIN>);
	  SWITCH: for ($set_client_system_select) {
	    /^n$|^no$/i && do {
              $set_client_system_select="no";
	      last SWITCH;
	    };
	    /.*/ && do {
              $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", "$color_warn");
	        } 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";
	      last SWITCH;
            };
          }
        }

	# Ask if user want to use graphic pxe boot menu for clients
	# When serial console is found in pxelinux config file, force to set
	# $use_graphic_pxelinux_menu=no
	# When CLIENT_INIT is chosen as text mode, default to use txt PXE menu
        my $SERIAL_CONSOLE=`LC_ALL=C grep -Ewi "^serial" $pxecfg_pd/pxelinux.cfg/default 2>/dev/null`;
	if ( $SERIAL_CONSOLE ){
	  print "Serial console parameters are found in $pxecfg_pd/pxelinux.cfg/default. Force to use text PXELINUX menu, no graphic background.\n";
	  $use_graphic_pxelinux_menu="no"
	}
        if ( "$CLIENT_INIT" eq "text"){
	  $graphic_pxelinux_menu_default="no";
	  $graphic_pxelinux_menu_prompt="y/N";
	}else{
	  $graphic_pxelinux_menu_default="yes";
	  $graphic_pxelinux_menu_prompt="Y/n";
	}
	if ( ! $use_graphic_pxelinux_menu ) {
          print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"use_graphic_pxelinux_menu\"}\n".
	         colored ("$lang_deploy{\"note_for_use_graphic_pxelinux_menu\"}\n", "$color_warn").
	        "[$graphic_pxelinux_menu_prompt] ";
          chomp($use_graphic_pxelinux_menu=<STDIN>);
	  if ( ! $use_graphic_pxelinux_menu ) { $use_graphic_pxelinux_menu=$graphic_pxelinux_menu_default }
	  SWITCH: for ($use_graphic_pxelinux_menu) {
	    /^n$|^no$/i && do {
	      print "Use text PXE Linux menu for the client.\n";
              $use_graphic_pxelinux_menu="no";
	      last SWITCH;
	    };
	    /.*/ && do {
	      print "Use graphic PXE Linux menu for the client.\n";
              $use_graphic_pxelinux_menu="yes";
	      last SWITCH;
            };
          }
        }
        print "$delimiter{\"dash_line\"}\n";

	# If Debian, ask if user want to set group plugdev and audio open
	# to all users
        if (-f "/etc/debian_version") {
	  if ( ! $set_DBN_client_audio_plugdev ) {
            print "$delimiter{\"dash_line\"}\n".
                  "$lang_deploy{\"set_DBN_client_audio_plugdev_etc_open_to_all\"}\n".
	          "[Y/n] ";
            chomp($set_DBN_client_audio_plugdev=<STDIN>);
	  }
	  SWITCH: for ($set_DBN_client_audio_plugdev) {
	    /^n$|^no$/i && do {
              $set_DBN_client_audio_plugdev="no";
	      last SWITCH;
	    };
	    /.*/ && do {
              $set_DBN_client_audio_plugdev="yes";
              print "$lang_deploy{\"ok_let_continue\"}\n";
              print "$delimiter{\"dash_line\"}\n";
	      last SWITCH;
            };
          }
        }

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

	# Ask if user want to turn DRBL server as a NAT server
	if ( ! $drbl_server_as_NAT_server ) {
          print "$delimiter{\"dash_line\"}\n".
                "$lang_deploy{\"drbl_server_as_NAT_server\"}\n".
	        "[Y/n] ";
          chomp($drbl_server_as_NAT_server=<STDIN>);
	}
	SWITCH: for ($drbl_server_as_NAT_server) {
	  /^n$|^no$/i && do {
            $drbl_server_as_NAT_server="no";
  	    print colored ("$lang_deploy{\"drbl_server_is_NOT_NAT_server\"}\n", "$color_warn");
	    last SWITCH;
	  };
	  /.*/ && do {
            $drbl_server_as_NAT_server="yes";
            print "$lang_deploy{\"ok_let_continue\"}\n";
            print "$delimiter{\"dash_line\"}\n";
	    last SWITCH;
	  };
        }

	# Ask if user want to purge client files if they exist
        $client_exist_flag=system("LC_ALL=C ls -d /tftpboot/nodes/* >/dev/null 2>&1") / 256;
        if ($client_exist_flag eq 0) {
	   # old clients exist
	   if ( ! $keep_client ) {
             print "$delimiter{\"dash_line\"}\n".
                   "$lang_deploy{\"keep_client_setting_question\"}\n".
	           "[Y/n] ";
             chomp($keep_client=<STDIN>);
           }
	   SWITCH: for ($keep_client) {
	     /^n$|^no$/i && do {
               $purge_client="yes";
               print "$lang_deploy{\"remove_client_setting\"}\n".
                     "$delimiter{\"star_line\"}\n";
	       last SWITCH;
	     };
	     /.*/ && do {
               $purge_client="no";
               print "$lang_deploy{\"keep_client_setting\"}\n".
                     "$delimiter{\"star_line\"}\n";
	       last SWITCH;
             };
           }
        }else{
	   # old clients do NOT exist, so it's not necessary to clean old files
           $purge_client="no";
        }

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

# output the config file
  	print CONFIG_FILE <<END_CFG;
#Setup for general
[general]
domain=$dnsdomain_sys
nisdomain=$nisdomain_sys
localswapfile=$localswapfile
client_init=$CLIENT_INIT
login_gdm_opt=$LOGIN_GDM_OPT
timed_login_time=$TIMED_LOGIN_TIME
maxswapsize=$maxswapsize
ocs_img_repo_dir=$ocs_img_repo_dir
total_client_no=$total_client_no
create_account=$create_account
account_passwd_length=$ACCOUNT_PASSWD_LENGTH_DEFAULT
hostname=$client_hostname_prefix
purge_client=$purge_client
client_autologin_passwd=$client_autologin_passwd
client_root_passwd=$client_root_passwd
client_pxelinux_passwd=$client_pxelinux_passwd
set_client_system_select=$set_client_system_select
use_graphic_pxelinux_menu=$use_graphic_pxelinux_menu
set_DBN_client_audio_plugdev=$set_DBN_client_audio_plugdev
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
run_drbl_ocs_live_prep=$run_drbl_ocs_live_prep
drbl_ocs_live_server=$drbl_ocs_live_server
clonezilla_mode=$clonezilla_mode
live_client_branch=$live_client_branch
live_client_cpu_mode=$live_client_cpu_mode
drbl_mode=$drbl_mode
drbl_server_as_NAT_server=$drbl_server_as_NAT_server
add_start_drbl_services_after_cfg=$add_start_drbl_services_after_cfg
continue_with_one_port=$continue_with_one_port

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
	  }
	  # Put gateway if only one ethernet port is available, i.e. No NAT on this server.
	  if ( $#ethernet_list == 0 ) {  # Only one port
            my $gateway;
	    chomp($gateway=`LANG=C PATH=$PATH:/sbin/:/usr/sbin route -n | awk '/^0.0.0.0/ {print \$2}'`);
  	    print CONFIG_FILE <<END_CFG;
gateway=$gateway
END_CFG
	  }
	  # Append a space line
  	  print CONFIG_FILE <<END_CFG;

END_CFG
	}

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

}#end of interactive_mode

# 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 {
# Part 1,
# get enough information, setup the DRBL server
#
  my $DNS_sys="/etc/resolv.conf";
  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 $ocs_img_repo_dir=$rHoH->{"general"}{"OCS_IMG_REPO_DIR"};
  my $purge_client=$rHoH->{"general"}{"PURGE_CLIENT"};
  my $language=$rHoH->{"general"}{"LANGUAGE"};
  my $set_client_system_select=$rHoH->{"general"}{"SET_CLIENT_SYSTEM_SELECT"};
  my $use_graphic_pxelinux_menu=$rHoH->{"general"}{"USE_GRAPHIC_PXELINUX_MENU"};
  my $set_DBN_client_audio_plugdev=$rHoH->{"general"}{"SET_DBN_CLIENT_AUDIO_PLUGDEV"};
  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"};
  my $client_root_passwd=$rHoH->{"general"}{"CLIENT_ROOT_PASSWD"};
  my $client_pxelinux_passwd=$rHoH->{"general"}{"CLIENT_PXELINUX_PASSWD"};
  my $clonezilla_mode=$rHoH->{"general"}{"CLONEZILLA_MODE"};
  my $run_drbl_ocs_live_prep=$rHoH->{"general"}{"RUN_DRBL_OCS_LIVE_PREP"};
  my $drbl_ocs_live_server=$rHoH->{"general"}{"DRBL_OCS_LIVE_SERVER"};
  my $live_client_branch=$rHoH->{"general"}{"LIVE_CLIENT_BRANCH"};
  my $live_client_cpu_mode=$rHoH->{"general"}{"LIVE_CLIENT_CPU_MODE"};
  my $drbl_mode=$rHoH->{"general"}{"DRBL_MODE"};
  my $drbl_server_as_NAT_server=$rHoH->{"general"}{"DRBL_SERVER_AS_NAT_SERVER"};
  # Note! We do not write and read $sh_debug and $verbose_opt to and from config file, since they are runtime parameter
  
  # 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 $account_passwd_length=$rHoH->{"general"}{"ACCOUNT_PASSWD_LENGTH"};
  my $total_client_no=$rHoH->{"general"}{"TOTAL_CLIENT_NO"};
  my $passwd_length=$rHoH->{"general"}{"ACCOUNT_PASSWD_LENGTH"};
  my $hostname_prefix=$rHoH->{"general"}{"HOSTNAME"};
  my $client_autologin_passwd=$rHoH->{"general"}{"CLIENT_AUTOLOGIN_PASSWD"};
  my $add_start_drbl_services_after_cfg=$rHoH->{"general"}{"ADD_START_DRBL_SERVICES_AFTER_CFG"};
  my $continue_with_one_port=$rHoH->{"general"}{"CONTINUE_WITH_ONE_PORT"};

  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 "ocs_img_repo_dir in system is $ocs_img_repo_dir\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;

  # get some setting in this server so that if some parameters are not set,
  # we can use the one in this system.
  chomp($dnsdomain_sys=`dnsdomainname`);
  chomp($nisdomain_sys=`nisdomainname`);
  print "DNSDOMAIN in system is $dnsdomain_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 = $dnsdomain_sys; 
   print "* dnsdomain 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, just in case
  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 system config file.\n";
     exit;
  }
  if ( ! $domain ) {
     print "Error! DOMAIN unset!\n"; 
     print "Please set it in config file \"$_[0]\" or system config file.\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", "$color_warn").
              "$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";
  }

  # detect kernel in server support udp over NFS or tcp over NFS (tcp is the default seting one for DRBL environment)
  # try to get if the kernel running the server supports NFS over TCP, if not, ust NFS over UDP
  $nfsd_tcp_rlt=system("#!/bin/bash; . $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", "$color_warn").
        "!\n".
        colored ("$lang_deploy{\"change_kernel_notes\"}\n", "$color_warn").
        "$lang_deploy{\"press_enter_to_continue\"}";
        chomp($line=<STDIN>);
  print "$delimiter{\"dash_line\"}\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 (nfsserver_all) if -f nfsserver_all;
  unlink (yp.conf) if -f yp.conf;
  unlink ($hosts_list) if -f $hosts_list;
  unlink ($CLIENT_IP_HOSTNAME_LIST) if -f $CLIENT_IP_HOSTNAME_LIST;
  unlink ($public_ip_list) if -f $public_ip_list;

  # open the config files for DRBL server
  open(DHCPD_OUT,">dhcpd.conf") or die "Can NOT write file \"dhcpd.conf\" \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(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(HOSTS_LIST_OUT,">$hosts_list") or die "Can NOT write file \"$hosts_list\" \n";
  open(CLIENT_HOST_IP_LIST_OUT,">$CLIENT_IP_HOSTNAME_LIST") or die "Can NOT write file \"$CLIENT_IP_HOSTNAME_LIST\" \n";
  open(SWAPCONF_OUT,">mkswapfile") or die "Can NOT write file \"mkswapfile\" \n";
  open(GLOBAL_SETTING,">drbl_deploy.conf") or die "Can NOT write file \"drbl_deploy.conf\" \n";

  ## get the etherboot zpxe filenames
  #print "Searching installed Etherboot files for dhcpd.conf... ";
  #chomp(my $etherboot_zpxe=`$query_pkglist_cmd drbl-etherboot | grep -E "eb-.*-etherboot-pci.zpxe\$" | xargs basename`);
  #chomp(my $sis900_zpxe=`$query_pkglist_cmd drbl-etherboot | grep -E "sis900.zpxe\$" | xargs basename`);
  #print "done! \n";
  print "$delimiter{\"star_line\"}\n";

  # some general option in dhcpd.conf, hosts, $main_sh
  print DHCPD_OUT <<EOF;
# Generated by DRBL. 
# Do NOT modify this file unless you know what you are doing!

default-lease-time			$DHCPD_DEFAULT_LEASE_TIME;
max-lease-time				$DHCPD_MAX_LEASE_TIME;
option subnet-mask			255.255.255.0;
option domain-name-servers  		$nameserver;
option domain-name			"$domain";	
ddns-update-style                       none;
server-name 				drbl;

filename = "pxelinux.0";
# gpxelinux.0 features: HTTP, DNS, TFTP, iSCSI, AoE, bzImage ELF, Multiboot, PXE, PXEXT. Ref: http://ols.fedoraproject.org/OLS/Reprints-2008/anvin-reprint.pdf
# filename = "gpxelinux.0";

## Uncomment the following "if block" when you have some buggy PXE NIC card (such as annoying sis900 NIC). Remember to modify the MAC vendor prefix and restart dhcpd service!!!
## This is a workround for some network card with BAD PXE code in firmware.
## It will only affect those clients with MAC vendor prefix you assigned.
## Ref: http://syslinux.zytor.com/archives/2005-August/005640.html

#if substring (option vendor-class-identifier, 0, 3) = "PXE" {
#     # **************************************************************
#     # ***MODIFY*** the MAC vendor prefix of client network card here.
#     # **************************************************************
#     # For annoying sis900 network card, maybe it is 00:07:95, 00:0C:6E...
#     if substring (hardware, 1, 3) = 00:0C:6E {
#         # sis900.zpxe is specially for sis900 NIC, you can download it from 
#         # http://rom-o-matic.net/etherboot/etherboot-5.4.4/contrib/rom-o-matic
#         filename = "sis900.zpxe";
#     }
#}

# Uncomment the following to get the debug/verbose messages in system log. The messages like the following will be shown:
# Client 0:c:29:3b:34:fb requests 1:2:3:5:6:b:c:d:f:10:11:12:2b:36:3c:43:80:81:82:83:84:85:86:87 - PXEClient:Arch:00000:UNDI:002001 - no dhcp-client-id
# Client 0:c:29:3b:34:fb requests 1:3:6:c:f:1c:28:29:2a - DRBLClient - no dhcp-client-id
# Begin of log command
#log(info, concat("Client ",
#        binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)),
#        " requests ",
#        binary-to-ascii(16, 8, ":", option dhcp-parameter-request-list),
#        " - ",
#        pick-first-value(option vendor-class-identifier, "no vendor-id"),
#        " - ",
#        pick-first-value(option dhcp-client-identifier, "no dhcp-client-id"))
#   );
# End of log command

# This class 'DRBL-Client' defines 3 kind of clients: PXE, Etherboot (1st stage) or DRBL client (2nd stage, i.e. in network initrd/initramfs (mkpxeinitrd-net)) to lease IP address.  This will only affect 'range' statement only, not the 'host' statement.
# Note! The following line(s) in the pool statement: 'allow members of "DRBL-Client";' is/are commented to disable this mechanism by default.
# If you do want to use this mechanism, uncomment all 'allow members of "DRBL-Client";', then only PXE, etherboot and DRBL client can lease IP address from this DHCP service.
# ///NOTE/// In summary, two cases you can turn on this mechanism:
# (1) This DRBL server is not used as a clonezilla server.
# (2) This DRBL server is used as a Clonezilla server, with the following conditions:
#     (a) 'range' statement is used in this DRBL service.
#     (b) There is an existing DHCP service which can provide IP address leases to the restored OS (either GNU/inux or MS Windows) in the client. Otherwise if you uncomment 'allow members of "DRBL-Client";', restored OS won't be able to lease IP address.

# The DRBL client class: PXE, Etherboot or DRBL client
class "DRBL-Client" {
  match if 
  (substring(option vendor-class-identifier, 0, 9) = "PXEClient") or
  (substring(option vendor-class-identifier, 0, 9) = "Etherboot") or
  (substring(option vendor-class-identifier, 0, 10) = "DRBLClient") ;
}

# If you want to use special port for DHCP service, edit here:
# For more info, ref: http://drbl.sourceforge.net/faq/index.php#path=./2_System&entry=37_coexist_with_existing_dhcp.faq
# local-port 1067;
# remote-port 1068;

EOF

  # set the config file for mkswapfile
  print SWAPCONF_OUT "maxswapsize=$maxswapsize\n";

  print CLIENT_HOST_IP_LIST_OUT "# Created by DRBL (drblpush), begin\n";

  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

# output the global setting for drbl_deploy
  print GLOBAL_SETTING <<GLOBAL_EOF;
##################################
# drbl_deploy global setting
# File automatically created by drblpush.
# It is better not to manually modify this file.
##################################
config_file="$config_file"
purge_client="$purge_client"
client_root_passwd="$client_root_passwd"
client_pxelinux_passwd="$client_pxelinux_passwd"
language="$language"
set_client_system_select="$set_client_system_select"
use_graphic_pxelinux_menu="$use_graphic_pxelinux_menu"
set_DBN_client_audio_plugdev="$set_DBN_client_audio_plugdev"
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
nfs_protocol="$nfs_protocol"
client_init="$CLIENT_INIT"
mkswapfile="$mkswapfile"
ocs_img_repo_dir="$ocs_img_repo_dir"
nfsserver_default="$nfsserver_default"
nameserver="$nameserver"
nameserver_="$nameserver_"
domain="$domain"
nisdomain="$nisdomain"
public_ip_list="$public_ip_list"
login_gdm_opt="$login_gdm_opt"
client_autologin_passwd="$client_autologin_passwd"
timed_login_time="$TIMED_LOGIN_TIME"
run_drbl_ocs_live_prep="$run_drbl_ocs_live_prep"
drbl_ocs_live_server="$drbl_ocs_live_server"
clonezilla_mode="$clonezilla_mode"
live_client_branch="$live_client_branch"
live_client_cpu_mode="$live_client_cpu_mode"
drbl_mode="$drbl_mode"
sh_debug="$sh_debug"
verbose_opt="$verbose_opt"
CLIENT_IP_HOSTNAME_LIST="$CLIENT_IP_HOSTNAME_LIST"
drbl_server_as_NAT_server="$drbl_server_as_NAT_server"
add_start_drbl_services_after_cfg="$add_start_drbl_services_after_cfg"
continue_with_one_port="$continue_with_one_port"
##################################
# End of global setting
##################################

GLOBAL_EOF

close(GLOBAL_EOF);
system("chmod 600 drbl_deploy.conf");
system("mkdir -p $drbl_syscfg; cp -f drbl_deploy.conf $drbl_syscfg/");

  print DISKLESS_OUT <<EOF;
#!/bin/bash $sh_debug
# **********************************************************************
# File automatically created by drblpush, 
# better not to modify this file manually.
# "drblpush" is written by K. L. Huang, klhaung _at_ gmail com,
# especially for Debian, then modified to use with Redhat by
# Steven Shiau, steven _at_ nchc org tw.
# **********************************************************************

# Load DRBL setting and functions
DRBL_SCRIPT_PATH="\${DRBL_SCRIPT_PATH:-/usr/share/drbl/}"

. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
. /etc/drbl/drbl_deploy.conf

# Get distribution ID and release number.
[ -e /etc/lsb-release ] && . /etc/lsb-release

# get the l10n message
if [ -f "$DRBL_SCRIPT_PATH/lang/bash/$language" ] ; then
 . $DRBL_SCRIPT_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

EOF

print DISKLESS_OUT q{
# Decide the sysv init service control program is update-rc.d or insserv in Debian or Ubuntu. The output variable is "$dbn_ubn_serv_control_prog".
if [ -e /etc/debian_version ]; then
  get_debian_ubuntu_init_serv_control_prog
fi

# Create the prerun/postrun dirs if they do not exist
mkdir -p $DRBLPUSH_PRERUN_DIR $DRBLPUSH_POSTRUN_DIR
# pre run
if [ -n "$(unalias ls 2>/dev/null; ls $DRBLPUSH_PRERUN_DIR/ 2>/dev/null)" ]; then
  echo "Some files are found in $DRBLPUSH_PRERUN_DIR. Run them first..."
  drbl-run-parts $DRBLPUSH_PRERUN_DIR
fi
# check if the space is enough to setup DRBL
echo -n "Checking the necessary disk space... "
# When none full drbl mode AND none full clonezilla mode, only 1 client. Otherwise we will generate all the clients.
if [ "$clonezilla_mode" != "full_clonezilla_mode" -a \
     "$drbl_mode" != "full_drbl_mode" ]; then
  total_client_no_for_checking="1"
else
  total_client_no_for_checking="$total_client_no"
fi
space_check=$(check_drbl_setup_space -n $total_client_no_for_checking)
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!"

# 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!"

# Do some checks...
if [ "$(dirname $drbl_common_root)" = "/" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "You can NOT assign the drbl_common_root as / in drbl.conf!!!"
  echo "Program terminated!!!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  exit 1
fi

# varlib_NOT_2_be_copied_2_each_client and varcache_2_be_copied_2_common_root are loaded from drbl.conf
# varlib_NOT_2_be_copied_2_each_client -> varlib_opts_common_to_each is processed in 
# sbin/drbl-gen-client-files

# "$DISTRIB_ID" is from /etc/lsb-release
if [ "$DISTRIB_ID" = "Ubuntu" ]; then
  case "$DISTRIB_RELEASE" in
   "10.10")
      # Weird Buggy Ubuntu 10.10 (Maverick)... The /var/lib/nfs/{sm,sm.bak} are not owned by statd in 1:1.2.2-1ubuntu1. It's owned by root. No idea how it happens, it's not always. Anyway force to add this for Ubuntu 10.10.
      if [ "$(LC_ALL=C stat -c %U /var/lib/nfs/sm)" != "statd" ]; then
        chown -R statd /var/lib/nfs/{sm,sm.bak}
      fi
    ;;
  esac
fi

# If purge_client = no, which means we will NOT overwrite the old files.
# we had better to add "-u" for rsync, and we assign keep_old_files_flag=yes
if [ "$purge_client" = "no" ]; then
  RSYNC_OPT_EXTRA="-u"
  keep_old_files_flag="yes"
else
  RSYNC_OPT_EXTRA=""
  keep_old_files_flag="no"
fi

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

# backup the original setting files in DRBL server
[ -f $DHCPDCONF_DIR/dhcpd.conf ] && mv -f $DHCPDCONF_DIR/dhcpd.conf $DHCPDCONF_DIR/dhcpd.conf.orig
[ -f /etc/netgroup ] && mv -f /etc/netgroup /etc/netgroup.drblsave
[ -f /var/yp/securenets ] && mv -f /var/yp/securenets /var/yp/securenets.drblsave
[ -f /etc/ypserv.securenets ] && mv -f /etc/ypserv.securenets /etc/ypserv.securenets.drblsave
# We do not want the old ethers, this will cause lag in network. Thanks to Dave Haakenhout <Dave.Haakenhout _at_ nccw nl>
[ -e /etc/ethers ] && mv -f /etc/ethers /etc/ethers.orig

# copy some config files (dhcpd.conf, yp.conf...) created
# in the drblpush DRBL server.

cp -f dhcpd.conf $DHCPDCONF_DIR/
cp -f mkswapfile $SYSCONF_PATH/mkswapfile

for icfg in yp.conf netgroup; do
  cp -f $icfg /etc/
done

# put the temp hostname to /etc/drbl
cp -f $CLIENT_IP_HOSTNAME_LIST $IP_HOST_TABLE

# create /etc/hosts based on drblpush.conf and dhcpd.conf, so must be after dhcpd.conf is copied to system.
drbl-etc-hosts

echo -n "Cleaning the stale files of the diskless nodes if they exist... "
# clean the config or setting files in $drbl_common_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

# Part 2,
# generate file system for clients, like what is done in Debian diskless-newimage
#

# Setting
echo "$msg_delimiter_star_line"
# get the distribution name and type: OS_Version and OS_type
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 GNU/Linux: $OS_Version"

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

# When user changes ocsroot, we need to modify drbl.conf (note: This must be after $drbl_common_root//$ocsroot is created)
# If this script is rerun, maybe clonezilla.lock exists.
if [ -f "$ocs_lock_dir/clonezilla.lock" ]; then
   echo "Your system is already in clonezilla mode... we will stop it when running drblpush so it will not in a mess."
   drbl-ocs -l 0 stop
else
   # prepare a dir for ocs lock file
   mkdir -p $ocs_lock_dir
fi
# We need the clonezilla image dir ($ocs_img_repo_dir for sever, and $drbl_common_root/$ocs_img_repo_dir for client to use it as a mount point) if it does not exist, and we will write it into drbl.conf so that the later script will read that.
mkdir -p $ocs_img_repo_dir $drbl_common_root/$ocs_img_repo_dir
# Create Clonezilla log dir
mkdir -p $ocs_log_dir

# ocsroot is supposed to be /home/partimag if untouched, if it is assigned to different one, we have to modify drbl.conf
# strip the last / if it exists ( avoid this does not match "/home/partimag" <-> "/home/partimag/" , actually they are same)
ocsroot="$(LC_ALL=C echo $ocsroot | sed -e "s|/[[:space:]]*$||g")"
ocs_img_repo_dir="$(LC_ALL=C echo $ocs_img_repo_dir | sed -e "s|/[[:space:]]*$||g")"
if [ "$ocs_img_repo_dir" != "$ocsroot" ]; then
  sub_cmd="s|^[[:space:]]*ocsroot=.*|ocsroot=\"$ocs_img_repo_dir\" # Modified by drblpush|g"
  perl -pi -e "$sub_cmd" /etc/drbl/drbl.conf
fi

case "$purge_client" in
   [yY][eE][sS])
      echo -n "Completely cleaning old common root files if they exist... " 
      # Clean the stalled files...
      [ -d $drbl_common_root/etc ] && rm -rf $drbl_common_root/etc
      [ -d $drbl_common_root/var ] && rm -rf $drbl_common_root/var
      echo "done !"
      
      echo -n "Completely cleaning old nodes if they exist... " 
      # Clean old node files
      for iclient in $drblroot/[0-9]*; do
        [ -d "$iclient" -a -n "$(echo "$iclient" | grep -E "[0-9]")" ] && 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 "."
# diskless_root_dir_1 are those necessary dir for mount point (from drbl.conf).
# From Debian Sid 201108, the /run (tmpfs) is required. Therefore if it can be found on server, append it. Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=620157
[ -d "/run" ] && diskless_root_dir_1="$diskless_root_dir_1 run"
# $diskless_root_dir_ro_user_add $diskless_root_dir_rw_user_add are user assigned dirs in drbl.conf
for d in $diskless_root_dir_1 $diskless_root_dir_ro_user_add $diskless_root_dir_rw_user_add; do
   mkdir -p $drbl_common_root/$d
done
# diskless_root_dir_2 are those necessary dir for mount point (from drbl.conf), too. These dirs depend on distribution, so we will test it before create it.
for d in $diskless_root_dir_2; do
   [ -d "/$d" ] && mkdir -p $drbl_common_root/$d
done

# locale en_US.UTF-8 will be the default locale for clonezilla dialog in console. Therefore we have to create that.
gen_locale_if_not_found en_US en_US.UTF-8

# 1/7/2006, since B2D does not have /media, but it will create and use that 
# once you plug the usb devices, so now we mkdir media for DRBL B2D client 
echo -n "."
if [ -e /etc/b2d-release ]; then
  mkdir -p $drbl_common_root/media
fi

echo -n "."
# copy some rc files to root home directory
for ir in .bashrc .bash_profile .profile .viminfo; do
  [ -f /root/$ir ] && rsync -a $RSYNC_OPT_EXTRA /root/$ir $drbl_common_root/root/
done

# create the console so that client can output message when entering init. This is especially for Debian. 
echo -n "."
# force to clean the old ones
for i in console null; do
  [ -c $drbl_common_root/dev/$i ] && rm -f $drbl_common_root/dev/$i
done
mknod -m 600 $drbl_common_root/dev/console c 5 1
mknod -m 666 $drbl_common_root/dev/null c 1 3

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

#
echo -n "."
rsync -a $RSYNC_OPT_EXTRA /bin $drbl_common_root/
# We need awk and cut in init.drbl.
# For RH-like, awk and cut are in /bin, however, in Debian, they are in /usr/bin, which is not mounted when trying to get IP address of NFS server in running init.drbl. So we have to copy them.
# Note!!! In Debian, we need the gawk, not awk, so we already installed gawk
# in drblsrv, and it will replace awk as /etc/alternatives/awk -> /usr/bin/gawk
# But maybe it is better to cp gawk -> awk ?
must_prog_for_init_drbl="cut gawk"
for imust in $must_prog_for_init_drbl; do
  [ -e "$drbl_common_root/bin/$imust" ] && rm -f $drbl_common_root/bin/$imust
  if [ -e "/usr/bin/$imust" ]; then
     #echo "Copying $imust from /usr/bin/ to $drbl_common_root/bin/..."
     cp -af --dereference /usr/bin/$imust $drbl_common_root/bin/
  else
     [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
     echo "FATAL error!!! $imust is not found in /usr/bin!!! Client will NOT be able to boot or run correctly!!!"
     [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  fi
done
# link gawk as awk for clients.
(cd $drbl_common_root/bin/; ln -fs gawk awk)
# For gawk_3.1.8+dfsg-0.1 on Debian sid (2011/07/30), it requires /usr/lib/*.so*# $ ldd /usr/bin/gawk
# linux-gate.so.1 =>  (0xb76eb000)
# libsigsegv.so.2 => /usr/lib/libsigsegv.so.2 (0xb76d7000)
# libdl.so.2 => /lib/i386-linux-gnu/i686/cmov/libdl.so.2 (0xb76d3000)
# libm.so.6 => /lib/i386-linux-gnu/i686/cmov/libm.so.6 (0xb76ac000)
# libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb7552000)
# /lib/ld-linux.so.2 (0xb76ec000)
#
export DESTDIR="$drbl_common_root"
[ -e "$(LC_ALL=C which gawk)" ] && copy_exec_drbl "$(LC_ALL=C which gawk)" /bin/

echo -n "."
# Creat a file $drbl_common_root/sbin/fsck.nfs to let rc.sysinit use 
# "fsck.nfs" always successfully
echo "#!/bin/bash
# dummy fsck.nfs file that always returns success.
# Created by drblpush to let rc.sysinit use fsck.nfs always successfully
exit 0" > $drbl_common_root/sbin/fsck.nfs
chmod 755 $drbl_common_root/sbin/fsck.nfs

echo -n "."

# Steven todo, make sure it is right ?
# $drbl_common_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 is better to keep $drbl_common_root/lib/security/ without updating.
# if [ -d $drbl_common_root/lib/security ]; then
#   rsync -a $RSYNC_OPT_EXTRA --exclude=modules/ --exclude=security/ /lib $drbl_common_root/
# else
#   rsync -a $RSYNC_OPT_EXTRA --exclude=modules/ /lib $drbl_common_root/
# fi
# 2006/6/1 Just sync it, otherwise /lib/security will not be updated, some files will be missing.
rsync -a $RSYNC_OPT_EXTRA --exclude=modules/ /lib $drbl_common_root/

# For x86_64
# For FC3 or later: /lib64 is a directory, not /lib32, only dir /lib
# For Ubuntu breezy amd64: /lib64 is a symbolic to /lib, /lib32 is a directory
for d in lib32 lib64; do
 if [ -L "/$d" ]; then
   # First, we copy the symbolic file itself (not followed the dir)
   echo -n "Copying symbolic link dir /$d to $drbl_common_root/..."
   rsync -a /$d $drbl_common_root/
   # 2nd, we copy the source file, e.g. "/emul" in the following.
   # E.g. For amd64 Debian Lenny 
   # ls -alFh /lib32
   # lrwxrwxrwx 1 root root 20 2008-11-11 22:49 /lib32 -> /emul/ia32-linux/lib/
   # ls -alFh /lib64
   # lrwxrwxrwx 1 root root 4 2008-10-31 19:58 /lib64 -> /lib/
   dir_top="$(LANG=C file -hs /$d | sed -e "s/symbolic link to//g" -e "s/'//g" | sed -e "s/\`//g" | awk -F":" '{print $2}')"  # dir_top e.g. /emul/ia32-linux/lib/
   dir_top="$(LANG=C echo $dir_top | awk -F"/" '{print $2}')"  # e.g. emul
   echo -n "Copying the source dir of symbolic link dir source by: rsync -a /$dir_top $drbl_common_root/"
   rsync -a /$dir_top $drbl_common_root/
 elif [ -d "/$d" ]; then
   echo -n "Copying normal dir /$d to $drbl_common_root/..."
   rsync -a $RSYNC_OPT_EXTRA /$d $drbl_common_root/
 fi
done

echo " done!"

# Copy or update the kernel for client if necessary...
echo "Update the kernel for client if necessary... "
update-drbl-client-kernel-from-server $verbose_opt $RSYNC_OPT_EXTRA

# copy /etc to template node
# etc_exclude_dirs is loaded from drbl.conf
etc_rsync_opt=""
for ietc in $etc_exclude_dirs; do
  etc_rsync_opt="$etc_rsync_opt --exclude=$ietc"
done
echo "Copying the directory /etc/ to clients common root $drbl_common_root..."
rsync -a $etc_rsync_opt $RSYNC_OPT_EXTRA /etc $drbl_common_root

# For Ubuntu 6.10 (edgy), there is no /etc/inittab, but upstart still respect 
# inittab. We will create one for client, but for edgy+1 or later, maybe not respect /etc/inittab, then we have to follow upstart in the future.
#if [ ! -f /etc/inittab ]; then
#  cat <<-INIT_END > $drbl_common_root/etc/inittab
## inittab created by DRBL.
## This file is created to be backward compatible with Ubuntu Dapper/Breezy and Debian Sarge/Etch. Although Ubuntu Edgy now uses upstart instead of sysvinit, it still respect /etc/inittab, but in Edgy+1 or later, maybe it will not respect.
#
## The default runlevel.
#id:2:initdefault:
#INIT_END
#fi
#

# 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 $drbl_common_root/etc/ssh/$ik &>/dev/null; then
     echo -n "Cleaning the ssh key file $ik copied from server... "
     rm -f $drbl_common_root/etc/ssh/$ik
     echo "done!"
  fi
done

# comment /etc/hosts.allow and /etc/hosts.deny in drbl client
for ik in hosts.deny hosts.allow; do
  echo -n "Commenting the TCPwrapper related file $drbl_common_root/etc/$ik copied from server... "
  perl -pi -e 's/^([^#][[:print:]]+)$/# $1 #  commented by DRBL/g' $drbl_common_root/etc/$ik
  echo "done!"
done

# clean the mtab in $drbl_common_root copied from server
rm -f $drbl_common_root/etc/mtab*

# For Debian udev, if $drbl_common_root/etc/udev/rules.d/z25_persistent-net.rules exists, remove it. Since it contains the network MAC address from drbl server, and we should let client automatically create that.
if [ -n "$(unalias ls 2>/dev/null; ls $drbl_common_root/etc/udev/rules.d/*persistent-net.rules 2>/dev/null)" ]; then
  rm -f $drbl_common_root/etc/udev/rules.d/*persistent-net.rules
fi

# 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 $drbl_common_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" $drbl_common_root/etc/hosts
fi

# create mkswapfile to $drbl_common_root/etc/init.d/
# This must before service to add
cp -f $drbl_setup_path/files/misc/{mkswapfile,drblthincli,arm-wol} $drbl_common_root/etc/init.d/
# ocs-run is a script to start clone for clonezilla, it only will be put in 
# client's rc1.d when clonezilla save/restart start.
cp -f $drbl_setup_path/files/ocs/ocs-run $drbl_common_root/etc/init.d/
# For Debian, there is no gdm-safe-restart script, we just copy it from drbl
# package. We need gdm-safe-restart for terminal mode setup.
[ ! -x /usr/sbin/gdm-safe-restart ] && cp -f $drbl_setup_path/files/misc/gdm-safe-restart /usr/sbin/gdm-safe-restart
chown root.root $drbl_common_root/etc/init.d/{mkswapfile,drblthincli,arm-wol}

# For MDK/Debian/SuSE, we put the one we wrote "firstboot.XXX.drbl" to 
# common root /etc/init.d as firstboot.
# There is already firstboot comes with RH/FC/CentOS.
# We do NOT use the firstboot comes with yast2-firstboot in SuSE.
if [ "$OS_type" != "RH" ]; then
  if [ -f "$drbl_setup_path/files/${OS_type}/${OS_Version}/firstboot.${OS_Version}.drbl" ]; then
    cp -f $drbl_setup_path/files/${OS_type}/${OS_Version}/firstboot.${OS_Version}.drbl $drbl_common_root/etc/init.d/firstboot
  else
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "Warning! Unable to find the fine-tune file ${drbl_setup_path}/files/${OS_type}/${OS_Version}/firstboot.${OS_Version}.drbl, use ${drbl_setup_path}/files/${OS_type}/firstboot.default-${OS_type}.drbl as /etc/init.d/firstboot for DRBL clients!"
    echo "This may cause some problems to DRBL clients!"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    cp -f $drbl_setup_path/files/${OS_type}/firstboot.default-${OS_type}.drbl $drbl_common_root/etc/init.d/firstboot
  fi
fi

# modify some bootup script or setting (System V is easier to do here.. all scripts are separated.)
if [ -e /etc/debian_version ]; then
  # Debian
  # For genuine Debian Sarge
  perl -pi -e 's/(^[[:space:]]*umount -ttmpfs.*)/#$1 # Modified by DRBL/g' $drbl_common_root/etc/init.d/umountfs
  perl -pi -e 's/(^[[:space:]]*umount -tnoproc)(,noprocfs.*)/$1,nonfs,notmpfs$2 # Modified by DRBL/g' $drbl_common_root/etc/init.d/umountfs
  # For genuine Debian Etch
  perl -pi -e 's/(^[[:space:]]*)(proc|procfs|linprocfs|devfs|sysfs|usbfs.*)/$1nfs|tmpfs|none|$2/g' $drbl_common_root/etc/init.d/umountfs
  # for B2D
  perl -pi -e 's/^[[:space:]]*umount \$FORCE -a -r.*/umount \$FORCE -tnoproc,nonfs,notmpfs,noprocfs,nodevfs,nosysfs,nousbfs,nousbdevfs,nodevpts -d -a -r # Modified by DRBL/g' $drbl_common_root/etc/init.d/umountfs
  # for Ubuntu Dapper
  # To avoid $DIR is noting.
  # Ref: https://lists.ubuntu.com/archives/ubuntu-users/2006-May/079378.html
  perl -pi -e 's|^([[:space:]]*)(umount -r -d \$DIRS*)|$1 [ -n "\$DIRS" ] && $2 # Modified by DRBL|g' $drbl_common_root/etc/init.d/umountfs
  # For Debian Squeeze, by default it uses parallel start service "startpar" (i.e. CONCURRENCY=makefile). We disable it in the client so that we won't have to modify the services. E.g. /etc/rc1.d/*ssh when running clonezilla SE job. 
  LC_ALL=C perl -pi -e "s|^CONCURRENCY=.*|CONCURRENCY=none # Mofified by DRBL|g" $drbl_common_root/etc/init.d/rc

elif [ -e /etc/SuSE-release ]; then
  # For SuSE
  # SuSE is unique here, it uses parallel start service "startpar", we do not
  # want that, otherwise some services might fail due to NFS client does not
  # finish yet.
  echo -n "Turn off runlevel scripts in parallel in clients... "
  perl -pi -e "s/^[[:space:]]*[#]*[[:space:]]*RUN_PARALLEL=.*/RUN_PARALLEL=no/g" $drbl_common_root/etc/sysconfig/boot
  echo "done!"
  # modify some services
  # 1. etc/init.d/boot, use -o remount so it will not complain when booting.
  perl -pi -e 's/^([[:space:]]*mount -n -t proc)(.*)/$1 -o remount $2 # Modified by DRBL/g' $drbl_common_root/etc/init.d/boot
  perl -pi -e 's/^([[:space:]]*mount -n -t sysfs)(.*)/$1 -o remount $2 # Modified by DRBL/g' $drbl_common_root/etc/init.d/boot
  # 2. boot.udev, we have to turn on runlevel 1 so that clonezilla will be ok.
  perl -pi -e 's/^[[:space:]]*#+[[:space:]]*Default-Start:.*/# Default-Start:     B 1/g' $drbl_common_root/etc/init.d/boot.udev
  # 3. boot.localfs, we add -l when umount in "boot.udev stop" (called by reboot/halt)
  perl -pi -e 's/^([[:space:]]*umount) -avt (noproc,nonfs.*)/$1 -avtl nosysfs,$2 # Modified by DRBL/g' $drbl_common_root/etc/init.d/boot.localfs
  # 3. nfs client, 
  # (a) For OpenSuSE 11.1, it seems if we do not restart dbus after NFS is run, something weird. E.g. When xdm start, an error:
  # Starting service gdm ** (gdm:2916): WARNING **: Couldn't connect to system bus: Failed to connect to socket /var/run/dbus/system_bus_socket: Connection refused startproc:  exit status of parent of /usr/sbin/gdm: 1 failed
  # Therefore we force to restart dbus after nfs dirs are mounted:
  perl -pi -e 's|^([[:space:]]*mount -at nfs.*)|$1; /etc/init.d/dbus restart # Modified by DRBL|g' $drbl_common_root/etc/init.d/nfs
  # (b) We do not want to recreate ld.so.cache, it is only provided
  # by DRBL server.
  # Note! recreate here will take a long time.
  # Note2: boot.ldconfig is run before nfs. 
  # It will not include some remote NFS directory 
  # (like /opt/kde/lib... /opt/gnome/lib...
  # we have to turn off boot.ldconfig in /etc/init.d/boot.d also.
  # Here we put "true" so that if there is only one command in the if/else block, the nfs start script won't fail.
  perl -pi -e 's|^([[:space:]]*#+)[[:space:]]*check if ld.so.cache needs to be refreshed.*|$1 DRBL comment this, we will not let boot.ldconfig run in DRBL client.|g' $drbl_common_root/etc/init.d/nfs
  perl -pi -e 's|/etc/init.d/(boot.ldconfig start.*)|true #$1|g' $drbl_common_root/etc/init.d/nfs
  rm -f $drbl_common_root/etc/init.d/boot.d/[SK][0-9][0-9]boot.ldconfig 
fi

# Remove the unnecessary service, 
# First, remove all the service
# Prepare the necessary env for chkconfig, update-rc.d or insserv
if [ -e /etc/debian_version ]; then
  # For Debian
  prepare_update_rc_d_env $drbl_common_root/
elif [ -e /etc/SuSE-release ]; then
  # For SuSE
  create_insserv_env $drbl_common_root/
else
  # For RH-like
  create_chkconfig_env $drbl_common_root/
fi
# Skip those do not support chkconfig, or actually, they are not services.
# reboot/halt are necessary for all dists.
service_to_be_kept="dualconf functions reboot halt killall single mandrake_consmap mandrake_everytime mandrake_firstime usb"
for isrv in /etc/init.d/*; do
  # Skip directory
  [ -d "$isrv" ] && continue
  i="$(basename $isrv)"
  # keep some services.
  [ -n "$(echo $service_to_be_kept | grep -w $i)" ] && continue
  if [ -e /etc/debian_version ]; then
    # For Debian
    # We should keep the services in rcS.d, but "update-rc.d remove" does
    # not support this. It will also clean all the services in rcS.d.
    # So we will copy those services of rcS.d to client's common root 
    # after this. NOTE! This can only be done after all updata-rc.d 
    # finished. Otherwise it will affect the update-rc.d
    if [ "$dbn_ubn_serv_control_prog" = "use-insserv" ]; then
      chroot $drbl_common_root/ insserv -f -r $i &> /dev/null
    else
      chroot $drbl_common_root/ /usr/sbin/update-rc.d -f $i remove &> /dev/null
    fi
  elif [ -e /etc/SuSE-release ]; then
    # For SuSE
    # There are a lot of boot.* services, we must exclude them also.
    # Special case: boot.udev, which only starts in boot, 2, 3, 5, but we need 
    # it to start in 1 also. So we remove boot.udev here, then modify it, then
    # add it later.
    [ "$i" = "boot.udev" ] && chroot $drbl_common_root/ /sbin/insserv -f -r $i
    [ -n "$(echo $i | grep "^boot.*")" ] && continue

    [ "$i" = "Makefile" ] && continue
    [ "$i" = "README" ] && continue
    [ "$i" = "rc" ] && continue
    chroot $drbl_common_root/ /sbin/insserv -f -r $i
  else
    # For RH-like
    chroot $drbl_common_root/ /sbin/chkconfig --del $i
    # Maybe it will fail to delete the service, so try to delete brutely. 
    # This happens in Mandriva 2007.0. Bugs report:
    # http://qa.mandriva.com/show_bug.cgi?id=24409
    # http://qa.mandriva.com/show_bug.cgi?id=23104
    # In Mandriva 2008.0, there is some special service start name "S-1", like:
    # ./rc.d/rc3.d/S-1nfs-common,  ./rc.d/rc3.d/S-1nfs-server
    # Therefore it's not "[SK][0-9][0-9]$i", it's "[SK][-0-9][0-9]$i" here.
    ( cd $drbl_common_root/etc
      find ./rc*.d -regex ".*[SK][-0-9][0-9]$i" -exec rm -f {} \;
    )
  fi
done

# Get the gdm or kdm config filename
get_gdm_kdm_conf_filename

if [ -z "$GDM_CFG" ]; then
  prepare_gdm_custom_conf
fi

# set gdm.conf for DRBL clients
if [ -f "$drbl_common_root/$GDM_CFG" -a "$set_drbl_gdmgreeter" = "yes" ]; then
  # force to use graphic greeting (gdmgreeter is available in sarge, not in woody. In woody, it is gdmlogin)
  # gdmgreeter: /usr/bin/gdmgreeter (sarge) or /usr/lib/gdm/gdmgreeter (breezy)
  # gnome 2.14: /usr/libexec/gdmgreeter
  GDM_GREETER="$($query_pkglist_cmd gdm 2>/dev/null | grep -E "\/gdmgreeter$")"
  if [ -n "$GDM_GREETER" ]; then
   # Set Greeter=$GDM_GREETER
   lines="$(get_block_line_in_gdm_kdm daemon $drbl_common_root/$GDM_CFG)"
   begin_line=$(echo $lines | awk -F" " '{print $1}')
   end_line=$(echo $lines | awk -F" " '{print $2}')
   chk_cmd="if ($begin_line..$end_line) {print}"
   if [ -n "$(perl -n -e "$chk_cmd" $drbl_common_root/$GDM_CFG | grep -i "^Greeter=")" ]; then
     sub_cmd="if ($begin_line..$end_line) {s|^Greeter=.*|Greeter=$GDM_GREETER|}"
     perl -pi -e "$sub_cmd" $drbl_common_root/$GDM_CFG
   else
     # insert 1 blank line
     sub_cmd="if ($((end_line))..$((end_line))) {s|^(.*)$|\$1\n|gi}"
     perl -pi -e "$sub_cmd" $drbl_common_root/$GDM_CFG
     # replace the one we want in the added blank line
     sub_cmd="if ($((end_line+1))..$((end_line+1))) {s|^$|Greeter=$GDM_GREETER|gi}"
     perl -pi -e "$sub_cmd" $drbl_common_root/$GDM_CFG
   fi
   # Set GraphicalTheme=drbl-gdm
   lines="$(get_block_line_in_gdm_kdm greeter $drbl_common_root/$GDM_CFG)"
   begin_line=$(echo $lines | awk -F" " '{print $1}')
   end_line=$(echo $lines | awk -F" " '{print $2}')
   chk_cmd="if ($begin_line..$end_line) {print}"
   if [ -n "$(perl -n -e "$chk_cmd" $drbl_common_root/$GDM_CFG | grep -i "^GraphicalTheme=")" ]; then
     sub_cmd="if ($begin_line..$end_line) {s|^GraphicalTheme=.*|GraphicalTheme=drbl-gdm|}"
     perl -pi -e "$sub_cmd" $drbl_common_root/$GDM_CFG
   else
     # insert 1 blank line
     sub_cmd="if ($((end_line))..$((end_line))) {s|^(.*)$|\$1\n|gi}"
     perl -pi -e "$sub_cmd" $drbl_common_root/$GDM_CFG
     # replace the one we want in the added blank line
     sub_cmd="if ($((end_line+1))..$((end_line+1))) {s|^$|GraphicalTheme=drbl-gdm|gi}"
     perl -pi -e "$sub_cmd" $drbl_common_root/$GDM_CFG
   fi
  fi
fi

# 2nd, add the service which DRBL client need
client_services=""
# Add the necessary services:
# firstboot is always necessary. Even for MDK, there is no firstboot in /etc/init.d, we will add it which is provided by DRBL. It will control the run level
# via chkconfig (i.e. for rc3, although the service is added, but it will
# not run.
# Note by Steven Shiau on 2006/09/26, we put firstboot in the beginning 
# (hence it's in front of the dm service of Mandriva), since in LSB based 
# service, we need to put firstboot before dm, otherwise dm might run 
# before firstboot.
client_services="$client_services firstboot"

# client_services_chklist is loaded in drbl.conf.

# check if the service listed exists
for iser in $client_services_chklist; do
   [ -e "/etc/init.d/$iser" ] && client_services="$client_services $iser"
done

# add the services only exist in DRBL client.
client_services="$client_services drblthincli $mkswapfile arm-wol"

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

# add some special services for specific distribution
if [ -e /etc/debian_version ]; then
  # For Debian
  # The umountfs is already modified by drblpush
  client_services="$client_services sendsigs umountfs"
elif [ -e /etc/SuSE-release ]; then
  # For SuSE
  # Suse uses xdm to start kdm/gdm/xdm, they are all in the same service name.
  # We foced to use the modified boot.udev (it's on in runlevel 1,2,3,4,5
  # Note: "nfs" is server in RH, but it's client in SuSE. So we have to add it
  # separately for SuSE.
  client_services="$client_services nfs xdm boot.udev"
else
  # For RH-like
  # IIim in FC2, iiim in FC3, scim for MDK 10.1 (scim is not a service, so skip this). Try to find which one...
  for iinput in IIim iiim; do
     if [ -n "$(LC_ALL=C [ -x /sbin/chkconfig ] && chkconfig --list $iinput 2>/dev/null | awk '/5:on/ {print $7}')" -o -n "$(LC_ALL=C [ -x /sbin/chkconfig ] && chkconfig --list $iinput 2>/dev/null | awk '/3:on/ {print $5}')" ]; then
        client_services="$client_services $iinput"
     fi
  done
  # Due to this bug, we force to turn on gpm in FC4.
  # https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=158620
  case "$OS_Version" in
    FC[4-9]|FC1[01234])
       # To avoid this bug, shit!
       # https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=158620
       if [ -e "$drbl_common_root/etc/init.d/gpm" ]; then
         client_services="$client_services gpm"
         # modify the gpm so that it will start in rc1, clonezilla is run in rc1.d
         perl -pi -e "s/^# chkconfig: 2345 85 15/# chkconfig: 12345 17 83/g" $drbl_common_root/etc/init.d/gpm
       fi
       ;;
  esac
fi

# add the services specified by user
if [ -f $drbl_setup_cfg/client-extra-service ]; then
  . $drbl_setup_cfg/client-extra-service
  client_services="$client_services $service_extra_added"
fi

echo "The startup services for DRBL client are:"
# strip the leading space
[ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
echo $(echo $client_services | sed -e "s/^ //g")
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL

# prepare the necessary env for chkconfig, update-rc.d or insserv
if [ -e /etc/debian_version ]; then
  # For Debian
  prepare_update_rc_d_env $drbl_common_root/
elif [ -e /etc/SuSE-release ]; then
  # For SuSE
  create_insserv_env $drbl_common_root/
else
  # For RH-like
  create_chkconfig_env $drbl_common_root/
fi
for i in $client_services; do
  if [ -e /etc/debian_version ]; then
    if [ "$dbn_ubn_serv_control_prog" = "use-insserv" ]; then
      # Use insserv
      chroot $drbl_common_root/ insserv $i &> /dev/null
    else
      # Use update-rc.d
      case "$i" in
        portmap)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 18 2 3 4 5 . start 32 0 6 . stop 32 1 . &> /dev/null
          ;;
        rpcbind)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 18 2 3 4 5 . start 32 0 6 . stop 32 1 . &> /dev/null
          ;;
        nis)
          # nis should be earlier than gdm (S13)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 12 2 3 4 5 . stop 12 0 1 6 . &> /dev/null
          ;;
        sendsigs)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 20 0 6 . &> /dev/null
          ;;
        umountfs)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 40 0 6 . &> /dev/null
          ;;
        mkswapfile)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 35 2 3 4 5 . stop 65 0 1 6 . &> /dev/null
          ;;
        firstboot)
          # chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 95 2 3 4 5 . stop 05 0 1 6 . &> /dev/null
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 95 S . &> /dev/null
          ;;
        drblthincli)
          # drblthincli must be before gdm/kdm
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 12 2 3 4 5 . stop 88 0 1 6 . &> /dev/null
          ;;
        nfs-common)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 21 2 3 4 5 . stop 79 0 1 6 . &> /dev/null
          ;;
        acpid)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 10 2 3 4 5 . stop 21 0 1 6 . &> /dev/null
          ;;
        acpi-support)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 99 2 3 4 5 . stop 20 0 1 6 . &> /dev/null
          ;;
        usplash)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 98 2 3 4 5 . stop 01 0 1 6 . &> /dev/null
          ;;
        arm-wol)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 99 2 3 4 5 . &> /dev/null
          ;;
        dbus)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 12 2 3 4 5 . &> /dev/null
          ;;
        hal)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i start 24 2 3 4 5 . &> /dev/null
          ;;
        *)
          chroot $drbl_common_root/ /usr/sbin/update-rc.d $i defaults &> /dev/null
          ;;
      esac
    fi 
  elif [ -e /etc/SuSE-release ]; then
    # SuSE
    chroot $drbl_common_root/ /sbin/insserv -f $i
  else
    # RH-like
    # Note by Steven Shiau on 2006/9/26
    # Mandriva 2007 uses LSB service config and parallel init. 
    # We have to modify some services
    case "$i" in
      ypbind)
        # remove ypserv
        perl -pi -e 's/^(#[[:space:]]*Should-Start: )(ypserv)(.*)/$1 $3/g' $drbl_common_root/etc/init.d/$i
        perl -pi -e 's/^(#[[:space:]]*Should-Stop: )(ypserv)(.*)/$1 $3/g' $drbl_common_root/etc/init.d/$i
        ;;
      dm)
        # We need drblthincli to run before dm, so when drblthincli is on, it
	# will start before dm.
        perl -pi -e 's/^#[[:space:]]*Required-Start:.*/# Required-Start: xfs firstboot netfs drblthincli/g' $drbl_common_root/etc/init.d/$i
        ;;
      netfs)
        # Mandriva 2009.0 or newer netfs will exit if /var/lock/subsys/network not existing.
	# It's: [ ! -f /var/lock/subsys/network -a ! -f /var/lock/subsys/NetworkManager ] && exit 0
        perl -pi -e 's|(^[[:space:]]*)(.*/var/lock/subsys/network.*)|$1#$2 # Modified by DRBL|g' $drbl_common_root/etc/init.d/$i
        ;;
    esac
    chroot $drbl_common_root/ /sbin/chkconfig --add $i
    case "$i" in
      ypbind)
      # When using chkconfig --add ypbind, client do not put in rcx.d, since on
      # RH/FC it is:
      # chkconfig: - 27 73
      # Hence we use chkconfig ypbind to turn on it.
      # For Mandriva 2010.0, "chkconfig ypbind on" will also make ypbind on in rc7.d (although it's "# chkconfig: 345 17 83" in mandriva's /etc/init.d/ypbind, but since mandriva 2007 it has used LSB service config instead of honor the chkconfig tag), but it will fail when running graphic mode since rpcbind is not on in rc7.d. Here we can not force to turn on it.
      if [ -n "$(grep -E "^# chkconfig: - " $drbl_common_root/etc/init.d/$i)" ]; then
        # For RH/FC case
        chroot $drbl_common_root/ /sbin/chkconfig $i on
      fi
    esac
  fi
done

# copy those rcS.d services for Debian, this can only be done after all updata-rc.d finished. Otherwise it will affect the update-rc.d
if [ -e /etc/debian_version ]; then
   # exclude those not necessary:
   # network is already done in initrd of client
   RCS_D_EXCLUDE=""
   unnecessary_rcsd_srv="networking"
   for isv in $unnecessary_rcsd_srv; do
     RCS_D_EXCLUDE="$RCS_D_EXCLUDE --exclude=S*${isv} "
   done
   rsync -a $RCS_D_EXCLUDE /etc/rcS.d/* $drbl_common_root/etc/rcS.d/
   # force to link some necessary services, since Knoppix or B2D won't have
   # them, but in DRBL, it's a must!!!
   (
     cd $drbl_common_root/etc/rcS.d/
     [ -f ../init.d/mountvirtfsn ] && ln -fs ../init.d/mountvirtfsn S02mountvirtfsn
     [ -f ../init.d/discover ] && ln -fs ../init.d/discover S36discover
     # B2D pureGnome 20051212 does not have hotplug* in rcS.d, but pureKDE has.
     # Anyway, for to link them.
     [ -f ../init.d/hotplug ] && ln -fs ../init.d/hotplug S40hotplug
     [ -f ../init.d/hotplug-net ] && ln -fs ../init.d/hotplug-net S41hotplug-net
     # change the hdparm from S07 to S60 (which is far after S41force-load-ide so we can access IDE device after IDE-related modules are loaded and ready).
     if [ -f ../init.d/hdparm ]; then
       [ -e "S07hdparm" ] && rm -f S07hdparm
       ln -fs ../init.d/hdparm S60hdparm
     fi
     [ -f ../init.d/portmap ] && ln -fs ../init.d/portmap S43portmap
     [ -f ../init.d/rpcbind ] && ln -fs ../init.d/rpcbind S43rpcbind
     [ -f ../init.d/mountnfs.sh ] && ln -fs ../init.d/mountnfs.sh S45mountnfs.sh
   )
   # modify some services which maybe not fit the requirement.
   # a. module-init-tools, since the method it detects rw is not quite well.
   if [ -e $drbl_common_root/etc/init.d/module-init-tools ]; then
     perl -pi -e 's|if \[ -w /lib/modules/\$KVER.*|if touch /lib/modules/\$KVER/modules.dep 2>/dev/null; then|g' $drbl_common_root/etc/init.d/module-init-tools
   fi

fi

vmware_as_server="$(grep "VMWare Inc" /proc/pci 2>/dev/null)"
# for VMWare, you have better to install the VMWare tools, 
if [ -n "$vmware_as_server" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo "It is VMWare as DRBL server ..., If you want to use X Window, make sure you already installed VMWare tools."
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fi
# First, clean the XF86Config, 
# let configure (like redhat-cfg-xfree86) in /etc/init.d/firstboot
# to create the first one.
# Remove XF86Config and xorg.conf (Both for RH/MDK) in common root
# NOTE! We can NOT remove XF86Config-4/xorg.conf for Debian... it is a template, just rename it.
if [ -e /etc/debian_version ]; then
  # Debian
  for ix in XF86Config-4 xorg.conf; do
    [ -e "$drbl_common_root/etc/X11/$ix" ] && mv -f $drbl_common_root/etc/X11/${ix} $drbl_common_root/etc/X11/${ix}.drbl.template
  done
  # Debian Sarge does not sync the locale setting of gdm with system. do it 
  if [ -f /etc/default/gdm ]; then
    # use subshell to avoid the running shell
    (
      # For B2D, it uses /etc/sysconfig/i18n...
      [ -e /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n
      # the environment priority is higher then /etc/sysconfig/i18n
      [ -e /etc/environment ] && . /etc/environment
      if [ -n "$LANG" ]; then
        if grep -q "^[[:space:]]*#*[[:space:]]*LANG=.*" $drbl_common_root/etc/default/gdm 2>/dev/null; then
           perl -pi -e "s/^[[:space:]]*#*[[:space:]]*LANG=.*/LANG=$LANG/g" $drbl_common_root/etc/default/gdm
        else
           echo "LANG=$LANG" >> $drbl_common_root/etc/default/gdm
        fi
      fi
    )
  fi
else
  # RH-like
  for ix in XF86Config xorg.conf; do
    [ -e "$drbl_common_root/etc/X11/$ix" ] && rm -f $drbl_common_root/etc/X11/${ix}*
  done
fi

# Remove the firstboot setting to aviod it says NO
[ -f $drbl_common_root/etc/sysconfig/firstboot ] && rm -f $drbl_common_root/etc/sysconfig/firstboot 
# Remove the /etc/reconfigSys to avoid firstboot run reconfig
[ -f $drbl_common_root/etc/reconfigSys ] && rm -f $drbl_common_root/etc/reconfigSys
# Disable the /usr/sbin/firstboot in the firstboot service, we should not reconfig ntp, user accounts for clients... This is for Redhat, Fedora...
perl -p -i -e 's|^(\s*)(/usr/sbin/firstboot.*)$|$1true # $2 # Modified by DRBL|g' $drbl_common_root/etc/init.d/firstboot

# Take care the hardware config files, clean old, make them be detected at boot.
if [ -e /etc/debian_version ]; then
  # Debian
  # In Debian, we need to keep the modules.conf* so that discover will work.
  # We can not force to put ide-cd ide-disk ide-generic  modules in /etc/modules (they are loaded by /etc/rcS.d/S20modutils), this will result chip driver (like piix and ide_core) is loaded afther them (by /etc/rcS.d/S40hotplut). This will cause a problem: unable to turn on IDE HD DMA ("HDIO_SET-DMA failed: Operation not permitted")
  # So we create a startup script after hotplug.
  if [ -f $drbl_common_root/etc/modules ]; then
    rm -f $drbl_common_root/etc/modules
    cat <<-MOD_END > $drbl_common_root/etc/modules
# /etc/modules: kernel modules to load at boot time.
#
# This file should contain the names of kernel modules that are
# to be loaded at boot time, one per line.  Comments begin with
# a "#", and everything on the line after them are ignored.

# Note from DRBL:
# These modules are cleaned by DRBL drblpush so that we have a clean file.
# You can add any module you need here. But do not force to put ide-cd ide-disk ide-generic modules here, this will result chip driver (like piix and ide_core) is loaded afther them (by /etc/rcS.d/S40hotplut). This will cause a problem: unable to turn on IDE HD DMA ("HDIO_SET-DMA failed: Operation not permitted")
# DRBL will load ide-* in /etc/rcS.d/S41force-load-ide 

MOD_END
  fi
  cp -f $drbl_setup_path/files/misc/force-load-ide $drbl_common_root/etc/init.d/force-load-ide
  prepare_update_rc_d_env $drbl_common_root/
  if [ "$dbn_ubn_serv_control_prog" = "use-insserv" ]; then
    chroot $drbl_common_root/ insserv force-load-ide &> /dev/null
  else
    chroot $drbl_common_root/ /usr/sbin/update-rc.d force-load-ide start 41 S . &> /dev/null
  fi
elif [ -e /etc/SuSE-release ]; then
  # SuSE
  # No more force to put some almost-must modules (ide-disk...) in /etc/sysconfig/kernel, same reason with the Debian one.
  # Here we modify hwscan to let it run in boot.d and add a service "force-load-ide" in boot.d
  # hwscan only exists in SuSE 9.3, in 10.0 or later it's gone!
  create_insserv_env $drbl_common_root/
  for i in parse-load-mod-suse force-load-ide; do
    cp -f $drbl_setup_path/files/misc/$i $drbl_common_root/etc/init.d/
    chroot $drbl_common_root/ /sbin/insserv -f $i
  done
  # modify boot.idedma service to make it after force-load-ide
  if [ -e "$drbl_common_root/etc/init.d/boot.idedma" ]; then
    chroot $drbl_common_root/ /sbin/insserv -f -r boot.idedma
    perl -pi -e 's/^#[[:space:]]*Required-Start:.*/# Required-Start: boot.loadmodules force-load-ide/g' $drbl_common_root/etc/init.d/boot.idedma
    chroot $drbl_common_root/ /sbin/insserv -f boot.idedma
  fi
  # process the hwscan for SuSE 9.3
  if [ -e "$drbl_common_root/etc/init.d/hwscan" ]; then
    perl -pi -e 's/^#[[:space:]]*Default-Start:.*/# Default-Start: B/g' $drbl_common_root/etc/init.d/hwscan
    chroot $drbl_common_root/ /sbin/insserv -f hwscan
  fi
  # xfs need account nobody, which only exists in YP, so we have to make xfs runs after ypbind.
  if [ -e "$drbl_common_root/etc/init.d/xfs" ]; then
    if ! grep -Eq "^#[[:space:]]*Required-Start:.* ypbind" $drbl_common_root/etc/init.d/xfs; then
      perl -pi -e 's/(^#[[:space:]]*Required-Start:.*)/$1 ypbind/g' $drbl_common_root/etc/init.d/xfs
    fi
    chroot $drbl_common_root/ /sbin/insserv -f xfs
  fi
  # To avoid the loop error (i.e. haldaemon need nfs, nfs need network, network need haldaemon, we remove haldaemon in network. Then we can make haldaemon after nfs. (Although network service is not enabled in client, but we still have to do this modification.) without "chroot $drbl_common_root/ /sbin/insserv -f network" it.
  if [ -e "$drbl_common_root/etc/init.d/network" ]; then
    chroot $drbl_common_root/ /sbin/insserv -f -r network
    perl -pi -e 's/(^#[[:space:]]*Required-Start:.*)haldaemon/$1/g' $drbl_common_root/etc/init.d/network
    chroot $drbl_common_root/ /sbin/insserv -f network
  fi
  # modify haldaemon service to make it after nfs, since 
  # ldd /usr/sbin/hald:
  #  ...
  #  libgobject-2.0.so.0 => /opt/gnome/lib/libgobject-2.0.so.0 (0xb7ec9000)
  #  libglib-2.0.so.0 => /opt/gnome/lib/libglib-2.0.so.0 (0xb7e43000)
  #  libdbus-1.so.2 => /usr/lib/
  #  ...
  # so we need to make it after NFS directories (/usr/, /opt) are mounted.
  if [ -e "$drbl_common_root/etc/init.d/haldaemon" ]; then
    chroot $drbl_common_root/ /sbin/insserv -f -r haldaemon
    perl -pi -e 's/^#[[:space:]]*Required-Start:.*/# Required-Start:	boot.localnet dbus nfs/g' $drbl_common_root/etc/init.d/haldaemon
    chroot $drbl_common_root/ /sbin/insserv -f haldaemon
  fi
  #
else
  # RH-like
  # Only for RH-like distribution, we can remove the modules.conf*
  # remove the etc/modules.conf in template so that the kudzu in the client can create their own hardware config file.
  # In Debian, we need to keep the modules.conf* so that discover will work.
  find $drbl_common_root/etc/ -name "modules.conf*" -exec rm -f {} \;
fi

# remove the script in rc[0,6].d to let the client can halt and reboot
if [ -e /etc/debian_version ]; then
  # Debian
  # For Debian, we use update-rc.d to assign which level run which program, so
  # no networking & umountnfs.sh
  true
elif [ -e /etc/SuSE-release ]; then
  # SuSE
  client_halt_reboot_runlevel_must_remove_srv="nfs network"
  for i in $client_halt_reboot_runlevel_must_remove_srv; do 
     # Note! Only for K[0-9][0-9]*, since nfs is nfs client in SuSE, we need it
     # to start, but do not want it to be killed when change runlevel, reboot
     # or halt.
     rm -f $drbl_common_root/etc/init.d/rc[123456].d/K[0-9][0-9]$i
  done
else
  # RH-like
  client_halt_reboot_runlevel_must_remove_srv="netfs network killall"
  for i in $client_halt_reboot_runlevel_must_remove_srv; do 
     rm -f $drbl_common_root/etc/rc[06].d/[SK][0-9][0-9]$i
  done
fi

# force to disable selinux in the client.
for ise in /etc/selinux/config /etc/sysconfig/selinux; do
  if [ -f $drbl_common_root/$ise ]; then
    perl -pi -e "s/^SELINUX=.*/SELINUX=disabled/g" $drbl_common_root/$ise
  fi
done

# switch the link in $drblcommont_root/sbin, some distributions, 
# like B2D, will link poweroff to init, for we have make it link to init.orig
# lnkfiles="halt poweroff reboot telinit"
lnkfiles="$(find $drbl_common_root/sbin/ -type l -lname "init" -print)"
for ilnk in $lnkfiles; do
  ( cd $drbl_common_root/sbin/; ln -fs init.orig $ilnk )
done

# remove the template's etc/sysconfig/hwconf which kudzu will log
[ -f $drbl_common_root/etc/sysconfig/hwconf ] && rm -f $drbl_common_root/etc/sysconfig/hwconf

# Prepare the critical program mount.nfs, since some lib could be in /usr/lib/ (e.g. Fedora 12 or Mandriva 2010.0).
# Variable DESTDIR is required for copy_exec_drbl use
export DESTDIR="$drbl_common_root"
[ -e "/sbin/mount.nfs" ] && copy_exec_drbl /sbin/mount.nfs /sbin/

# The root over NFS mount is done in sbin/init which Steven modified,
# $nfsserver:$drbl_common_root
# so remove this file
[ -f $drbl_common_root/etc/fstab ] && rm -f $drbl_common_root/etc/fstab

# clean the rhn config, client should not do that.
[ -d $drbl_common_root/etc/sysconfig/rhn ] && rm -rf $drbl_common_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/misc/init.drbl $drbl_common_root/sbin/init
# Find if the dir /run is mounted as tmpfs. If so, enable that for client.
run_fs="$(LC_ALL=C df -T /run 2>/dev/null |grep -Ew "/run" | awk -F" " '{print $1}')"
if [ "$run_fs" = "tmpfs" ]; then
  perl -pi -e "s/^TMPFS_RUN=.*/TMPFS_RUN=\"true\" # Enabled by drblpush./g" $drbl_common_root/sbin/init
fi
chown root.root $drbl_common_root/sbin/init
chown 755 $drbl_common_root/sbin/init

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

# copy dev tarball to $drbl_common_root/etc/diskless-image
if [ -x "$drbl_common_root/sbin/udevd" ]; 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 $drbl_common_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

# Switch client graphic/text mode
case "$OS_type" in
RH|MDK|SUSE)
  # set the init to user specifies
  case "$client_init" in
    "text")
          CLIENT_INIT_RL=3
          ;;
    "graphic")
          CLIENT_INIT_RL=5
          ;;
  esac
  perl -p -i -e "s/^id:[1-5]:initdefault:/id:$CLIENT_INIT_RL:initdefault:/g" $drbl_common_root/etc/inittab
  ;;
DBN)
  default_dm="$(drbl-check-dm 2> /dev/null)"
  if [ -n "$default_dm" ]; then
    case "$client_init" in
      "text")
          echo "Set text mode for Debian DRBL client..."
          prepare_update_rc_d_env $drbl_common_root/
          if [ "$dbn_ubn_serv_control_prog" = "use-insserv" ]; then
            chroot $drbl_common_root/ insserv -f -r $default_dm &> /dev/null
          else
            chroot $drbl_common_root/ /usr/sbin/update-rc.d -f $default_dm remove &> /dev/null
          fi
          #clean_update_rc_d_env $drbl_common_root/
	  # For upstart 0.6.3 (Ubuntu 9.10) or later it uses /etc/init/*.conf
	  if [ -e "$drbl_common_root/etc/init/${default_dm}.conf" ]; then
            switch_upstart_service $drbl_common_root/etc/init/${default_dm}.conf off
	  fi
          ;;
      "graphic")
        if [ -n "$default_dm" ]; then
          echo "Set graphic mode for Debian DRBL client..."
          prepare_update_rc_d_env $drbl_common_root/
          # gdm should be later than nis (S12), and should be later than hal (S24)
          if [ "$dbn_ubn_serv_control_prog" = "use-insserv" ]; then
            chroot $drbl_common_root/ insserv $default_dm &> /dev/null
          else
            chroot $drbl_common_root/ /usr/sbin/update-rc.d $default_dm start 30 2 3 4 5 . stop 01 0 1 6 . &> /dev/null
          fi
          #clean_update_rc_d_env $drbl_common_root/
	  # For upstart 0.6.3 (Ubuntu 9.10) or later it uses /etc/init/*.conf
	  if [ -e "$drbl_common_root/etc/init/${default_dm}.conf" ]; then
            switch_upstart_service $drbl_common_root/etc/init/${default_dm}.conf on
	  fi
        fi
        ;;
    esac
  else
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "The default display manager is NOT found! We can NOT set text or graphic mode for Debian DRBL client."
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  fi
  ;;
esac

# Turn off all the xinted/inted services in clients.
# Set the tftpd to on when xinetd/inted starts in server.
# (1) for client:
if [ -e /etc/debian_version ]; then
  # Debian
  if grep -q "^tftp[[:space:]]+" $drbl_common_root/etc/inetd.conf 2>/dev/null; then
    # Note: /usr/sbin/update-inetd is perl, and require some perl modules.
    # It need /usr/share/perl5/DebianNet.pm, but it depends on perl version.
    #chroot $drbl_common_root /usr/sbin/update-inetd --remove tftp
    # Here we use easier method, just delete the tftp in /etc/inetd.conf
    # It looks like: 
    # tftp           dgram   udp     wait    root  /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /var/lib/tftpboot
    perl -pi -e "s/^tftp[[:space:]]+.*//g" $drbl_common_root/etc/inetd.conf
  fi
  if [ -e $drbl_common_root/etc/init.d/tftpd-hpa ]; then
    # it's a standalone daemon
    prepare_update_rc_d_env $drbl_common_root/
    if [ "$dbn_ubn_serv_control_prog" = "use-insserv" ]; then
      chroot $drbl_common_root/ insserv -f -r tftpd-hpa &> /dev/null
    else
      chroot $drbl_common_root/ /usr/sbin/update-rc.d -f tftpd-hpa remove &> /dev/null
    fi
  fi
else
  # RH-like & SuSE
  perl -p -i -e "s/disable.*=.*/disable                 = yes/g" $drbl_common_root/etc/xinetd.d/tftp 
fi

# (2) for server
# set the tftp to on when xinetd/inted starts and portmap or rpcbind settings in server.
if [ -e /etc/debian_version ]; then
  # Debian
  # (1) tftpd
  # Force to remove tftpd in inetd if it's set, and we will add it later 
  # and put our arguments "-s /tftpboot/nbi_img"
  if grep -q "^tftp" /etc/inetd.conf 2>/dev/null; then
    /usr/sbin/update-inetd --remove tftp
  fi
  if [ -e /etc/init.d/tftpd-hpa ]; then
    # Patch the /etc/init.d/tftp-hpa, the "set -e" should not be put otherwise
    # if tftpd-hpa is not started, "/etc/init.d/tftpd-hpa restart" (insted of
    # "/etc/init.d/tftpd-hpa start") will just stop and fail, will not start it.
    perl -p -i -e "s/^[[:space:]]*set -e.*/#set -e/g" /etc/init.d/tftpd-hpa

    # From tftpd-hpa 5.0, the config file is different
    # /etc/init.d/tftpd-hpa is for Debian, while /etc/init/tftpd-hpa.conf is for Ubuntu's upstart
    if [ -n "$(grep -E TFTP_DIRECTORY /etc/init.d/tftpd-hpa 2>/dev/null)" -a \
         -n "$(grep -E TFTP_USERNAME /etc/init.d/tftpd-hpa 2>/dev/null)" ] || \
       [ -n "$(grep -E TFTP_DIRECTORY /etc/init/tftpd-hpa.conf 2>/dev/null)" -a \
         -n "$(grep -E TFTP_USERNAME /etc/init/tftpd-hpa.conf 2>/dev/null)" ]; then
      # Version 5.0 or later.
      cat <<-TFTP_END > /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot/nbi_img"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"
TFTP_END
    else
      # Version 0.49 or before.
      # it's a standalone daemon
      cat <<-TFTP_END > /etc/default/tftpd-hpa
RUN_DAEMON="yes"
OPTIONS="-l -s /tftpboot/nbi_img"
TFTP_END
    fi
    # (2) Portmap. From portmap (6.0-11), when new installation, default the question whether to bind to the loopback interface only. We have to open it.
    if [ -e /etc/default/portmap ]; then
      perl -pi -e 's/^(OPTIONS=.*)/#$1 # Commented by DRBL/g' /etc/default/portmap
    fi 
  else
    # it's a daemon in inetd, set it in inetd.conf
    /usr/sbin/update-inetd --group BOOT --add 'tftp	dgram	udp	wait	root	/usr/sbin/in.tftpd	/usr/sbin/in.tftpd	-s /tftpboot/nbi_img' 
  fi
else
  # RH-like & SuSE
  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
fi

# create a config file for each diskless host to mount its fstab
# Steven to do, what's master ?
cat <<-CONFIG_END > $drbl_common_root/etc/diskless-image/config

nfsserver_default=$nfsserver_default
nfsimagedir=$drbl_common_root
nfshostsdir=$drblroot
nameserver=$nameserver

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 $drbl_common_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 resolv.conf 
# //NOTE// For resolvconf on Ubuntu 12.04, the /etc/resolv.conf is linked to /run/resolvconf/resolv.conf, which is a tmpfs file system. Here just remove it.
rm -f $drbl_common_root/etc/resolv.conf

for nameserver in $nameserver_; do 
  echo "nameserver $nameserver" >> $drbl_common_root/etc/resolv.conf
done

# rc.sysinit only in RH-like (BSD), no rc.sysinit in Debian/SuSE
case "$OS_type" in
  RH|MDK)
    # For distribution RH/FC/CO/MDK/MDV
    if [ -f "${drbl_setup_path}/files/${OS_type}/${OS_Version}/rc.sysinit.${OS_Version}.drbl" ]; then
      cp -f ${drbl_setup_path}/files/${OS_type}/${OS_Version}/rc.sysinit.${OS_Version}.drbl $drbl_common_root/etc/rc.d/rc.sysinit
    else
      # Can not find fine-tune file, show warning.
      [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
      echo "Warning! Unable to find the fine-tune file ${drbl_setup_path}/files/${OS_type}/${OS_Version}/rc.sysinit.${OS_Version}.drbl, use ${drbl_setup_path}/files/${OS_type}/rc.sysinit.default-${OS_type}.drbl as /etc/rc.d/rc.sysinit for DRBL clients!"
      echo "This may cause some problems to DRBL clients!"
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
      cp -f ${drbl_setup_path}/files/${OS_type}/rc.sysinit.default-${OS_type}.drbl $drbl_common_root/etc/rc.d/rc.sysinit
    fi
    ;;
esac

# "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"
if [ ! -L "$drbl_common_root/boot" ]; then
  (cd $drbl_common_root; ln -fs tmp/boot boot)
fi

# create the CLEAN rc.boot/boot.local/rc.local to avoid some commands copied from server
if [ -e /etc/debian_version ]; then
  # Debian
  [ -d "$drbl_common_root/etc/rc.boot" ] && rm -f $drbl_common_root/etc/rc.boot/*
elif [ -e /etc/SuSE-release ]; then
  # SuSE
  if [ -f "$drbl_common_root/etc/init.d/boot.local" ]; then
    perl -pi -e "s/^[[:space:]]*[^#]+//g" $drbl_common_root/etc/init.d/boot.local
  fi
else
  # RH-like
  # 1st, clean rc.local 
  [ -f $drbl_common_root/etc/rc.d/rc.local ] && rm -f $drbl_common_root/etc/rc.d/rc.local
  
  # 2nd, create a clean rc.local 
  cat <<-RC_LOCAL > $drbl_common_root/etc/rc.d/rc.local
#!/bin/bash
#
# 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.
export PATH=\$PATH:$DRBL_SCRIPT_PATH/sbin:$DRBL_SCRIPT_PATH/bin

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-detect-cdrom)"
  [ -n "\$cddev" ] && ln -fs /dev/\$cddev /dev/cdrom
fi

# For Mandrake, it use /mnt (tmpfs) instead of /media for cdrom, floppy, create the mount point in tmpfs, since mandrake does not create them automatically.
# Although the problem is only in mandrake, but we still create them for all RH-like dists, since user maybe want to use these mount points.
for d in floppy cdrom loop disk usb; do
  [ ! -d "/mnt/\$d" ] && mkdir -p /mnt/\$d
done

RC_LOCAL

  #change its mode
  chown root.root $drbl_common_root/etc/rc.d/rc.local
  chmod 775 $drbl_common_root/etc/rc.d/rc.local
fi

# Modify some rc programs.
# For RH-like, use the modified template etc/init.d/halt, which remove all the umount command
# For Debian and SuSE, just use perl to modify them.
if [ -e /etc/debian_version ]; then
  # Debian
  # For genuine Debian
  # remove -i in "reboot -d -f -i" so it won't stop network before reboot
  # remove -i in "halt -d -f -i -p" so it won't stop network before halt
  perl -pi -e 's/^([[:space:]]*reboot .*)-i(.*)/$1 $2 # Modified by DRBL/' $drbl_common_root/etc/init.d/reboot
  perl -pi -e 's/^([[:space:]]*halt .*)-i(.*)/$1 $2 # Modified by DRBL/' $drbl_common_root/etc/init.d/halt
  # For B2D, the reboot and halt is a little different, except the above,
  # we have to comment umount -a 
  perl -pi -e 's/^([[:space:]]*umount -a.*)/#$1 # Modified by DRBL/' $drbl_common_root/etc/init.d/reboot
  perl -pi -e 's/^([[:space:]]*umount -a.*)/#$1 # Modified by DRBL/' $drbl_common_root/etc/init.d/halt
  # To force do not turn off network when rebooting/halting.
  if grep -Eq "^NETDOWN=" $drbl_common_root/etc/init.d/halt; then
    # If we found "NETDOWN=..." in /etc/init.d/halt, force to write NETDOWN=no in client's /etc/default/halt
    if ! grep -Eq "^NETDOWN=" $drbl_common_root/etc/default/halt; then
      echo "NETDOWN=no  # Modified by DRBL" >> $drbl_common_root/etc/default/halt
    else
      perl -pi -e 's/^NETDOWN=.*/NETDOWN=no # Modified by DRBL/' $drbl_common_root/etc/default/halt
    fi
  fi
  # Disable the /lib/init/rw removinig. Otherwise harmless errors will be shown during clents booting.
  if [ -e /lib/init/bootclean.sh ]; then
    LC_ALL=C perl -pi -e 's|(^[[:space:]]*)(clean /lib/init/rw "! -type d".*$)|$1#$2 # Modified by DRBL|g' $drbl_common_root/lib/init/bootclean.sh
  fi

  # Do not clean or remove etc/mtab when boots, and force not to update etc/mtab
  if [ -e $drbl_common_root/etc/init.d/checkroot.sh ]; then
    perl -pi -e 's|^([[:space:]]*:> $MTAB_PATH.*)|#$1 # Modified by DRBL|' $drbl_common_root/etc/init.d/checkroot.sh
    perl -pi -e 's|^([[:space:]]*rm -f \${MTAB_PATH}~.*)|#$1 # Modified by DRBL|' $drbl_common_root/etc/init.d/checkroot.sh
    perl -pi -e 's|^([[:space:]]*)INIT_MTAB_FILE=yes|$1 INIT_MTAB_FILE=no # Modified by DRBL|' $drbl_common_root/etc/init.d/checkroot.sh
  fi
  if [ -e $drbl_common_root/etc/init.d/checkfs.s ]; then
    # Do not remove /fastboot, DRBL client is always fastboot
    perl -pi -e 's|^([[:space:]]*rm -f )(/fastboot)(.*)|$1 $3 # modified by DRBL|' $drbl_common_root/etc/init.d/checkfs.sh
  fi
  # bootmisc.sh will prevent client to login by showning
  # "System bootup in progress - please wait" > /etc/nologin
  # We must avoid /etc/nologin to be created by set DELAYLOGIN=no in client's /etc/default/rcS
  perl -pi -e 's|^[[:space:]]*DELAYLOGIN=.*|DELAYLOGIN=no # modified by DRBL|' $drbl_common_root/etc/default/rcS

  if [ -x "$drbl_common_root/etc/init.d/linux-restricted-modules-common" ]; then
    # $drbl_common_root/lib/modules/$KERNEL_VER/volatile is already created in drblsrv-offline for Ubuntu. Here we have to modify linux-restricted-modules-common service so that it can write in /lib/modules/$KERNEL_VER/volatile, otherwise it is Read-Only NFS filesystem.
    # /sbin/lrm-manager --quick -> 
    # mount -n -t tmpfs tmpfs /lib/modules/`uname -r`/volatile; /sbin/lrm-manager --quick # Modified by DRBL
    perl -pi -e 's|^([[:space:]]*)(/sbin/lrm-manager --quick.*)|$1mount -n -t tmpfs tmpfs /lib/modules/`uname -r`/volatile; $2 # Modified by DRBL|g' $drbl_common_root/etc/init.d/linux-restricted-modules-common
  fi

  # Debian Etch has NetworkManager/NetworkManagerDispatcher under dbus, we can not let it start in client. Otherwise the network in client will be reset.
  rm -f $drbl_common_root/etc/dbus-1/event.d/[0-9][0-9]NetworkManager*

  # For Ubuntu dapper, /etc/init.d/mountnfs.sh is no more, and moved to /etc/network/if-up.d/mountnfs.sh. It will be run when ifup starts successfully in networking service. However, in DRBL client, network is actually started in initrd.
  # For Debian testing (on 2006/09/15), the mountnfs.sh from initscripts 2.86.ds1-19 or later use the same skill with waitnfs.sh, but it's name is mountnfs.sh. Hence we have to use the keyword "Wait for network file systems" to judge that, since in the mountnfs.sh, there is:
# Short-Description: Wait for network file systems to be mounted
  # Ugly! This is a workaround, it's better to make the ifup command work in /etc/init.d/networking, then the /etc/network/if-up.d/mountnfs.sh can be run in client.
  use_start_srv_after_ifup="no"
  if grep -q -E "Wait for network file systems" $drbl_common_root/etc/init.d/mountnfs.sh 2>/dev/null; then
    use_start_srv_after_ifup="yes"
  elif [ -e $drbl_common_root/etc/init.d/waitnfs.sh ]; then
    use_start_srv_after_ifup="yes"
  fi
  if [ "$use_start_srv_after_ifup" = "yes" ]; then
    # mountnfs.sh is called in start-srv-after-ifup
    cp -f $drbl_setup_path/files/misc/start-srv-after-ifup $drbl_common_root/etc/init.d/
    for infsf in waitnfs.sh mountnfs.sh; do
     if [ -e $drbl_common_root/etc/init.d/$infsf ]; then
      # Here we also insert a line to create a dir /tmp/boot (/tmp is tmpfs so we have to use a service to do that everytime client boots) so the /boot link to /tmp/boot/ will work.
      # case (1): The function name is do_start (dapper)
      perl -pi -e 's|(^[[:space:]]*)do_start([[:space:]]*$)|$1/etc/init.d/start-srv-after-ifup; mkdir -p /tmp/boot; do_start # Modified by DRBL $2|' $drbl_common_root/etc/init.d/$infsf
      # case (2): The function name is do_wait_async_mount (etch), in this case
      # We'd better to force ASYNCMOUNTNFS=yes in /etc/default/rcS 
      perl -pi -e 's|(^[[:space:]]*)do_wait_async_mount([[:space:]]*$)|$1/etc/init.d/start-srv-after-ifup; mkdir -p /tmp/boot; do_wait_async_mount # Modified by DRBL $2|' $drbl_common_root/etc/init.d/$infsf
      # mountnfs.sh is buggy, too. Actually it's mountpoint bug, which failed to identify some mount point as mount point, e.g. /usr/ and /var (mounted in init.drbl)
      # https://bugs.launchpad.net/ubuntu/+source/sysvinit/+bug/93634
      # A workaround is (1) not to put "/usr/" and "/var" in the list and (2) shorten the TIMEOUT.
      # Code for (1) to be commented in mountnfs.sh from Debian Lenny/Squeeze:
      #	case "$MTPT" in
      #	  /usr/local|/usr/local/*)
      #		;;
      #	  /usr|/usr/*)
      #		waitnfs="$waitnfs $MTPT"
      #		;;
      #	  /var|/var/*)
      #		waitnfs="$waitnfs $MTPT"
      #		;;
      #	esac
      # (1)
      mountnfs_file="$drbl_common_root/etc/init.d/$infsf"
      case_to_be_commented="usr var"
      for i in $case_to_be_commented; do
        chk_line_no="$(LC_ALL=C grep -n -F -- "/$i|/$i/*)" $mountnfs_file | cut -d":" -f1)"
        [ -z "$chk_line_no" ] && continue
        chk_next_line="$((chk_line_no + 1))"
        perl -pi -e "if (${chk_next_line}..${chk_next_line}) {s/^([[:space:]]+)(waitnfs=.*)/\$1#\$2   # Modified by DRBL/g}" $mountnfs_file
      done
      # (2)
      perl -pi -e 's/^([[:space:]]+)TIMEOUT=[[:digit:]]+/$1TIMEOUT=30 # Modified by DRBL/g' $drbl_common_root/etc/init.d/$infsf
      perl -pi -e 's|^[[:space:]]*ASYNCMOUNTNFS=.*|ASYNCMOUNTNFS=yes # Modified by DRBL|g' $drbl_common_root/etc/default/rcS
     fi
    done
  fi
  # UGLY!
  # The upstart (/etc/event.d/rc-default) in Ubuntu 6.10 to 9.04 is buggy, it does not honor the [013456] in /proc/cmdline
  # Ref: https://launchpad.net/ubuntu/+source/upstart/+bug/85014
  # It's fixed in Ubuntu 9.10 or later.
  [ -e /etc/lsb-release ] && . /etc/lsb-release
  if [ "$DISTRIB_ID" = "Ubuntu" ]; then
    case "$DISTRIB_RELEASE" in
     "6.10")
        cp -f $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/rc-default  $drbl_common_root/etc/event.d/rc-default
        # For ubuntu 6.10-7.10 upstart problem.
        # Ref: https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/65230
        # Change the contents of /etc/event.d/tty[1-6]:
        # start on runlevel 2 -> start on stopped rc2
        for i in $drbl_common_root/etc/event.d/tty[0-9]; do
          perl -pi -e "s/^start on runlevel /start on stopped rc/g" $i
        done
	;;
     "7.04"|"7.10"|"8.04"|"8.10"|"9.04")
        cp -f $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/rc-default  $drbl_common_root/etc/event.d/rc-default
        # For ubuntu 6.10-7.10 upstart problem.
        # Ref: https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/65230
        # Change the contents of /etc/event.d/tty[1-6]:
        # start on runlevel 2 -> start on stopped rc2
        for i in $drbl_common_root/etc/event.d/tty[0-9]; do
          perl -pi -e "s/^start on runlevel /start on stopped rc/g" $i
        done
        # Disable the recovery-menu, use sulogin, otherwise the error messages of Clonezilla will be overwritten.
        if [ -e "$drbl_common_root/etc/event.d/rcS-sulogin" ]; then
          perl -pi -e "s|(^[[:space:]]*) /usr/share/recovery-mode/recovery-menu.*|\$1 /sbin/sulogin # Modified by DRBL. Force to use sulogin!|g" $drbl_common_root/etc/event.d/rcS-sulogin
        fi
	;;
     "9.10")
        # The released rc-sysinit.conf is buggy. We use the one we patched.
        cp -af $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/rc-sysinit.conf $drbl_common_root/etc/init/rc-sysinit.conf
        cp -af $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/drbl-client-boot.conf $drbl_common_root/etc/init/drbl-client-boot.conf
	;;
     *)
        # For Ubuntu 10.04 or later.
	if [ -e "$drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/drbl-client-boot.conf" ]; then
          cp -af $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/drbl-client-boot.conf $drbl_common_root/etc/init/drbl-client-boot.conf
	else
          [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
          echo "Warning! Unable to find the fine-tune file $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/drbl-client-boot.conf, use $drbl_setup_path/files/Ubuntu/drbl-client-boot-default.conf for DRBL clients!"
          echo "This may cause some problems to DRBL clients!"
          [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
          cp -af $drbl_setup_path/files/Ubuntu/drbl-client-boot-default.conf $drbl_common_root/etc/init/drbl-client-boot.conf
	fi
	if [ -e "$drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/S00wait-drbl" ]; then
          cp -af $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/S00wait-drbl $drbl_common_root/etc/rcS.d/
	else
          [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
          echo "Warning! Unable to find the fine-tune file $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/S00wait-drbl, use $drbl_setup_path/files/Ubuntu/S00wait-drbl-default for DRBL clients!"
          echo "This may cause some problems to DRBL clients!"
          [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
          cp -af $drbl_setup_path/files/Ubuntu/S00wait-drbl-default $drbl_common_root/etc/init/S00wait-drbl
	fi
	# For plymouth.conf, we won't let plymouthd to run in rc=1, even with --mode=shutdown, otherwise when running clonezilla job in the client, the initial screen might be in vt 7, and the clonezilla job is run at vt 1.
	if [ -e "$drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/plymouth.conf" ]; then
          cp -af $drbl_setup_path/files/Ubuntu/$DISTRIB_RELEASE/plymouth.conf $drbl_common_root/etc/init/plymouth.conf
	else
          perl -pi -e 's|^([[:space:]]*)(exec /sbin/plymouthd --mode=shutdown)|$1true #$2 # Commented by DRBL to avoid no Clonezilla SE output messages on console 1|g' $drbl_common_root/etc/init/plymouth.conf
	fi
	;;
    esac
  fi
  # Modify upstart 0.6.3 /etc/init.d/*.conf.
  if [ -d "$drbl_common_root/etc/init" ]; then
    # For Ubuntu 9.10 upstart problem.
    # Ref: https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/405847
    # Change the contents of /etc/init/rc-sysinit.conf, since this rc-sysinit.conf file will be used for Clonezilla live and DRBL, in Clonezilla live we do not change the "start", but in DRBL we do. If we do not change it to be "drbl-client-boot", which is after "startup", the /sbin/init.orig will do nothing since in DRBL client, it's diskless, so no "filesystem".
    # start on .* -> start on startup.
    # For portmap.conf, one more extra line, i.e.:
    #start on (local-filesystems
    #          and net-device-up IFACE=lo)
    # upstart_conf_2_be_startup is for those conf will be "start on startup"
    # So the sequence: 
    # 1st group: startup -> udev.conf and portmap.conf
    # 2nd group: drbl-client-boot (which contains virtual fs, dubs, hal, nfs...)
    # 3rd group: after drbl-client-boot -> rc-sysinit.conf
    # For Ubuntu 11.10, (1) Make mounted-var.conf start on startup since /var/run need to be linked to /run so it's writable for other daemons. (2) Commented dbus.conf since it will be started in drbl-client-boot.conf. Otherwise drbl-client-boot.conf will exit with error code.
    upstart_conf_2_be_startup="udev.conf portmap.conf mounted-var.conf"
    upstart_conf_2_be_after_drbl_client_boot="rc-sysinit.conf"
    upstart_conf_2_be_commented="dbus.conf mountall.conf mountall-net.conf resolvconf.conf"
    for i in $upstart_conf_2_be_startup; do
      if [ -e "$drbl_common_root/etc/init/$i" ]; then
        perl -pi -e "s/^start on.*/start on startup # Modified by DRBL/g" $drbl_common_root/etc/init/$i
      fi
    done
    for i in $upstart_conf_2_be_after_drbl_client_boot; do
      if [ -e "$drbl_common_root/etc/init/$i" ]; then
        perl -pi -e "s/^start on.*/start on startup and started drbl-client-boot # Modified by DRBL/g" $drbl_common_root/etc/init/$i
      fi
    done
    # Remove the extra one line "and net-device-up IFACE=lo)"
    if [ -e "$drbl_common_root/etc/init/portmap.conf" ]; then
      perl -pi -e "s/^[[:space:]]*and net-device-up IFACE=lo.*//g" $drbl_common_root/etc/init/portmap.conf
    fi
    for i in $upstart_conf_2_be_commented; do
      if [ -e "$drbl_common_root/etc/init/$i" ]; then
        perl -pi -e "s/^(start on.*)/# \$1 # Modified by DRBL/g" $drbl_common_root/etc/init/$i
      fi
    done
    # Disable the recovery-menu, use sulogin, otherwise the error messages of Clonezilla will be overwritten.
    if [ -e "$drbl_common_root/etc/init/rcS.conf" ]; then
      perl -pi -e "s|(^[[:space:]]*exec) /usr/share/recovery-mode/recovery-menu.*|\$1 /sbin/sulogin # Modified by DRBL. Force to use sulogin!|g" $drbl_common_root/etc/init/rcS.conf
      # We have to force to enter different runlevel, not in runlevel 1 , otherwise the Clonezilla job (/etc/rc1.d/S19ocs-run) will be run again.
      perl -pi -e "s|(^[[:space:]]*) start --no-wait rc-sysinit.*|\$1 telinit 2 # Modified by DRBL. Force to enter runlevel 2 to avoid clonezilla job is run again!|g" $drbl_common_root/etc/init/rcS.conf
    fi
  fi

elif [ -e /etc/SuSE-release ]; then
  # SuSE
  # 1. In SuSE, /etc/init.d/reboot is link to halt, so we just have to modify
  # halt.
  perl -pi -e 's|^(> /success.*)|#$1 # Modified by DRBL|' $drbl_common_root/etc/init.d/halt
  perl -pi -e 's|^(umount -anvt proc.*)|#$1 # Modified by DRBL|' $drbl_common_root/etc/init.d/halt
  perl -pi -e 's|^(test -z.*fuser -sk -HUP $hupon)|#$1 # Modified by DRBL|' $drbl_common_root/etc/init.d/halt 
  # 2. Do not clean or remove etc/mtab when boots
  perl -pi -e 's|^([[:space:]]*)(rm -f /etc/mtab.*)|$1# $2 # Modified by DRBL|' $drbl_common_root/etc/init.d/boot.rootfsck
  # 3. For OpenSuSE 10.0, clean /fastboot in boot.localfs is:
  #	rm -f /etc/mtab* /etc/nologin /nologin /fastboot /forcefsck /success
  # Not only etc/mtab, do not remove /fastboot, either, keep it, since DRBL client is always fastboot
  perl -pi -e 's|^([[:space:]]*rm -f )/etc/mtab\* (.*)/fastboot(.*)|$1 $2 $3 # Modified by DRBL|' $drbl_common_root/etc/init.d/boot.localfs
  # It's not easy to write in one command, so for OpenSuSE 10.1, we add another line to clean /fastboot in /etc/init.d/boot.localfs:
  #	rm -f /etc/nologin /nologin /fastboot /forcefsck /success
  # Do not remove /fastboot, keep it, since DRBL client is always fastboot
  perl -pi -e 's|^([[:space:]]*rm -f .*)/fastboot(.*)|$1 $2 # Modified by DRBL|' $drbl_common_root/etc/init.d/boot.localfs
  # Do not umount -t tmpfs.
  perl -pi -e 's|umount -t tmpfs.*;;|continue ;; # Modified by DRBL|' $drbl_common_root/etc/init.d/boot.localfs
  # For OpenSuSE 11.3, the unmounting tmpfs part has changed. Modify here:
  perl -pi -e 's|^(typeset -r nomnt=autofs,.*)|$1,tmpfs # Modified by DRBL|' $drbl_common_root/etc/init.d/boot.localfs

  # 4. boot.rootfsck, we comment the mount -f / to avoid / be mounted twice.
  perl -pi -e 's|^([[:space:]]*)(mount -f /)|$1# $2 # Modified by DRBL|g' $drbl_common_root/etc/init.d/boot.rootfsck

  # 5. Force /etc/init.d/rc1.d/S*single to be at S90, not too early. In OpenSuSE 11.1, it's S10single, while ocs-run is S19.
  (cd $drbl_common_root/etc/init.d/rc1.d/; mv S*single S90single)
else
  # RH-like
  if [ -f "$drbl_setup_path/files/${OS_type}/${OS_Version}/halt.$OS_Version.drbl" ]; then
    cp -f $drbl_setup_path/files/${OS_type}/${OS_Version}/halt.$OS_Version.drbl $drbl_common_root/etc/init.d/halt
  else
    # not Debian, it's RH-like (BSD style), so show warning.
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "Warning! Unable to find the fine-tune file ${drbl_setup_path}/files/${OS_type}/${OS_Version}/halt.${OS_Version}.drbl, use ${drbl_setup_path}/files/${OS_type}/halt.default-${OS_type}.drbl as /etc/init.d/halt for DRBL clients!"
    echo "This may cause some problems to DRBL clients!"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    cp -f $drbl_setup_path/files/${OS_type}/halt.default-${OS_type}.drbl $drbl_common_root/etc/init.d/halt
  fi
  # From Fedora 9, upstart is used, and the post script of rc1 will force to terminate all programs after S19ocs-run is run in the end of rc1. i.e. when client finishes cloning in Clonezilla SE, a reboot or shutdown command (e.g. ocs-sr -p reboot...) will be killed by the post-stop script of rc1. Therefore we comment it.
  # The post script in /etc/event.d/rc1 is:
  #post-stop script
  #	clear
  #	TEXTDOMAIN=initscripts
  #	. /etc/profile.d/lang.sh
  #	echo $"Telling INIT to go to single user mode."
  #	exec telinit S
  #end script
  if [ -e "$drbl_common_root/etc/event.d/rc1" ]; then
    perl -pi -e 's|(^[[:space:]]*)(clear)|$1# $2 # Modified by DRBL|' $drbl_common_root/etc/event.d/rc1
    perl -pi -e 's|(^[[:space:]]*)(.*Telling INIT to go to single user mode.*)|$1# $2 # Modified by DRBL|' $drbl_common_root/etc/event.d/rc1
    perl -pi -e 's|(^[[:space:]]*)(exec telinit S)|$1# $2 # Modified by DRBL|' $drbl_common_root/etc/event.d/rc1
    # Instead, we put a modified single to be run after S19ocs-run
    cp -af $drbl_setup_path/files/RH/single.drbl $drbl_common_root/etc/rc1.d/S99single
  fi
fi

# 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 clients common root template... "
usrdel_file_need="/usr/sbin/userdel"
cp --parents $usrdel_file_need $drbl_common_root
if ldd $usrdel_file_need &>/dev/null; then
  usrdel_lib_need=$(ldd /usr/sbin/userdel | sed -e "s/.*=> //g" -e "s/(0x.*)//g" | awk '{print $1}')
  for imod in $usrdel_lib_need; do
      cp --parents $imod $drbl_common_root
  done
fi
# UGLY... For SuSE, we need to copy /usr/lib/pwdutils/ to $drbl_common_root, 
# but why ? Here it's just a lots of try-and-errors...
[ -d /usr/lib/pwdutils/ ] && cp --parents -r /usr/lib/pwdutils $drbl_common_root
[ -x /usr/sbin/userdel-pre.local ] && cp --parents /usr/sbin/userdel-pre.local $drbl_common_root 
[ -x /usr/sbin/userdel-post.local ] && cp --parents /usr/sbin/userdel-post.local $drbl_common_root 
# /usr/bin/crontab exists in /usr/sbin/userdel-pre.local in SuSE
[ -x /usr/bin/crontab ] && cp --parents /usr/bin/crontab $drbl_common_root 

user_to_del="$(drbl-get-common-username 2>/dev/null)"
for u in $user_to_del; do
  if grep -q "^$u:" $drbl_common_root/etc/passwd; then
    chroot $drbl_common_root /usr/sbin/userdel $u 2>/dev/null
  fi
done
# We need nobody user. However, since some services are started before yp/nis, we will let nobody as local account. Comment this one.
#echo "Exporting nfsnobody in NIS/YP...".
#perl -pi -e "s/^.*NFSNOBODYUID=.*/NFSNOBODYUID=0/g" /var/yp/Makefile
#perl -pi -e "s/^.*NFSNOBODYGID=.*/NFSNOBODYGID=0/g" /var/yp/Makefile
# Oct/25/2011, for better security, do not show the hashed yp passwd. Thanks to Robert Arkiletian <robark _at_ gmail com> for reporting this issue.
perl -pi -e "s/^MERGE_PASSWD=.*/MERGE_PASSWD=false/g" /var/yp/Makefile
perl -pi -e "s/^MERGE_GROUP=.*/MERGE_GROUP=false/g" /var/yp/Makefile
# Enable "shadow" in "all line" in /var/yp/Makefile.
# For Fedora/CentOS, the "all line" is like:
# all:  passwd group hosts rpc services netid protocols mail \
#	# netgrp shadow publickey networks ethers bootparams printcap \
#	# amd.home auto.master auto.home auto.local passwd.adjunct \
#	# timezone locale netmasks
# For Debian/Ubuntu, it is like:
# ALL =   passwd group hosts rpc services netid protocols netgrp
# #ALL += publickey mail ethers bootparams printcap
# ##ALL += amd.home auto.master auto.home auto.local
# ##ALL += timezone locale networks netmasks
# #
# ## Autodetect /etc/shadow if it's there
# #ifneq ($(wildcard $(SHADOW)),)
# #ALL += shadow
# #endif
# #
# ## Autodetect /etc/passwd.adjunct if it's there
# #ifneq ($(wildcard $(ADJUNCT)),)
# #ALL += passwd.adjunct
# #endif
# #
# #all:   $(ALL)
if [ -z "$(LC_ALL=C grep -Ew "^all:.*shadow.*" /var/yp/Makefile)" ]; then
  perl -pi -e 's|(^all:)(.*)|$1 shadow $2|g' /var/yp/Makefile
fi
echo "done!"

# Enable the NIS client for this template
# For Mandrake/Debian, there is no authconfig, 
# Mandrake use drakauth, but not interactive ?
echo -n "Enabling the NIS client in the common root template... "
# For RH-like, used to use /usr/sbin/authconfig, but in FC5, it's python... not easy to create the "create_authconfig_env $drbl_common_root/"
# turn on the nis in common root's /etc/nsswitch.conf, this is necessary for MDK/DBN since MDK/DBN does NOT have /usr/sbin/authconfig 
perl -pi -e "s/^passwd:.*/passwd:     files nis/" $drbl_common_root/etc/nsswitch.conf 
perl -pi -e "s/^shadow:.*/shadow:     files nis/" $drbl_common_root/etc/nsswitch.conf 
perl -pi -e "s/^group:.*/group:     files nis/" $drbl_common_root/etc/nsswitch.conf 
perl -pi -e "s/^hosts:.*/hosts:     files nis dns/" $drbl_common_root/etc/nsswitch.conf 

# Patch for mandriva, e.g. 2009 or 2010, the /etc/init.d/sound is using /root/tmp/ as the temp dir. This will make /etc/init.d/sound not work in client because it's early before NFS /root is mounted. We have filed a bug report in https://qa.mandriva.com/show_bug.cgi?id=55929 to suggest to use /tmp/ instead of /root/tmp/.
if [ -e "$drbl_common_root/etc/init.d/sound" ]; then
  perl -pi -e 's|^([[:space:]]*)MIXER_SETTINGS=/root/tmp/asound.state_tmp|$1MIXER_SETTINGS=/tmp/asound.state_tmp|g' $drbl_common_root/etc/init.d/sound
fi

# For Debian
if [ -e /etc/debian_version ]; then
  if [ -f $drbl_common_root/etc/default/nis ]; then
    perl -p -i -e "s/^NISSERVER=.*/NISSERVER=false/" $drbl_common_root/etc/default/nis
    perl -p -i -e "s/^NISCLIENT=.*/NISCLIENT=true/" $drbl_common_root/etc/default/nis
  fi
fi
# Turn off wicd autostart, otherwise user need to enter password when entering XFCE in drbl client. It's not required because the network configuration on drbl client is done during booting.  This is especially for DRBL live.
if [ -e $drbl_common_root/etc/xdg/autostart/wicd-tray.desktop ]; then
  cat <<-WICD_END > $drbl_common_root/etc/xdg/autostart/wicd-tray.desktop
[Desktop Entry]
# Disabled by DRBL.
Hidden=true
WICD_END
fi
echo "done!"

echo -n "Creating some necessary files in the clients common root template..."
# set the arguments "-q" in kudzu to let system do configuration that
# doesn't require user input
if [ -d "$drbl_common_root/etc/sysconfig" -a "$drbl_common_root/etc/sysconfig/kudzu" ]; then
    if ! grep -qE "^KUDZU_ARGS=-q" $drbl_common_root/etc/sysconfig/kudzu 2>/dev/null; then
      echo "KUDZU_ARGS=-q" >> $drbl_common_root/etc/sysconfig/kudzu
    fi
fi

#echo -n "."
# write the ntp server setting
#if ! grep -q "^server pool.ntp.org" /etc/ntp.conf 2>/dev/null; then
#  echo "server pool.ntp.org" >> /etc/ntp.conf
#fi

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

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

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 $drbl_common_root/

echo -n "."

# For SuSE, we need to copy /var/X11R6 to clients also. How about /var/adm ?
[ -n "$(unalias ls 2>/dev/null; ls /var/X11R6/* 2>/dev/null)" ] && rsync -a $RSYNC_OPT_EXTRA /var/X11R6/* $drbl_common_root/var/X11R6/
# UGLY!
# /var/yp/nicknames is importand in clients, otherwise "ypcat passwd" won't work.
[ -e /var/yp/nicknames ] && cp -a /var/yp/nicknames $drbl_common_root/var/yp/

# Copy all /var/lib/* to the common root
# For /var/lib/, we can not use $RSYNC_OPT_EXTRA, since if we just run drblsrv
# some files, like in /var/lib/rpm/, it's newer than those in the system.
# We force to sync that in the server to client.
# varlib_NOT_2_be_copied_2_common_root is loaded from drbl.conf
# prepare the options for rsync to exclude when copy files in
# /var/lib/* to /tftpboot/node_root/var/lib/
varlib_opts_common_to_common=""
for iv in $varlib_NOT_2_be_copied_2_common_root; do
  varlib_opts_common_to_common="$varlib_opts_common_to_common --exclude=$iv/ "
done
[ -d /var/lib ] && rsync -a $varlib_opts_common_to_common /var/lib/* $drbl_common_root/var/lib/

# Copy selected /var/cache/* to the common root
for icache in $varcache_2_be_copied_2_common_root; do
  [ -d "/var/cache/$icache" ] && rsync -a $RSYNC_OPT_EXTRA /var/cache/$icache $drbl_common_root/var/cache/
done

# In OpenSUSE 10.1, if "/var/log/lastlog" does NOT exist in client, pam_lastlog will refuse to run, and user or root won't be able to login in client's console.
# The error in client will be like:
# May 20 06:40:48 opensuse101102 login[2996]: pam_lastlog(login:session): unable to open /var/log/lastlog: No such file or directory
touch $drbl_common_root/var/log/lastlog
# For OpenSuSE 10.1, if /var/lib/nfs/state does not exist, it will show err.
touch $drbl_common_root/var/lib/nfs/state
# For Debian 4.0, if /var/log/dmesg does not exist, it will complain when first boot.
touch $drbl_common_root/var/log/dmesg

};

# print all the nfsserver to $drbl_common_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"};
  # Try to get setting from system also
  # use the NIC "eth1, eth2..." of DRBL server as default nfsserver_sys...
  my $nfsserver_sys;
  chomp($nfsserver_sys=`drbl-get-ipadd $interface`);
  # 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 system config file.\n";
     exit;
  }
    #---------------
    #print "nfsserver: $nfsserver\n";
    print NFSSERVER_OUT "$nfsserver ";

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

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

echo "done!"
};

# Part 3,
# create every client node, like Debian's diskless-newhost
#
  print DISKLESS_OUT q{
# create every client node, like Debian's diskless-newhost
};

  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 $gateway=$rHoH->{$k1}{"GATEWAY"};
    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($gateway)==0 ) { $gateway=$nfsserver; }
    if( length($nbi)==0 ) { $nbi=$rHoH->{"general"}{"NBI"}; }
    # Try to get setting from system also
    # use the NIC "eth1, eth2..." of DRBL server as default nfsserver_sys...
    chomp($hostname_sys=`hostname`);
    chomp($netmask_sys=`drbl-get-netmask $interface`);
    chomp($ipaddr_sys=`drbl-get-ipadd $interface`);
    # the IP address for server is the NFS server for client
    my $nfsserver_sys=$ipaddr_sys;
    my $bootserver_sys=$nfsserver_sys;
    my $nisserver_sys=$nfsserver_sys;
    # 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...
    # For interface like vmnet1, we will not extract that so that the
    # hostname won't conflict.
    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 system config file.\n";
       exit;
    }

    if ( ! $network ) { 
      # Since there are two versions of ipcalc, we use the perl one, which is
      # from http://jodies.de/ipcalc
      $network = `drbl-ipcalc $ipaddr_sys $netmask_sys | awk -F' ' '/Network:/ {print \$2}' | sed -e "s|/.*||g"`;
      chomp($network);
      print colored ("The calculated NETWORK for $interface is $network.\n", "$color_warn");
    }

    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;   
    }
    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;   
    }
    if ( ! $gateway ) { 
     $gateway = $bootserver; 
     print "* gateway is not set in config file, \nUse bootserver as gateway.\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 system config file.\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;
    }
    unless ( $gateway ) {
       print "Error! GATEWAY is unset!\n";
       print "Please set gateway in config file \"$_[0]\"\n";
       exit;
    }
    
    # go 
    @nfsserverIp=split(/\./,$nfsserver);
    @networkIp=split(/\./,$network);

    # For alias IP address, we need something like:
    # Ref: https://lists.isc.org/pipermail/dhcp-users/2010-September/012053.html
    #shared-network "some-identifier" {
    #   subnet 192.168.100.0 netmask 255.255.255.0 {
    #     option subnet-mask  255.255.255.0;
    #     option routers 192.168.100.254;
    #     next-server 192.168.100.254;
    #
    #     pool {
    #       range 192.168.100.1 192.168.100.3;
    #     }
    #   }
    #   subnet 192.168.120.0 netmask 255.255.255.0 {
    #   }
    #}
    if ( $interface =~ /eth[0-9]+:[0-9]+/ ) {
      print DHCPD_OUT <<EOF;
shared-network "alias-interface-identifier" {
EOF
    }

    print DHCPD_OUT <<EOF;
subnet $network netmask $netmask_sys {
    option subnet-mask	$netmask_sys;
    option routers $gateway;
    next-server $bootserver;

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=$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"; 
    }

    # 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 default name will like fc101, fc2201...,
      # i.e. $prefix{ethx}{client no}
      # If the hostname is assigned in /etc/drbl/client-ip-hostname, 
      # we will ust that.
      $label_default="";
      if($i<10) { $label_default=$hostname."0".$i; }
      elsif($i<=254) { $label_default=$hostname.$i; }
      elsif($i>254) { last; } # minus 2 ip: $network.0 $network.255
      $label_assigned="";
      chomp($label_assigned=`LC_ALL=C get-assigned-hn-by-ip $networkIp[0].$networkIp[1].$networkIp[2].$i`);
      if ($label_assigned) {
        $label=$label_assigned;
      }else{
        $label=$label_default;
      }

      # 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      
	# without nbi set in config file
        print DHCPD_OUT <<EOF;
    host $label {
        hardware ethernet  $_;
        fixed-address $ip;
	# option host-name "$label";
    }
EOF
      } elsif( length($range)!=0 ) { 
	# range
        $ip=$_;
      }
      
      # clean the temp range file
      unlink ($temprange) if -f $temprange;

      # generate netgroup
      print NETGROUP_OUT "($label,,) ";

      # generate $CLIENT_IP_HOSTNAME_LIST
      print CLIENT_HOST_IP_LIST_OUT "$ip $label\n";

      # append the hosts to hosts_list
      print HOSTS_LIST_OUT <<EOF;
$ip
EOF

#
      print DISKLESS_OUT q{
      # When none full drbl mode AND none full clonezilla mode, we turn on pseudo option
      [ "$clonezilla_mode" != "full_clonezilla_mode" -a "$drbl_mode" != "full_drbl_mode" ] && [ "$pseudo_flag" = "on" ] && pseudo_opt="-p"
      };
      print DISKLESS_OUT <<EOF;
      # $keep_old_files_flag is assigned in shell, not from perl.
      drbl-gen-client-files -l $language -h $ip -k \$keep_old_files_flag -n $nfsserver -a $label -i $nisserver \$pseudo_opt
      [ -z "\$template_client" ] && template_client="$ip"
EOF
      print DISKLESS_OUT q{
      pseudo_flag=on
      };

      # next one
      $i++;
    }

    # generate dhcpd.conf 
    if( length($mac)!=0 ) { # mac - just close it 
      print DHCPD_OUT "}\n";
    } 
    elsif( length($range)!=0 ) { # range - generate range & filename
        # without nbi set in config file
        my($rs,$re)=split(/-/,$range,2);
        print DHCPD_OUT <<EOF;
    pool {
      # allow members of "DRBL-Client";
      range $networkIp[0].$networkIp[1].$networkIp[2].$rs $networkIp[0].$networkIp[1].$networkIp[2].$re;
    }
}

EOF
    }
    if ( $interface =~ /eth[0-9]+:[0-9]+/ ) {
      my $main_nic = $interface;
      my $main_nic_ip;
      my $main_nic_netmask;
      my $main_nic_subnet;
      # find the main NIC, i.e. eth0:1 -> eth0
      $main_nic =~ s/:[0-9]+//g;
      chomp($main_nic_ip=`drbl-get-ipadd $main_nic`);
      chomp($main_nic_netmask=`drbl-get-netmask $main_nic`);
      chomp($main_nic_subnet=`LC_ALL=C drbl-ipcalc $main_nic_ip/$main_nic_netmask | grep -Ei "^Network:" | awk -F " " '{print \$2}' | sed -re "s|\/.*||g"`);
      print DHCPD_OUT <<EOF;
subnet $main_nic_subnet netmask $main_nic_netmask { }
}
EOF
    }
    close(MAC_IN);
  }

#
print DISKLESS_OUT q{
# Generate the files for DRBL single system image SSI
# Create the tarball template for DRBL SSI mode or Clonezilla box mode.
if [ "$drbl_mode" = "drbl_ssi_mode" -o \
     "$clonezilla_mode" = "clonezilla_box_mode" ]; then
  echo "Template client for DRBL SSI, Clonezilla box mode or Clonezilla live client is $template_client"
  drbl-gen-ssi-files -n -t $template_client
fi

#
if [ "$run_drbl_ocs_live_prep" = "yes" ]; then
  if [ "$clonezilla_mode" = "clonezilla_live_mode" ]; then
    drbl_ocs_live_server_opt=""
    [ -n "$drbl_ocs_live_server" ] && drbl_ocs_live_server_opt="-s $drbl_ocs_live_server"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo 'Preparing the system to use clonezilla live as the OS of clients...'
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    drbl-ocs-live-prep -b $live_client_branch -a $live_client_cpu_mode $drbl_ocs_live_server_opt
  else
    # Clean the previous Clonezilla live configuration.
    drbl-ocs-live-prep -u
  fi
fi

# output dhcpd arguments or interfaces to sysconfig file
dhcp_eths="$(awk -F"=" '/^interface=.*/ {print $2}' $config_file)"
# if the itnerface is alias, print the original interface
# i.e. if eth0:1, we print eth0
dhcp_eths="$(echo $dhcp_eths | sed -e "s/:[0-9]*//g")"
if [ -e "/etc/debian_version" ]; then
   # Debian, use the parameter "INTERFACES"
   echo "INTERFACES=\"$dhcp_eths\"" > $SYSCONF_PATH/$DHCP_SRV_NAME
elif [ -e "/etc/SuSE-release" ]; then
   perl -pi -e "s/^[#]*[[:space:]]*[#]*DHCPD_INTERFACE=.*/DHCPD_INTERFACE=\"$dhcp_eths\"/g" $SYSCONF_PATH/$DHCP_SRV_NAME
else
   # RH-like, use the parameter "DHCPDARGS"
   echo "DHCPDARGS=\"$dhcp_eths\"" > $SYSCONF_PATH/$DHCP_SRV_NAME
fi

# turn on pxelinux passwd if set
if [ -n "$client_pxelinux_passwd" ]; then
  drbl-pxelinux-passwd -e --stdin $client_pxelinux_passwd
else
  drbl-pxelinux-passwd --disable
fi

# write the NISDOMAIN to system config file in DRBL server
NET_sys_RH="/etc/sysconfig/network"
NIS_Debian="/etc/defaultdomain"
NIS_SuSE="/etc/defaultdomain"
if [ -e /etc/debian_version ]; then
  echo "$nisdomain" > $NIS_Debian
  perl -p -i -e "s/^NISSERVER=.*/NISSERVER=master/" /etc/default/nis
  perl -p -i -e "s/^NISCLIENT=.*/NISCLIENT=true/"   /etc/default/nis
elif [ -e /etc/SuSE-release ]; then
  # SuSE
  echo "$nisdomain" > $NIS_SuSE
else
  # RH-like
  NIS_sys=$(grep NISDOMAIN $NET_sys_RH 2>/dev/null)
  if [ -z "$NIS_sys" ]; then
    echo "NISDOMAIN=$nisdomain" >> $NET_sys_RH
  else
    perl -p -i -e "s/^NISDOMAIN=.*/NISDOMAIN=$nisdomain/" $NET_sys_RH
  fi
fi

# before restart NIS, force the variable NISDOMAIN now is that set in config file
nisdomainname $nisdomain

# Since we set tcp as the default NFS protocol, if tcp over NFS is not supported in the server running kernel, make a switch for client to use udp. 
# Ex:for RH9, tcp over NFS is not supported in the runnking kernel 2.4.20-8
if [ "$nfs_protocol" = "udp" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo 'Switch "tcp over NFS" to "udp over NFS" for the DRBL clients...'
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  drbl-nfs-conf --no-gen-ssi --protocol udp
fi

[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "Now add necessary services to this DRBL server: DHCP, TFTP, NFS, NIS..."
[ "$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

# create NFS exports
drbl-nfs-exports --no-restart generate

# start the iptables NAT
case "$drbl_server_as_NAT_server" in
  n|N|[nN][oO])
     [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
     echo "$msg_drbl_server_is_NOT_NAT_server"
     [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
     drbl-nat-rules clean ;;
  *) 
     drbl-nat-rules generate ;;
esac

# set the YP securenets
drbl-yp-securenets --no-restart generate

# add drbl-clients-nat service for Debian DRBL server.
if [ -e /etc/debian_version ]; then
   cp -f $drbl_setup_path/files/misc/drbl-clients-nat /etc/init.d
   # before we do it, clean it to avoid the stalled files.
   if [ "$dbn_ubn_serv_control_prog" = "use-insserv" ]; then
     insserv -f -r drbl-clients-nat &>/dev/null
   else
     update-rc.d -f drbl-clients-nat remove &>/dev/null
     # It will be added to rcX.d by "drbl-all-service add", so we do not add it here
   fi
fi

# flush the YP
echo "Update YP..."
if [ -e /etc/debian_version ]; then
  # For Debian woody, it seems that /etc/networks is not automaticaly created.
  # If we can not find it, just touch it
  [ ! -e /etc/networks ] && touch /etc/networks
fi
# The hostname for the master is stored within each NIS map and so if you do not regenerate the maps the master returned will not change.
# Ref: http://www.usenetlinux.com/archive/topic.php/t-224905.html
# We need to update hosts.byname, hosts.byaddr...
[ -e /var/yp/Makefile ] && touch /var/yp/Makefile
make -C /var/yp all &> /dev/null

# Clean those pseudo clients (empty directories)
rmdir $drblroot/* 2>/dev/null

# reset some stale status, maybe drblpush is run again.
if [ -e "$ocs_lock_dir/clonezilla.lock" ]; then
  if type drbl-ocs &>/dev/null; then
    echo -n "Your system is already in clonezilla mode... we will stop the stale status... "
    drbl-ocs -n -l 0 stop &>/dev/null
    echo "done!"
  fi
fi

# add and (re)start all the service which DRBL server need.
# drbl-all-service will automatically add them to rcX.d before start them .
if [ "$add_start_drbl_services_after_cfg" != "no" ]; then
  drbl-all-service start
  retv=$?
  if [ "$retv" -gt 0 ]; then
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo "$msg_something_went_wrong_when_start_drbl_related_srv"
    echo "$msg_you_can_try_to_run_the_following_again:"
    echo "drbl-all-service start"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  fi
else
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo $msg_drbl_related_services_not_added_started
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fi

# 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-powerful-thin-client --no-gen-ssi --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-powerful-thin-client --no-gen-ssi --powerful -ln $language
	    ;;
     esac
     drbl-client-system-select $client_select_opt -t $client_system_boot_timeout on
     ;;
   n|N|[nN][oO])
     drbl-client-system-select off
     ;;
esac
# set graphic/text pxe boot menu for clients
case "$use_graphic_pxelinux_menu" in
   y|Y|[yY][eE][sS])
     switch-pxe-bg-mode -m graphic
     ;;
   n|N|[nN][oO])
     switch-pxe-bg-mode -m text
     ;;
esac

# if drbl_mode is none, disable drbl in pxelinux menu, and set default as local
if [ "$drbl_mode" = "none" ]; then
  # disable the DRBL in pxelinux menu
  hide_reveal_pxe_img drbl hide $pxecfg_pd/pxelinux.cfg/default
  # set local as default
  set-default-pxe-img -i local -c $pxecfg_pd/pxelinux.cfg/default
fi

# Force to update the pxelinux config
case "$drbl_mode" in
  "full_drbl_mode") drbl_mode_opt="-d 0" ;;
  "drbl_ssi_mode")  drbl_mode_opt="-d 1" ;;
  "none")           drbl_mode_opt="-d 2" ;;
esac
case "$clonezilla_mode" in
  "full_clonezilla_mode") clonezilla_mode_opt="-z 0" ;;
  "clonezilla_box_mode")  clonezilla_mode_opt="-z 1" ;;
  "none")                 clonezilla_mode_opt="-z 2" ;;
  "clonezilla_live_mode") clonezilla_mode_opt="-z 3" ;;
esac
tune-clientdir-opt -l $language --no-create-ssi-template $drbl_mode_opt $clonezilla_mode_opt

#
case "$purge_client" in
   n|N|[nN][oO])
     # Do not prompt user to restart client if no existing client exists
     tune_DBN_audio_plugdev_extra_opt="-r"
     ;;
esac
# set the DBN clients audio and plugdev if set
if [ -e /etc/debian_version ]; then
  case "$set_DBN_client_audio_plugdev" in
     y|Y|[yY][eE][sS])
       tune-debian-dev-group-perm -l $language -g "$desktop_user_group_debian" -e $tune_DBN_audio_plugdev_extra_opt
       ;;
  esac
fi

# post run
if [ -n "$(unalias ls 2>/dev/null; ls $DRBLPUSH_POSTRUN_DIR/ 2>/dev/null)" ]; then
  echo "Some files are found in $DRBLPUSH_POSTRUN_DIR. Run them now..."
  drbl-run-parts $DRBLPUSH_POSTRUN_DIR
fi

#
# echo warning message if TCPwrapper is set.
host_allow_set=$(grep -v "^[[:space:]]*#" /etc/hosts.allow 2>/dev/null)
host_deny_set=$(grep -v "^[[:space:]]*#" /etc/hosts.deny 2>/dev/null)
if [ -n "$host_allow_set" -o -n "$host_deny_set" ]; then
   client_ips="$(get-client-ip-list)"
   [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
   echo "$msg_hosts_allow_deny_is_set"
   echo "$msg_you_must_make_sure_these_clients"
   # format the output, 4 IP addresses in one line
   # --------------------
   i=0
   for ip in $client_ips; do
    i=$(($i+1))
    echo -n "$ip "
    [ "$(expr $i % 4)" -eq 0 ] && echo
   done
   echo
   # --------------------
   echo "$msg_can_access_this_DRBL_server"
   echo "$msg_otherwise_client_fail_to_boot"
   [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
   echo "TFTP open timeout"
   echo "TFTP......."
   [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
   echo "$msg_or"
   [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
   echo "mount: RPC: Unable to receive; errno = Connection refused"
   [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fi

# Check the NFSD no, it's very important when heavy client traffic.
RUNNING_NFSDCOUNT="$(ps -ef | grep nfsd | grep -v grep | wc -l)"
total_necessary_nfsd="$(get-necessary-nfsd-no)"
if [ -z "$total_necessary_nfsd" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo "Warning! Unable to get the total necessary NFS daemon number!!!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fi
if [ "$RUNNING_NFSDCOUNT" -lt "$total_necessary_nfsd" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo "The number of running NFS services in this DRBL number ($RUNNING_NFSDCOUNT) is not enough for clients, $total_necessary_nfsd nsfd is expected! The performance will NOT be good! Check the NFS setting in /etc/sysconfig/ or /etc/default/!!!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fi

#
#echo "$msg_delimiter_star_line"
#echo "Now syncing - flush filesystem buffers..." 
sync;sync;sync
#
export LC_ALL=$LC_ALL_org

echo "$msg_delimiter_star_line"
echo "Enjoy DRBL!!!"
echo "http://drbl.org; http://drbl.nchc.org.tw"
echo "NCHC Free Software Labs, Taiwan. http://free.nchc.org.tw"
echo "$msg_delimiter_star_line"

# 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 in some Linux (RH8 ?).
echo "$msg_if_you_like_you_can_reboot_to_make_sure_everthing"
echo "$msg_delimiter_star_line"
if [ "$add_start_drbl_services_after_cfg" != "no" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo "$msg_drbl_server_is_ready $msg_all_set_you_can_turn_on_clients"
  echo "$msg_note! $msg_etherboot_5_4_is_required"
  echo "$msg_run_drblpush_with_config_again"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
else
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo $msg_drbl_related_services_not_added_started
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fi
};

  print NETGROUP_OUT "\n";
  print NETGROUP_OUT "# Added by DRBL, end\n";
  print CLIENT_HOST_IP_LIST_OUT "# Created by DRBL (drblpush), end\n";

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

  # 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 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 2>&1");
  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", "$color_warn").
          "$lang_deploy{\"press_enter_to_continue\"}";
          chomp($line=<STDIN>);
    print "$delimiter{\"dash_line\"}\n";
  }else{
   # MAC file exists, check if it contains illegal 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{\"illegal_char_in_MAC\"},". 
            colored ("\"$macfile_check\"\n", "$color_fail").
            "$lang_deploy{\"fix_wrong_MAC_file\"} \n".
            "$lang_word{\"program_stop\"}!!!\n";
      exit(1);
   }
  }
} # end of check_MAC_file

#########################################
# Main program
my $no_deploy = 0;
my $config_file = "";
our $verbosity = 1;
# NOTE!!! Remember to update the usage_details also.
our $usage="Usage: $0 [-c|--config config_file] [-d|--debug] [-e|--accept-one-nic] [-h|--help] [-i|--interactive] [-k|--keep_clients Y/n] [-l|--language index_number] [-m|--client_startup_mode 1/2] [-n|--no_deploy] [-o|--clonezilla_home DIR] [-p|--port_client_no number] [-q|--quiet] [-r|--drbl_mode 0|1|2] [-t|--live_client_branch 0|1|2|3] [-s|--swap_create y/N] [-v|--verbose] [-z|--clonezilla_mode 0|1|2|3] [--skip-drbl-ocs-live-prep] [--drbl-ocs-live-server IP]";
sub usage_details{
  die "$usage\n".
  "-b, --not-add-start-drbl-srvi Do NOT add and start DRBL related services after the configuration is done\n".
  "-c, --config      The DRBL config file, text format\n".
  "-d, --debug       Turn on debug mode when run shell script\n".
  "-e, --accept-one-nic   Accept to run DRBL service in only one network card. ///NOTE/// This might mess up your network environment especially if there is an existing DHCP service in your network environment.\n".
  "-h, --help        Show this help message\n".
  "-i, --interactive Interactive mode, setup step by step.\n".
  "-k, --keep_clients Y/n Keep previously saved files for clients.\n".
  "-m, --client_startup_mode [1|2] Assign client mode, 1 for graphic mode, 2 for text mode.\n".
  "-n, --no_deploy   Just create files, do NOT deploy the files into system\n".
  "-o, --clonezilla_home DIR  Use DIR as the clonezilla image directory\n".
  "-p, --port_client_no number The client no. in each NIC port.\n".
  "-q, --quiet             Be less verbose\n".
  "-r, --drbl_mode [0|1|2] Assign DRBL mode (0: Full DRBL mode, 1: DRBL SSI mode, 2: Do NOT provide diskless Linux service to clients)\n".
  "-s, --swap_create y/N   Switch to create and use local swap in clients (yes or no)\n".
  "-t, --live_client_branch [0|1|2|3] Assign the Clonezilla live release branch to be used, 0 is stable branch (Debian-based), 1 is testing branch (Debian-based), 2 is alternative stable branch (Ubuntu-based), 3 is alternative testing branch (Ubuntu-based). This option should be used when -z|--clonezilla_mode = 3\n".
  "-u, --live_client_cpu_mode [0|1|2]  Assign the CPU mode for client when doing Clonezilla job with Clonezilla live (0: i486, 1: i686, 2: amd64)\n".
  "-v, --verbose           Be more verbose\n".
  "-z, --clonezilla_mode [0|1|2|3] Assign Clonezilla mode (0: Full DRBL mode, 1: Clonezilla box mode, 2: Do NOT provide clonezilla service to clients, 3: Use Clonezilla live as the OS of clients)\n".
  "--skip-drbl-ocs-live-prep  Force to skip running drbl-ocs-live-prep\n".
  "--drbl-ocs-live-server IP  Assign the Clonezilla live server as IP when running drbl-ocs-live-prep\n".
  "-l, --language INDEX  Set the language to be shown (deprecated! Use environmental LC_ALL or LANG instead).\n".
  "                      [0]: English\n".
  "                      [1]: Traditional Chinese (Big5) - Taiwan\n".
  "                      [2]: Traditional Chinese (UTF-8, Unicode) - Taiwan\n".
  "                      [a|ask]: Prompt to ask the language index\n".
  "--ln INDEX            Set the language to be shown (deprecated! Use environmental LC_ALL or LANG instead).\n".
  "                      [en_US]: English\n".
  "                      [zh_TW.BIG5]: Traditional Chinese (Big5) - Taiwan\n".
  "                      [zh_TW.UTF-8]: Traditional Chinese (UTF-8, Unicode) - Taiwan\n".
  ";"
} # end of usage_details

# 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) =~ /^(-)?(-)?ln$/) {
     $language = 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)?$/) {
     $verbose_opt="-v";
     $verbosity++;
   } elsif (lc($arg) =~ /^(-)?(-)?q(uiet)?$/) {
     $verbosity--;
   } elsif (lc($arg) =~ /^(-)?(-)?p(ort_client_no)?$/) {
     $assign_client_no_each_port = shift(@ARGV);
   } elsif (lc($arg) =~ /^(-)?(-)?h(elp)?$/) {
     usage_details();
   } elsif (lc($arg) =~ /^(-)?(-)?i(nteractive)?$/) {
     $mode = "create_config_file";
   } elsif (lc($arg) =~ /^(-)?(-)?k(eep_clients)?$/) {
     $keep_client = shift(@ARGV);
   } elsif (lc($arg) =~ /^(-)?(-)?m(ode)?$/) {
     $client_startup_mode = shift(@ARGV);
   } elsif (lc($arg) =~ /^(-)?(-)?s(wap_mode)?$/) {
     $swap_create = shift(@ARGV);
   } elsif (lc($arg) =~ /^-z$|^--clonezilla_mode$/) {
     $clonezilla_mode = shift(@ARGV);
   } elsif (lc($arg) =~ /^-t$|^--live_client_branch$/) {
     $live_client_branch= shift(@ARGV);
   } elsif (lc($arg) =~ /^-u$|^--live_client_cpu_mode$/) {
     $live_client_cpu_mode = shift(@ARGV);
   } elsif (lc($arg) =~ /^-r$|^--drbl_mode$/) {
     $drbl_mode = shift(@ARGV);
   } elsif (lc($arg) =~ /^-o$|^--clonezilla_home$/) {
     $ocs_img_repo_dir = shift(@ARGV);
   } elsif (lc($arg) =~ /^-b$|^--not-add-start-drbl-srvi$/) {
     $add_start_drbl_services_after_cfg = "no";
   } elsif (lc($arg) =~ /^-e$|^--accept-one-nic$/) {
     $continue_with_one_port = "yes";
   } elsif (lc($arg) =~ /^--skip-drbl-ocs-live-prep$/) {
     $run_drbl_ocs_live_prep = "no";
   } elsif (lc($arg) =~ /^--drbl-ocs-live-server$/) {
     $drbl_ocs_live_server = shift(@ARGV);
   } elsif (lc($arg) =~ /^(-)?(-)?d(ebug)?$/) {
     $sh_debug = "-x"; 
   } else {
     usage_details();
   }
}

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

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

# check if drbl server package is installed or not
print "$delimiter{\"star_line\"}\n";
print "$lang_deploy{\"searching_installed_drbl_packages\"}\n";
# just pick package drbl to test

# return code is number divided by 256
my $drbl_rpm = system("LC_ALL=C rpm -q drbl > /dev/null 2>&1") / 256;
my $drbl_deb = system("LC_ALL=C dpkg -L drbl > /dev/null 2>&1") / 256;
my $drbl = $drbl_rpm * $drbl_deb;
if ($drbl eq 0) {
        print "$lang_deploy{\"finished_searching_installed_drbl_packages\"}\n";
	print "$delimiter{\"star_line\"}\n";
}else{
	print "$delimiter{\"star_line\"}\n".
	       colored ("$delimiter{\"warning_line\"}\n", "$color_warn").
	      "$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;
                };
        }
}

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
       # 2 possibilities, $config_file is inputted as absolute or relative path.
       # (1) $config_file is inputted as absolute path, like /etc/drbl/drblpush.conf
       system("[ -f $config_file ] && cp -f $config_file .");
       # (2) If the $config_file is input as relative path, like ./drblpush.conf, we have to copy it from $orig_wd, since now it's in working dir.
       system("[ -f $orig_wd/$config_file ] && cp -f $orig_wd/$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 2>&1");

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

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

print "$delimiter{\"star_line\"}\n";
print "purge_client: $purge_client\n" if $verbosity >=2;
if ( $client_exist_flag = "0" && $purge_client eq "no" ) { 
   # old clients exist and we want to keep them, show warning messages
   print colored ("$lang_deploy{\"note_for_keep_client_setting\"}\n", "$color_warn").
         "$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", "$color_warn").
	      colored ("$lang_deploy{\"backup_firewall_rule\"}\n", "$color_warn").
	      "[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\"} ","$color_warn") ."$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
         } 
        }
}
#
chdir ($orig_wd) || die ("Could not change to the original working directory!!!");
# clean the temp working directory
rmtree ($drblpush_wd) if -d $drblpush_wd;

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