rc.d can now take --started, --stopped, --auto, --noauto as option which
help user to filter 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            |  124 +++++++++++++++++++++++++++++++++++++++---------------
 zsh-completion  |    8 +---
 3 files changed, 101 insertions(+), 51 deletions(-)

diff --git a/bash-completion b/bash-completion
index d78484e..4b4593b 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='-s --started -S --stopped -a --auto -A --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..3f2835e 100755
--- a/rc.d
+++ b/rc.d
@@ -4,74 +4,128 @@ 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 <action> [options] [daemons]
 
-<daemon> is the name of a script in /etc/rc.d
+options:
+  -s, --started     Filter started daemons
+  -S, --stopped     Filter stopped daemons
+  -a, --auto        Filter auto started daemons
+  -A, --noauto      Filter manually started daemons
+
+<daemons> is a space separated list of script in /etc/rc.d
 <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}
+}
+
+# filter list of daemons
+filter_daemons() {
+       local -a new_daemons=()
+       for daemon in "${daemons[@]}"; do
+               # check if daemons is valid
+               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
+               # check filter
+               ((${filter[started]} == 1)) && ck_daemon "$daemon" && continue
+               ((${filter[stopped]} == 1)) && ! ck_daemon "$daemon" && continue
+               ((${filter[auto]} == 1)) && ck_autostart "$daemon" && continue
+               ((${filter[noauto]} == 1)) && ! ck_autostart "$daemon" && 
continue
+               new_daemons+=("$daemon")
+       done
+       daemons=("${new_daemons[@]}")
 }
 
 (( $# < 1 )) && usage
 
+# ret store the return code of rc.d
 declare -i ret=0
-case $1 in
+# daemons store daemons on which action will be executed
+declare -a daemons=()
+# filter store current filter mode
+declare -A filter=([started]=0 [stopped]=0 [auto]=0 [noauto]=0)
+
+# parse options
+argv=$(getopt -l 'started,stopped,auto,noauto' -- 'sSaA' "$@") || usage
+eval set -- "$argv"
+
+# create an initial daemon list
+while [[ "$1" != -- ]]; do
+       case "$1" in
+               -s|--started)           filter[started]=1 ;;
+               -S|--stopped)           filter[stopped]=1 ;;
+               -a|--auto)                      filter[auto]=1 ;;
+               -A|--noauto)            filter[noauto]=1 ;;
+       esac
+       shift
+done
+
+# remove --
+shift
+# get action
+action=$1
+shift
+
+# get initial daemons list
+for daemon; do
+       daemons+=("$daemon")
+done
+
+# going into script directory
+cd /etc/rc.d
+
+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
+               filter_daemons
+               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
+               # other actions need an explicit daemons list
+               [[ -z $daemons ]] && usage
+               filter_daemons
                # 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..58fdfab 100644
--- a/zsh-completion
+++ b/zsh-completion
@@ -4,11 +4,10 @@ _rc.d () {
        local curcontext="$curcontext" state line
        typeset -A opt_args
 
-        _arguments "1: :->action" "*: :->service"
-
+       _arguments "1: :->action" "*: :->service" {-s,--started} {-S,--stopped} 
{-a,--auto} {-A,--noauto}
        case $state in
                action)
-                       _arguments "1:action:(list help start stop restart)"
+                       _arguments "*:action:(list help start stop restart)"
                        ;;
                service)
                        local action="$words[2]"
@@ -18,9 +17,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