#! /bin/sh # waitfor --- notify you when a user logs in # Copyright (C) 1991, 1994 Noah S. Friedman # Author: Noah Friedman # Created: 1991-08-08 # $Id: waitfor,v 1.4 1996/03/03 23:03:30 friedman Exp $ # 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, you can either send email to this # program's maintainer or write to: The Free Software Foundation, # Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. # Commentary: # Notifies invoker when specified user logs onto any of the specified # hosts. This script will automatically background itself. There's no # need to call it with a "&" operator. # Code: # Name by which this script was invoked. progname=`echo "$0" | sed -e 's/[^\/]*\///g'` # To prevent hairy quoting and escaping later. bq='`' eq="'" usage="Usage: $progname {options} [user] {host1} {host2} {...} Options are: -D, --debug Turn on shell debugging ($bq${bq}set -x$eq$eq). -F, --force Do not examine ownership of tty to decide whether to terminate. Use of this option is discouraged because failure to kill this program at logout will annoy the next user to log in. -h, --help You're looking at it. -i, --interval SECONDS Number of seconds between checks, default 60. If no hosts are specified, the current host is assumed. " # Clever way to save arguments whilst preserving quoting. # Note that only one set of args can be saved at a time. # Usage: eval "$save_current_args" # eval "$restore_saved_args" save_current_args=' { _saved_args= while : ; do case $# in 0 ) break ;; esac eval _saved_args$#=\$1 _saved_args="$_saved_args \"\$_saved_args$#\"" shift done eval "$restore_saved_args" }' restore_saved_args=' { eval '\''{ eval set fnord $_saved_args ; }'\'' shift }' # Usage: eval "$getopt"; value=$optarg # or optarg_optional=t; eval "$getopt"; value=$optarg # # This function automatically shifts the positional args as appropriate. # The argument to an option is optional if the variable `optarg_optional' # is non-empty. Otherwise, the argument is required and getopt will cause # the program to exit on an error. optarg_optional is reset to be empty # after every call to getopt. The argument (if any) is stored in the # variable `optarg'. # # Long option syntax is `--foo=bar' or `--foo bar'. 2nd argument # won't get used if first long option syntax was used. # # Note: because of broken bourne shells, using --foo=bar syntax can # actually screw the quoting of args that end with trailing newlines. # Specifically, most shells strip trailing newlines from substituted # output, regardless of quoting. getopt=' { optarg= case "$1" in --*=* ) optarg=`echo "$1" | sed -e "1s/^[^=]*=//"` shift ;; * ) case ${2+set} in set ) optarg="$2" shift shift ;; * ) case "$optarg_optional" in "" ) case "$1" in --*=* ) option=`echo "$1" | sed -e "1s/=.*//;q"` ;; * ) option="$1" ;; esac exec 1>&2 echo "$progname: option $bq$option$eq requires argument." echo "$progname: use $bq--help$eq to list option syntax." exit 1 ;; esac ;; esac ;; esac optarg_optional= }' # Initialize variables. # Don't use `unset' since old bourne shells don't have this command. # Instead, assign them an empty value. debug= daemonp=f force= sleep_interval=60 eval "$save_current_args" # Parse command line arguments. # Make sure that all wildcarded options are long enough to be unambiguous. # It's a good idea to document the full long option name in each case. # Long options which take arguments will need a `*' appended to the # canonical name to match the value appended after the `=' character. while test $# != 0; do case $# in 0) break ;; esac case "$1" in --daemon ) daemonp=t shift ;; -D | --debug | --d* ) debug=t shift ;; -F | --force | --f* ) force=t shift ;; -h | --help | --h ) echo "$usage" 1>&2 exit 1 ;; -i | --interval* | --i* ) eval "$getopt" sleep_interval="$optarg" ;; -- ) # Stop option processing shift break ;; -? | --* ) case "$1" in --*=* ) arg=`echo "$1" | sed -e 's/=.*//'` ;; * ) arg="$1" ;; esac exec 1>&2 echo "$progname: unknown or ambiguous option $bq$arg$eq" echo "$progname: Use $bq--help$eq for a list of options." exit 1 ;; -??* ) # Split grouped single options into separate args and try again optarg="$1" shift set fnord `echo "x$optarg" | sed -e 's/^x-//;s/\(.\)/-\1 /g'` ${1+"$@"} shift ;; * ) break ;; esac done case "$debug" in t ) set -x ;; esac case $# in 0 ) exec 1>&2 echo "$progname: You must supply a username." echo "$usage" exit 1 ;; esac case "$force" in t ) : ;; * ) TTY=${TTY-`tty 2> /dev/null`} case "$TTY" in /dev/* ) : ;; * ) echo "$progname: Can't run without a tty." 1>&2 exit 1 ;; esac USER=${USER-${LOGNAME-`(whoami) 2> /dev/null \ || id | sed -ne 's/.*uid=[0-9]*(//;s/).*//;p'`}} export TTY USER tty_sed='s/ / /g s/^[^ ]* *[0-9]* *// s/ .*// p' tty_owner=`ls -ld "$TTY" | sed -ne "$tty_sed"` case "$tty_owner" in "$USER" ) : ;; * ) exec 1>&2 echo "$progname: You must own $TTY to run this script." ls -ld "$TTY" exit 1 ;; esac ;; esac case "$daemonp" in f ) eval "$restore_saved_args" $0 --daemon ${1+"$@"} & echo "$progname backgrounded." exit 0 ;; esac tmpfile="/tmp/$progname$$" target_user="$1" shift case $# in 0 ) set fnord `hostname` shift ;; esac trap 'exitstat=$? rm -f "$tmpfile" 2> /dev/null trap "" 1 2 3 15 exit $exitstat ' 1 2 3 15 while : ; do case "$force" in t ) : ;; * ) tty_owner=`ls -ld "$TTY" | sed -ne "$tty_sed"` case "$tty_owner" in "$USER" ) : ;; * ) rm -f "$tmpfile" 2> /dev/null exit 0 ;; esac ;; esac rusers -l ${1+"$@"} 2> /dev/null \ | grep "^$target_user" > "$tmpfile" 2> /dev/null if test -s "$tmpfile" ; then echo "*** $progname: $target_user has logged in:" cat "$tmpfile" echo "*** $progname: Terminating." rm -f "$tmpfile" exit 0 fi sleep "$sleep_interval" done # waitfor ends here