179f697e0SAnthony Wilson#!/bin/sh -e
279f697e0SAnthony Wilson
379f697e0SAnthony Wilsonset -euo pipefail
479f697e0SAnthony Wilson
5189cf248SAnthony WilsonOPTS="bmcstate,bootprogress,chassiskill,chassisoff,chassison,chassisstate,hoststate,\
6*a65d30d1SVishwanatha Subbannaosstate,power,poweroff,poweron,state,status,hostrebootoff,hostrebooton,recoveryoff,recoveryon,\
7*a65d30d1SVishwanatha Subbannabmcrebootoff, bmcrebooton"
80f35983dSAnthony Wilson
960c3ac8cSAndrew JefferyUSAGE="Usage: obmcutil [-h] [--wait] [--verbose]
100f35983dSAnthony Wilson                {$OPTS}"
1179f697e0SAnthony Wilson
1279f697e0SAnthony WilsonINTERFACE_ROOT=xyz.openbmc_project
1379f697e0SAnthony WilsonSTATE_INTERFACE=$INTERFACE_ROOT.State
146d3a2c54SVishwanatha SubbannaCONTROL_INTERFACE=$INTERFACE_ROOT.Control
1579f697e0SAnthony Wilson
1679f697e0SAnthony WilsonOBJECT_ROOT=/xyz/openbmc_project
1779f697e0SAnthony WilsonSTATE_OBJECT=$OBJECT_ROOT/state
186d3a2c54SVishwanatha SubbannaCONTROL_OBJECT=$OBJECT_ROOT/control
1979f697e0SAnthony Wilson
207a787dd7SVishwanatha SubbannaHOST_TIMEOUT_TARGET=obmc-host-timeout@0.target
2184b3b29eSVishwanatha SubbannaHOST_CRASH_TARGET=obmc-host-crash@0.target
227a787dd7SVishwanatha Subbanna
23acf54d08SAnthony Wilson## NOTE: The following global variables are used only in the run_timeout cmd.
24acf54d08SAnthony Wilson## By declaring these globally instead of passing them through the
25acf54d08SAnthony Wilson## intermediary functions, which may not be "best practice", the readability
26acf54d08SAnthony Wilson## and cleanliness of the code should at least be increased.
27acf54d08SAnthony Wilson
28acf54d08SAnthony Wilson# The command passed in to be executed (e.g. poweron/off, status, etc.)
29acf54d08SAnthony Wilson# This will be be used in some instances of error reporting
30acf54d08SAnthony WilsonG_ORIG_CMD=
31acf54d08SAnthony Wilson# The state an interface should be in after executing the requested command.
32acf54d08SAnthony WilsonG_REQUESTED_STATE=
33acf54d08SAnthony Wilson# The query to run during a poweron/off or chassison/off to check that
34acf54d08SAnthony Wilson# the requested state (G_REQUESTED_STATE) of the interface has been reached.
35acf54d08SAnthony WilsonG_QUERY=
36acf54d08SAnthony Wilson# Wait the set period of time for state transitions to be successful before
37acf54d08SAnthony Wilson# continuing on with the program or reporting an error if timeout reached.
38acf54d08SAnthony WilsonG_WAIT=
3960c3ac8cSAndrew Jeffery# Print the journal to the console
4060c3ac8cSAndrew JefferyG_VERBOSE=
41acf54d08SAnthony Wilson
42f3f16fa9SAnthony Wilsonprint_help ()
43f3f16fa9SAnthony Wilson{
44f3f16fa9SAnthony Wilson    echo "$USAGE"
45f3f16fa9SAnthony Wilson    echo ""
46f3f16fa9SAnthony Wilson    echo "positional arguments:"
470f35983dSAnthony Wilson    echo "  {$OPTS}"
48f3f16fa9SAnthony Wilson    echo ""
496d3a2c54SVishwanatha Subbanna    echo "Examples:"
506d3a2c54SVishwanatha Subbanna    echo ""
51*a65d30d1SVishwanatha Subbanna    echo "obmcutil hostrebootoff Disable auto reboot of Host from Quiesce state"
52*a65d30d1SVishwanatha Subbanna    echo "obmcutil hostrebooton  Enable auto reboot of Host from Quiesce state"
53*a65d30d1SVishwanatha Subbanna    echo ""
54*a65d30d1SVishwanatha Subbanna    echo "obmcutil bmcrebootoff  Disable reboot of BMC"
55*a65d30d1SVishwanatha Subbanna    echo "obmcutil bmcrebooton   Enable reboot of BMC"
566d3a2c54SVishwanatha Subbanna    echo ""
5784b3b29eSVishwanatha Subbanna    echo "obmcutil recoveryoff   Disable handling boot watchdog timeout and host crash"
58*a65d30d1SVishwanatha Subbanna    echo "                       Also, disable BMC and Host auto reboots"
59*a65d30d1SVishwanatha Subbanna    echo ""
6084b3b29eSVishwanatha Subbanna    echo "obmcutil recoveryon    Enable handling boot watchdog timeout and host crash"
61*a65d30d1SVishwanatha Subbanna    echo "                       Also, enable BMC and Host auto reboots"
627a787dd7SVishwanatha Subbanna    echo ""
63f3f16fa9SAnthony Wilson    echo "optional arguments:"
64f3f16fa9SAnthony Wilson    echo "  -h, --help          show this help message and exit"
65acf54d08SAnthony Wilson    echo "  -w, --wait          block until state transition succeeds or fails"
6660c3ac8cSAndrew Jeffery    echo "  -v, --verbose       print the journal to stdout if --wait is supplied"
67f3f16fa9SAnthony Wilson    exit 0
68f3f16fa9SAnthony Wilson}
69f3f16fa9SAnthony Wilson
70acf54d08SAnthony Wilsonrun_timeout ()
71acf54d08SAnthony Wilson{
72acf54d08SAnthony Wilson    local timeout="$1"; shift
73acf54d08SAnthony Wilson    local cmd="$@"
7460c3ac8cSAndrew Jeffery    local verbose_child=
7560c3ac8cSAndrew Jeffery
762869a926SAndrew Jeffery    if [ -n "$G_VERBOSE" ]; then
7760c3ac8cSAndrew Jeffery        journalctl -f &
7860c3ac8cSAndrew Jeffery        verbose_child=$!
7960c3ac8cSAndrew Jeffery    fi
80acf54d08SAnthony Wilson
81acf54d08SAnthony Wilson    $cmd
82acf54d08SAnthony Wilson
83acf54d08SAnthony Wilson    # Run a background query for the transition to the expected state
84acf54d08SAnthony Wilson    # This will be killed if the transition doesn't succeed within
85acf54d08SAnthony Wilson    # a timeout period.
86acf54d08SAnthony Wilson    (
87acf54d08SAnthony Wilson        while ! grep -q $G_REQUESTED_STATE <<< $(handle_cmd $G_QUERY) ; do
88acf54d08SAnthony Wilson            sleep 1
89acf54d08SAnthony Wilson        done
90acf54d08SAnthony Wilson    ) &
9160c3ac8cSAndrew Jeffery    wait_child=$!
92acf54d08SAnthony Wilson
93acf54d08SAnthony Wilson    # Could be bad if process is killed before 'timeout' occurs if
94acf54d08SAnthony Wilson    # transition doesn't succeed.
95acf54d08SAnthony Wilson    trap -- "" SIGTERM
96acf54d08SAnthony Wilson
97acf54d08SAnthony Wilson    # Workaround for lack of 'timeout' command.
98acf54d08SAnthony Wilson    (
99acf54d08SAnthony Wilson        sleep $timeout
10060c3ac8cSAndrew Jeffery        kill $wait_child
101acf54d08SAnthony Wilson    ) > /dev/null 2>&1 &
102acf54d08SAnthony Wilson
10360c3ac8cSAndrew Jeffery    if ! wait $wait_child; then
104acf54d08SAnthony Wilson        echo "Unable to confirm '$G_ORIG_CMD' success" \
105acf54d08SAnthony Wilson        "within timeout period (${timeout}s)"
106acf54d08SAnthony Wilson    fi
10760c3ac8cSAndrew Jeffery
1088be70293SAndrew Jeffery    if [ -n "$verbose_child" ]; then
10960c3ac8cSAndrew Jeffery        kill $verbose_child
11060c3ac8cSAndrew Jeffery    fi
111acf54d08SAnthony Wilson}
112acf54d08SAnthony Wilson
113acf54d08SAnthony Wilsonrun_cmd ()
114acf54d08SAnthony Wilson{
115acf54d08SAnthony Wilson    local cmd="$@";
116acf54d08SAnthony Wilson
117acf54d08SAnthony Wilson    if [ -n "$G_WAIT" ]; then
118acf54d08SAnthony Wilson        run_timeout $G_WAIT "$cmd"
119acf54d08SAnthony Wilson    else
120acf54d08SAnthony Wilson        $cmd
121acf54d08SAnthony Wilson    fi
122acf54d08SAnthony Wilson}
123acf54d08SAnthony Wilson
1243ae0a354SAnthony Wilsonset_property ()
1253ae0a354SAnthony Wilson{
126acf54d08SAnthony Wilson    run_cmd busctl set-property "$@"
1273ae0a354SAnthony Wilson}
1283ae0a354SAnthony Wilson
12979f697e0SAnthony Wilsonget_property ()
13079f697e0SAnthony Wilson{
131acf54d08SAnthony Wilson    G_WAIT=""
132acf54d08SAnthony Wilson    run_cmd busctl get-property "$@"
13379f697e0SAnthony Wilson}
13479f697e0SAnthony Wilson
13579f697e0SAnthony Wilsonstate_query ()
13679f697e0SAnthony Wilson{
13779f697e0SAnthony Wilson    local state=$(get_property "$@" | cut -d '"' -f2)
13879f697e0SAnthony Wilson    printf "%-20s: %s\n" $4 $state
13979f697e0SAnthony Wilson}
14079f697e0SAnthony Wilson
141ea87db40SAnthony Wilsonprint_usage_err ()
142ea87db40SAnthony Wilson{
143ea87db40SAnthony Wilson    echo "ERROR: $1" >&2
144ea87db40SAnthony Wilson    echo "$USAGE"
145ea87db40SAnthony Wilson    exit 1
146ea87db40SAnthony Wilson}
147ea87db40SAnthony Wilson
1487a787dd7SVishwanatha Subbannamask_systemd_target ()
1497a787dd7SVishwanatha Subbanna{
1507a787dd7SVishwanatha Subbanna    target="$@"
1517a787dd7SVishwanatha Subbanna    systemctl mask $target
1527a787dd7SVishwanatha Subbanna}
1537a787dd7SVishwanatha Subbanna
1547a787dd7SVishwanatha Subbannaunmask_systemd_target ()
1557a787dd7SVishwanatha Subbanna{
1567a787dd7SVishwanatha Subbanna    target="$@"
1577a787dd7SVishwanatha Subbanna    systemctl unmask $target
1587a787dd7SVishwanatha Subbanna}
1597a787dd7SVishwanatha Subbanna
160*a65d30d1SVishwanatha Subbannadisable_bmc_reboot ()
161*a65d30d1SVishwanatha Subbanna{
162*a65d30d1SVishwanatha Subbanna    dir="/run/systemd/system/"
163*a65d30d1SVishwanatha Subbanna    file="reboot-guard.conf"
164*a65d30d1SVishwanatha Subbanna    units=("reboot" "poweroff" "halt")
165*a65d30d1SVishwanatha Subbanna
166*a65d30d1SVishwanatha Subbanna    for unit in "${units[@]}"; do
167*a65d30d1SVishwanatha Subbanna        mkdir -p ${dir}${unit}.target.d
168*a65d30d1SVishwanatha Subbanna        echo -e "[Unit]\nRefuseManualStart=yes" >> ${dir}${unit}.target.d/${file}
169*a65d30d1SVishwanatha Subbanna    done
170*a65d30d1SVishwanatha Subbanna}
171*a65d30d1SVishwanatha Subbanna
172*a65d30d1SVishwanatha Subbannaenable_bmc_reboot ()
173*a65d30d1SVishwanatha Subbanna{
174*a65d30d1SVishwanatha Subbanna    dir="/run/systemd/system/"
175*a65d30d1SVishwanatha Subbanna    file="reboot-guard.conf"
176*a65d30d1SVishwanatha Subbanna    units=("reboot" "poweroff" "halt")
177*a65d30d1SVishwanatha Subbanna
178*a65d30d1SVishwanatha Subbanna    for unit in "${units[@]}"; do
179*a65d30d1SVishwanatha Subbanna        rm -rf ${dir}${unit}.target.d/${file}
180*a65d30d1SVishwanatha Subbanna        rm -rf ${dir}${unit}.target.d
181*a65d30d1SVishwanatha Subbanna    done
182*a65d30d1SVishwanatha Subbanna}
183*a65d30d1SVishwanatha Subbanna
18479f697e0SAnthony Wilsonhandle_cmd ()
18579f697e0SAnthony Wilson{
18679f697e0SAnthony Wilson    case "$1" in
1873ae0a354SAnthony Wilson        chassisoff)
1883ae0a354SAnthony Wilson            OBJECT=$STATE_OBJECT/chassis0
1893ae0a354SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
1903ae0a354SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Chassis
1913ae0a354SAnthony Wilson            PROPERTY=RequestedPowerTransition
1923ae0a354SAnthony Wilson            VALUE=$INTERFACE.Transition.Off
193acf54d08SAnthony Wilson            G_REQUESTED_STATE=$INTERFACE.PowerState.Off
194acf54d08SAnthony Wilson            G_QUERY="chassisstate"
1953ae0a354SAnthony Wilson            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
1963ae0a354SAnthony Wilson            ;;
1973ae0a354SAnthony Wilson        chassison)
1983ae0a354SAnthony Wilson            OBJECT=$STATE_OBJECT/chassis0
1993ae0a354SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
2003ae0a354SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Chassis
2013ae0a354SAnthony Wilson            PROPERTY=RequestedPowerTransition
2023ae0a354SAnthony Wilson            VALUE=$INTERFACE.Transition.On
203acf54d08SAnthony Wilson            G_REQUESTED_STATE=$INTERFACE.PowerState.On
204acf54d08SAnthony Wilson            G_QUERY="chassisstate"
2053ae0a354SAnthony Wilson            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
2063ae0a354SAnthony Wilson            ;;
2073ae0a354SAnthony Wilson        poweroff)
2083ae0a354SAnthony Wilson            OBJECT=$STATE_OBJECT/host0
2093ae0a354SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
2103ae0a354SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Host
2113ae0a354SAnthony Wilson            PROPERTY=RequestedHostTransition
2123ae0a354SAnthony Wilson            VALUE=$INTERFACE.Transition.Off
213acf54d08SAnthony Wilson            G_REQUESTED_STATE=$INTERFACE.HostState.Off
214acf54d08SAnthony Wilson            G_QUERY="hoststate"
2153ae0a354SAnthony Wilson            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
2163ae0a354SAnthony Wilson            ;;
2173ae0a354SAnthony Wilson        poweron)
2183ae0a354SAnthony Wilson            OBJECT=$STATE_OBJECT/host0
2193ae0a354SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
2203ae0a354SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Host
2213ae0a354SAnthony Wilson            PROPERTY=RequestedHostTransition
2223ae0a354SAnthony Wilson            VALUE=$INTERFACE.Transition.On
223acf54d08SAnthony Wilson            G_REQUESTED_STATE=$INTERFACE.HostState.Running
224acf54d08SAnthony Wilson            G_QUERY="hoststate"
2253ae0a354SAnthony Wilson            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
2263ae0a354SAnthony Wilson            ;;
22779f697e0SAnthony Wilson        bmcstate)
22879f697e0SAnthony Wilson            OBJECT=$STATE_OBJECT/bmc0
22979f697e0SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
23079f697e0SAnthony Wilson            INTERFACE=$STATE_INTERFACE.BMC
23179f697e0SAnthony Wilson            PROPERTY=CurrentBMCState
23279f697e0SAnthony Wilson            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
23379f697e0SAnthony Wilson            ;;
23479f697e0SAnthony Wilson        chassisstate)
23579f697e0SAnthony Wilson            OBJECT=$STATE_OBJECT/chassis0
23679f697e0SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
23779f697e0SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Chassis
23879f697e0SAnthony Wilson            PROPERTY=CurrentPowerState
23979f697e0SAnthony Wilson            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
24079f697e0SAnthony Wilson            ;;
24179f697e0SAnthony Wilson        hoststate)
24279f697e0SAnthony Wilson            OBJECT=$STATE_OBJECT/host0
24379f697e0SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
24479f697e0SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Host
24579f697e0SAnthony Wilson            PROPERTY=CurrentHostState
24679f697e0SAnthony Wilson            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
24779f697e0SAnthony Wilson            ;;
24886cffd9cSAlexander Filippov        osstate)
24986cffd9cSAlexander Filippov            OBJECT=$STATE_OBJECT/host0
25086cffd9cSAlexander Filippov            SERVICE=$(mapper get-service $OBJECT)
25186cffd9cSAlexander Filippov            INTERFACE=$STATE_INTERFACE.OperatingSystem.Status
25286cffd9cSAlexander Filippov            PROPERTY=OperatingSystemState
25386cffd9cSAlexander Filippov            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
25486cffd9cSAlexander Filippov            ;;
25579f697e0SAnthony Wilson        state|status)
25686cffd9cSAlexander Filippov            for query in bmcstate chassisstate hoststate bootprogress osstate
25779f697e0SAnthony Wilson            do
25879f697e0SAnthony Wilson                handle_cmd $query
25979f697e0SAnthony Wilson            done
26079f697e0SAnthony Wilson            ;;
26150c5f88dSAnthony Wilson        bootprogress)
26250c5f88dSAnthony Wilson            OBJECT=$STATE_OBJECT/host0
26350c5f88dSAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
26450c5f88dSAnthony Wilson            INTERFACE=$STATE_INTERFACE.Boot.Progress
26550c5f88dSAnthony Wilson            PROPERTY=BootProgress
26650c5f88dSAnthony Wilson            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
26750c5f88dSAnthony Wilson            ;;
2680f35983dSAnthony Wilson        power)
2690f35983dSAnthony Wilson            OBJECT=/org/openbmc/control/power0
2700f35983dSAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
2710f35983dSAnthony Wilson            INTERFACE=org.openbmc.control.Power
2720f35983dSAnthony Wilson            for property in pgood state pgood_timeout
2730f35983dSAnthony Wilson            do
2740f35983dSAnthony Wilson                # get_property can potentially return several
2750f35983dSAnthony Wilson                # different formats of values, so we do the parsing outside
2760f35983dSAnthony Wilson                # of get_property depending on the query. These queries
2770f35983dSAnthony Wilson                # return 'i VALUE' formatted strings.
2780f35983dSAnthony Wilson                STATE=$(get_property $SERVICE $OBJECT $INTERFACE $property \
2790f35983dSAnthony Wilson                    | sed 's/i[ ^I]*//')
2800f35983dSAnthony Wilson                printf "%s = %s\n" $property $STATE
2810f35983dSAnthony Wilson            done
2820f35983dSAnthony Wilson            ;;
283189cf248SAnthony Wilson        chassiskill)
284189cf248SAnthony Wilson            /usr/libexec/chassiskill
285189cf248SAnthony Wilson            ;;
286*a65d30d1SVishwanatha Subbanna        hostrebootoff)
2876d3a2c54SVishwanatha Subbanna            OBJECT=$CONTROL_OBJECT/host0/auto_reboot
2886d3a2c54SVishwanatha Subbanna            SERVICE=$(mapper get-service $OBJECT)
2896d3a2c54SVishwanatha Subbanna            INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
2906d3a2c54SVishwanatha Subbanna            PROPERTY=AutoReboot
2916d3a2c54SVishwanatha Subbanna            VALUE=false
2926d3a2c54SVishwanatha Subbanna            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
2936d3a2c54SVishwanatha Subbanna            ;;
294*a65d30d1SVishwanatha Subbanna        hostrebooton)
2956d3a2c54SVishwanatha Subbanna            OBJECT=$CONTROL_OBJECT/host0/auto_reboot
2966d3a2c54SVishwanatha Subbanna            SERVICE=$(mapper get-service $OBJECT)
2976d3a2c54SVishwanatha Subbanna            INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
2986d3a2c54SVishwanatha Subbanna            PROPERTY=AutoReboot
2996d3a2c54SVishwanatha Subbanna            VALUE=true
3006d3a2c54SVishwanatha Subbanna            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
3016d3a2c54SVishwanatha Subbanna            ;;
302*a65d30d1SVishwanatha Subbanna        bmcrebootoff)
303*a65d30d1SVishwanatha Subbanna            disable_bmc_reboot
304*a65d30d1SVishwanatha Subbanna            ;;
305*a65d30d1SVishwanatha Subbanna        bmcrebooton)
306*a65d30d1SVishwanatha Subbanna            enable_bmc_reboot
307*a65d30d1SVishwanatha Subbanna            ;;
3087a787dd7SVishwanatha Subbanna        recoveryoff)
309*a65d30d1SVishwanatha Subbanna            handle_cmd hostrebootoff
310*a65d30d1SVishwanatha Subbanna            handle_cmd bmcrebootoff
3117a787dd7SVishwanatha Subbanna            mask_systemd_target $HOST_TIMEOUT_TARGET
31284b3b29eSVishwanatha Subbanna            mask_systemd_target $HOST_CRASH_TARGET
3137a787dd7SVishwanatha Subbanna            ;;
3147a787dd7SVishwanatha Subbanna        recoveryon)
315*a65d30d1SVishwanatha Subbanna            handle_cmd hostrebooton
316*a65d30d1SVishwanatha Subbanna            handle_cmd bmcrebooton
3177a787dd7SVishwanatha Subbanna            unmask_systemd_target $HOST_TIMEOUT_TARGET
31884b3b29eSVishwanatha Subbanna            unmask_systemd_target $HOST_CRASH_TARGET
3197a787dd7SVishwanatha Subbanna            ;;
32079f697e0SAnthony Wilson        *)
321ea87db40SAnthony Wilson            print_usage_err "Invalid command '$1'"
32279f697e0SAnthony Wilson            ;;
32379f697e0SAnthony Wilson    esac
32479f697e0SAnthony Wilson}
32579f697e0SAnthony Wilson
326ea87db40SAnthony Wilsonfor arg in "$@"; do
327ea87db40SAnthony Wilson    case $arg in
328acf54d08SAnthony Wilson        -w|--wait)
329acf54d08SAnthony Wilson            G_WAIT=30
330acf54d08SAnthony Wilson            continue
331acf54d08SAnthony Wilson            ;;
332ea87db40SAnthony Wilson        -h|--help)
333ea87db40SAnthony Wilson            print_help
334ea87db40SAnthony Wilson            ;;
33560c3ac8cSAndrew Jeffery        -v|--verbose)
33660c3ac8cSAndrew Jeffery            G_VERBOSE=y
33760c3ac8cSAndrew Jeffery            ;;
338ea87db40SAnthony Wilson        -*)
339ea87db40SAnthony Wilson            print_usage_err "Unknown option: $arg"
340ea87db40SAnthony Wilson            ;;
341ea87db40SAnthony Wilson        *)
342acf54d08SAnthony Wilson            G_ORIG_CMD=$arg
343ea87db40SAnthony Wilson            handle_cmd $arg
344ea87db40SAnthony Wilson            break
345ea87db40SAnthony Wilson            ;;
346ea87db40SAnthony Wilson    esac
347ea87db40SAnthony Wilsondone
348