PROBLEM: The environment variable PROMPT_COMMAND provides a way to run an arbitrary command before the prompt is shown (post-execution hook), but there is no way to run a command after the command-line has been entered but before it has been executed (pre-execution hook). MOTIVATION: I want to set the xterm title to show the command currently running, so that I can see what a minimized or obscured window is doing by looking at the taskbar. Other uses for this could be menu systems, computer-based exercises or monitoring. PROPOSITION: Before each command is executed, the environment variable SPAWN_COMMAND is inspected and executed if filled. The command-line is accessible for this command through the use of the environment variable CMD_LINE. IMPLEMENTATION: A new global variable 'global_command_line' is introduced, and the history module sets this variable to be the contents of the last command-line parsed. A new function 'execute_spawn_command' is introduced, that reads the contents of the SPAWN_COMMAND environment variable, sets the CMD_LINE variable to the last command-line known, executes the commands and restores the old value of CMD_LINE. A call to execute_spawn_command() is added right before the call to execute_command() in the main loop. This a place that was found to be safe for such hooking. Adding it in execute_command() or further down the chain gives odd effects due to recursive calls. The option '--no-spawn-command' was added to enable the user to disable the functionality. VERSION: The patch is done against bash version 2.05. KNOWN ISSUES: The use of a savestring() unmatched by an xfree() as an argument to bind_variable() seems logical since bind_variable() would adopt the responsibility of the memory for the variable. However, the same thing done for parse_and_execute() does not seem logical to me, but the string is appearently corrupted if this is not done. Please confirm that this is safe to do in respect to memory leaks. A new global variable to hold the contents of the command-line seems redundant, but I'm having problems accessing the history records from outside the history module, and I didn't bother to use any time to figure out why it seemed state dependent. A core dump may be triggered upon exit from a subshell if variable substitution is used within the SPAWN_COMMAND variable. COMPATABILITY: Old scripts that happens to use the environment variable SPAWN_COMMAND, will undoubtly behave very strange. For this reason, the option --no-spawn-command is introduced to enable bash to revert to 2.05 behavior, where SPAWN_COMMAND is not interpreted. DOCUMENTATION: I suggest that the following paragraphs is added to the manual: --no-spawn-command If this option is NOT set (which is the default), the contents of the environment variable SPAWN_COMMAND is executed before the execution of the command-line. The environment variable CMD_LINE will be filled with the unexpanded contents of the command-line, for the duration of that command only (i.e. it reverts to its previous contents before the command-line executes). Example: To display the current running process in the title bar of an xterm window, and reset the title before the prompt is shown again, put the following commands in your ~/.bashrc export SPAWN_COMMAND='echo -ne "\033]2;$CMD_LINE\007"' export PROMPT_COMMAND='echo -ne "\033]2;idle\007"' or, you may want to use a command that append information about the current user and directory for the command: export PROMPT_COMMAND='/bin/echo -ne "\033]0;idle in `/usr/bin/whoami`@`/bin/hostname | /bin/cut -d. -f 1`:`/bin/pwd | /bin/sed "s% ^$HOME%~%g"`\007"' export SPAWN_COMMAND='/bin/echo -ne "\033]2;${CMD_LINE} in `/usr/bin/whoami`@`/bin/hostname | /bin/cut -d. -f 1`:`/bin/pwd | /bin/sed "s% ^$HOME%~%g"`\007"' AUTHORS: Roland Kaufmann <roland at ii dot uib dot no> Hevard Lygre <hklygre at online dot no>
Created attachment 45199 [details] Patch against bash 2.05 to enable pre-execution hook
I've sent a message to the base package maintainers asking their opinion on this. I'm not sure about it myself, since there's both some good use (like what you're suggesting) and some potential for abuse and of course overhead. Waiting on feedback from base maintainers.
I don't think that it is more prone to abuse than the PROMPT_COMMAND construct, except perhaps for that commands can be cancelled (which was intended as a feature). When it comes to overhead, SPAWN_COMMAND is only evaluated in interactive shells, and thus takes typically a lot less time to evaluate than the latency of the user. I have used it myself for three months now, and have never experienced it as interruptive of my work.
Created attachment 61166 [details] Stripped-down patch with minimum required functionality
I have created a new patch (against the version of bash that comes with RedHat 7.3), that only contains the around 10 lines of code that contains the minimum required functionality for the pre-execution hook to work. It gets rid of some ugly code to retrieve the last command-line, but instead relys on that history is enabled so that the user can set the variable like this: export SPAWN_COMMAND='echo -ne "\033]0;`history 1 | cut -c 8-` in ${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}\007"'
Created attachment 61245 [details] Reduced patch (only 3 lines!); now equivalent to PROMPT_COMMAND
Created attachment 64104 [details] Patch to enable SPAWN_COMMAND environment variable
Created attachment 64105 [details] Patch to enable LASTCMD environment variable
The latest two patches give back most of the functionality of the original proposal. SPAWN_COMMAND is an environment variable understood by the shell in the same way as the PROMPT_COMMAND variable is already except that it is executed before instead of after the command. LASTCMD is an environment variable set by the shell in the same way as the HISTCMD variable except that it will contain the actual contents of the command line instead of its history number. These patches has been tested against RedHat Linux 7.3. Due to the appearant lack of interest in this functionality, further patches will not be posted to Bugzilla but to my website only.