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 <[email protected]>
> ---
>  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

Reply via email to