#!/usr/bin/perl -X
#
# Copyright (C) 2002-2003 by NCHC, Steven Shiau, K. L. Huang
# (steven@nchc.org.tw, c00hkl00@nchc.org.tw)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Version 0.1, by K. L. Huang, c00hkl00@nchc.org.tw, especially for Debian
# Modified by Steven Shiau, steven@nchc.org.tw DRBL for Redhat

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

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

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

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

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

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

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

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


#
our $DRBL_SCRIPT_PATH="/opt/drbl";
our $drbl_setup_path="$DRBL_SCRIPT_PATH/setup";
our $purge_client;

# use some perl modules
use Term::ANSIColor;

#
# ------------------------------------------------------------------------
# Begin of the program
# subroutines
sub lang_set{
  my $lang_opt=$_[0];
  if ( "$lang_opt" eq "" ){
    # l10n
    print "Language | y| 語言 ?\n".
          "[0]: English\n".
          "[1]: Chinese Traditional (Big5) - Taiwan |  (jX) - xW\n".
          "[2]: Chinese Traditional (UTF-8, Unicode) - Taiwan | 中文 (萬國標準碼) - 台灣\n".
          "[0] ";
    chomp($language=<STDIN>);
  } else {
    $language=$lang_opt;
  }
  if ($language eq "1"){
    $language="tw.BIG5";
  } elsif ($language eq "2"){
    $language="tw.UTF-8";
  } else {
    $language="en";
  }
  return $language;
} # end of lang

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="empty";
  my $saved_gw="empty";
  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_client_1\"} (it's IP in DRBL is $IP) ($saved_ip)\n";
    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\"} $IP ($saved_gw)\n";
    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\"} $IP ($saved_netmask)\n";
    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=`mktemp /tmp/public_ip_tmp.XXXXXX`);
  open(PUBLIC_IP_FILE,">$public_ip_tmp") or die "$lang_deploy{\"failed_to_open_file\"}  \"$config_interactive\"\n";
  print "Clients' IPs: @drbl_ip\n" if $verbosity >=2;
  
  
  print PUBLIC_IP_FILE <<END_PUBLIC_IP;
# The private IP is for the client connected to DRBL server
# public IP is for the client connected to WAN
#------------------------------------------------------------
#private IP \t public IP \t netmask \t gateway
END_PUBLIC_IP
  
  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
  
  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_FILE <<END_PUBLIC_IP;
