#!/bin/bash
#
# Function to display/select/kill a session
#
LOC_FILE="/tmp/wout.`/bin/date +\"%s\"`"
TR=/usr/bin/tr
CUT=/usr/bin/cut
AWK=/bin/awk
PS=/bin/ps
NETSTAT=/bin/netstat
GREP=/bin/grep
CAT=/bin/cat
RM=/bin/rm

killSession() {
	i=$1
	sessionFlag="VALID"
	typeset -i HungSessionRange=$SessionsCount+$HungSessionsCount
	if [ $i -lt $SessionsCount ] ; then
		devptsnode="/dev/${t_a[i]}"
		sessionFlag="VALID"
	elif [ $i -lt $HungSessionRange ] ; then
		ptsnode="pts/${t_a_hungs[$i-$SessionsCount]}"
		devptsnode="/dev/$ptsnode"
		sessionFlag="HUNGSESSION"
		typeset -i arrayindex=$i-$SessionsCount
	else
		sessionFlag="HUNGPROCESS"
		typeset -i arrayindex=$i-$SessionsCount-$HungSessionsCount
	fi
	if [ "$sessionFlag" != "HUNGPROCESS" ] ; then
		/sbin/fuser -v $devptsnode >${LOC_FILE}
		fuserResult=$?
		if [ $fuserResult -ne 0 ]
	    	then
			printf "\nPermission Denied! Bailing Out!\n"
			exit
		fi
	fi
		printf "\n______________________________________________________________________________\n"
		printf " USER     TTY      IDLE     LOGIN@ FROM\n"
		printf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
	if [ "$sessionFlag" == "VALID" ] ; then
		printf " %-8.12s %-8.12s %-8.12s %-6.12s %-16.128s\n" \
	    	"${u_a[i]}" "${t_a[i]}" "${i_a[i]}" "${l_a[i]}" "${f_a[i]}"
	elif [ "$sessionFlag" == "HUNGSESSION" ] ; then
	  	printf " %-8.12s %-8.12s %-8.12s %-6.12s %-16.128s\n" \
	      	"N/A" "$ptsnode" "N/A"  "N/A"  "${t_f_hungs[$arrayindex]}"
		#printf "Hung Session : $devptsnode\n"
	else
	
	  	printf " %-8.12s %-8.12s %-8.12s %-6.12s %-16.128s\n" \
	      	"N/A" "${p_ty[$arrayindex]}" "N/A" "N/A" "${p_from[$arrayindex]}"
			
	fi
		printf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
	printf "Confirm Kill Session (Y/[N]): "
	read choice
	case $choice in
	    (Y|y|Yes|yes|YES) printf "\nKilling Session...."
		if [ "$sessionFlag" == "HUNGPROCESS" ]; then
			kill ${p_pr[$arrayindex]} 1>/dev/null 2>$1
		else	
		/sbin/fuser -k -9 $devptsnode 1>/dev/null 2>&1
		fi
		/bin/sleep 1s
		printf "  Done!\n"
		if [ "$sessionFlag" != "HUNGPROCESS" ]; then
			errlogtest -i "SEC-3082" -a $devptsnode
		fi
		;;
	    (*)printf "NOT confirmed - No action taken\n" exit ;;
	esac
}

# Function to list a list of sessions showing marks, if any
listSessions() {
	if [ $SessionsCount -eq 0 ]
	    then
		printf "No sessions found!\n"
		exit
	fi
	printf "\n\n                   List of sessions (%d found)\n" $SessionsCount
	printf "______________________________________________________________________________\n"
	printf " Session No   USER     TTY      IDLE     LOGIN@ FROM\n"
	printf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
	typeset -i i=0 SessionCount
	while [ $i -lt "$SessionsCount" ]
	  do
	  printf " %5d        %-8.12s %-8.12s %-8.12s %-6.12s %-16.128s\n" \
	      $i  "${u_a[i]}" "${t_a[i]}" "${i_a[i]}" "${l_a[i]}" "${f_a[i]}"
	  i=i+1
	done
	printf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
	if [ "$HungSessionsCount" -gt "0" -o "$HungProcessesCount" -gt "0" ] ; then

		printf "                   List of possible hung sessions\n"
		printf "______________________________________________________________________________\n"
		typeset -i h=0
		while [ $h -lt "$HungSessionsCount" ]
		do
			printf " %5d       N/A        pts/%d	 N/A    N/A	%-16.128s\n" "$i" "${t_a_hungs[$h]}" "${t_f_hungs[$h]}"
			h=h+1
			i=i+1
		done
		typeset -i hp=0
		while [ "$hp" -lt "$HungProcessesCount" ]
		do
	  		#printf " %5d        %-8.12s %-8.12s %-8.12s %-6.12s\n" \
	      		#$i  "${p_pr[$hp]}" "${p_ty[$hp]}" "${p_tm[$hp]}"
			printf " %5d       N/A        %-8.12s  N/A   N/A   %-16.128s\n" "$i" "${p_ty[$hp]}" "${p_from[$hp]}"
			hp=hp+1
			i=i+1
		done
		printf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
	fi	
}

