#!/bin/bash # On Sat, 10 Jan 2004, Aaron Fweed wrote: # > # > ("mctl", by the way, is my imperfect "mult-argument script" for mosctl. # > It just allows me to pass multiple arguments to mosctl, calling mosctl # > once for each one. It's not perfect, though: It won't work with # > multi-parameter arguments, e.g. mctl setspeed 9213 would not work # > because mctl treats "setspeed" and "9213" as separate arguments to # > mosctl. I haven't figured out how to get around that, yet. welcome suggestions.> Anyhow, mctl takes up to 4 arguments and it is # > available at http://kludgekollection.lafeyette.net if you want it. ) # > # Date: 10 Jan 2004 # baro@democritos.it # # I rewrote GETARGS from "mctl", now it works with multiple arguments. # There are other ways to do it, this is just an exmaple. # Hope it's useful. # # NOTE: sorry for my awful english ;) # Your English is superior to that spoken and written by many Americans. # You have nothing to be sorry for! ;-) # Usage: # ./test.sh "arg1.0 arg1.1" arg2 arg3 'arg4.0 arg4.1' # ./test.sh "arg1.0 arg1.1" arg2 arg3 "" 'arg5.0 arg5.1' # DEBUG=1 ./test.sh [args...] # call basename once for all, instead of calling it each # time you need the script name (10 times in mctl...) myself="$(basename $0)" # dummy mosctl for testing #MOSCTL="echo &>/dev/null" MOSCTL=`which mosctl` # declare a global array on which the arguments # parsed from the command line will be stored declare -a arguments #### #### # # Function Definitions. # #### #### function bell { # if stderr is a terminal (not a file), ring the bell test -t 2 && echo -ne >&2 "\a" return 0 # always success } function warn # Not clear what this does. { # just a wrapper echo -e >&2 "*** $@" return 0 # always success } function die { # exit with an error message (optional) test ! -z "$*" && { bell ; warn "$@" ; } exit 1 } function debug { # debugging print--when debugging flag is set, sends output to stderr (&2) # It reports whatever $@ is set to, e.g. program stage, a function name, # a status (or error) message, your mother's hatsize.... test -z "$DEBUG" || echo -e >&2 "debug: $@" return 0 # always success } function execute { # notify which command will be executed and execute it echo >&2 "$myself: executing command: [$@]" eval "$@" # eval returns the exit status of the executed command return $? # superfluous } function ask ## This may be redundant, since ASK is normally a separate utility in the ## KludgeKollection. However, it is nice to have it built into the program ## and this will probably be incorporated into new versions of the NewScript ## template. Still, it does NOT deprecate the stand-alone ASK utility, which ## can be called from other scripts and programs. { # "Are you sure?" family routine # success if answer is y or Y, # failure otherwise echo -ne "$@ " ####### -ne means no new-line after the echo. read -n 1 y echo echo $y | grep -qi "^y$" } function ERROR ## Probably a much nicer way of handling errors than I had. Now, I can ## do an even better job of passing errors to this. Nice, Moreno! { # exit status as first argument, assumes that # remaining argument(s) is the warning message retval=$1 shift warn "$@" exit $retval } function GETARGS { # get mosctl (or whatever) arguments from the command line: # - interactive mode if the cmdline is empty; # - by parsing the cmdline if arguments given. # initialize counter local i=0 debug "IN GETARGS...." if [ -z "$*" ] then # no arguments at all # # Do not check for $1, consider this: # ./test.sh "" valid args ... # $1 is empty but more arguments may follow debug "interactive" while true # never ending loop do # just a prompt echo -ne "Please specify argument $i to pass to mosctl: " # read each argument from command line # note that the whole line is read from stdin, so more # words can be stored into the same argument # e.g.: arg1.0 arg1.1 arg1.2 read arguments[$i] # if the line is empty (carriage return), we assume # that the user ends to give arguments if [ -z "${arguments[$i]}" ] then # remove last (empty) argument from the array unset arguments[$i] warn "empty argument, assume end of arguments" break fi let ++i done # no arguments given, nothing to do test $i = 0 && die "no arguments specified, exiting" else # well, command line is full of funny things # Not clear: Originally thought this was a comment that there may # be invalid characters on the command-line, but the code seems to be # for processing commands into the array, from which they will be processed # later. It does some error-checking, too. for arg in "$@" # note the ["] do # WTH! The argument is empty (""), skip it. # A command line argument is missing. We skip it with this routine. # This might happen if someone types the program name, and then some # thing like "" or something, or puts "" between other args? if [ -z "$arg" ] then warn "empty command line argument #$i" continue fi debug "$i --- $arg" # store the argument and increment counter arguments[$i]="$arg" let ++i done fi # notify what the user asked for echo "You have built the following command:" echo -e "\n\t$myself $(SHOWARGS)\n" # confirm? ask "Is this what you want?" if [ $? -ne 0 ]; then ERROR 20 "you enter an incorrect interactive command line" fi } function SHOWARGS { # compose arguments on a single line (ONLY in order to show them) # is not the same of ${arguments[@]} or ${arguments[*]} # I want that subarguments been grouped inside "" # e.g.: "arg1.0 arg1.1" "arg2" "arg3" "arg5.0 arg5.1" local i=0 while [ $i -lt ${#arguments[@]} ] do echo -ne "\"${arguments[$i]}\" " let ++i done } function DO_SOMETHING_WITH_ARGS { # do something useful with the given arguments debug "IN DO_SOMETHING_WITH_ARGS...." local i=0 while [ $i -lt ${#arguments[@]} ] do debug "arg${i}: ${arguments[$i]}" if [ -z $MOSCTL ]; then ERROR 30 "The command mosctl is missing on this system!" fi execute $MOSCTL ${arguments[$i]} let ++i done } # MAIN # GETARGS "$@" DO_SOMETHING_WITH_ARGS # /MAIN # #EOF