$IP \t $public_ip \t $public_netmask \t $public_gw
END_PUBLIC_IP
  }
  
  print "$lang_deploy{\"set_client_public_IP_as\"}\n";
  print "#$delimiter{\"dash_line\"}\n";
  system("cat $public_ip_tmp");
  print "#$delimiter{\"dash_line\"}\n";
  print "$lang_text{\"Accept\"} ? (Y/n)\n".
        "$lang_deploy{\"accept_or_enter\"}\n";
  chomp($value=<STDIN>);
  if ($value eq "Y" || $value eq "y" || $value eq "") {
    system("cp -f $public_ip_tmp $public_ip_file");
  } else {
    # 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);
} #end of sub set_client_public_ip

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

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

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

        unless ( $domain_sys ) {
           print "$delimiter{\"dash_line\"}\n".
                 "$lang_deploy{\"domain_unset_prompt\"}\n".
	         "[drbl.sf.net] ";
	   chomp($domain_sys=<STDIN>);
           if ($domain_sys eq "") {
             $domain_sys="drbl.sf.net";
           }
	   print "$lang_deploy{\"set_domain_as\"} $domain_sys\n";
        }
        unless ( $nisdomain_sys ) {
           print "$delimiter{\"dash_line\"}\n".
                 "$lang_deploy{\"nisdomain_unset_prompt\"}\n".
	         "[penguinzilla] ";
           while (<STDIN>) {
              chomp;
              $nisdomain_sys=$_;
	      if ( "$nisdomain_sys" =~ / |\/|\\/ ) {
  	        print "\" \" (space), \"/\" or \"\\\" $lang_deploy{\"not_allowed_nisdomainname\"}\n";
              } else {
	        # if empty, use default name
                if ($nisdomain_sys eq "") {
                  $nisdomain_sys="penguinzilla";
                }
	        print "$lang_deploy{\"set_domain_as\"} $nisdomain_sys\n";
                last;
              }
           }
        }
        print "$delimiter{\"dash_line\"}\n".
              "$lang_deploy{\"enter_client_hostname_prefix\"}\n".
	      "[$client_hostname_prefix_default[0]] ";
           while (<STDIN>) {
              chomp;
              $client_hostname_prefix=$_;
	      if ( "$client_hostname_prefix" =~ / |\/|\\/ ) {
  	        print "\" \" (space), \"/\" or \"\\\" $lang_deploy{\"not_allowed_hostname\"}\n";
              } else {
	        # if empty, use default name
                if ($client_hostname_prefix eq "") {
                  $client_hostname_prefix="$client_hostname_prefix_default[0]";
                }
                print "$lang_deploy{\"set_client_hostname_prefix\"} $client_hostname_prefix\n".
                "$delimiter{\"dash_line\"}\n";
                last;
              }
           }
        # try to find all the NIC for clients, i.e. eth1, eth2...
        for($i=0;$i<=$#ethernet_list;$i++) {
	 $ethx="eth"."$ethernet_list[$i]";
   	 if ( -f "$NIC_prefix"."$ethx" ) {
	   # orig script: `/sbin/ifconfig | grep -A1 $ethx | grep -v $ethx | sed 's/^.*inet addr:\([0-9\.]\+\).*$/\1/'`;
	   # Specially, we do not want the alias interface, such as:eth0:1
           my $IP=`/sbin/ifconfig $ethx | grep -A1 $ethx | grep -v $ethx | grep \"inet addr\" | sed 's/^.*inet addr:\\([0-9\\.]\\+\\).*\$\/\\1\/'`;
	   chomp($IP);
	   if ( "$IP" =~ /^192.168.*/ ) {
  	     print "Found private IP \"$IP\" in $ethx on your system!\n";
  	     push @ethernet_sys, $ethx;
           } else {
             print "Found $ethx IP ($IP) in your system, $lang_deploy{\"but_not_private_IP_or_configured\"}\n".
	           "$lang_deploy{\"we_will_skip\"} $ethx!\n";
           }

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

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

# detect the mac address
    print "$delimiter{\"star_line\"}\n".
          "$lang_deploy{\"collect_MAC_prompt\"}\n".
	  "[y/N] ";
    chomp($line=<STDIN>);
    if ($line eq "y" || $line eq "Y" || $line eq "yes" || $line eq "YES") {
     print "$delimiter{\"star_line\"}\n".
           "$lang_deploy{\"ok_let_do_it\"}\n";
     my $whoiam = `/usr/bin/id -nu`;
     chomp($whoiam);
     if ("$whoiam" eq "root") { 
         system("$DRBL_SCRIPT_PATH/sbin/drbl-collect-mac @ethernet_sys");
     }else{
         print "$lang_deploy{\"you_are_not_root\"},\n". 
               "$lang_word{\"please_enter\"} ". colored("$lang_word{\"root_passwd\"} ",'red'). "to collect those MAC addresses...\n"; 
         my $su_rlt=system("su -c \"$DRBL_SCRIPT_PATH/sbin/drbl-collect-mac @ethernet_sys\" root");
         while ($su_rlt == 256) { 
                $su_rlt=system("su -c \"$DRBL_SCRIPT_PATH/sbin/drbl-collect-mac @ethernet_sys\" root");
         }
     } 
    }
    print "$delimiter{\"star_line\"}\n".
          "$lang_deploy{\"ok_let_continue\"}\n".
          "$delimiter{\"star_line\"}\n";

# ask user to input client no.
        for($i=0;$i<=$#ethernet_sys;$i++) {
	 $ethx="$ethernet_sys[$i]";
          my $NIC_sys="/etc/sysconfig/network-scripts/ifcfg-$ethx";
          # Try to get setting from system also
          my $rNIC = read_config("$NIC_sys");
          # get the ipaddress of NIC "eth1, eth2..." 
          my $ip_sys_tmp=$rNIC->{"general"}{"IPADDR"};
          my @ip_sys_sp=split(/\./,$ip_sys_tmp);
          $ip_sys[$i]=$ip_sys_tmp;
          $ip_sys_prefix[$i]="$ip_sys_sp[0].$ip_sys_sp[1].$ip_sys_sp[2]";

  	  print "$lang_deploy{\"fix_eth_IP_prompt\"} ".
	         colored("$ethx",'red').
		 " ?\n".
	  "[y/N] ";
	  chomp($MAC=<STDIN>);
	  if ($MAC eq "y" || $MAC eq "Y" || $MAC eq "yes" || $MAC eq "YES") {
            # user want to fix the IP address for DRBL client 
	    print "$delimiter{\"star_line\"}\n".
	          "$lang_deploy{\"MAC_file_prompt\"} $ethx. (macadr-$ethx.txt) \n";
            while (<STDIN>) {
	      chomp;
	      if ( $_ eq "" ) {
	        $MAC_file[$i]="macadr-$ethx.txt";
	      }else{
	        $MAC_file[$i]=$_;
	      }
              # get the client no from user input
	      # 1st, get the initial value of the last set of digits in the IP address in this subnet
	      print "$delimiter{\"star_line\"}\n".
	            "$lang_deploy{\"IP_start_prompt\"} $ethx.\n",
		    "[1] ";

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

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

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

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

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

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

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

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

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

END_CFG


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

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

END_CFG
	  }
	}

        close(CONFIG_FILE);
	# set mode for more secure
	system("chmod 600 $config_interactive");

	return $config_interactive;
}#end of interactive_mode

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

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

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

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

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

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

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

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

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

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

}


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

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

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

  return( \%HoH );  
}

