#!/usr/bin/perl require 5.003; use strict; ############################################################################### # prompt_bell -- execute arbitrary commands contingent upon CPU time # # Copyright (C) 2000 Robb Matzke # # 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 of the License, 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; see the file COPYING. If not, write to the Free # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # # Purpose: # # This program is intended to be called each time a shell prompt is # displayed. It looks at current CPU times (user+system) for the shell and # its children, and if the CPU time is more than some user-specified amount # then user-specified commands are executed. The author uses it to provide # an audio indication of when a long-running command completes. # # Usage: # # The prompt_bell command takes two arguments: the name of a file # containing the latest CPU usage information for the shell and its # children, and some optional state information from the environment # variable $PROMPT_BELL_STATE. # # The times file simply contains one or more times, zero or more to a line, # each of the form `#h#m#.#s' where `#' is a sequence of one or more # decimal digits and `#h' is the optional number of hours, `#m' is the # required number of minutes, and `#.#s' is the number of seconds and # fractions thereof. The total time is the sum of all the times in this # file. Example: # # 0m0.050s 0m0.060s # 0m15.790s 0m0.220s # # The output from this command is one or more semicolon-separated shell # commands which should be eval'd by the caller. If the difference between # the current CPU times and the previous CPU times (stored in environment # variable PROMPT_BELL_STATE) is more than $PROMPT_BELL_TIME seconds # (default 10) then the commands printed include the value of environment # variable PROMPT_BELL_CMD (default is "echo -ne '\a'"). # # Typical usage is: # eval "`prompt_bell $TIMES_FILE $PROMPT_BELL_STATE`" # # and this command is usually part of the bash PROMPT_COMMAND. The author's # .bashrc contains the following: # # PROMPT_BELL_TIME=15 # PROMPT_BELL_CMD="echo -e 'done.\a'" # # COMMAND_PROMPT='TIMES_FILE=/tmp/times.$$; # times >$TIMES_FILE; # eval "`prompt_bell $TIMES_FILE $PROMPT_BELL_STATE`"; # /bin/rm -f $TIMES_FILE' # export PROMPT_BELL_TIME PROMPT_BELL_CMD COMMAND_PROMPT # # Note: the output of `times' is stored in a temporary file to prevent it # from being executed in a subshell whose CPU times are always nearly zero. # ############################################################################## # Convert #h#m#s to seconds. sub seconds { my($hms) = @_; my($h,$m,$s) = $hms =~ /^(?:(\d+)h)?(\d+)m(\d+\.\d+)s/; return $h*3600 + $m*60 + $s; } # Obtain processor times in seconds my $times_file = shift; my $ptime_cur = 0; open TIMES_FILE, $times_file or die "prompt_bell: $times_file: $!

"; while (<TIMES_FILE>) { s/(?:(\d+)h)?(\d+)m(\d+(?:\.\d+)?)s/$ptime_cur+=$1*3600+$2*60+$3/eg; } close TIMES_FILE; # Obtain previous state to compute deltas. my $ptime_prev = shift; # If the processor time was more than $PROMPT_BELL_TIME or 10 seconds # then beep. my $beep; my $limit = exists $ENV{PROMPT_BELL_TIME}?$ENV{PROMPT_BELL_TIME}:10; if ($ptime_cur-$ptime_prev>$limit) { $beep = ";" . ($ENV{PROMPT_BELL_CMD} || "echo -ne '\\a'"); } # Generate the shell commands print "PROMPT_BELL_STATE=$ptime_cur$beep

"; exit 0;