# Modified to run under RHEL 5.4 # @(#) idleout.sh 23.2 91/11/07 # # Copyright (C) 1987-1991 The Santa Cruz Operation, Inc. # All Rights Reserved. # The information in this file is provided for the exclusive use of # the licensees of The Santa Cruz Operation, Inc. Such users have the # right to use, modify, and incorporate this code into other products # for purposes authorized by the license agreement provided they include # this notice and the associated copyright notice with any such product. # The information in this file is provided "AS IS" without warranty. # # idleout(C) # SIGHUP is ignored so that if the root user who invoked the # idleout process gets logged out (or logs out) the idleout # process will not die. # Idleout has to work in the background. It pulls some trickery # so that the user does not have to invoke it in the background. # The first invocation of idleout(C) calls itself recursively with # the environment variable RECURSE equal to 1. # The command ``idleout 0'' turns off idle logout. # PATH=/bin:/usr/bin PATH=/bin:/usr/bin:/acorp/bin:$PATH DEFFILE=/acorp/bin/idleoutdef DEFFIELD="IDLETIME=" LOCKD="/acorp/tmp/locks" LOCKF="LCK..idleout" progname="$0" trap "" 1 IFS=:$IFS # Force command line args to be parsed again with ":" as a separator [ $# -ne 0 ] && set $@ # save the args because shell functions will clobber them argc=$# arg1=$1 arg2=$2 hours=0 minutes=0 defhours=0 defminutes=0 # This program uses "who -u" which loses track after 24 hours MAXHOURS=23 MAXMINUTES=59 # idleout(C) uses a default file, /etc/default/idleout, to provide # a system default for the amount of time a user can remain idle before # being logged out. It should have one entry of the form: # # IDLETIME=[hours:]minutes # # indicating the amount of time a user can remain idle before # being logged out. # Function definitions # Print usage message and exit printusage() { echo "usage: $progname [ minutes | hours:minutes ]" >&2 exit 1 } # Make sure we are superuser, because only they can execute the program superuser() { [ `id | sed 's/(.*$//'` != "uid=0" ] && { echo "$progname: must be root" >&2 exit 5 } return } # Verify that args to the program are numeric. checkargs() { # If there are zero args just return [ $# -eq 0 ] && return # verify args (if present) are numeric using the expr command [ $# -ge 1 ] && { expr $1 + 1 > /dev/null 2>&1 || printusage; } [ $# -ge 2 ] && { expr $2 + 1 > /dev/null 2>&1 || printusage; } return } # This function reads a time out of the default file. It reads # either the default logout time. # It puts the time into the global vars ``defhours'' and ``defminutes''. getdefault() { msg="$progname: $DEFFILE contains badly formatted information for $FIELD" # Make sure there's a default file [ ! -r $DEFFILE ] && return 0 # Get then set the time as positional parms to this function # Also save the old command line args i=`fgrep $DEFFIELD $DEFFILE | sed s/$DEFFIELD//`; set $i # If no such entry then return [ $# -eq 0 ] && return 0 # Check number of terms: 1 or 2 allowed in [hours:]minutes [ $# -gt 2 ] && { echo "$msg" >&2; return 1; } # Verify validity: make sure each term is a number for x do # This next line fails if the term is not a number expr "$x" + 1 > /dev/null 2> /dev/null || { echo "$msg" >&2; return 2 } done # Got 1 or 2 valid arguments if [ $# -eq 1 ] then { defhours=0; defminutes=$1; } else { defhours=$1; defminutes=$2; } fi return 0 } # This routine determines the logout time. First the command line # arguments are evaluated. If they're null the defaults are used. # Then the result, if nonzero, is compared with the maximum time # and the minimum of the two is used. The final value is put into # the two globals ``hours'' and ``minutes''. gettime() { # Get the logout time case $# in 0 ) hours=$defhours; minutes=$defminutes ;; 1 ) hours=0; minutes=$1 ;; 2 ) hours=$1; minutes=$2 ;; esac # Translate minutes > 60 to hours while [ $minutes -ge 60 ] do hours=`expr $hours + 1` minutes=`expr $minutes - 60` done time=`expr $hours '*' 60 + $minutes` max=`expr $MAXHOURS '*' 60 + $MAXMINUTES` [ $time -gt $max ] && { echo "$progname: warning: using maximum logout time of $MAXHOURS:$MAXMINUTES" hours=$MAXHOURS minutes=$MAXMINUTES } } # rmlock # # Look for an idleout lock file. If found, get pid from the file, # kill that process, and remove the file. # rmlock() { if [ -r $LOCKD/$LOCKF ] then read pid < $LOCKD/$LOCKF && \ kill -9 $pid > /dev/null 2> /dev/null rm $LOCKD/$LOCKF fi } # mklock # # Create a lock file containing our pid. mklock() { if [ ! -d $LOCKD ] then mkdir $LOCKD > /dev/null 2> /dev/null || return fi echo $$ > $LOCKD/$LOCKF } # This function builds a command which uses who(C) and awk(C) to # kill(C) users who have been idle. # # The parameters to this function are $1=hours and $2=minutes # The awk patterns print the shell process ids of users who have # been logged in a long time. Then those pids are killed -9. Users # who are current are skipped in the first pattern. Users who are old # are printed in the second pattern. This program has a hardwired # maximum of 24 hours because who -u stops counting at 23:59 and # reports "old". The bracketed statement assigns the users idle hours # and minutes to the variables x and y respectively. Then users idle # longer that h:m are printed. h and m are awk parameters taken from # arguments to this function. # The output of `who -u' is being put into a tmp file and awk # is being called to act upon that because when I piped the # output of who -u into awk nothing happend. killer() { TMPFILE=/acorp/tmp/killlist who -u > $TMPFILE kill_list=` awk ' \ $1 == "admin" { next } \ $1 == "fax" { next } \ $1 == "arcadmins" { next } \ $5 == "." { next } \ $1 == "root" { next } \ $1 == "swarc" { next } \ $1 == "arc1" { next } \ $5 == "old" { print $6 ; next } \ { i=index($5,":"); \ x=substr($5,1,i-1); \ y=substr($5,i+1,length($5)-i); \ if ( x+0 > h+0 ) { print $6 ; next } \ if ( x+0 == h+0 && y+0 >= m+0 ) { print $6 ; next } \ } ' h=$1 m=$2 $TMPFILE ` if [ -n "$kill_list" ] then kill -9 $kill_list fi rm $TMPFILE } # main # If this is a recursive call, don't do any checking. # Indicated by 3 args, #1 is hours, #2 is minutes, #3 is "-" if [ $argc -eq 2 -a "$RECURSE" = "1" ] # Check for recursive call then # Only recursive call executes here mklock # make a lock file while true do killer $arg1 $arg2 sleep 60 done fi # # Only nonrecursive call executes here. Do checking and arg evaluation # superuser # are we suser? only suser allowed [ $argc -gt 2 ] && printusage # verify arg count argc <= 2 checkargs $arg1 $arg2 # verify args are numeric getdefault # Get default idletime from default file gettime $arg1 $arg2 # compute idle time for logouts rmlock # remove previous lock file if any [ $hours -eq 0 -a $minutes -eq 0 ] && exit 0 # if zero, do nothing # Make the recursive call RECURSE=1; export RECURSE # make sure next invocation stays # exec /bin/sh $progname $hours $minutes & exec $progname $hours $minutes &