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 <seblu@seblu.net> --- 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