#
# Function to get the sessions and store them in an arry
#

getSessions() {
	printf "\nCollecting login information...."
	SessionsCount=0
	typeset -i i=0 
	/usr/bin/w -f > ${LOC_FILE}

	{
		read uptime_details
		read column_headers
		while read u_a[$i] t_a[$i] f_a[$i] l_a[$i] i_a[$i] j_a[$i] p_a[$i] c_a[$i]
		    do
			i=i+1
		done 
	} < ${LOC_FILE}

	SessionsCount=$i
#listing the hung session if any 
	HungSessionsCount=0
	typeset -i j=0 
	/bin/ls -1 /dev/pts/ > ${LOC_FILE}
	{
		while read t_a_numbers[$j]
		do
			j=j+1
		done 
	} < ${LOC_FILE}
	AllSessionsCount=$j
	typeset -i j=0
	typeset -i h=0
	while [ $j -lt $AllSessionsCount ]
	  do
		typeset -i i=0 
		while [ $i -lt $SessionsCount ]
		do
			# compare if any /dev/pts not listed as part of w/who command is considered as hung session 
			if [ "pts/${t_a_numbers[$j]}" == ${t_a[$i]} ]
			then
				break
			fi
			i=i+1
			if [ $i -eq $SessionsCount ] 
			then
				t_a_hungs[$h]=${t_a_numbers[$j]}
				associatepid=`/sbin/fuser /dev/pts/${t_a_hungs[$h]} | $AWK '{ print $2}'`
				associatedppid=`$PS -f $associatepid | $AWK 'NR > 1 { print $3}'`
				associatedfromip=`$NETSTAT -anp | $GREP "$associatedppid/" | $AWK '{ print $5}' | $CUT -d ':' -s -f1`
				t_f_hungs[$h]=$associatedfromip
				h=h+1
			fi
		done
	  	j=j+1
	done
	HungSessionsCount=$h

# Get hung sessions which become when pts is not associated with the process but the command line 

#!/bin/sh
SAVE_FILE=/tmp/Savefile
TEMP_FILE=/tmp/Tempfile
TEMP_FILE1=/tmp/Tempfile1
HungProcessesCount=0
typeset -i i=0
# List the all pids running as sshd or in.telnetd
$PS -C sshd | $AWK 'NR > 1 { print $1 }' > ${SAVE_FILE}
$PS -C in.telnetd | $AWK 'NR > 1 { print $1 }' >> ${SAVE_FILE}
{
	while read pid 
	do
        if [ -d "/proc/$pid/fd" ]; then
		/bin/ls -l /proc/$pid/fd | $GREP '/dev/ptmx' > ${TEMP_FILE}
		if [ -s ${TEMP_FILE} ] ; then
			#if content si present means valid pts is attached this process
			continue
		else
			cmdline=`$CAT /proc/$pid/cmdline`
			#Check if scp session established and ignore and not list part of hung sessions
			if [ "$cmdline" == "sshd: root@notty" ] ; then
				continue
			elif [ "$cmdline" == "/usr/sbin/sshd" ] ; then
				#This process pid is ssh service so returning.
				continue
			else
			# this is consider as hung process since ptmx is not present 
			#but command line present. 
			$PS -p $pid > ${TEMP_FILE1}
        		{
                		read header
                		while read p_pr[$i] p_ty[$i] p_tm[$i] p_cm[$i]
                    		do
					p_from[$i]=`$NETSTAT -anp | $GREP "${p_pr[$i]}/" | $AWK '{ print $5}' | $CUT -d ':' -s -f1`
                        		i=i+1
                		done
     		   	} < ${TEMP_FILE1}
			fi
		fi
        fi
	done

} < ${SAVE_FILE} 
HungProcessesCount=$i
# Remove temparary files"
$RM -f ${SAVE_FILE}
$RM -f ${TEMP_FILE}
$RM -f ${TEMP_FILE1}

}

# main starts here (keep bugging the user until s/he decides to quit)

while :
    do
	getSessions
	listSessions
	printf "\nPlease verify the Session details and Enter a Number to terminate (q to quit) "
	read choice
	case $choice in
	    (Q|q) exit ;;
	    (""|*[!0-9]*) printf "Please enter a number\n" >&2 ;;
	    (*)
	    if [ $choice -lt 0 -o $choice -ge $((SessionsCount+HungSessionsCount+HungProcessesCount)) ]
		then
		    printf "Please enter a value between 0 and $((SessionsCount+HungSessionsCount+HungProcessesCount-1))\n"
	    else
	
		    killSession $choice
	    fi
	esac
done # main while
#remove temparary files 