sub drbl_server_parse {

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

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

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

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

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

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

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

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

  if ( ! $nisdomain ) {
     print "Error! NISDOMAIN is unset!\n"; 
     print "Please set it in config file \"$_[0]\" or $NET_sys.\n";
     exit;
  }
  if ( ! $domain ) {
     print "Error! DOMAIN unset!\n"; 
     print "Please set it in config file \"$_[0]\" or $NET_sys.\n";
     exit;
  }
  #
  if ($localswapfile eq "y" || $localswapfile eq "Y" || $localswapfile eq "yes" || $localswapfile eq "YES") {
      $mkswapfile="mkswapfile";
  }else{
      $mkswapfile="";
  }

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

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

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

  $main_sh="drbl_deploy.sh";
  # file to record the hosts
  $hosts_list="hosts_list.drbl";
  # file to record the public IP for clients
  $public_ip_list="public_ip.drbl";
  # delete the old files
  unlink ($main_sh) if -f $main_sh;
  unlink (dhcpd.conf) if -f dhcpd.conf;
  unlink (dhcpd) if -f dhcpd;
  unlink (hosts) if -f hosts;
  unlink (exports) if -f exports;
  unlink (nfsserver_all) if -f nfsserver_all;
  unlink (yp.conf) if -f yp.conf;
  unlink (securenets) if -f securenets;
  unlink ($hosts_list) if -f $hosts_list;
  unlink ($public_ip_list) if -f $public_ip_list;
  #unlink ($AUTO_LOGIN_ID_PASSWD) if -f $AUTO_LOGIN_ID_PASSWD;

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

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

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



EOF


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

  print DHCPDITF_OUT "DHCPDARGS=\"";

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

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

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

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

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

# Source function library.
. /etc/rc.d/init.d/functions
 
# store the orig LC_ALL, then set it as C
LC_ALL_org=\$LC_ALL
export LC_ALL=C


# global setting
DRBL_SCRIPT_PATH="$DRBL_SCRIPT_PATH"
drbl_setup_path="$drbl_setup_path"
purge_client="$purge_client"
client_root_passwd="$client_root_passwd"
set_client_system_select="$set_client_system_select"
client_system_boot_timeout="$client_system_boot_timeout"

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

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

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

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

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

EOF

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



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

print DISKLESS_OUT q{
# Setting
# 8.0:/etc/issue or /etc/redhat-release: Red Hat Linux release 8.0 (Psyche)
# 9.0:/etc/issue or /etc/redhat-release: Red Hat Linux release 9 (Shrike)
# FC1:/etc/fedora-release: Fedora Core release 1 (Yarrow)
# FC2:/etc/fedora-release: Fedora Core release 2 (Tettnang)
# $OS_Version will be the index for rc.sysinit
echo
echo "******************************************************"
grep "Red Hat Linux release 8.0 (Psyche)" /etc/redhat-release 2>/dev/null && OS_Version="RH8.0"
grep "Red Hat Linux release 9 (Shrike)" /etc/redhat-release 2>/dev/null && OS_Version="RH9"
grep "Fedora Core release 1 (Yarrow)" /etc/fedora-release 2>/dev/null && OS_Version="RHFC1"
grep "Fedora Core release 2 (Tettnang)" /etc/fedora-release 2>/dev/null && OS_Version="RHFC2"
grep "Mandrake Linux release 9.2 (FiveStar) for i586" /etc/mandrake-release 2>/dev/null && OS_Version="MDK9.2"
grep "Mandrake Linux release 10.0 (Community) for i586" /etc/mandrake-release 2> /dev/null && OS_Version="MDK10.0"
grep "Mandrake Linux release 10.0 (Official) for i586" /etc/mandrake-release 2> /dev/null && OS_Version="MDK10.0"
echo "******************************************************"
if [ -z "$OS_Version" ]; then
  echo "Can NOT determine the Linux version number you are using!!!"
  echo "Please enter the version number..."
  read OS_Version
  case "$OS_Version" in
  RH8|RH8.0|RH9|RH9.0)
              echo "The version number you entered is $OS_Version."
              ;;
  "RHfc1"|"RHFC1"|"Fedora Core 1"|"RHfc2"|"RHFC2"|"Fedora Core 2")
              echo "The version number you entered is $OS_Version."
              ;;
  "MDK9.2"|"mdk9.2"|"MDK10.0")
              echo "The version number you entered is $OS_Version."
              ;;
  *)
              echo "$OS_Version is not supported version, program stop!."
	      echo "Please press ctrl-c to stop the program!"
	      exit 1 
  esac
