#!/bin/bash
# Steven Shiau <steven@nchc.org.tw>
# License: GPL
# Description: To set the login mode for DRBL clients

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

#
PWD_NO_0_1_MSG="Note!!! To avoid confusing, the random password does NOT contain digit 0 (zero) and digit 1 (one)!!!"

#
usage() {
  echo "Switch the login mode for DRBL clients."
  echo "Usage: $0 [-n|--normal] [-a|--auto] [-t|--timed TIMED_LOGIN_TIME] [-h|--host IP_ADDRESS] [-u|--no_nis_update] [-v|--verbose ] [-p|--password_opt PASSWORDD_OPT]"
  echo "-n, --normal: normal login for clients"
  echo "-a, --auto:   auto login for clients"
  echo "-t, --timed:  timed login within time TIMED_LOGIN_TIME (sec)"
  echo "-h, --host IP_ADDRESS:  set login mode ony for the host with IP_ADDRESS instead of all DRBL clients"
  echo "-u, --no_nis_update:  do NOT run NIS update"
  echo "-p, --password_opt: the password option for auto and timed login."
  echo "-v, --verbose:  verbose mode."
  echo "PASSWORD_OPT:"
  echo "If one digit, it's the length of randomly created password."
  echo "If blank, it will be randomly generated with some (say:8) characters."
}

#
check_if_root

