Index: etc/rc.subr =================================================================== --- etc/rc.subr (revision 272976) +++ etc/rc.subr (working copy) @@ -698,7 +698,10 @@ # "start stop restart rcvar status poll ${extra_commands}" # If there's a match, run ${argument}_cmd or the default method # (see below). +# _run_rc_command0() is the main routine and run_rc_command() is +# a wrapper to handle multiple instances. # +# # If argument has a given prefix, then change the operation as follows: # Prefix Operation # ------ --------- @@ -755,6 +758,9 @@ # # ${name}_nice n Nice level to run ${command} at. # +# ${name}_pidfile n This to be used in /etc/rc.conf to override +# ${pidfile}. +# # ${name}_user n User to run ${command} as, using su(1) if not # using ${name}_chroot. # Requires /usr to be mounted. @@ -863,6 +869,57 @@ # run_rc_command() { + local _act _instances _name _desc _rcvar + + _act=$1 + shift + eval _instances=\$${name}_instances + + # Check if instance is specified, e.g. "start:instance,...". + case ${_act%:*} in + $_act) ;; # no instance specified + *) + _instances=$(echo ${_act#*:} | tr "," " ") + _act=${_act%:*} + ;; + esac + + # Use reverse order for stop. + case $_act in + *stop) _instances=$(reverse_list $_instances) ;; + esac + + case $_instances in + "") + _name=$name + _inst= + _run_rc_command0 $_act "$@" + ;; + *) + _name=$name + _desc=$desc + _rcvar=$rcvar + for _inst in $_instances; do + # Use a subshell to preserve variables. + ( + name=${_name}_$_inst + eval desc=\"$_desc\${${name}_desc+:\ }\$${name}_desc\" + rcvar=${_rcvar%_enable}_${_inst}_enable + _run_rc_command0 $_act "$@" + ) + done + ;; + esac +} + +getnameparam() +{ + + eval echo \${$1_$_inst${_inst:+_}$2-\$$1_$2} +} + +_run_rc_command0() +{ _return=0 rc_arg=$1 if [ -z "$name" ]; then @@ -904,8 +961,12 @@ ;; esac - eval _override_command=\$${name}_program - command=${_override_command:-$command} + if [ -z "$command" ]; then + command=$(getnameparam $_name program) + fi + if [ -z "$pidfile" ]; then + pidfile=$(getnameparam $_name pidfile) + fi _keywords="start stop restart rcvar enabled $extra_commands" rc_pid= @@ -936,13 +997,16 @@ if [ -n "$flags" ]; then # allow override from environment rc_flags=$flags else - eval rc_flags=\$${name}_flags + rc_flags=$(getnameparam $_name flags) fi - eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \ - _nice=\$${name}_nice _user=\$${name}_user \ - _group=\$${name}_group _groups=\$${name}_groups \ - _fib=\$${name}_fib _env=\$${name}_env \ - _prepend=\$${name}_prepend + _chdir=$(getnameparam $_name chdir) + _chroot=$(getnameparam $_name chroot) + _nice=$(getnameparam $_name nice) + _user=$(getnameparam $_name user) + _group=$(getnameparam $_name group) + _groups=$(getnameparam $_name groups) + _env=$(getnameparam $_name env) + _prepend=$(getnameparam $_name prepend) if [ -n "$_user" ]; then # unset $_user if running as that user if [ "$_user" = "$(eval $IDCMD)" ]; then @@ -977,9 +1041,9 @@ # if there's a custom ${XXX_cmd}, # run that instead of the default # - eval _cmd=\$${rc_arg}_cmd \ - _precmd=\$${rc_arg}_precmd \ - _postcmd=\$${rc_arg}_postcmd + _cmd=$(getnameparam $rc_arg cmd) + _precmd=$(getnameparam $rc_arg precmd) + _postcmd=$(getnameparam $rc_arg postcmd) if [ -n "$_cmd" ]; then _run_rc_precmd || return 1 @@ -1134,16 +1198,10 @@ echo "" fi echo "#" - # Get unique vars in $rcvar $rcvars - for _v in $rcvar $rcvars; do - case $v in - $_v\ *|\ *$_v|*\ $_v\ *) ;; - *) v="${v# } $_v" ;; - esac - done # Display variables. - for _v in $v; do + for _v in $(getinstlist $_name "$_inst" $rcvar $rcvars); + do if [ -z "$_v" ]; then continue fi @@ -1150,24 +1208,20 @@ eval _desc=\$${_v}_desc eval _defval=\$${_v}_defval - _h="-" + eval _val=\$$_v - eval echo \"$_v=\\\"\$$_v\\\"\" - # decode multiple lines of _desc - while [ -n "$_desc" ]; do - case $_desc in - *^^*) - echo "# $_h ${_desc%%^^*}" - _desc=${_desc#*^^} - _h=" " - ;; - *) - echo "# $_h ${_desc}" - break - ;; - esac - done - echo "# (default: \"$_defval\")" + case $_defval in + $_val) + _e= + _m= + ;; + *) + _e=" # (default: \"$_defval\")" + _m="(*)" + ;; + esac + echo "# $_v$_m${_desc+: }$_desc" + eval echo \"$_v=\\\"\$$_v\\\"\" \$_e done echo "" ;; @@ -1308,11 +1362,104 @@ } # +# uniqlist var list +# Put a list into $var with duplicate words removed. +# +uniqlist() +{ + local _uv _v + + _uv= + for _v in "$@"; do + case $_uv in + $_v|$_v\ *|*\ $_v|*\ $_v\ *) ;; + *) _uv="${_uv# }${_uv:+ }$_v" ;; + esac + done + echo "$_uv" +} +# +# createinstlist() name inst list +# Generate a variable list with the instance name. +# +createinstlist() +{ + local _name _inst _v + + _name=$1 + _inst=$2 + shift 2 + for _v in $(uniqlist "$@"); do + echo "${_name}_${_inst}${_inst+_}${_v#${_name}_}" + done +} +# +# getinstlist() name inst list +# Get a variable list only with the instance name. +# +getinstlist() +{ + local _name _inst _v _l + + _name=$1 + _inst=$2 + shift 2 + _l= + for _v in $(uniqlist "$@"); do + case $_v in + ${_name}${_inst:+_}${_inst}_*) _l="${_l# }${_l:+ }$_v" ;; + esac + done + uniqlist $_l +} + +# # load_rc_config name # Source in the configuration file for a given name. +# load_rc_config0() is the main routine and load_rc_config() is +# a wrapper to handle multiple instances. # load_rc_config() { + local _instances _inst _name _rcvars _defval _desc _k _v _ul + + # XXX: normalization + ltr "$name" "-" "_" name + ltr "$1" "-" "_" _name + _load_rc_config0 $_name + + eval _instances=\$${_name}_instances + _rcvars=$rcvars + + for _inst in $_instances; do + # Set default values for ${_name}_$_inst. + + for _k in $(uniqlist $_rcvars); do + # _k includes _name + eval _defval=\${${_k}_defval} + eval _desc=\${${_k}_desc} + set_rcvar $(createinstlist $_name $_inst $_k) \ + "$_defval" "$_desc" + done + for _k in $_rc_namevarlist; do + if [ "$_k" = "instances" ]; then + continue + fi + _k=${_name}_$_k + # _k includes _name + eval _defval=\${${_k}_defval} + eval _desc=\${${_k}_desc} + if [ -n "$_defval" ]; then + set_rcvar $(createinstlist $_name $_inst $_k) \ + "$_defval" "$_desc" + fi + done + _load_rc_config0 ${_name}_$_inst + done +} + +_load_rc_config0() +{ local _name _rcvar_val _var _defval _v _msg _new _d _name=$1 if [ -z "$_name" ]; then