1#!/bin/ksh 2# 3# $OpenBSD: rcctl.sh,v 1.120 2024/09/29 14:36:13 kn Exp $ 4# 5# Copyright (c) 2014, 2015-2022 Antoine Jacoutot <ajacoutot@openbsd.org> 6# Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> 7# 8# Permission to use, copy, modify, and distribute this software for any 9# purpose with or without fee is hereby granted, provided that the above 10# copyright notice and this permission notice appear in all copies. 11# 12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 20_special_svcs="accounting check_quotas ipsec library_aslr multicast pf 21 spamd_black" 22readonly _special_svcs 23 24# get local functions from rc.subr(8) 25FUNCS_ONLY=1 26. /etc/rc.d/rc.subr 27_rc_parse_conf 28 29usage() 30{ 31 local _a _i 32 for _i in ${_rc_actions}; do _a=${_a:+${_a}|}$_i; done 33 34 _rc_err \ 35 "usage: rcctl get|getdef|set daemon|service [variable [argument ...]] 36 rcctl [-df] ${_a} daemon ... 37 rcctl disable|enable|order [daemon ...] 38 rcctl ls all|failed|off|on|rogue|started|stopped" 39} 40 41needs_root() 42{ 43 [ "$(id -u)" -ne 0 ] && _rc_err "${0##*/}: \"$*\" needs root privileges" 44} 45 46rcctl_err() 47{ 48 _rc_err "${0##*/}: ${1}" ${2} 49} 50 51ls_rcscripts() 52{ 53 local _s 54 55 cd /etc/rc.d && set -- * 56 for _s; do 57 [[ ${_s} == +([[:alnum:]_]) ]] || continue 58 [ ! -d "${_s}" ] && echo "${_s}" 59 done 60} 61 62pkg_scripts_append() 63{ 64 local _svc=$1 65 [ -n "${_svc}" ] || return 66 67 rcconf_edit_begin 68 if [ -z "${pkg_scripts}" ]; then 69 echo pkg_scripts="${_svc}" >>${_TMP_RCCONF} 70 elif ! echo ${pkg_scripts} | grep -qw -- ${_svc}; then 71 grep -v "^pkg_scripts.*=" /etc/rc.conf.local >${_TMP_RCCONF} 72 echo pkg_scripts="${pkg_scripts} ${_svc}" >>${_TMP_RCCONF} 73 fi 74 rcconf_edit_end 75} 76 77pkg_scripts_order() 78{ 79 local _svcs="$*" 80 [ -n "${_svcs}" ] || return 81 82 needs_root ${action} 83 local _pkg_scripts _svc 84 for _svc in ${_svcs}; do 85 if svc_is_base ${_svc} || svc_is_special ${_svc}; then 86 rcctl_err "${_svc} is not a pkg script" 87 elif ! svc_get ${_svc} status; then 88 rcctl_err "${_svc} is not enabled" 89 fi 90 done 91 _pkg_scripts=$(echo "${_svcs} ${pkg_scripts}" | tr "[:blank:]" "\n" | \ 92 awk -v ORS=' ' '!x[$0]++') 93 rcconf_edit_begin 94 grep -v "^pkg_scripts.*=" /etc/rc.conf.local >${_TMP_RCCONF} 95 echo pkg_scripts=${_pkg_scripts} >>${_TMP_RCCONF} 96 rcconf_edit_end 97} 98 99pkg_scripts_rm() 100{ 101 local _svc=$1 102 [ -n "${_svc}" ] || return 103 104 [ -z "${pkg_scripts}" ] && return 105 106 rcconf_edit_begin 107 sed "/^pkg_scripts[[:>:]]/{s/[[:<:]]${_svc}[[:>:]]//g 108 s/['\"]//g;s/ *= */=/;s/ */ /g;s/ $//;/=$/d;}" \ 109 /etc/rc.conf.local >${_TMP_RCCONF} 110 rcconf_edit_end 111} 112 113rcconf_edit_begin() 114{ 115 _TMP_RCCONF=$(mktemp -p /etc -t rc.conf.local.XXXXXXXXXX) || \ 116 rcctl_err "cannot create temporary file under /etc" 117 if [ -f /etc/rc.conf.local ]; then 118 cat /etc/rc.conf.local >${_TMP_RCCONF} || \ 119 rcctl_err "cannot append to ${_TMP_RCCONF}" 120 else 121 touch /etc/rc.conf.local || \ 122 rcctl_err "cannot create /etc/rc.conf.local" 123 fi 124} 125 126rcconf_edit_end() 127{ 128 sort -u -o ${_TMP_RCCONF} ${_TMP_RCCONF} || \ 129 rcctl_err "cannot modify ${_TMP_RCCONF}" 130 if ! cmp -s ${_TMP_RCCONF} /etc/rc.conf.local; then 131 install -F -m0644 -o0 -g0 ${_TMP_RCCONF} /etc/rc.conf.local || 132 rcctl_err "cannot write to /etc/rc.conf.local" 133 fi 134 if [ ! -s /etc/rc.conf.local ]; then 135 rm /etc/rc.conf.local || \ 136 rcctl_err "cannot remove /etc/rc.conf.local" 137 fi 138 rm -f ${_TMP_RCCONF} 139 _rc_parse_conf # reload new values 140} 141 142svc_is_avail() 143{ 144 local _svc=$1 145 _rc_check_name "${_svc}" || return 146 147 [ -x "/etc/rc.d/${_svc}" ] && return 148 svc_is_special ${_svc} 149} 150 151svc_is_base() 152{ 153 local _svc=$1 154 [ -n "${_svc}" ] || return 155 156 local _cached _ret 157 158 _cached=$(eval echo \${cached_svc_is_base_${_svc}}) 159 [ "${_cached}" ] && return "${_cached}" 160 161 grep -qw "^${_svc}_flags" /etc/rc.conf 162 _ret=$? 163 164 set -A cached_svc_is_base_${_svc} -- ${_ret} 165 return ${_ret} 166} 167 168svc_is_meta() 169{ 170 local _svc=$1 171 [ -n "${_svc}" ] || return 172 173 local _cached _ret 174 175 _cached=$(eval echo \${cached_svc_is_meta_${_svc}}) 176 [ "${_cached}" ] && return "${_cached}" 177 178 [ -r "/etc/rc.d/${_svc}" ] && ! grep -qw "^rc_cmd" /etc/rc.d/${_svc} 179 _ret=$? 180 181 set -A cached_svc_is_meta_${_svc} -- ${_ret} 182 return ${_ret} 183} 184 185svc_is_special() 186{ 187 local _svc=$1 188 [ -n "${_svc}" ] || return 189 190 local _cached _ret 191 192 _cached=$(eval echo \${cached_svc_is_special_${_svc}}) 193 [ "${_cached}" ] && return "${_cached}" 194 195 echo ${_special_svcs} | grep -qw -- ${_svc} 196 _ret=$? 197 198 set -A cached_svc_is_special_${_svc} -- ${_ret} 199 return ${_ret} 200} 201 202svc_ls() 203{ 204 local _lsarg=$1 205 [ -n "${_lsarg}" ] || return 206 207 # we do not want to return the "status" nor the rc.d(8) script retcode 208 local _ret=0 _on _svc _started 209 210 case ${_lsarg} in 211 all) 212 ( 213 ls_rcscripts 214 echo ${_special_svcs} | tr "[:blank:]" "\n" 215 ) | sort 216 ;; 217 failed) 218 for _svc in $(svc_ls on); do 219 ! svc_is_special ${_svc} && \ 220 ! /etc/rc.d/${_svc} check >/dev/null && \ 221 echo ${_svc} && _ret=1 222 done 223 ;; 224 off|on) 225 for _svc in $(svc_ls all); do 226 svc_get ${_svc} status && _on=1 227 [ "${_lsarg}" = "on" -a -n "${_on}" ] || \ 228 [ "${_lsarg}" = "off" -a -z "${_on}" ] && \ 229 echo ${_svc} 230 unset _on 231 done 232 ;; 233 rogue) 234 for _svc in $(svc_ls off); do 235 ! svc_is_special ${_svc} && \ 236 /etc/rc.d/${_svc} check >/dev/null && \ 237 echo ${_svc} && _ret=1 238 done 239 ;; 240 started|stopped) 241 for _svc in $(ls_rcscripts); do 242 /etc/rc.d/${_svc} check >/dev/null && _started=1 243 [ "${_lsarg}" = "started" -a -n "${_started}" ] || \ 244 [ "${_lsarg}" = "stopped" -a -z "${_started}" ] && \ 245 echo ${_svc} 246 unset _started 247 done 248 ;; 249 *) 250 _ret=1 251 ;; 252 esac 253 254 return ${_ret} 255} 256 257svc_get() 258{ 259 local _svc=$1 260 [ -n "${_svc}" ] || return 261 262 local _status=0 _val _var=$2 263 local daemon_class daemon_execdir daemon_flags daemon_logger 264 local daemon_rtable daemon_timeout daemon_user 265 266 if svc_is_special ${_svc}; then 267 daemon_flags="$(eval echo \${${_svc}})" 268 else 269 # set pkg daemon_flags to "NO" to match base svc 270 if ! svc_is_base ${_svc}; then 271 if ! echo ${pkg_scripts} | grep -qw -- ${_svc}; then 272 daemon_flags="NO" 273 fi 274 fi 275 276 if ! svc_is_meta ${_svc}; then 277 # these are expensive, make sure they are explicitly requested 278 if [ -z "${_var}" -o "${_var}" = "class" ]; then 279 getcap -f /etc/login.conf.d/${_svc}:/etc/login.conf \ 280 ${_svc} 1>/dev/null 2>&1 && daemon_class=${_svc} 281 [ -z "${daemon_class}" ] && \ 282 daemon_class="$(svc_getdef ${_svc} class)" 283 fi 284 if [ -z "${_var}" -o "${_var}" = "execdir" ]; then 285 [ -z "${daemon_execdir}" ] && \ 286 daemon_execdir="$(eval echo \"\${${_svc}_execdir}\")" 287 [ -z "${daemon_execdir}" ] && \ 288 daemon_execdir="$(svc_getdef ${_svc} execdir)" 289 fi 290 if [[ -z ${_var} || ${_var} == @(flags|status) ]]; then 291 [ -z "${daemon_flags}" ] && \ 292 daemon_flags="$(eval echo \"\${${_svc}_flags}\")" 293 [ -z "${daemon_flags}" ] && \ 294 daemon_flags="$(svc_getdef ${_svc} flags)" 295 fi 296 if [ -z "${_var}" -o "${_var}" = "logger" ]; then 297 [ -z "${daemon_logger}" ] && \ 298 daemon_logger="$(eval echo \"\${${_svc}_logger}\")" 299 [ -z "${daemon_logger}" ] && \ 300 daemon_logger="$(svc_getdef ${_svc} logger)" 301 fi 302 if [ -z "${_var}" -o "${_var}" = "rtable" ]; then 303 [ -z "${daemon_rtable}" ] && \ 304 daemon_rtable="$(eval echo \"\${${_svc}_rtable}\")" 305 [ -z "${daemon_rtable}" ] && \ 306 daemon_rtable="$(svc_getdef ${_svc} rtable)" 307 fi 308 if [ -z "${_var}" -o "${_var}" = "timeout" ]; then 309 [ -z "${daemon_timeout}" ] && \ 310 daemon_timeout="$(eval echo \"\${${_svc}_timeout}\")" 311 [ -z "${daemon_timeout}" ] && \ 312 daemon_timeout="$(svc_getdef ${_svc} timeout)" 313 fi 314 if [ -z "${_var}" -o "${_var}" = "user" ]; then 315 [ -z "${daemon_user}" ] && \ 316 daemon_user="$(eval echo \"\${${_svc}_user}\")" 317 [ -z "${daemon_user}" ] && \ 318 daemon_user="$(svc_getdef ${_svc} user)" 319 fi 320 fi 321 fi 322 323 [ "${daemon_flags}" = "NO" ] && _status=1 324 325 if [ -n "${_var}" ]; then 326 [ "${_var}" = "status" ] && return ${_status} 327 eval _val=\${daemon_${_var}} 328 [ -z "${_val}" ] || print -r -- "${_val}" 329 else 330 svc_is_meta ${_svc} && return ${_status} 331 if svc_is_special ${_svc}; then 332 echo "${_svc}=${daemon_flags}" 333 else 334 echo "${_svc}_class=${daemon_class}" 335 echo "${_svc}_execdir=${daemon_execdir}" 336 echo "${_svc}_flags=${daemon_flags}" 337 echo "${_svc}_logger=${daemon_logger}" 338 echo "${_svc}_rtable=${daemon_rtable}" 339 echo "${_svc}_timeout=${daemon_timeout}" 340 echo "${_svc}_user=${daemon_user}" 341 fi 342 return ${_status} 343 fi 344} 345 346# to prevent namespace pollution, only call in a subshell 347svc_getdef() 348{ 349 local _svc=$1 350 [ -n "${_svc}" ] || return 351 352 local _status=0 _val _var=$2 353 local daemon_class daemon_execdir daemon_flags daemon_logger 354 local daemon_rtable daemon_timeout daemon_user 355 356 if svc_is_special ${_svc}; then 357 # unconditionally parse: we always output flags and/or status 358 _rc_parse_conf /etc/rc.conf 359 daemon_flags="$(eval echo \${${_svc}})" 360 [ "${daemon_flags}" = "NO" ] && _status=1 361 else 362 if ! svc_is_base ${_svc}; then 363 _status=1 # all pkg_scripts are off by default 364 else 365 # abuse /etc/rc.conf behavior of only setting flags 366 # to empty or "NO" to get our default status; 367 # we'll get our default flags from the rc.d script 368 [[ -z ${_var} || ${_var} == status ]] && \ 369 _rc_parse_conf /etc/rc.conf 370 [ "$(eval echo \${${_svc}_flags})" = "NO" ] && _status=1 371 fi 372 373 if ! svc_is_meta ${_svc}; then 374 rc_cmd() { } 375 . /etc/rc.d/${_svc} >/dev/null 2>&1 376 377 daemon_class=daemon 378 [ -z "${daemon_rtable}" ] && daemon_rtable=0 379 [ -z "${daemon_timeout}" ] && daemon_timeout=30 380 [ -z "${daemon_user}" ] && daemon_user=root 381 fi 382 fi 383 384 if [ -n "${_var}" ]; then 385 [ "${_var}" = "status" ] && return ${_status} 386 eval _val=\${daemon_${_var}} 387 [ -z "${_val}" ] || print -r -- "${_val}" 388 else 389 svc_is_meta ${_svc} && return ${_status} 390 if svc_is_special ${_svc}; then 391 echo "${_svc}=${daemon_flags}" 392 else 393 echo "${_svc}_class=${daemon_class}" 394 echo "${_svc}_execdir=${daemon_execdir}" 395 echo "${_svc}_flags=${daemon_flags}" 396 echo "${_svc}_logger=${daemon_logger}" 397 echo "${_svc}_rtable=${daemon_rtable}" 398 echo "${_svc}_timeout=${daemon_timeout}" 399 echo "${_svc}_user=${daemon_user}" 400 fi 401 return ${_status} 402 fi 403} 404 405svc_rm() 406{ 407 local _svc=$1 408 [ -n "${_svc}" ] || return 409 410 rcconf_edit_begin 411 if svc_is_special ${_svc}; then 412 grep -v "^${_svc}.*=" /etc/rc.conf.local >${_TMP_RCCONF} 413 ( svc_getdef ${_svc} status ) && \ 414 echo "${_svc}=NO" >>${_TMP_RCCONF} 415 else 416 grep -Ev "^${_svc}_(execdir|flags|logger|rtable|timeout|user).*=" \ 417 /etc/rc.conf.local >${_TMP_RCCONF} 418 ( svc_getdef ${_svc} status ) && \ 419 echo "${_svc}_flags=NO" >>${_TMP_RCCONF} 420 fi 421 rcconf_edit_end 422} 423 424svc_set() 425{ 426 local _svc=$1 _var=$2 427 [ -n "${_svc}" -a -n "${_var}" ] || return 428 429 shift 2 430 local _args="$*" 431 432 # don't check if we are already enabled or disabled because rc.conf(8) 433 # defaults may have changed in which case we may have a matching 434 # redundant entry in rc.conf.local that we can drop 435 if [ "${_var}" = "status" ]; then 436 if [ "${_args}" = "on" ]; then 437 _var="flags" 438 # keep our flags if we're already enabled 439 eval "_args=\"\${${_svc}_${_var}}\"" 440 [ "${_args}" = "NO" ] && unset _args 441 if ! svc_is_base ${_svc} && ! svc_is_special ${_svc}; then 442 pkg_scripts_append ${_svc} 443 fi 444 elif [ "${_args}" = "off" ]; then 445 if ! svc_is_base ${_svc} && ! svc_is_special ${_svc}; then 446 pkg_scripts_rm ${_svc} 447 fi 448 svc_rm ${_svc} 449 return 450 else 451 rcctl_err "invalid status \"${_args}\"" 452 fi 453 else 454 svc_get ${_svc} status || \ 455 rcctl_err "${svc} is not enabled" 456 fi 457 458 if svc_is_special ${_svc}; then 459 [ "${_var}" = "flags" ] || return 460 rcconf_edit_begin 461 grep -v "^${_svc}.*=" /etc/rc.conf.local >${_TMP_RCCONF} 462 ( svc_getdef ${_svc} status ) || \ 463 echo "${_svc}=YES" >>${_TMP_RCCONF} 464 rcconf_edit_end 465 return 466 fi 467 468 if [ -n "${_args}" ]; then 469 if [ "${_var}" = "execdir" ]; then 470 [[ ${_args%${_args#?}} == / ]] || 471 rcctl_err "\"${_args}\" must be an absolute path" 472 fi 473 if [ "${_var}" = "logger" ]; then 474 logger -p "${_args}" </dev/null >/dev/null 2>&1 || 475 rcctl_err "unknown priority name: \"${_args}\"" 476 fi 477 if [ "${_var}" = "rtable" ]; then 478 [[ ${_args} != +([[:digit:]]) || ${_args} -lt 0 ]] && \ 479 rcctl_err "\"${_args}\" is not an integer" 480 fi 481 if [ "${_var}" = "timeout" ]; then 482 [[ ${_args} != +([[:digit:]]) || ${_args} -le 0 ]] && \ 483 rcctl_err "\"${_args}\" is not a positive integer" 484 fi 485 if [ "${_var}" = "user" ]; then 486 getent passwd "${_args}" >/dev/null || \ 487 rcctl_err "user \"${_args}\" does not exist" 488 fi 489 # unset flags if they match the default enabled ones 490 [ "${_args}" = "$(svc_getdef ${_svc} ${_var})" ] && \ 491 unset _args 492 fi 493 494 # protect leading whitespace 495 [ "${_args}" = "${_args# }" ] || _args="\"${_args}\"" 496 497 # reset: value may have changed 498 unset ${_svc}_${_var} 499 500 rcconf_edit_begin 501 grep -v "^${_svc}_${_var}.*=" /etc/rc.conf.local >${_TMP_RCCONF} 502 if [ -n "${_args}" ] || \ 503 ( svc_is_base ${_svc} && ! svc_getdef ${_svc} status && [ "${_var}" == "flags" ] ); then 504 echo "${_svc}_${_var}=${_args}" >>${_TMP_RCCONF} 505 fi 506 rcconf_edit_end 507} 508 509unset _RC_DEBUG _RC_FORCE 510while getopts "df" c; do 511 case "$c" in 512 d) _RC_DEBUG=-d;; 513 f) _RC_FORCE=-f;; 514 *) usage;; 515 esac 516done 517shift $((OPTIND-1)) 518[ $# -gt 0 ] || usage 519 520action=$1 521ret=0 522 523case ${action} in 524 ls) 525 lsarg=$2 526 [[ ${lsarg} == @(all|failed|off|on|rogue|started|stopped) ]] || usage 527 ;; 528 order) 529 shift 1 530 svcs="$*" 531 for svc in ${svcs}; do 532 svc_is_avail ${svc} || \ 533 rcctl_err "service ${svc} does not exist" 2 534 done 535 ;; 536 disable|enable|start|stop|restart|reload|check|configtest) 537 shift 1 538 svcs="$*" 539 [ -z "${svcs}" ] && usage 540 for svc in ${svcs}; do 541 # it's ok to disable a non-existing daemon 542 if [ "${action}" != "disable" ]; then 543 svc_is_avail ${svc} || \ 544 rcctl_err "service ${svc} does not exist" 2 545 # but still check for bad input 546 else 547 _rc_check_name "${svc}" || \ 548 rcctl_err "service ${svc} does not exist" 2 549 fi 550 done 551 ;; 552 get|getdef) 553 svc=$2 554 var=$3 555 [ -z "${svc}" ] && usage 556 [ "${svc}" = "all" ] || svc_is_avail ${svc} || \ 557 rcctl_err "service ${svc} does not exist" 2 558 if [ -n "${var}" ]; then 559 [ "${svc}" = "all" ] && usage 560 [[ ${var} != @(class|execdir|flags|logger|rtable|status|timeout|user) ]] && usage 561 if svc_is_meta ${svc}; then 562 [ "${var}" != "status" ] && \ 563 rcctl_err "/etc/rc.d/${svc} is a meta script, cannot \"${action} ${var}\"" 564 fi 565 if svc_is_special ${svc}; then 566 [[ ${var} == @(class|execdir|logger|rtable|timeout|user) ]] && \ 567 rcctl_err "\"${svc}\" is a special variable, cannot \"${action} ${var}\"" 568 fi 569 fi 570 ;; 571 set) 572 svc=$2 573 var=$3 574 [ $# -ge 3 ] && shift 3 || shift $# 575 args="$*" 576 [ -z "${svc}" ] && usage 577 # it's ok to disable a non-existing daemon 578 if [ "${action} ${var} ${args}" != "set status off" ]; then 579 svc_is_avail ${svc} || \ 580 rcctl_err "service ${svc} does not exist" 2 581 # but still check for bad input 582 else 583 _rc_check_name "${svc}" || \ 584 rcctl_err "service ${svc} does not exist" 2 585 fi 586 [[ ${var} != @(class|execdir|flags|logger|rtable|status|timeout|user) ]] && usage 587 svc_is_meta ${svc} && [ "${var}" != "status" ] && \ 588 rcctl_err "/etc/rc.d/${svc} is a meta script, cannot \"${action} ${var}\"" 589 [[ ${var} = flags && ${args} = NO ]] && \ 590 rcctl_err "\"flags NO\" contradicts \"${action}\"" 591 if svc_is_special ${svc}; then 592 [[ ${var} != status ]] && \ 593 rcctl_err "\"${svc}\" is a special variable, cannot \"${action} ${var}\"" 594 fi 595 [[ ${var} == class ]] && \ 596 rcctl_err "\"${svc}_class\" is a read-only variable set in login.conf(5)" 597 ;; 598 *) 599 usage 600 ;; 601esac 602 603case ${action} in 604 disable) 605 needs_root ${action} 606 for svc in ${svcs}; do 607 svc_set ${svc} status off || ret=$?; 608 done 609 exit ${ret} 610 ;; 611 enable) 612 needs_root ${action} 613 for svc in ${svcs}; do 614 svc_set ${svc} status on || ret=$?; 615 done 616 exit ${ret} 617 ;; 618 get|getdef) 619 if [ "${svc}" = "all" ]; then 620 for svc in $(svc_ls all); do 621 ( svc_${action} ${svc} "${var}" ) 622 done 623 return 0 # we do not want the svc status 624 else 625 ( svc_${action} ${svc} "${var}" ) 626 fi 627 ;; 628 ls) 629 # some rc.d(8) scripts need root for rc_check() 630 [[ ${lsarg} == @(started|stopped|failed|rogue) ]] && needs_root ${action} ${lsarg} 631 svc_ls ${lsarg} 632 ;; 633 order) 634 if [ -n "${svcs}" ]; then 635 needs_root ${action} 636 pkg_scripts_order ${svcs} 637 else 638 [[ -z ${pkg_scripts} ]] || echo ${pkg_scripts} 639 fi 640 ;; 641 set) 642 needs_root ${action} 643 svc_set ${svc} "${var}" "${args}" 644 ;; 645 start|stop|restart|reload|check|configtest) 646 for svc in ${svcs}; do 647 if svc_is_special ${svc}; then 648 rcctl_err "\"${svc}\" is a special variable, no rc.d(8) script" 649 fi 650 /etc/rc.d/${svc} ${_RC_DEBUG} ${_RC_FORCE} ${action} || ret=$?; 651 done 652 exit ${ret} 653 ;; 654 *) 655 usage 656 ;; 657esac 658