set_gdm_auto_login() {
    local inode="$1"
    if [ ! -f $inode/$GDM_CFG ]; then
      [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING 
      echo "$inode/$GDM_CFG is NOT found!!!"  
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    fi
    #echo -n "Setting node `basename $inode`..."
    # disable other types login, i.e. timed login
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*TimedLoginEnable=.*/TimedLoginEnable=false/" $inode/$GDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*TimedLogin=.*/TimedLogin=/" $inode/$GDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*TimedLoginDelay=.*/TimedLoginDelay=/" $inode/$GDM_CFG
    # set auto login enable
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*AutomaticLoginEnable=.*/AutomaticLoginEnable=true/" $inode/$GDM_CFG
}

set_gdm_timed_login() {
    local inode="$1"
    local tlogin_time="$2"
    # set the timed login time
    [ -z "$tlogin_time" ] && tlogin_time="$TIMED_GDM_TIME_DEFAULT"

    #echo -n "Setting node `basename $inode`..."
    # disable other types login, i.e. auto login
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*AutomaticLoginEnable=.*/AutomaticLoginEnable=false/" $inode/$GDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*AutomaticLogin=.*/AutomaticLogin=/" $inode/$GDM_CFG
    # set timed login
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*TimedLoginEnable=.*/TimedLoginEnable=true/" $inode/$GDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*TimedLoginDelay=.*/TimedLoginDelay=$tlogin_time/" $inode/$GDM_CFG
}

set_gdm_normal_login() {
    local inode="$1"
    #echo -n "Setting node `basename $inode`..."
    # disable auto and timed login
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*AutomaticLoginEnable=.*/AutomaticLoginEnable=false/" $inode/$GDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*AutomaticLogin=.*/AutomaticLogin=/" $inode/$GDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*TimedLoginEnable=.*/TimedLoginEnable=false/" $inode/$GDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*TimedLogin=.*/TimedLogin=/" $inode/$GDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*TimedLoginDelay=.*/TimedLoginDelay=/" $inode/$GDM_CFG
}

set_kdm_auto_login() {
    local inode="$1"
    if [ ! -f $inode/$KDM_CFG ]; then
      [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING 
      echo "$inode/$KDM_CFG is NOT found!!!"  
      [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    fi
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*AutoLoginEnable=.*/AutoLoginEnable=true/" $inode/$KDM_CFG
    perl -p -i -e "s/^[[:space:]]*#*[[:space:]]*AutoLoginUser=.*/AutoLoginUser=$auto_login_id/" $inode/$KDM_CFG
#	   #
#           cat <<-AUTOLOGIN_END > $inode/$SYSCONF_PATH/autologin
#USER=$auto_login_id
#AUTOLOGIN=yes
#AUTOLOGIN_END
}

#
create_autologin_account() {
    local ihost="$1"
    # $auto_login_id and $echo_no_digit_0_1 are global variables
    # auto login username is set as hostname
    if [ -e /etc/debian_version ]; then
      # Debian
      auto_login_id="$(cat $ihost/etc/hostname)"
    elif [ -e /etc/SuSE-release ]; then
      # SuSE
      auto_login_id="$(cat $ihost/etc/HOSTNAME | sed -e "s/\..*//g")"
    else
      # RH-like
      . $ihost/$SYSCONF_PATH/network
      auto_login_id="$HOSTNAME"
    fi
    [ -z "$auto_login_id" ] && echo "Unable to get client's hostname! Program terminated!!!" && exit 1
    if ! grep -q $auto_login_id /etc/passwd ; then
      # account $auto_login_id not exists, create it.
           create_account=1
           # echo the message $PWD_NO_0_1_MSG in the file $AUTO_LOGIN_ID_PASSWD
	   # if not existing.
           if [ -z "`grep $PWD_NO_0_1_MSG  $AUTO_LOGIN_ID_PASSWD 2>/dev/null`" ]; then
     	     [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING 
     	     echo $PWD_NO_0_1_MSG | tee -a $AUTO_LOGIN_ID_PASSWD
             [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
           fi
           echo_no_digit_0_1=1
           echo -n "Creating account $auto_login_id..."
           echo "The password_opt is set as \"$password_opt\"" 
           /usr/sbin/useradd -m $auto_login_id

           # set the passwd
           case "$password_opt" in
            [0-9]|"")
               # get one digit, so it must be the length of password
               # or it's empty, we set it as $password_opt_default
               if [ -z "$password_opt" ]; then
                 echo "You did NOT set the length of password, set it as $PASSWD_LENGTH_DEFAULT." 
                 password_opt="$PASSWD_LENGTH_DEFAULT"
               fi
               echo "Randomly set password from password length..." 
               if [ -x "$rand_pw_exec_file" ]; then
                 passwd_now=`$rand_pw_exec_file $password_opt`
               else
                 echo "No random password generating script!"
               fi
               #echo "The password of $auto_login_id is \"$passwd_now\""
               echo "$auto_login_id:$passwd_now" | /usr/sbin/chpasswd
               ;;
            *)
               echo "Set password from input..." 
               #echo "The password of $auto_login_id is \"$password_opt\""
     	       passwd_now="$password_opt"
               echo "$auto_login_id:$passwd_now" | /usr/sbin/chpasswd
           esac  
           echo "$auto_login_id $passwd_now" >> $AUTO_LOGIN_ID_PASSWD
    fi
}

clean_old_auto_login_id_passwd_file() {
    local AUTO_LOGIN_ID_PASSWD="$1"
    local ihost="$2"
    # use client's hostname as the auto-login ID.
    if [ -e /etc/debian_version ]; then
      # Debian
      auto_login_id="$(cat $ihost/etc/hostname)"
    elif [ -e /etc/SuSE-release ]; then
      # SuSE
      auto_login_id="$(cat $ihost/etc/HOSTNAME | sed -e "s/\..*//g")"
    else
      # RH-like
      . $ihost/$SYSCONF_PATH/network
      auto_login_id="$HOSTNAME"
    fi
    [ -z "$auto_login_id" ] && echo "Unable to get client's hostname! Program terminated!!!" && exit 1
    # clean the old file
    if [ -f "$AUTO_LOGIN_ID_PASSWD" ]; then
      if grep -q $auto_login_id $AUTO_LOGIN_ID_PASSWD; then
     	[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING 
        echo "Found the old file \"$AUTO_LOGIN_ID_PASSWD\", rename it as \"$AUTO_LOGIN_ID_PASSWD.drblsave\""
        [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
	mv $AUTO_LOGIN_ID_PASSWD $AUTO_LOGIN_ID_PASSWD.drblsave
      fi
    fi
}

#
output_result_and_update_yp() {
    # $create_account and $no_nis_update are global variables
    if [ "$create_account" -gt 0 ]; then
             [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING 
	     echo "The created ID and password are in $AUTO_LOGIN_ID_PASSWD, please backup this file."
             #echo $PWD_NO_0_1_MSG | tee -a $AUTO_LOGIN_ID_PASSWD
             [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
             # update the NIS
             [ "$no_nis_update" != "on" ] && make -C /var/yp
    fi
}
     
# main
# set the flag for create account and echo prompt
create_account=0
echo_no_digit_0_1=0
     
while [ $# -gt 0 ]; do
  case "$1" in
    -n|--normal)
		shift; login_dm_mode="normal_login"
                ;;
    -a|--auto)
		shift; login_dm_mode="auto_login"
                ;;
    -t|--timed)
		shift; login_dm_mode="timed_login"
                if [ -z "$(echo $1 |grep ^-.)" ]; then
                  # skip the -xx option, in case 
		  timed_login_time="$1"
		  shift
                fi
                ;;
    -h|--host)
		shift; specified_host="$1"
		shift
                ;;
    -v|--verbose)
		shift; verbose="on"
                ;;
    -u|--no_nis_update)
		shift; no_nis_update="on"
                ;;
    -p|--password_opt)
		shift; password_opt="$1"
		shift
                ;;

    -*)		echo "${0}: ${1}: invalid option" >&2
		usage >& 2
		exit 2 ;;
    *)		break ;;
  esac
