summaryrefslogtreecommitdiff
path: root/usr.sbin/rcctl/rcctl.sh
diff options
context:
space:
mode:
authorAntoine Jacoutot <ajacoutot@cvs.openbsd.org>2015-01-06 11:47:51 +0000
committerAntoine Jacoutot <ajacoutot@cvs.openbsd.org>2015-01-06 11:47:51 +0000
commit50c20a585da962d8f29d5fd86fa43820882518c3 (patch)
tree318622f4d0bf78ba7e836e28c9a7fcf233977f4f /usr.sbin/rcctl/rcctl.sh
parent8f6e8cfcc35a35e78e0ab07e341e4a9b1c4c28ce (diff)
Major rcctl(8) rewrite to simplify it and add new features. It can now
configure "user" and "timeout". Committing now because there's been no release yet including rcctl(8) so it's easier to modify its usage. Usage extended (*retaining full backward compatibility for now*) to: rcctl set|get|getdef foobar [flags|user|timeout|status] The followings will be dropped soon but not right now to give people time to adjust: rcctl enable sshd flags # 'enable' takes no flags, use 'rcctl set ...' rcctl status sshd # use 'rcctl get sshd [flags|status|timeout|user]' rcctl default sshd # use 'rcctl getdef sshd [flags|status|timeout|user]' rcctl status # use 'rcctl getall' Man page changes will come soon. Make sure you have an up-to-date rc.subr. discussed with schwarze@ robert@ jasper@ sthen@ "love the idea" jasper@ ok schwarze@
Diffstat (limited to 'usr.sbin/rcctl/rcctl.sh')
-rw-r--r--usr.sbin/rcctl/rcctl.sh411
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}