[arch-projects] [INITSCRIPTS][PATCH] rc.d: handle a set of options
Lukas Fleischer
archlinux at cryptocrack.de
Tue Aug 23 10:58:33 EDT 2011
On Tue, Aug 23, 2011 at 03:32:32PM +0200, Sebastien Luttringer wrote:
> rc.d can now take --started, --stopped, --auto, --noauto as option which
> help user to populate list of daemon for all actions
>
> As a corollary list command can now take a list of dameon to display
> All kind of arguments can be mixed to obtain the proper output.
>
> zsh and bash completion are updated
>
> Note: Output of help command exit 0 and is no more printed on stderr
>
> Signed-off-by: Sebastien Luttringer <seblu at seblu.net>
> ---
> bash-completion | 20 +++++-----
> rc.d | 109 ++++++++++++++++++++++++++++++++++++++-----------------
> zsh-completion | 5 +--
> 3 files changed, 86 insertions(+), 48 deletions(-)
>
> diff --git a/bash-completion b/bash-completion
> index d78484e..1df229e 100644
> --- a/bash-completion
> +++ b/bash-completion
> @@ -3,20 +3,20 @@
> _rc_d()
> {
> local action cur prev
> - action="help list start stop reload restart"
> + actions='help list start stop reload restart'
> + options='--started --stopped --auto --noauto'
> _get_comp_words_by_ref cur prev
> - if ((COMP_CWORD == 1)); then
> - COMPREPLY=($(compgen -W "${action}" -- "$cur"))
> - elif [[ "$prev" == help ]]; then
> + _get_first_arg
> + if [[ -z "$arg" ]]; then
> + COMPREPLY=($(compgen -W "${actions} ${options}" -- "$cur"))
> + elif [[ "$arg" == help ]]; then
> COMPREPLY=()
> - elif [[ "$prev" == list ]]; then
> - ((COMP_CWORD == 2)) && COMPREPLY=($(compgen -W "started stopped" -- "$cur")) || COMPREPLY=()
> - elif [[ "$prev" == start ]]; then
> + elif [[ "$arg" == start ]]; then
> COMPREPLY=($(comm -23 <(cd /etc/rc.d && compgen -f -X 'functions*' "$cur"|sort) <(cd /run/daemons/ && compgen -f "$cur"|sort)))
> - elif [[ "$prev" =~ stop|restart|reload ]]; then
> + elif [[ "$arg" =~ stop|restart|reload ]]; then
> COMPREPLY=($(cd /run/daemons/ && compgen -f "$cur"|sort))
> - elif ((COMP_CWORD > 1)); then
> - COMPREPLY=($(cd /etc/rc.d && compgen -f -X 'functions*' "$cur"|sort))
> + else
> + COMPREPLY=($(compgen -W "${options} $(cd /etc/rc.d && compgen -f -X 'functions*')" -- "$cur"))
> fi
> }
> complete -F _rc_d rc.d
> diff --git a/rc.d b/rc.d
> index 9b0f092..907439b 100755
> --- a/rc.d
> +++ b/rc.d
> @@ -4,74 +4,115 @@ NEED_ROOT=0 # this script can be run without be root
> . /etc/rc.conf
> . /etc/rc.d/functions
>
> +# print usage and exit
> usage() {
> local name=${0##*/}
> cat >&2 << EOF
> -usage: $name <action> <daemon> [daemon] ...
> - $name list [started|stopped]
> - $name help
> +usage: $name [options] <action> [daemons]
"usage: $name <action> [options] [daemons]". Although it doesn't really
matter, `rc.d list --started` should be the default way of specifying
arguments, see your examples further below.
>
> -<daemon> is the name of a script in /etc/rc.d
> +options:
> + --started Append started daemons to the list
> + --stopped Append stopped dameons to the list
> + --auto Append autostarted daemons to the list
> + --noauto Append not autostarted daemons to the list
> +
> +<daemons> is space separated list of script in /etc/rc.d
... is *a* space separated list of script*s*.
> <action> can be a start, stop, restart, reload, status, ...
> WARNING: initscripts are free to implement or not the above actions.
>
> e.g: $name list
> - $name list started
> - $name help
> + $name list sshd gpm
> + $name list --started gpm
> $name start sshd gpm
> + $name stop --noauto
> + $name help
> EOF
> - exit 1
> + exit ${1:-1}
> }
>
> (( $# < 1 )) && usage
>
> +# parse options
> +argv=$(getopt -l 'started,stopped,auto,noauto' -- '' "$@")
> +(( $? )) && usage
`argv=$(getopt -l 'started,stopped,auto,noauto' -- '' "$@") || usage`.
> +eval set -- "$argv"
> +
> +# going into script directory
> +cd /etc/rc.d
> +
> +# create an initial daemon list
> +declare -a daemons=()
> +while [[ "$1" != -- ]]; do
> + case "$1" in
> + --started)
> + for d in *; do have_daemon "$d" && ! ck_daemon "$d" && daemons+=("$d"); done
> + ;;
> + --stopped)
> + for d in *; do have_daemon "$d" && ck_daemon "$d" && daemons+=("$d"); done
> + ;;
> + --auto)
> + for d in *; do have_daemon "$d" && ! ck_autostart "$d" && daemons+=("$d"); done
> + ;;
> + --noauto)
> + for d in *; do have_daemon "$d" && ck_autostart "$d" && daemons+=("$d"); done
> + ;;
Oh. I thought of an implicit conjunction over the single filter options
here. This is advantageous if you want to list running auto-started
daemons (`rc.d list --started --auto`) etc. I would just set some flag
when parsing the options and filter the daemon list in a single loop
later on (which is faster, also).
> + esac
> + shift
> +done
> +
> +# remove --
> +shift
> +# get action
> +action=$1
> +shift
> +
> +# add daemons
> +for daemon; do
> + if ! have_daemon "$daemon"; then
> + printf "${C_FAIL}:: ${C_DONE}Dameon script ${C_FAIL}${daemon}${C_DONE} does \
> +not exist or is not executable.${C_CLEAR}\n" >&2
> + exit 2
> + fi
> + daemons+=("$daemon")
> +done
Same here. Explicitly specified daemons should not be added to the list,
but used as input to the filter options (if any). I would suggest
following procedure:
Iterate over the daemons specified on the command line if any,
"/etc/rc.d/*" otherwise:
* Set some flag to 1 (indicating whether the daemon will be included in
the list or not).
* If "--started" or "--stopped" are specified (you stored this in some
other flag earlier), possibly reset the flag to 0, depending on what
ck_daemon() returns.
* Do the same thing with "--auto" or "--noauto" (and ck_autostart()).
* Add the daemon to some array if the flag is still set to 1.
This removes the need for special treatment in any of the action cases
below, also.
> +
> declare -i ret=0
> -case $1 in
> +case $action in
> help)
> - usage
> - ;;
> + usage 0 2>&1
> + ;;
> list)
> - shift
> - cd /etc/rc.d/
> - for d in *; do
> - have_daemon "$d" || continue
> + # list take all daemons by default
> + [[ -z $daemons ]] && for d in *; do have_daemon "$d" && daemons+=("$d"); done
> + for daemon in "${daemons[@]}"; do
> # print running / stopped satus
> - if ! ck_daemon "$d"; then
> - [[ "$1" == stopped ]] && continue
> - printf "${C_OTHER}[${C_DONE}STARTED${C_OTHER}]"
> + if ! ck_daemon "$daemon"; then
> + s_status="${C_OTHER}[${C_DONE}STARTED${C_OTHER}]"
> else
> - [[ "$1" == started ]] && continue
> - printf "${C_OTHER}[${C_FAIL}STOPPED${C_OTHER}]"
> + s_status="${C_OTHER}[${C_FAIL}STOPPED${C_OTHER}]"
> fi
> # print auto / manual status
> - if ! ck_autostart "$d"; then
> - printf "${C_OTHER}[${C_DONE}AUTO${C_OTHER}]"
> + if ! ck_autostart "$daemon"; then
> + s_auto="${C_OTHER}[${C_DONE}AUTO${C_OTHER}]"
> else
> - printf "${C_OTHER}[${C_FAIL} ${C_OTHER}]"
> + s_auto="${C_OTHER}[${C_FAIL} ${C_OTHER}]"
> fi
> - printf " ${C_CLEAR}$d\n"
> + printf "$s_status$s_auto${C_CLEAR} $daemon\n"
> done
> ;;
> *)
> # check min args count
> - (( $# < 2 )) && usage
> - action=$1
> - shift
> + [[ -z $daemons ]] && usage
> # set same environment variables as init
> runlevel=$(/sbin/runlevel)
> - ENV=("PATH=/bin:/usr/bin:/sbin:/usr/sbin"
> + ENV=('PATH=/bin:/usr/bin:/sbin:/usr/sbin'
> "PREVLEVEL=${runlevel%% *}"
> "RUNLEVEL=${runlevel##* }"
> "CONSOLE=${CONSOLE:-/dev/console}"
> "TERM=$TERM")
> cd /
> - for i; do
> - if [[ -x "/etc/rc.d/$i" ]]; then
> - env -i "${ENV[@]}" "/etc/rc.d/$i" "$action"
> - else
> - printf "${C_FAIL}:: ${C_DONE}Daemon ${C_FAIL}$i${C_DONE} does not exist \
> -or is not executable${C_CLEAR}\n"
> - fi
> + for daemon in "${daemons[@]}"; do
> + env -i "${ENV[@]}" "/etc/rc.d/$daemon" "$action"
> (( ret += !! $? )) # clamp exit value to 0/1
> done
> ;;
> diff --git a/zsh-completion b/zsh-completion
> index e5c2850..69b3896 100644
> --- a/zsh-completion
> +++ b/zsh-completion
> @@ -4,7 +4,7 @@ _rc.d () {
> local curcontext="$curcontext" state line
> typeset -A opt_args
>
> - _arguments "1: :->action" "*: :->service"
> + _arguments "1: :->action" "*: :->service" "--started" "--stopped" "--auto" "--noauto"
>
> case $state in
> action)
> @@ -18,9 +18,6 @@ _rc.d () {
> help)
> _arguments "*: :"
> ;;
> - list)
> - _arguments "2: :(started stopped)"
> - ;;
> start)
> _arguments "*: :($(comm -23 <(echo /etc/rc.d/*(N-*:t)|tr ' ' '\n') <(echo /run/daemons/*(N:t)|tr ' ' '\n')))"
> ;;
> --
> Sebastien "Seblu" Luttringer
More information about the arch-projects
mailing list