#!/bin/bash askfirst () { #- Asks the user if they would like to perform the command given as #parameters or on stdin (call with sole paremeter of "-"). #- Return code is the return code of the command, #127 if no command or 126 if user chooses to not run the command. #- All user IO is done on stderr; something like: # askfirst ls -al "2>&1" | tee -a /tmp/teefile #allows you to log all output from the command. #- Set ASKFIRSTHELP to some hint as to why you're asking the user to #run this. No problem if left blank. It should be the answer to the #question, "Why do you want me to run this?" #- If your sudo command is something other than "sudo", set #SUDO="/path/to/sudo" #- askfirst can be used in any step of a pipeline. It can even #be used in multiple steps, but the user prompts get mixed together. unset DOTHIS if [ $# -eq 0 ]; then echo 'askfirst invoked without any parameters; use at least "-" to read ' >/dev/stderr echo 'command from stdin.' >/dev/stderr else if [ "z$*" = 'z-' ]; then #command given on stdin - we hope ;-) read DOTHIS else DOTHIS="$*" fi fi if [ -z "$DOTHIS" ]; then return 127 fi SUDO=${SUDO:-"sudo"} AVAILABLEOPTIONS="(Y/N/" SUDOHELP="" if [ "$EUID" != "0" ]; then #Little point in asking root if they want to use sudo. #Cannot put quotes around "sudo *"; use backslash escape instead case "$DOTHIS" in #No point in asking for sudo if sudo already there. $SUDO\ *|/usr/bin/sudo\ *) : ;; *) AVAILABLEOPTIONS="${AVAILABLEOPTIONS}S/" SUDOHELP="S\tRun the command under sudo" ;; esac fi AVAILABLEOPTIONS="${AVAILABLEOPTIONS}E/?)" unset FINISHED while [ "$FINISHED" != "YES" ]; do echo " Shall I run \"$DOTHIS\"" >/dev/stderr echo -n " as $USER in `pwd` ${AVAILABLEOPTIONS}:" >/dev/stderr unset CHOICE #Reading from stderr falls in the "decidedly cheesy" category and would probably #give the POSIX group heart murmurs, but it does work on Linux and frees up stdin #for feeding in the command to run. read CHOICE /dev/stderr AFRETVAL=126 #False; command failed, in a sense. FINISHED="YES" ;; S|s) eval "$SUDO $DOTHIS" AFRETVAL="$?" FINISHED="YES" ;; E|e) echo " NOT running \"$DOTHIS\", exiting" >/dev/stderr exit 1 ;; ?) echo " " >/dev/stderr if [ -n "$ASKFIRSTHELP" ]; then echo " Here is why you're being asked to run this:" >/dev/stderr echo " $ASKFIRSTHELP" >/dev/stderr fi echo " Here are your options:" >/dev/stderr echo -e " Y\tYes, run the command" >/dev/stderr echo -e " N\tNo, do not run the command" >/dev/stderr if [ -n "$SUDOHELP" ]; then echo -e " $SUDOHELP" >/dev/stderr fi echo -e " E\tExit the program completely and don't run the command" >/dev/stderr echo -e " ?\tShow this help" >/dev/stderr ;; *) echo " Unrecognized choice." >/dev/stderr ;; esac done return $AFRETVAL } #Working examples #Simple commands ASKFIRSTHELP="Give a directory listing." askfirst ls -al ASKFIRSTHELP="Creating a flag file for later test." askfirst touch /tmp/asdf #Sudo already in command ASKFIRSTHELP="sudo in command" askfirst sudo touch /tmp/asdf ASKFIRSTHELP="/usr/bin/sudo in command" askfirst /usr/bin/sudo touch /tmp/asdf #Give command to run on stdin instead of on the command line. echo "ls -al" | ASKFIRSTHELP="Piped in command" askfirst - #Assigning output to a string OUTTEXT=`ASKFIRSTHELP='Help line' askfirst 'ls -al /root'` echo separator echo "$OUTTEXT" | head #Pipe stdout and stderr into tee ASKFIRSTHELP="Dir listing of root" askfirst "ls -al /root 2>&1" | tee -a /tmp/teefile #Alternate form, works just as well ASKFIRSTHELP="Dir listing of root" askfirst ls -al /root "2>&1" | tee -a /tmp/teefile #In second stage of 3 stage pipeline echo Hi | ASKFIRSTHELP="Pass along welcome string as root." askfirst cat | cat #By setting PRECOMMAND to one of the following, you can run raw, run #under sudo, or use askfirst to let user choose. The eval's in 1+2 are #necessary because of possible quoting of command parmaters like "2>&1". PRECOMMAND="eval" #PRECOMMAND="eval sudo" #PRECOMMAND="askfirst" ASKFIRSTHELP="I need to see if root's home directory exists." $PRECOMMAND ls -al /root "2>&1" | sed -e 's/^/ZZZ/'