done

# check if the mode is set or net 
[ -z "$login_dm_mode" ] && usage && exit 1


#
if [ -n "$specified_host" ]; then
 [ ! -d "$drblroot/$specified_host" ] && echo "Can NOT find DRBL client $specified_host (i.e. no $drblroot/$specified_host)! Program terminated!" && exit 1
 [ -n "$verbose" ] && echo "specified_host: $specified_host"
fi

# set the login option for GDM
 [ -n "$verbose" ] && echo -n "The GDM login option: $login_dm_mode..."

# set the host to be processed
# host_list is the IP address of client, like 192.168.1.1...
host_list=""
if [ -n "$specified_host" ]; then
   # set the host path
   host_list=$drblroot/$specified_host
else
   # withoud specified_host, it must be all clients, append each one to $host_list
   for ihost in $drblroot/*; do
     host_list="$host_list $ihost"
   done
fi

RC=""
preferred="$($DRBL_SCRIPT_PATH/bin/check_dm)"
RC=$?

[ $RC -eq 0 ] && echo "The display manager we selected for your DRBL client is \"$preferred\"..."

#
case "$preferred" in
   gdm)
    #
    for ihost in $host_list; do
     case "$login_dm_mode" in
       "auto_login"|"timed_login")
     
     	    case "$login_dm_mode" in
     	      "auto_login")
     	         set_gdm_auto_login $ihost
                 echo -n "Setting node `basename $ihost` as auto_login..."
     	         ;;
     	      "timed_login")
     	         set_gdm_timed_login $ihost $timed_login_time
                 echo -n "Setting node `basename $ihost` as timed_login..."
     	         ;;
     	    esac
     
            # clean the old file
            clean_old_auto_login_id_passwd_file $AUTO_LOGIN_ID_PASSWD $ihost

	    # create auto login account if necessary
	    create_autologin_account $ihost

	    # set the mode for $AUTO_LOGIN_ID_PASSWD as root access only
	    [ -f "$AUTO_LOGIN_ID_PASSWD" ] && chmod 600 $AUTO_LOGIN_ID_PASSWD

     	    # set the login account
     	    case "$login_dm_mode" in
     	      "auto_login")
                      # set auto login account
                      perl -p -i -e "s/^AutomaticLogin=.*/AutomaticLogin=$auto_login_id/" $ihost/$GDM_CFG
     	         ;;
     	      "timed_login")
                      # set timed login account
                      perl -p -i -e "s/^TimedLogin=.*/TimedLogin=$auto_login_id/" $ihost/$GDM_CFG
     	         ;;
     	    esac

     	    echo "done!"
       ;;
       "normal_login")
               echo -n "Setting node `basename $ihost` as normal_login..."
     	       set_gdm_normal_login $ihost
     	       echo "done!"
        ;;
     esac
     
    done
    # output result and update yp
    output_result_and_update_yp
  ;;
  kdm|mdkkdm)
     # No timed_login for KDE... only auto_login or nornam_login
     [ "$login_dm_mode" = "timed_login" ] && echo "No timed login for KDE... only auto login or normal login, so set it as auto login..."
     for ihost in $host_list; do
       case "$login_dm_mode" in
         "auto_login"|"timed_login")
           
           echo -n "Setting node `basename $ihost` as auto_login..."
     
           # clean the old file
           clean_old_auto_login_id_passwd_file $AUTO_LOGIN_ID_PASSWD $ihost
	   # create auto login account if necessary
	   create_autologin_account $ihost
	   # set the mode for $AUTO_LOGIN_ID_PASSWD as root access only
	   [ -f "$AUTO_LOGIN_ID_PASSWD" ] && chmod 600 $AUTO_LOGIN_ID_PASSWD

           set_kdm_auto_login $ihost

           echo "done!"
         ;;
         "normal_login")
           echo -n "Setting node `basename $ihost` as normal_login..."
           [ -f "$ihost/$SYSCONF_PATH/autologin" ] && rm -f $ihost/$SYSCONF_PATH/autologin
           echo "done!"
	 ;;
       esac
     done
     # output result and update yp
     output_result_and_update_yp
  ;;
esac
