diff options
-rw-r--r-- | usr.sbin/rcctl/rcctl.sh | 411 |
1 files changed, 232 insertions, 179 deletions
diff --git a/usr.sbin/rcctl/rcctl.sh b/usr.sbin/rcctl/rcctl.sh index 26aca62f10d..aa451070c96 100644 --- a/usr.sbin/rcctl/rcctl.sh +++ b/usr.sbin/rcctl/rcctl.sh @@ -1,8 +1,8 @@ #!/bin/sh # -# $OpenBSD: rcctl.sh,v 1.55 2015/01/01 09:44:20 ajacoutot Exp $ +# $OpenBSD: rcctl.sh,v 1.56 2015/01/06 11:47:50 ajacoutot Exp $ # -# Copyright (c) 2014 Antoine Jacoutot <ajacoutot@openbsd.org> +# Copyright (c) 2014, 2015 Antoine Jacoutot <ajacoutot@openbsd.org> # Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> # # Permission to use, copy, modify, and distribute this software for any @@ -27,8 +27,8 @@ _rc_parse_conf usage() { - _rc_err "usage: ${0##*/} [-df] enable|disable|status|default|order|action - [service | daemon [flags [arguments]] | daemons]" + _rc_err "usage: ${0##*/} [-df] enable|disable|get|set|getdef|getall|order|action + [service | daemon [variable [arguments]] | daemons]" } needs_root() @@ -46,6 +46,57 @@ ls_rcscripts() { done } +pkg_scripts_append() +{ + local _svc=$1 + [ -n "${_svc}" ] || return + + rcconf_edit_begin + if [ -z "${pkg_scripts}" ]; then + echo pkg_scripts="${_svc}" >>${_TMP_RCCONF} + elif ! echo ${pkg_scripts} | grep -qw -- ${_svc}; then + grep -v "^pkg_scripts.*=" /etc/rc.conf.local >${_TMP_RCCONF} + echo pkg_scripts="${pkg_scripts} ${_svc}" >>${_TMP_RCCONF} + fi + rcconf_edit_end +} + +pkg_scripts_order() +{ + local _svcs="$*" + [ -n "${_svcs}" ] || return + + needs_root ${action} + local _pkg_scripts _svc + for _svc in ${_svcs}; do + if svc_is_base ${_svc} || svc_is_special ${_svc}; then + _rc_err "${0##*/}: ${_svc} is not a pkg script" + elif ! svc_get ${_svc} status; then + _rc_err "${0##*/}: ${_svc} is not enabled" + fi + done + _pkg_scripts=$(echo "${_svcs} ${pkg_scripts}" | tr "[:blank:]" "\n" | \ + awk -v ORS=' ' '!x[$0]++') + rcconf_edit_begin + grep -v "^pkg_scripts.*=" /etc/rc.conf.local >${_TMP_RCCONF} + echo pkg_scripts=${_pkg_scripts} >>${_TMP_RCCONF} + rcconf_edit_end +} + +pkg_scripts_rm() +{ + local _svc=$1 + [ -n "${_svc}" ] || return + + [ -z "${pkg_scripts}" ] && return + + rcconf_edit_begin + sed "/^pkg_scripts[[:>:]]/{s/[[:<:]]${_svc}[[:>:]]//g + s/['\"]//g;s/ *= */=/;s/ */ /g;s/ $//;/=$/d;}" \ + /etc/rc.conf.local >${_TMP_RCCONF} + rcconf_edit_end +} + rcconf_edit_begin() { _TMP_RCCONF=$(mktemp -p /etc -t rc.conf.local.XXXXXXXXXX) || exit 1 @@ -64,19 +115,19 @@ rcconf_edit_end() if [ ! -s /etc/rc.conf.local ]; then rm /etc/rc.conf.local || exit 1 fi + _rc_parse_conf # reload new values } -svc_avail() +svc_is_avail() { local _svc=$1 - [ -n "${_svc}" ] || return 1 + [ -n "${_svc}" ] || return - [ "${_svc}" = "rc.subr" ] && return 1 [ -x "/etc/rc.d/${_svc}" ] && return 0 - svc_special ${_svc} + svc_is_special ${_svc} } -svc_base() +svc_is_base() { local _svc=$1 [ -n "${_svc}" ] || return @@ -84,219 +135,196 @@ svc_base() grep "^start_daemon " /etc/rc | cut -d ' ' -f2- | grep -qw -- ${_svc} } -svc_enabled() +svc_is_special() { local _svc=$1 [ -n "${_svc}" ] || return - [ "$(svc_flags ${_svc})" != "NO" ] + echo ${_special_services} | grep -qw -- ${_svc} } -svc_enabled_default() +svc_get() { local _svc=$1 [ -n "${_svc}" ] || return - local _ret=1 - - _rc_parse_conf /etc/rc.conf - svc_enabled ${_svc} && _ret=0 - _rc_parse_conf - - return ${_ret} -} -svc_flags() -{ - local _svc=$1 - [ -n "${_svc}" ] || return - local daemon_flags + local _status=0 _val _var=$2 + local daemon_flags daemon_timeout daemon_user - if svc_special ${_svc}; then - echo "$(eval echo \${${_svc}})" + if svc_is_special ${_svc}; then + daemon_flags="$(eval echo \${${_svc}})" else # set pkg daemon_flags to "NO" to match base svc - if ! svc_base ${_svc}; then + if ! svc_is_base ${_svc}; then if ! echo ${pkg_scripts} | grep -qw -- ${_svc}; then - echo "NO" && return + daemon_flags="NO" fi fi + [ -z "${daemon_flags}" ] && \ daemon_flags="$(eval echo \"\${${_svc}_flags}\")" [ -z "${daemon_flags}" ] && \ - daemon_flags="$(svc_flags_default ${_svc})" - - [ -n "${daemon_flags}" ] && print -r -- "${daemon_flags}" + daemon_flags="$(svc_getdef ${_svc} flags)" + [ -z "${daemon_timeout}" ] && \ + daemon_timeout="$(eval echo \"\${${_svc}_timeout}\")" + [ -z "${daemon_timeout}" ] && \ + daemon_timeout="$(svc_getdef ${_svc} timeout)" + [ -z "${daemon_user}" ] && \ + daemon_user="$(eval echo \"\${${_svc}_user}\")" + [ -z "${daemon_user}" ] && \ + daemon_user="$(svc_getdef ${_svc} user)" fi -} -# to prevent namespace pollution, only call in a subshell -svc_flags_default() -{ - local _svc=$1 - [ -n "${_svc}" ] || return + [ "${daemon_flags}" = "NO" ] && _status=1 - if svc_special ${_svc}; then - svc_enabled_default ${_svc} && echo "YES" || echo "NO" + if [ -n "${_var}" ]; then + [ "${_var}" = "status" ] && return ${_status} + eval _val=\${daemon_${_var}} + [ -z "${_val}" ] || print -r -- "${_val}" else - rc_cmd() { } - . /etc/rc.d/${_svc} >/dev/null 2>&1 - [ -n "${daemon_flags}" ] && print -r -- "${daemon_flags}" + if svc_is_special ${_svc}; then + echo "${_svc}=${daemon_flags}" + else + echo "${_svc}_flags=${daemon_flags}" + echo "${_svc}_timeout=${daemon_timeout}" + echo "${_svc}_user=${daemon_user}" + fi + return ${_status} fi } -svc_special() +# to prevent namespace pollution, only call in a subshell +svc_getdef() { local _svc=$1 [ -n "${_svc}" ] || return - echo ${_special_services} | grep -qw -- ${_svc} -} + local _status=0 _val _var=$2 + local daemon_flags daemon_timeout daemon_user -svc_status() -{ - local _i _svc=$1 - - if [ -n "${_svc}" ]; then - svc_flags ${_svc} - svc_enabled ${_svc} + if svc_is_special ${_svc}; then + # unconditionally parse: we always output flags and/or status + _rc_parse_conf /etc/rc.conf + daemon_flags="$(eval echo \${${_svc}})" + [ "${daemon_flags}" = "NO" ] && _status=1 else - for _i in $(ls_rcscripts); do - echo "${_i}_flags=$(svc_flags ${_i})" - done - for _i in ${_special_services}; do - echo "${_i}=$(svc_flags ${_i})" - done - fi -} + if ! svc_is_base ${_svc}; then + _status=1 # all pkg_scripts are off by default + else + + # abuse /etc/rc.conf behavior of only setting flags + # to empty or "NO" to get our default status; + # we'll get our default flags from the rc.d script + [[ -z ${_var} || ${_var} == status ]] && \ + _rc_parse_conf /etc/rc.conf + [ "$(eval echo \${${_svc}_flags})" = "NO" ] && _status=1 + fi -svc_status_default() -{ - local _i _svc=$1 + rc_cmd() { } + . /etc/rc.d/${_svc} >/dev/null 2>&1 + + [ -z "${daemon_timeout}" ] && daemon_timeout=30 + [ -z "${daemon_user}" ] && daemon_user=root + fi - if [ -n "${_svc}" ]; then - ( svc_flags_default ${_svc} ) - svc_enabled_default ${_svc} + if [ -n "${_var}" ]; then + [ "${_var}" = "status" ] && return ${_status} + eval _val=\${daemon_${_var}} + [ -z "${_val}" ] || print -r -- "${_val}" else - for _i in $(ls_rcscripts); do - echo "${_i}_flags=$(svc_flags_default ${_i})" - done - for _i in ${_special_services}; do - echo "${_i}=$(svc_flags_default ${_i})" - done + if svc_is_special ${_svc}; then + echo "${_svc}=${daemon_flags}" + else + echo "${_svc}_flags=${daemon_flags}" + echo "${_svc}_timeout=${daemon_timeout}" + echo "${_svc}_user=${daemon_user}" + fi + return ${_status} fi } -pkg_scripts_append() +svc_rm() { local _svc=$1 [ -n "${_svc}" ] || return rcconf_edit_begin - if [ -z "${pkg_scripts}" ]; then - echo pkg_scripts="${_svc}" >>${_TMP_RCCONF} - elif ! echo ${pkg_scripts} | grep -qw -- ${_svc}; then - grep -v "^pkg_scripts.*=" /etc/rc.conf.local >${_TMP_RCCONF} - echo pkg_scripts="${pkg_scripts} ${_svc}" >>${_TMP_RCCONF} + if svc_is_special ${_svc}; then + grep -v "^${_svc}.*=" /etc/rc.conf.local >${_TMP_RCCONF} + ( svc_getdef ${_svc} status ) && \ + echo "${_svc}=NO" >>${_TMP_RCCONF} + else + grep -Ev "^${_svc}_(flags|user|timeout).*=" \ + /etc/rc.conf.local >${_TMP_RCCONF} + ( svc_getdef ${_svc} status ) && \ + echo "${_svc}_flags=NO" >>${_TMP_RCCONF} fi rcconf_edit_end } -pkg_scripts_order() +svc_set() { - local _svcs="$*" - [ -n "${_svcs}" ] || return - - needs_root ${action} - local _pkg_scripts _svc - for _svc in ${_svcs}; do - if svc_base ${_svc} || svc_special ${_svc}; then - _rc_err "${0##*/}: ${_svc} is not a pkg script" - elif ! svc_enabled ${_svc}; then - _rc_err "${0##*/}: ${_svc} is not enabled" + local _svc=$1 _var=$2 + [ -n "${_svc}" -a -n "${_var}" ] || return + + shift 2 + local _flags="$*" + + if [ "${_var}" = "status" ]; then + if [ "${_flags}" = "on" ]; then + _var="flags" + # keep our flags if we're already enabled + eval "_flags=\"\${${_svc}_${_var}}\"" + [ "${_flags}" = "NO" ] && unset _flags + if ! svc_is_base ${_svc} && ! svc_is_special ${_svc}; then + pkg_scripts_append ${_svc} + fi + elif [ "${_flags}" = "off" ]; then + if ! svc_is_base ${_svc} && ! svc_is_special ${_svc}; then + pkg_scripts_rm ${_svc} + fi + svc_rm ${_svc} + return + else + _rc_err "${0##*/}: invalid status \"${_flags}\"" fi - done - _pkg_scripts=$(echo "${_svcs} ${pkg_scripts}" | tr "[:blank:]" "\n" | \ - awk -v ORS=' ' '!x[$0]++') - rcconf_edit_begin - grep -v "^pkg_scripts.*=" /etc/rc.conf.local >${_TMP_RCCONF} - echo pkg_scripts=${_pkg_scripts} >>${_TMP_RCCONF} - rcconf_edit_end -} - -pkg_scripts_rm() -{ - local _svc=$1 - [ -n "${_svc}" ] || return - - [ -z "${pkg_scripts}" ] && return - - rcconf_edit_begin - sed "/^pkg_scripts[[:>:]]/{s/[[:<:]]${_svc}[[:>:]]//g - s/['\"]//g;s/ *= */=/;s/ */ /g;s/ $//;/=$/d;}" \ - /etc/rc.conf.local >${_TMP_RCCONF} - rcconf_edit_end -} - -add_flags() -{ - local _svc=$1 - [ -n "${_svc}" ] || return + else + svc_get ${_svc} status || \ + _rc_err "${0##*/}: ${svc} is not enabled" + fi - if svc_special ${_svc}; then + if svc_is_special ${_svc}; then + [ "${_var}" = "flags" ] || return rcconf_edit_begin grep -v "^${_svc}.*=" /etc/rc.conf.local >${_TMP_RCCONF} - if ! svc_enabled_default ${_svc}; then + ( svc_getdef ${_svc} status ) || \ echo "${_svc}=YES" >>${_TMP_RCCONF} - fi rcconf_edit_end return fi - local _flags - - if [ -n "$2" ]; then - shift 2 - _flags="$*" - else - # keep our flags since none were given - eval "_flags=\"\${${_svc}_flags}\"" - [ "${_flags}" = "NO" ] && unset _flags + if [ "${_var}" = "timeout" ]; then + [[ ${_flags} != +([[:digit:]]) || ${_flags} -le 0 ]] && \ + _rc_err "${0##*/}: \"${_flags}\" is not an integer" fi # unset flags if they match the default enabled ones if [ -n "${_flags}" ]; then - [ "${_flags}" = "$(svc_flags_default ${_svc})" ] && \ + [ "${_flags}" = "$(svc_getdef ${_svc} ${_var})" ] && \ unset _flags fi # protect leading whitespace [ "${_flags}" = "${_flags# }" ] || _flags="\"${_flags}\"" - rcconf_edit_begin - grep -v "^${_svc}_flags.*=" /etc/rc.conf.local >${_TMP_RCCONF} - if [ -n "${_flags}" ] || \ - ( svc_base ${_svc} && ! svc_enabled_default ${_svc} ); then - echo "${_svc}_flags=${_flags}" >>${_TMP_RCCONF} - fi - rcconf_edit_end -} - -rm_flags() -{ - local _svc=$1 - [ -n "${_svc}" ] || return + # reset: value may have changed + unset ${_svc}_${_var} rcconf_edit_begin - if svc_special ${_svc}; then - grep -v "^${_svc}.*=" /etc/rc.conf.local >${_TMP_RCCONF} - if svc_enabled_default ${_svc}; then - echo "${_svc}=NO" >>${_TMP_RCCONF} - fi - else - grep -v "^${_svc}_flags.*=" /etc/rc.conf.local >${_TMP_RCCONF} - if svc_enabled_default ${_svc}; then - echo "${_svc}_flags=NO" >>${_TMP_RCCONF} - fi + grep -v "^${_svc}_${_var}.*=" /etc/rc.conf.local >${_TMP_RCCONF} + if [ -n "${_flags}" ] || \ + ( svc_is_base ${_svc} && ! svc_getdef ${_svc} status && [ "${_var}" == "flags" ] ); then + echo "${_svc}_${_var}=${_flags}" >>${_TMP_RCCONF} fi rcconf_edit_end } @@ -324,47 +352,60 @@ else fi if [ -n "${svc}" ]; then - if ! svc_avail ${svc}; then + [[ ${action} = getall ]] && usage + svc_is_avail ${svc} || \ _rc_err "${0##*/}: service ${svc} does not exist" 2 - fi -elif [[ ${action} != @(default|order|status) ]] ; then +elif [[ ${action} != @(getall|order|status) ]] ; then usage fi if [ -n "${flag}" ]; then - if [ "${flag}" = "flags" ]; then - if [ "${action}" != "enable" ]; then - _rc_err "${0##*/}: \"${flag}\" can only be set with \"enable\"" - fi - if svc_special ${svc} && [ -n "${flags}" ]; then - _rc_err "${0##*/}: \"${svc}\" is a special variable, cannot set \"${flag}\"" - fi - if [ "${flag}" = "flags" -a "${flags}" = "NO" ]; then - _rc_err "${0##*/}: \"flags ${flags}\" contradicts \"enable\"" + [[ ${flag} != @(flags|status|timeout|user) ]] && usage + [[ ${action} != @(enable|get|getdef|set) ]] && usage + [[ ${action} == @(enable|set) && ${flag} = flags && ${flags} = NO ]] && \ + _rc_err "${0##*/}: \"flags NO\" contradicts \"${action}\"" + if svc_is_special ${svc}; then + if [[ ${flag} != @(flags|status) || \ + ${action} != @(set|get|getdef|enable) ]] || \ + [[ ${action} == @(enable|set) && -n ${flags} ]]; then + _rc_err "${0##*/}: \"${svc}\" is a special variable, cannot \"${action} ${svc} ${flag}\"" fi - else - usage fi + [[ ${action} == enable && ${flag} != flags ]] && \ + _rc_err "${0##*/}: invalid action \"${action} ${svc} ${flag}\"" +elif [ ${action} = "set" ]; then + usage fi case ${action} in - default) - svc_status_default ${svc} + default) # XXX backward compat + ( svc_getdef ${svc} flags ) + ( svc_getdef ${svc} status ) ;; disable) needs_root ${action} - if ! svc_base ${svc} && ! svc_special ${svc}; then - pkg_scripts_rm ${svc} - fi - rm_flags ${svc} + svc_set ${svc} status off ;; enable) needs_root ${action} - add_flags ${svc} "${flag}" "${flags}" - if ! svc_base ${svc} && ! svc_special ${svc}; then - pkg_scripts_append ${svc} + svc_set ${svc} status on + # XXX backward compat + if [ -n "${flag}" ]; then + svc_set ${svc} "${flag}" "${flags}" fi ;; + get) + svc_get ${svc} "${flag}" + ;; + getall) + for i in $(ls_rcscripts) ${_special_services}; do + svc_get ${i} + done + return 0 # we do not want the "status" + ;; + getdef) + ( svc_getdef ${svc} "${flag}" ) + ;; order) if [ -n "${svcs}" ]; then needs_root ${action} @@ -373,11 +414,23 @@ case ${action} in [[ -z ${pkg_scripts} ]] || echo ${pkg_scripts} fi ;; - status) - svc_status ${svc} + set) + needs_root ${action} + svc_set ${svc} "${flag}" "${flags}" + ;; + status) # XXX backward compat + if [ -n "${svc}" ]; then + svc_get ${svc} flags + svc_get ${svc} status + else + for i in $(ls_rcscripts) ${_special_services}; do + svc_get ${i} + done + return 0 # we do not want the "status" + fi ;; start|stop|restart|reload|check) - if svc_special ${svc}; then + if svc_is_special ${svc}; then _rc_err "${0##*/}: \"${svc}\" is a special variable, no rc.d(8) script" fi /etc/rc.d/${svc} ${_RC_DEBUG} ${_RC_FORCE} ${action} |