From: lpeters@postmaster@hq.af.mil (Leslie D Peters)
Newsgroups: comp.unix.shell
Subject: Re: zapuser script questions
Keywords: How do I remove last argument from a variable?
Date: 21 Dec 92 13:27:07 GMT
Reply-To: lpeters@marge.hq.af.mil
Organization: 7th Communications Group

Here is a script that I hacked up to handle terminating user sessions
on our systems.   The first file is the routines that perform the
display and kill functions.  The second file is a front end to the
first.
-----CUT HERE-----     -----CUT HERE-----     -----CUT HERE-----
#! /bin/ksh
#
# File ID: T3
#
# Version: 3.1
# Date: 16 Dec 92
# Author(s): Peters
#
# Purpose: to provide an option-oriented user session terminator
#
# Usage: T3 -l   : list current user sessions
#           -d n : display process tree for session n
#           -k n : terminate session n by killing Shell process
#           -c n : terminate session n by killing children of the
#                    Shell process first, then the Shell process
#
# Changes:
#
# V3.0: Initial release - 15 Dec 92 - ldp
# V3.1: modified user interface - 16 Dec 92 - ldp
#
#****************************************************************

usage() {
   echo " Usage: T3 -l   : list current user sessions";
   echo "           -d n : display process tree for session n";
   echo "           -k n : terminate session n by killing Shell process";
   echo "           -c n : terminate session n by killing children of the";
   echo "                    Shell process first, then the Shell process";
   return;
}

single_space() {
   /bin/awk '{for (i=1;i<=NF;i++) printf("%s ", $i); printf("\n")}' -
}

list_sessions() {
   echo "Number of users: \c"
   who -u | /bin/awk '$1 ~ /[a-z]+/ { print $1 }' | sort | uniq | wc -l
   echo "Number of sessions: \c"
   who -u | /bin/awk '$1 ~ /[a-z]+/ { print $1 }' | sort | wc -l
   echo "\n              Idle          Shell   ---Login---"
   echo " # User     S Time  Line     PID    Date   Time"
   echo "-----------------------------------------------"
   /bin/who -u | \
    /bin/awk '$1 ~ /[a-z]+/ \
       { printf("%s:%s:%s:%d:%s:%02d%s\n",$1,$6,$2,$7,$5,$4,$3)}' | \
    sort | \
      /bin/awk -F':' '\
      {
         session[$1]++;
         x = session[$1];
   
         if ( $2 == "." )
         {
            time[$1, x] = "0:00";
            tty[$1, x] = $3;
            rpid[$1, x] = $4;
            lhr[$1, x] = $5;
            lmn[$1, x] = $6;
            ldt[$1, x] = $7;
         }
         else
         {
            if ( $2 == "old" )
            {
               time[$1, x] = "old";
               tty[$1, x] = $3;
               rpid[$1, x] = $4;
               lhr[$1, x] = $5;
               lmn[$1, x] = $6;
               ldt[$1, x] = $7;
            }
            else
            {
               time[$1, x] = $2":"$3;
               tty[$1, x] = $4;
               rpid[$1, x] = $5;
               lhr[$1, x] = $6;
               lmn[$1, x] = $7;
               ldt[$1, x] = $8;
            }
         }
      }
      END {
         for (i in session)
         {
            for (j = 1; j <= session[i]; j++)
            {
               printf("%-8s %d ", i, j);
               printf("%s  %-6s ", time[i, j], tty[i, j]);
               printf("%6d   %s %2d:%02d\n",rpid[i, j],ldt[i, j],
                                            lhr[i, j], lmn[i, j]);
            }
         }
      }' | \
      sort | /bin/awk '{printf("%2d %s\n", NR, $0)}'
   return 0
}

kill_shell() {
   SESS=$1
   LINE=`list_sessions | /bin/awk '$1 == sess {print $5}' sess=$SESS`
   RPID=`/bin/ps -ft $LINE | /bin/awk 'BEGIN {getline} {print}' | \
      /bin/sort +4 -5 | \
      /bin/awk 'BEGIN {getline; print $2}'`
   # kill -9 $RPID;
   echo "Shell process $RPID killed";
}