fi
echo "The version number for your Linux: $OS_Version"

};

print DISKLESS_OUT <<EOF;

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

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

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

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

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

# Note!!! For rsync, do NOT to append "/" in the /sbin, .i.e. NO /sbin/
rsync -a /sbin /tftpboot/node_root/

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

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

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

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

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

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

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

# copy /etc to template node
echo -n "."
rsync -a /etc /tftpboot/node_root

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

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

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

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


EOF

print DISKLESS_OUT q{

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

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

   case "\$OS_Version" in
     RH8.0|RH9|RHFC1|RHFC2)
       service_added="netfs portmap crond nfslock sshd crond xfs ypbind kudzu firstboot $mkswapfile"
       ;;
     MDK9.2|MDK10.0)
       service_added="netfs portmap crond nfslock sshd crond xfs ypbind firstboot harddrake dm alsa sound keytable $mkswapfile"
       ;;
   esac

EOF

print DISKLESS_OUT q{
   for i in $service_added; do
      /usr/sbin/chroot /tftpboot/node_root/ /sbin/chkconfig --add $i
   done

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

   # create an automatically X config program, if you like, but for Redhat 8.0,
   # better to use Redhat 8.0's /etc/init.d/firstboot
   # First, clean the XF86Config, 
   # let redhat-cfg-xfree86 in /etc/init.d/firstboot
   # to create the first one.

   if [ -n "$vmware_as_server" ]; then
     [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
     echo "It's VMWare as DRBL server ..., If you want to use X Window, make sure you already installed VMWare tools."
     [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
   fi
   # Remove XF86Config in common root
   [ -f /tftpboot/node_root/etc/X11/XF86Config ] && rm -f /tftpboot/node_root/etc/X11/XF86Config*
   
   RH_version=`grep 7.3 /etc/issue`
   # RH7.3 has no firstboot, so we add a service setupx to do that.
   if [ "$RH_version" != "" ]; then
     tar xzf $drbl_setup_path/files/setupx_redhat.tgz -C /tftpboot/node_root/etc/rc.d
     # enable the setupx for this template
     /usr/sbin/chroot /tftpboot/node_root /sbin/chkconfig --add setupx
   fi
   
   # remove the script in rc[0,6].d to let the client can halt and reboot
   drbl_client_must_remove="netfs network killall"
   for i in $drbl_client_must_remove
   do 
      rm -f /tftpboot/node_root/etc/rc0.d/*$i*
      rm -f /tftpboot/node_root/etc/rc6.d/*$i*
   done
   
   # remove the etc/modules.conf in template
   MOD_sys=$(find /tftpboot/node_root/etc/ -name "modules.conf*" -print)
   [ -n "$MOD_sys" ] && rm -f /tftpboot/node_root/etc/modules.conf*
   touch /tftpboot/node_root/etc/modules.conf

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

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

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

   # copy dev tarball to /tftpboot/node_root/etc/diskless-image
   drbl_pkgdir="/opt/drbl/share/"
   if [ -f $drbl_pkgdir/dev.tgz ]; then
     cp -f $drbl_pkgdir/dev.tgz /tftpboot/node_root/etc/diskless-image
   else
     [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
     echo "Can NOT find the dev.tgz, did you already setup the DRBL server ?"
     echo "Please press Ctrl-C to stop the program!"
     [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
     read
     exit 1 
   fi
};

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

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

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

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

CONFIG_END

# for clients' public IP 
if [ -f "$public_ip_list" ]; then
  cp -f $public_ip_list /tftpboot/node_root/etc/diskless-image/
fi

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

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

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

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

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

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

touch /var/lock/subsys/local

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

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

RC_LOCAL

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

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

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

# set the boot prompt for clients if set
case "\$set_client_system_select" in
   y|Y|[yY][eE][sS])
      $DRBL_SCRIPT_PATH/sbin/drbl-client-system-select -t \$client_system_boot_timeout on
      ;;
   n|N|[nN][oO])
      $DRBL_SCRIPT_PATH/sbin/drbl-client-system-select off
      ;;
esac

EOF

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

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

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

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

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

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

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

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

};

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

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

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

};

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

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

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

echo "done!"
};


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

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

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

    if ( ! $nfsserver ) { 
     $nfsserver = $nfsserver_sys; 
     print "* nfsserver is not set in config file, \nthe one \"$nfsserver\" got from system will be used.\n" if $verbosity >= 2;   
    }
    if ( ! $bootserver ) { 
     $bootserver = $bootserver_sys; 
     print "* bootserver is not set in config file, \nthe one \"$bootserver\" got from system will be used.\n" if $verbosity >= 2;   
     ot
    }
    if ( ! $nisserver ) { 
     $nisserver = $nisserver_sys; 
     print "* nisserver is not set in config file, \nthe one \"$nisserver\" got from system will be used.\n" if $verbosity >= 2;   
    }
    
    # Last check if the values are set in config file or system  
    unless ( $hostname ) {
       print "Error! HOSTNAME is unset!\n";
       print "Please set hostname in config file \"$_[0]\" or HOSTNAME in $NIC_sys.\n";
       exit;
    }
    unless ( $nfsserver ) {
       print "Error! NFSSERVER is unset!\n";
       print "Please set nfsserver in config file \"$_[0]\" or IPADDR in $NIC_sys.\n";
       exit;
    }
    unless ( $bootserver ) {
       print "Error! BOOTSERVER is unset!\n";
       print "Please set bootserver in config file \"$_[0]\" or IPADDR in $NIC_sys.\n";
       exit;
    }
    unless ( $nisserver ) {
       print "Error! NISSERVER is unset!\n";
       print "Please set nisserver in config file \"$_[0]\" or IPADDR in $NIC_sys.\n";
       exit;
    }
    #---------------
    # warring
    #    unless ($interface && $network && $nfsserver && ($mac||$range) && $hostname ) 
    #{
    #  print "WARNING: the configuration in block [$k1] is incorrect\n";
    #  print "following is your configuration:\n";
    #  print "[$k1]\n";
    #  print "interface=$interface\n";
    #  print "network=$network\n";
    #  print "nfsserver=$nfsserver\n";
    #  print "bootserver=$bootserver\n";
    #  print "nisserver=$nisserver\n";
    #  print "nbi=$nbi\n";
    #  print "mac=$mac\n";
    #  print "range=$range\n";
    #  print "hostname=$hostname\n";
    #  next ;
    #}

    # go 
    @nfsserverIp=split(/\./,$nfsserver);
    @networkIp=split(/\./,$network);

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

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

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

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

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

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

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

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

        # generate dhcpd.conf      
	if ( ! $nbi ) {
	  # without nbi set in config file
          print DHCPD_OUT <<EOF;
    host $label {
        hardware ethernet  $_;
        fixed-address $ip;
    }
EOF
	}else{
  	  # without nbi set in config file
          print DHCPD_OUT <<EOF;
    host $label {
        hardware ethernet  $_;
        fixed-address $ip;
        filename "$nbi";
    }
EOF
        }
      } elsif( length($range)!=0 ) { # range
        $ip=$_;
      }
      else {}
      
      # generate hosts
      print HOSTS_OUT <<EOF;
$ip $label.$domain $label
EOF
      # append the hosts to hosts_list
      print HOSTS_LIST_OUT <<EOF;
$ip
EOF
      # generate exports
      print EXPORTS_OUT <<EOF;
/tftpboot/node_root $ip(ro,sync,async,no_root_squash)
/tftpboot/nodes/$ip/ $ip(rw,sync,async,no_root_squash)
/usr $ip(ro,sync,async,no_root_squash)
/opt $ip(ro,sync,async,no_root_squash)
/home $ip(rw,sync,async,no_root_squash)
/var/spool/mail $ip(rw,sync,async,root_squash)

EOF

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

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

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

# must have some dev for initrd when boot
cp -a /dev/console /dev/null /dev/tty[0-5] /tftpboot/nodes/$ip/dev

# output the file to $ip/etc/fstab

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

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

HOSTNAME_END

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

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

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

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

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

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

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

EOF

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


      # next one
      $i++;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# process the special case... for specific OS_Version
case "$OS_Version" in
    "RH9"|"RH9.0")
     # for RH9, NFS with tcp seems to be buggy... I can NOT solve it... so
     # force to use udp instead of the default tcp.
     echo "For RH9, NFS is buggy with tcp, so change to udp now..."
     $DRBL_SCRIPT_PATH/sbin/drbl-nfs-conf --protocol udp
    ;;
esac

#restore the old LC_ALL
export LC_ALL=$LC_ALL_org

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

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

  print DHCPDITF_OUT "\"";

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


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

} # end of the drbl_server_parse

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

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

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

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

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

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

if ("$action" eq "create_config_file") {
        print "$delimiter{\"dash_line\"}\n".
	      "$lang_deploy{\"interactive_mode_prompt\"}\n".
              "$delimiter{\"dash_line\"}\n";
        $config_file=interactive_mode("config.interactive");
}
unless ( $config_file ) { die "$usage\n"; }

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

# set public IP for client
print "$delimiter{\"dash_line\"}\n".
      "$lang_deploy{\"set_client_alias_IP\"}\n".
      "[y/N] ";
chomp($line=<STDIN>);
if ($line eq "y" || $line eq "Y" || $line eq "yes" || $line eq "YES") {
  print "$delimiter{\"star_line\"}\n".
        "OK! Let's do it!\n".
        "$delimiter{\"dash_line\"}\n";
  set_client_public_ip("$hosts_list","$public_ip_list");
}

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

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

# ready to go
if ( $no_deploy ) { 
	print "$delimiter{\"warning_line\"}\n".
	      "$lang_deploy{\"no_deploy_prompt\"}\n";
}
else {
	print "$delimiter{\"star_line\"}\n".
	      "$lang_deploy{\"ready_to_deploy\"}\n".
	      colored ("$lang_deploy{\"overwrite_firewall_rule\"}\n", 'red').
	      colored ("$lang_deploy{\"backup_firewall_rule\"}\n", 'red').
	      "[Y/n] ";
	chomp($line=<STDIN>);
	if ($line eq "n" || $line eq "N" || $line eq "no" || $line eq "NO") {
	 print "$delimiter{\"exclamation_line\"}\n".
	       "$lang_deploy{\"oh_quit_now\"}\n";
	 exit(1);
         unlink ($main_sh) if -f $main_sh;
	} else {
	 print "$delimiter{\"star_line\"}\n".
               "$lang_deploy{\"ok_let_do_it\"}\n";
         my $whoiam = `/usr/bin/id -nu`;
	 chomp($whoiam);
	 if ("$whoiam" eq "root") { 
	     system("./$main_sh");
         }else{
             print "$lang_deploy{\"you_are_not_root\"},\n". 
	           "$lang_word{\"please_enter\"} ". colored("$lang_word{\"root_passwd\"} ",'red') ."$lang_word{\"to_deploy_them\"}...\n"; 
	     my $su_rlt=system("su -c ./$main_sh root");
	     while ($su_rlt == 256) { 
	            $su_rlt=system("su -c ./$main_sh root");
	     }
         } 
        }
}

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