#/usr/local/bin/perl # process command line var settings $idle = -1; $dot = 60; $colon = 10; ($me = $0) =~ s%.*/%%; sub another { print stderr "Interrupted!\n"; exit 1;} $SIG{'INT'} = 'another'; eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift; # parse switches while ($ARGV[0] =~ /^-/) { $ARGV[0] =~ /^-a/ && ($all++,shift,next); $ARGV[0] =~ /^-d/ && ($debug++,shift,next); $ARGV[0] =~ /^-n/ && ($idle = 0,shift,next); $ARGV[0] =~ /^-w/ && ($window++,shift,next); $ARGV[0] =~ /^-l/ && ($long++,shift,next); $ARGV[0] =~ /^-b/ && ($broadcast++,shift,next); $ARGV[0] =~ /^-m/ && ($multicast++,shift,next); $ARGV[0] =~ /^-s/ && ($slumber++,shift,next); $ARGV[0] =~ /^-i/ && (shift,$idle=$ARGV[0],shift,next); last; } $hosts && $multicast++; if ($idle =~ /[:h]/) { $hours = $minutes = 0; ($hours = $idle) =~ s/[:h].*$//; ($minutes = $idle) =~ s/.*[:h]//; $idle = $hours * 60 + $minutes; if ($debug) { print "you said $idle m idle\n"; } } elsif ($idle < 0) { $idle = $dot; } $sleep = 60 unless $sleep; $idle = 999E10 if $all; if ( $ARGV[0] =~ /^-/ ) { select (stderr); printf "usage: %s [vars] [-b | -m] [-a] [-n] [-l] [-w] [-s] [target ...]\n", $me; printf "\t-b to broadcast to the ruserd\n"; printf "\t-m to multicast to the ruserd\n"; printf "\t-a for ALL, even very idle people\n"; printf "\t-n for people active NOW short idles\n"; printf "\t-l for LONG listing\n"; printf "\t-w to dynamically compute WINDOW size\n"; printf "\t-s to sleep and repeat until all targets found\n"; printf "\tvars \$idle ($idle) and \$sleep ($sleep) can be set with var=value\n"; printf "\t as can \$hosts, \$dot ($dot), and \$colon ($colon)\n"; exit 1; } # compute width according to window size $ENV{"TERMCAP"} =~ /:co#(\d+):/ && ($cols = int($1/25)); if ( $window ) { open(win,"(stty all > /dev/tty ) 2>&1 |") || die "can't run stty"; while () { chop; split; $cols = int($_[7]/ 25); last; } close win; } $cols = 3 unless $cols; if ($multicast && !$hosts) { $machines = '/usr/adm/MACHINES'; open machines || die "$me: can't open $machines: $!\n"; open(saveout, ">&stdout"); # much cheaper than invoking sh close(stdout); while () { next if /norpc/; chop; s/\s.*//; if (do ping($_)) { # no sh here! #print stderr $_, " ok\n"; push(@hosts,$_); } else { #printf stderr "%s is down!\n", $_; } } open(stdout, ">&saveout"); close machines; close saveout; $debug && print "hosts are: ", join(' ',@hosts),"\n"; } restart: $count = $#ARGV + 1; $PIPE = "/usr/ucb/rwho"; if ($broadcast || $multicast) { $PIPE = "/usr/ucb/rusers -l "; $multicast && $PIPE .= $hosts ? $hosts : join(' ',@hosts); } $PIPE .= "|sort|"; $debug && printf "PIPE is %s", $PIPE; open PIPE || die "$me: can't popen \"$PIPE\": $!\n"; PIPEline: while () { s/-ex0//; $matched = 0; if ( $count ) { matchcheck: for ( $i = 0; $i < $count; $i++ ) { $str = $ARGV[$i]; $matched = /$str/; if ( $matched ) { if ($debug) { printf "YES: `%s' MATCH <%s>\n", $str, $_ ; } last matchcheck; # break } else { if ($debug) { printf "NO: `%s' DIDN'T <%s>\n", $str, $_ ; } } } if ( ! $matched ) { next PIPEline; } } $_[5] = ""; split; $myidle = 0; if ( $_[5] =~ /^[:0-9]*$/ ) { $hours = $minutes = 0; if ( $_[5] =~ /[0-9]:/ ) { $hours = $_[5]; $hours =~ s/:.*$//; } $minutes = $_[5]; $minutes =~ s/^.*://; $myidle = $hours * 60 + $minutes; } next PIPEline if $myidle > $idle; $found{$str}++ if ($slumber); if ( $long ) { print; } else { if ($debug) { printf "%s@%s is %d\n", $_[0],$_[1],$myidle; } if ($myidle < $dot && $myidle > $colon) { $_[1] =~ s/:/./; } elsif ($myidle > $dot) { $_[1] =~ s/:/ /; } push(users,sprintf("%-9s%15s", $_[0], $_[1])); } } exit if $long && ! $slumber; $rows = int(($#users+$cols) / $cols); # { printf "found %d matches\n", $#users+1; } # { printf "rows are %s, cols are %s\n", $rows, $cols; } if ($slumber && $restarted && $#users >= $[) { printf "\n%s: bingo! at %s%c\n", $me, `date`, 7; } for ($elt = 0; $elt < $rows * $cols; $elt++) { $targ = ($elt%$cols) * $rows + int(($elt/$cols)); printf "%s ", $targ < ($#users+1) ? $users[$targ] : ""; #if ($debug) { #printf "%d ", $targ < ($#users+1) ? $targ : -1; } print "\n" if (($elt+1) % $cols) == 0; } print "\n" if ($elt+1) % $cols == 0; close PIPE; if ($slumber) { @nargv = (); @users = (); for ($i = 0; $i < $count; $i++) { ! $found{$ARGV[$i]} && push(@nargv,$ARGV[$i]); } @ARGV = @nargv; if ($#ARGV >= $[) { exit if ($forked++ == 0 && fork); sleep $sleep; $restarted = 1; ($whoami = `who am i`) =~ s/.*!([^ ]*).*/$1/; exit if $whoami != $ENV{"USER"}; goto restart; } } sub ping { local($host) = @_; if (fork) { wait; exit if $? & 0xff; # interrupted return $? == 0; } else { exec 'pong', $host, 1; } }