kill_children() {
   SESS=$1
   LINE=`list_sessions | /bin/awk '$1 == sess {print $5}' sess=$SESS`
   RPID=`ps -ft $LINE | /bin/awk 'BEGIN {getline} {print}' | sort +4 -5 | \
      /bin/awk 'BEGIN {getline; print $2}'`
   recurse $RPID | sed -e "s/-//g" | \
      /bin/awk '\
      { x[NR] = $1 }
      END {
         for (i=NR; i>1; i--)
            print x[i]
      }' | \
      while read cpid
      do
         # kill -9 $cpid
         echo "Child process $cpid killed"
      done;
   # kill -9 $RPID;
   echo "Shell process $RPID killed";
}

disp_process () {
   TAB=
   SESS=$1
   LINE=`list_sessions | /bin/awk '$1 == sess {print $5}' sess=$SESS`
   echo
   RPID=`ps -ft $LINE | /bin/awk 'BEGIN {getline} {print}' | sort +4 -5 | \
      /bin/awk 'BEGIN {getline; print $2}'`
   recurse $RPID
}

recurse() {
   PPID=$1
   ps -fp $PPID | /bin/awk 'BEGIN {getline} { print }' |&
   while read -p user pid ppid c stime rest
   do
      if test `echo $stime | /bin/awk '{print length($1)}'` -ne 3
      then
         cmd=`echo $rest | single_space | cut -d' ' -f3-`
         echo "($stime)  $pid $TAB$cmd"
      else
         day=`echo $rest | single_space | cut -d' ' -f1`
         cmd=`echo $rest | single_space | cut -d' ' -f4-`
         echo "($stime $day)  $pid $TAB$cmd"
      fi
   done
   TAB=`echo "$TAB   "`
   export TAB
   ps -ef | /bin/awk '$3 == ppid {print $2}' ppid=$PPID | while read cpid
   do
      recurse $cpid
   done
   return
}

case $# in
0)  usage; exit 1;;
1)  case $1 in
    -l)  list_sessions;;
    *)   usage; exit 1;;
    esac;;
2)  case $1 in
    -d)  disp_process $2;;
    -k)  kill_shell $2;;
    -c)  kill_children $2;;
    *)   usage; exit 1;;
    esac;;
*)  usage; exit 1;;
esac
exit 0
-----CUT HERE: T3-----     -----CUT HERE: T3-----

-----CUT HERE-----      -----CUT HERE------    ------CUT HERE-----
# File ID: teuproc
#
# Version: 1.0
# Date: 16 Dec 92
# Author(s): Peters
#
# Purpose: provide a clean user interface to T3
#
#**********************************************

WDIR=/u/lpeters/work/teuproc
while :
do
   $WDIR/T3 -l
   echo "\n(D)isplay, (S)hell kill, (C)hildren kill, or (E)xit: \c"
   read opt
   case $opt in
     e|E)  exit 0;;
     d|D)  echo "\nSession to display (RETURN to abort): \c";
           read sess;
           if test -n "$sess"; then
           T3 -d $sess; fi;;
     c|C)  echo "\nSession to kill (RETURN to abort): \c";
           read sess;
           if test -n "$sess"; then
           T3 -c $sess; fi;;
     s|S)  echo "\nSession to kill (RETURN to abort): \c";
           read sess;
           if test -n "$sess"; then
           T3 -k $sess; fi;;
     *)    echo "\nIllegal option.";;
   esac
   echo
done       
-----CUT HERE: TEUPROC-----     ---CUT HERE: TEUPROC-------

I welcome comments/flames on this labor of love.
-- 
/============================================================================\
|                                            |                               |
|                    ___                     |                               |
|       ___....-----'---`-----....___        |   I haven't lost my mind --   |
| =========================================  |                               |
|        ___`---..._______...---'___         |    it's backed up on          |
|       (___)      _|_|_|_      (___)        |           tape somewhere.     |
|         \\____.-'_.---._`-.____//          |                               |
|           ~~~~`.__`---'__.'~~~~            |   lpeters@marge.hq.af.mil     |
|                   `~~~'                    |                               |
|                                            |     Les Peters                |
\============================================================================/