openpkg/rc

changeset 13
cb59d6afeb61
child 427
71503088f51b
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/openpkg/rc	Tue Jan 06 23:40:39 2009 +0100
     1.3 @@ -0,0 +1,687 @@
     1.4 +#!@l_prefix@/lib/openpkg/bash --noprofile
     1.5 +##
     1.6 +##  rc -- OpenPKG Run-Command Processor
     1.7 +##  Copyright (c) 2000-2007 OpenPKG Foundation e.V. <http://openpkg.net/>
     1.8 +##  Copyright (c) 2000-2007 Ralf S. Engelschall <http://engelschall.com/>
     1.9 +##
    1.10 +##  Permission to use, copy, modify, and distribute this software for
    1.11 +##  any purpose with or without fee is hereby granted, provided that
    1.12 +##  the above copyright notice and this permission notice appear in all
    1.13 +##  copies.
    1.14 +##
    1.15 +##  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    1.16 +##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    1.17 +##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    1.18 +##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
    1.19 +##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.20 +##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.21 +##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    1.22 +##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    1.23 +##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    1.24 +##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    1.25 +##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.26 +##  SUCH DAMAGE.
    1.27 +##
    1.28 +
    1.29 +##
    1.30 +##  configuration
    1.31 +##
    1.32 +
    1.33 +#   program name, version and date
    1.34 +progname="rc"
    1.35 +progvers="1.2.0"
    1.36 +progdate="28-Jul-2003"
    1.37 +
    1.38 +#   path to OpenPKG instance
    1.39 +prefix="@l_prefix@"
    1.40 +
    1.41 +#   path to GNU bash and GNU shtool
    1.42 +bash="$prefix/lib/openpkg/bash"
    1.43 +shtool="$prefix/lib/openpkg/shtool"
    1.44 +
    1.45 +#   path to rc.d, rc.conf and rc.func
    1.46 +rcdir="$prefix/etc/rc.d"
    1.47 +rcconf="$prefix/etc/rc.conf"
    1.48 +rcfunc="$prefix/etc/rc.func"
    1.49 +
    1.50 +#   helper variables
    1.51 +NL="
    1.52 +"
    1.53 +
    1.54 +##
    1.55 +##  command line option parsing
    1.56 +##
    1.57 +
    1.58 +#   default parameters
    1.59 +silent=0
    1.60 +verbose=0
    1.61 +debug=0
    1.62 +help=0
    1.63 +keep=0
    1.64 +print=0
    1.65 +eval=0
    1.66 +config=0
    1.67 +query=0
    1.68 +
    1.69 +#   iterate over argument line
    1.70 +while [ $# -gt 0 ]; do
    1.71 +    opt=$1
    1.72 +    case $opt in
    1.73 +        -*=*) arg=${opt/-*=/} ;;
    1.74 +           *) arg='' ;;
    1.75 +    esac
    1.76 +    case $opt in
    1.77 +        -s|--silent  ) silent=1      ;;
    1.78 +        -v|--verbose ) verbose=1     ;;
    1.79 +        -d|--debug   ) debug=1       ;;
    1.80 +        -h|--help    ) help="Usage"  ;;
    1.81 +        -k|--keep    ) keep=1        ;;
    1.82 +        -p|--print   ) print=1       ;;
    1.83 +        -e|--eval    ) eval=1        ;;
    1.84 +        -c|--config  ) config=1      ;;
    1.85 +        -q|--query   ) query=1       ;;
    1.86 +        -*           ) help="Invalid option \`$opt'"; break ;;
    1.87 +        *            ) break         ;;
    1.88 +    esac
    1.89 +    shift
    1.90 +done
    1.91 +
    1.92 +#   display error or usage message
    1.93 +if [ ".$help" != .0 ]; then
    1.94 +    if [ ".$help" != ".Usage" ]; then
    1.95 +        echo "$progname:ERROR: $help" 1>&2
    1.96 +    fi
    1.97 +    echo "Usage: $progname [-s|--silent] [-v|--verbose] [-d|--debug] [-k|--keep] [-h|--help]" 1>&2
    1.98 +    echo "       [-p|--print] [-e|--eval] [-c|--config] [-q|--query]" 1>&2
    1.99 +    echo "       <package> <command> [<command> ...]"  1>&2
   1.100 +    if [ ".$help" != ".Usage" ]; then
   1.101 +        exit 1
   1.102 +    else
   1.103 +        exit 0
   1.104 +    fi
   1.105 +fi
   1.106 +
   1.107 +#   determine a reasonable default silent/verbose situation in case
   1.108 +#   nothing was explicitly specified or a conflicting situation was
   1.109 +#   specified. Else is silent either disabled by default or was
   1.110 +#   explicitly enabled.
   1.111 +if [ $silent -eq $verbose ]; then
   1.112 +    if [ -t 2 ]; then
   1.113 +        #   stdout connected to a terminal device, so no need to be silent
   1.114 +        silent=0
   1.115 +    else
   1.116 +        #   stdout NOT connected to a terminal device, so be silent
   1.117 +        silent=1
   1.118 +    fi
   1.119 +fi
   1.120 +
   1.121 +#   extend run-time environment with local OpenPKG tools (shtool, rpmtool, etc)
   1.122 +PATH_ORIG="$PATH"
   1.123 +PATH="$prefix/bin:$PATH"
   1.124 +PATH="$prefix/sbin:$PATH"
   1.125 +PATH="$prefix/lib/openpkg:$PATH"
   1.126 +
   1.127 +#   establish secure temporary directory
   1.128 +i=0
   1.129 +while [ $i -lt 10 ]; do
   1.130 +   tmpdir="/tmp/rc-`date '+%Y%m%d%H%M%S'`-$$"
   1.131 +   (umask 022; mkdir $tmpdir >/dev/null 2>&1) && break
   1.132 +   i=$(($i + 1))
   1.133 +   sleep 1
   1.134 +done
   1.135 +if [ $i -eq 10 ]; then
   1.136 +    echo "openpkg:rc:ERROR: unable to establish secure temporary directory" 1>&2
   1.137 +    exit 1
   1.138 +fi
   1.139 +declare -r tmpdir
   1.140 +trap "trap - EXIT INT ABRT QUIT TERM; rm -rf $tmpdir >/dev/null 2>&1 || true" EXIT INT ABRT QUIT TERM
   1.141 +
   1.142 +#   determine reasonable temporary files
   1.143 +tmpfile="$tmpdir/rc.tmp"
   1.144 +outfile="$tmpdir/rc.out"
   1.145 +errfile="$tmpdir/rc.err"
   1.146 +allfile="$tmpdir/rc.all"
   1.147 +
   1.148 +#   handle --query option
   1.149 +if [ ".$query" = .1 ]; then
   1.150 +    #   suck in all %config sections of all scripts
   1.151 +    #   (rc.openpkg is special: has to be first and requires pre-inclusion of rc.conf)
   1.152 +    touch $tmpfile
   1.153 +    sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
   1.154 +    echo ". $rcconf" >>$tmpfile
   1.155 +    scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'`
   1.156 +    for s_name in $scripts; do
   1.157 +        sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
   1.158 +    done
   1.159 +    . $tmpfile
   1.160 +
   1.161 +    #   apply override values to get effective values
   1.162 +    . $rcconf
   1.163 +
   1.164 +    #   display variable value
   1.165 +    for var in $*; do
   1.166 +        eval "echo \${$var}"
   1.167 +    done
   1.168 +
   1.169 +    #   stop processing immediately
   1.170 +    exit 0
   1.171 +fi
   1.172 +
   1.173 +#   handle --config option
   1.174 +if [ ".$config" = .1 ]; then
   1.175 +    #   suck in all %config sections of all scripts
   1.176 +    #   (rc.openpkg is special: has to be first and requires pre-inclusion of rc.conf)
   1.177 +    touch $tmpfile
   1.178 +    sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
   1.179 +    echo ". $rcconf" >>$tmpfile
   1.180 +    scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'`
   1.181 +    for s_name in $scripts; do
   1.182 +        sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
   1.183 +    done
   1.184 +    . $tmpfile
   1.185 +
   1.186 +    #   remember default values
   1.187 +    vars=""
   1.188 +    OIFS="$IFS"; IFS="$NL"
   1.189 +    for assign in `egrep '[ 	]*[a-zA-Z_][a-zA-Z_0-9]*=' $tmpfile | sort`; do
   1.190 +        var=`echo "$assign" | sed -e 's;^[ 	]*\([a-zA-Z_][a-zA-Z_0-9]*\)=.*;\1;'`
   1.191 +        vars="$vars $var"
   1.192 +        eval "${var}_def=\"\$$var\""
   1.193 +    done
   1.194 +    IFS="$OIFS"
   1.195 +
   1.196 +    #   apply override values to get effective values
   1.197 +    . $rcconf
   1.198 +
   1.199 +    #   determine how to print in bold mode in case output
   1.200 +    #   is connected to a terminal device
   1.201 +    if [ -t 1 ]; then
   1.202 +        begin_bold=`$shtool echo -e '%B'`
   1.203 +        end_bold=`$shtool echo -e '%b'`
   1.204 +    else
   1.205 +        begin_bold=""
   1.206 +        end_bold=""
   1.207 +    fi
   1.208 +
   1.209 +    #   iterate over all variables and display name, default and effective value
   1.210 +    echo "${begin_bold}Configuration Variable   Effective Value              Default Value${end_bold}"
   1.211 +    echo "------------------------ ------------------------- -- -------------------------"
   1.212 +    for var in . $vars; do
   1.213 +        test ".$var" = .. && continue
   1.214 +        eval "val=\"\$$var\""
   1.215 +        eval "def=\"\$${var}_def\""
   1.216 +        tag="!="
   1.217 +        begin="$begin_bold"
   1.218 +        end="$end_bold"
   1.219 +        if [ ".$val" = ".$def" ]; then
   1.220 +            tag="=="
   1.221 +            begin=""
   1.222 +            end=""
   1.223 +        fi
   1.224 +        printf "%s%-24s %-25s %s %-25s%s\n" "$begin" "$var" "\"$val\"" "$tag" "\"$def\"" "$end"
   1.225 +    done
   1.226 +
   1.227 +    #   stop processing immediately
   1.228 +    exit 0
   1.229 +fi
   1.230 +
   1.231 +#   determine script(s) to use and make sure they exist
   1.232 +if [ $# -lt 1 ]; then
   1.233 +    echo "openpkg:rc:ERROR: no package and command(s) specified" 1>&2
   1.234 +    exit 1
   1.235 +fi
   1.236 +if [ $# -lt 2 ]; then
   1.237 +    echo "openpkg:rc:ERROR: no command(s) specified for package" 1>&2
   1.238 +    exit 1
   1.239 +fi
   1.240 +scripts="${1/*rc./}"
   1.241 +shift
   1.242 +isall=0
   1.243 +if [ ".$scripts" = ".all" ]; then
   1.244 +    isall=1
   1.245 +    . $rcconf
   1.246 +    if [ ".$openpkg_runall" != . ]; then
   1.247 +        #   backward compatibility only
   1.248 +        echo "openpkg:rc:WARNING: variable \"openpkg_runall\" was renamed to \"openpkg_rc_all\"." 1>&2
   1.249 +        echo "openpkg:rc:WARNING: value of deprecated variable \"openpkg_runall\" taken over for compatibility." 1>&2
   1.250 +        echo "openpkg:rc:WARNING: please update your local configuration in \"$rcconf\"." 1>&2
   1.251 +        openpkg_rc_all="$openpkg_runall"
   1.252 +    fi
   1.253 +    case "$openpkg_rc_all" in
   1.254 +        [Nn][Oo] | [Ff][Aa][Ll][Ss][Ee] | [Oo][Ff][Ff] | 0 ) exit 0 ;;
   1.255 +    esac
   1.256 +    scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;"`
   1.257 +else
   1.258 +    if [ ! -f "$rcdir/rc.$scripts" ]; then
   1.259 +        echo "openpkg:rc:ERROR: package \"$scripts\" not found" 1>&2
   1.260 +        exit 1
   1.261 +    fi
   1.262 +fi
   1.263 +
   1.264 +#   determine current run-time user
   1.265 +user=`(id -un) 2>/dev/null ||\
   1.266 +      (id | sed -e 's;^[^(]*(\([^)]*\)).*;\1;') 2>/dev/null ||\
   1.267 +      (whoami) 2>/dev/null ||\
   1.268 +      (who am i | cut "-d " -f1) 2>/dev/null ||\
   1.269 +      echo ${LOGNAME:-${USER}}`
   1.270 +if [ ".$user" = . ]; then
   1.271 +    echo "openpkg:rc:ERROR: unable to determine current username" 1>&2
   1.272 +    exit 1
   1.273 +fi
   1.274 +
   1.275 +#   iterate over the specified commands
   1.276 +rv=0
   1.277 +cmds="$*"
   1.278 +for cmd in $cmds; do
   1.279 +    #   create "all outputs" file for execution operation (i.e. not --print and --eval)
   1.280 +    if [ ".$print" = .0 -a ".$eval" = .0 ]; then
   1.281 +        rm -f $allfile
   1.282 +        touch $allfile
   1.283 +    fi
   1.284 +
   1.285 +    #   find scripts which contain the command and determine
   1.286 +    #   their individual user/priority settings
   1.287 +    list=''
   1.288 +    for s_name in $scripts; do
   1.289 +        enable=yes
   1.290 +
   1.291 +        #   check for upgraded package with unresolved configuration file conflicts
   1.292 +        if [ -d "$prefix/etc/$s_name" -a ".$eval" != .1 ]; then
   1.293 +            if [ ".`(find $prefix/etc/$s_name -type f -print; find $prefix/etc/$s_name -type l -print) 2>/dev/null | egrep -v '.*/\.(snap|snapshot)/.*' | egrep '.*\.rpm(new|orig|save)$'`" != . ]; then
   1.294 +                case "$cmd" in
   1.295 +                    start|restart ) type="ERROR"   ;;
   1.296 +                    * )             type="WARNING" ;;
   1.297 +                esac
   1.298 +                echo "openpkg:rc:${type}: package \"$s_name\" has unresolved configuration file conflicts" 1>&2
   1.299 +                echo "openpkg:rc:${type}: indicated by \"*.rpm(new|orig|save)\" files in or below the" 1>&2
   1.300 +                echo "openpkg:rc:${type}: directory \"$prefix/etc/$s_name\". Please resolve first!" 1>&2
   1.301 +                if [ ".$type" = .ERROR ]; then
   1.302 +                    continue
   1.303 +                fi
   1.304 +            fi
   1.305 +        fi
   1.306 +
   1.307 +        #   check whether command exists in script at all
   1.308 +        cmdline=`grep "^%$cmd" $rcdir/rc.$s_name | sed -e "s;^%$cmd[^ 	].*;;"`
   1.309 +        if [ ".$cmdline" != . ]; then
   1.310 +            #   parse local command options
   1.311 +            cmdopts=`echo "$cmdline" | sed -e "s;^%$cmd *;;"`
   1.312 +            s_user=$user
   1.313 +            s_prio=500
   1.314 +            s_output=no
   1.315 +            set -- $cmdopts
   1.316 +            prev=''
   1.317 +            for opt
   1.318 +            do
   1.319 +                if [ ".$prev" != . ]; then
   1.320 +                    opt="$prev$opt"
   1.321 +                    prev=''
   1.322 +                fi
   1.323 +                case $opt in
   1.324 +                    -*=*       ) arg=${opt/-*=/} ;;
   1.325 +                    -[a-zA-Z]* ) arg=${opt/-[a-zA-Z0-9]/} ;;
   1.326 +                              *) arg='' ;;
   1.327 +                esac
   1.328 +                case $opt in
   1.329 +                    -u|-p         ) prev=$opt    ;;
   1.330 +                    -e|--enable   ) enable=yes   ;;
   1.331 +                    -d|--disable  ) enable=no    ;;
   1.332 +                    -o|--output   ) s_output=yes ;;
   1.333 +                    -u*|--user=*  ) s_user=$arg  ;;
   1.334 +                    -p*|--prio=*  ) s_prio=$arg  ;;
   1.335 +                    *             ) echo "openpkg:rc:WARNING: invalid local option \"$opt\" in \"$rcdir/rc.$s_name:%$cmd\""; break ;;
   1.336 +                esac
   1.337 +                shift
   1.338 +            done
   1.339 +
   1.340 +            #   sanity check: is operation supported by current environment?
   1.341 +            if [ ".$s_user" != ".$user" -a ".$user" != ".root" -a ".$print" = .0 ]; then
   1.342 +                echo "openpkg:rc:ERROR: $s_name:%$cmd: require root privileges to run as user \"$s_user\"" 1>&2
   1.343 +                exit 1
   1.344 +            fi
   1.345 +
   1.346 +            #   skip this script if script is disabled
   1.347 +            if [ ".$enable" != .yes ]; then
   1.348 +                continue
   1.349 +            fi
   1.350 +
   1.351 +            #   accumulate the determined information
   1.352 +            list="$list,$s_prio:$s_name:$s_user:$s_output"
   1.353 +        else
   1.354 +            #   command not found in script
   1.355 +            if [ ".$isall" = .0 ]; then
   1.356 +                echo "openpkg:rc:ERROR: $s_name: command \"$cmd\" not found" 1>&2
   1.357 +                exit 1
   1.358 +            fi
   1.359 +        fi
   1.360 +    done
   1.361 +
   1.362 +    #   if operating on all scripts, complain if a non-standard command
   1.363 +    #   was used and it was not found in any(!) script at all. The
   1.364 +    #   standard commands are accepted to perform no operation if no
   1.365 +    #   packages are currently installed which provide such commands.
   1.366 +    if [ ".$list" = . -a ".$isall" = .1 ]; then
   1.367 +        case "$cmd" in
   1.368 +            start|stop|monthly|weekly|daily|hourly|quarterly )
   1.369 +                ;;
   1.370 +            * )
   1.371 +                echo "openpkg:rc:ERROR: command \"$cmd\" not found in any script" 1>&2
   1.372 +                rv=1
   1.373 +                break
   1.374 +                ;;
   1.375 +        esac
   1.376 +    fi
   1.377 +
   1.378 +    #   generate global (loop invariant) header for script in case of
   1.379 +    #   --print and --eval (for the execution approach we cannot do
   1.380 +    #   this, because there a new script is generated from scratch for
   1.381 +    #   each package.
   1.382 +    if [ ".$print" = .1 -o ".$eval" = .1 ]; then
   1.383 +        rm -f $tmpfile
   1.384 +        touch $tmpfile
   1.385 +
   1.386 +        #   generate: optionally enable shell debugging
   1.387 +        if [ ".$debug" = .1 ]; then
   1.388 +            echo "set -x" >>$tmpfile
   1.389 +        fi
   1.390 +
   1.391 +        #   generate: inclusion of the run-command helper functions
   1.392 +        echo ". $rcfunc" >>$tmpfile
   1.393 +
   1.394 +        #   generate: all %config sections of all(!) scripts. We cannot
   1.395 +        #   just include those which have the current command in it
   1.396 +        #   because by design all command scripts see the %config
   1.397 +        #   section of all(!) scripts. Because of $openpkg_rc_def the
   1.398 +        #   variable, we place the %config section of "openpkg" to the front.
   1.399 +        #   And we have to extra pre-include the rc.conf to allow
   1.400 +        #   rc.conf to override the default of $openpkg_rc_def, too.
   1.401 +        sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
   1.402 +        echo ". $rcconf" >>$tmpfile
   1.403 +        l_scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'`
   1.404 +        for l_name in $l_scripts; do
   1.405 +            sed <$rcdir/rc.$l_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
   1.406 +        done
   1.407 +
   1.408 +        #   generate: inclusion of the application of override variables
   1.409 +        echo ". $rcconf" >>$tmpfile
   1.410 +
   1.411 +        #   for --eval redirect stderr and stdout (but remember stdout)
   1.412 +        #   (let stderr pass unfiltered in case of debug mode)
   1.413 +        if [ ".$eval" = .1 ]; then
   1.414 +            if [ ".$debug" = .1 ]; then
   1.415 +               echo "exec 3<&1- 1>/dev/null" >>$tmpfile
   1.416 +            else
   1.417 +               echo "exec 3<&1- 1>/dev/null 2>/dev/null" >>$tmpfile
   1.418 +            fi
   1.419 +        fi
   1.420 +    fi
   1.421 +
   1.422 +    #   iterate over all packages (in priority order!) where the command
   1.423 +    #   was found in order to execute, print, or evaluate their scripts
   1.424 +    verbose_pos=0
   1.425 +    for entry in `echo $list | tr ',' '\012' | sort -n`; do
   1.426 +        [ ".$entry" = . ] && continue
   1.427 +
   1.428 +        #   re-determine the script name, script and whether to print output
   1.429 +        eval `echo $entry | sed -e 's%^[0-9]*:\(.*\):\(.*\):\(.*\)$%s_name="\1"; s_user="\2"; s_output="\3";%'`
   1.430 +
   1.431 +        #   display verbose progress message parts
   1.432 +        if [ ".$print" = .0 -a ".$eval" = .0 -a ".$silent" = .0 ]; then
   1.433 +            #   line break if we already have output more than 70
   1.434 +            #   characters (notice that usually already more characters
   1.435 +            #   where printed, because of the name of the last script)
   1.436 +            if [ $verbose_pos -gt 70 ]; then
   1.437 +                verbose_pos=0
   1.438 +                echo "" 1>&2
   1.439 +            fi
   1.440 +
   1.441 +            #   display verbose message parts: prefix (on first), separator and package
   1.442 +            if [ $verbose_pos -eq 0 ]; then
   1.443 +                output=$(printf "OpenPKG: %s: " "$cmd")
   1.444 +                echo -n "$output" 1>&2
   1.445 +                verbose_pos=$(($verbose_pos + ${#output}))
   1.446 +                output_prefix=""
   1.447 +            else
   1.448 +                output_prefix=", "
   1.449 +            fi
   1.450 +            output=$(printf "%s%s" "$output_prefix" "$s_name")
   1.451 +            echo -n "$output" 1>&2
   1.452 +            verbose_pos=$(($verbose_pos + ${#output}))
   1.453 +        fi
   1.454 +
   1.455 +        #   now operate on the particular script
   1.456 +        if [ ".$print" = .1 ]; then
   1.457 +            #   special case: under --print we just add the %common and
   1.458 +            #   command scripts to the generated output script and do
   1.459 +            #   not execute anything at this point.
   1.460 +            sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d'
   1.461 +            sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d'
   1.462 +        elif [ ".$eval" = .1 ]; then
   1.463 +            #   special case: under --eval we just add the %common and
   1.464 +            #   command scripts to the generated output script and do
   1.465 +            #   not execute anything at this point. Additionally, we
   1.466 +            #   emulate a real sub-shell environment.
   1.467 +            sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d'
   1.468 +            echo "while [ 1 ]; do" >>$tmpfile
   1.469 +            sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d' \
   1.470 +                -e 's/^exit[^;]*/break 99/'   -e 's/\([^a-zA-Z0-9_]\)exit[^;]*/\1break 99/g' \
   1.471 +                -e 's/^return[^;]*/break 99/' -e 's/\([^a-zA-Z0-9_]\)return[^;]*/\1break 99/g'
   1.472 +            echo "break" >>$tmpfile
   1.473 +            echo "done" >>$tmpfile
   1.474 +        else
   1.475 +            #   the regular case of executing the command script directly
   1.476 +
   1.477 +            #   prepare temporary files
   1.478 +            rm -f $tmpfile $outfile $errfile
   1.479 +            (umask 077; touch $tmpfile $outfile $errfile)
   1.480 +
   1.481 +            #   generate: optionally enable shell debugging
   1.482 +            if [ ".$debug" = .1 ]; then
   1.483 +                echo "set -x" >>$tmpfile
   1.484 +            fi
   1.485 +
   1.486 +            #   generate: inclusion of the run-command helper functions
   1.487 +            echo ". $rcfunc" >>$tmpfile
   1.488 +
   1.489 +            #   generate: all %config sections of all(!) scripts. We cannot
   1.490 +            #   just include those which have the current command in it
   1.491 +            #   because by design all command scripts see the %config
   1.492 +            #   section of all(!) scripts. Because of $openpkg_rc_def the
   1.493 +            #   variable, we place the %config section of "openpkg" to the front.
   1.494 +            #   And we have to extra pre-include the rc.conf to allow
   1.495 +            #   rc.conf to override the default of $openpkg_rc_def, too.
   1.496 +            sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
   1.497 +            echo ". $rcconf" >>$tmpfile
   1.498 +            l_scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'`
   1.499 +            for l_name in $l_scripts; do
   1.500 +                sed <$rcdir/rc.$l_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
   1.501 +            done
   1.502 +
   1.503 +            #   generate: inclusion of the application of override variables
   1.504 +            echo ". $rcconf" >>$tmpfile
   1.505 +
   1.506 +            #   generate: %common section and particular command section
   1.507 +            sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d'
   1.508 +            sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d'
   1.509 +
   1.510 +            #   execute the generated script with GNU Bash
   1.511 +            if [ ".$user" != ".$s_user" ]; then
   1.512 +                #   execute as different user
   1.513 +                if [ ".$verbose" = .1 ]; then
   1.514 +                    echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: executing as user $s_user"
   1.515 +                fi
   1.516 +                if [ ".$user" = ".@l_susr@" -a ".@l_susr@" = ".root" ]; then
   1.517 +                    chown $s_user $tmpfile
   1.518 +                    if [ ".$debug" = .1 ]; then
   1.519 +                        su - $s_user -c "PATH=\"$PATH\"; $bash $tmpfile" >$outfile
   1.520 +                        rc=$?
   1.521 +                    else
   1.522 +                        su - $s_user -c "PATH=\"$PATH\"; $bash $tmpfile" >$outfile 2>$errfile
   1.523 +                        rc=$?
   1.524 +                    fi
   1.525 +                elif [ ".@l_susr@" != ".root" ]; then
   1.526 +                    #   do not complain if we would not have any chance
   1.527 +                    #   at all to switch the user because we are running
   1.528 +                    #   in a non-privileged instance. Else we would just
   1.529 +                    #   trash the mailbox of the user receiving the
   1.530 +                    #   output of periodic run-commands.
   1.531 +                    rc=0
   1.532 +                else
   1.533 +                    echo "openpkg:rc:WARNING: $prefix:$s_name:%$cmd: require root privileges to run as user \"$s_user\"" 1>&2
   1.534 +                    rc=1
   1.535 +                fi
   1.536 +            else
   1.537 +                #   execute as current user
   1.538 +                if [ ".$verbose" = .1 ]; then
   1.539 +                    echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: executing as user $user"
   1.540 +                fi
   1.541 +                if [ ".$debug" = .1 ]; then
   1.542 +                    $bash $tmpfile >$outfile
   1.543 +                    rc=$?
   1.544 +                else
   1.545 +                    $bash $tmpfile >$outfile 2>$errfile
   1.546 +                    rc=$?
   1.547 +                fi
   1.548 +            fi
   1.549 +            if [ $rc -ne 0 ]; then
   1.550 +                if [ ".$silent" = .0 ]; then
   1.551 +                    #   indicate failure of execution on verbose message line
   1.552 +                    echo ":FAILED" 1>&2
   1.553 +                    verbose_pos=0
   1.554 +                fi
   1.555 +                #   give details of execution failure
   1.556 +                ( echo "openpkg:rc:WARNING: $prefix:$s_name:%$cmd: failed with return code $rc"
   1.557 +                  if [ ".`cat $outfile $errfile`" != . ]; then
   1.558 +                      echo "openpkg:rc:NOTICE: output from stdout/stderr is following:"
   1.559 +                      echo "+----------------------------------------------------------------------"
   1.560 +                      cat $outfile $errfile | sed -e 's;^;| ;'
   1.561 +                      echo "+----------------------------------------------------------------------"
   1.562 +                  else
   1.563 +                      echo "openpkg:rc:NOTICE: no output occurred on stdout/stderr"
   1.564 +                  fi
   1.565 +                ) 1>&2
   1.566 +
   1.567 +                #   enforce global return value
   1.568 +                rv=1
   1.569 +            else
   1.570 +                #   give details of execution success in case verbose operation is requested
   1.571 +                if [ ".$verbose" = .1 ]; then
   1.572 +                    ( echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: succeeded with return code $rc"
   1.573 +                      if [ ".`cat $outfile $errfile`" != . ]; then
   1.574 +                          echo "openpkg:rc:NOTICE: output from stdout/stderr is following:"
   1.575 +                          echo "+----------------------------------------------------------------------"
   1.576 +                          cat $outfile $errfile | sed -e 's;^;| ;'
   1.577 +                          echo "+----------------------------------------------------------------------"
   1.578 +                      else
   1.579 +                          echo "openpkg:rc:NOTICE: no output occurred on stdout/stderr"
   1.580 +                      fi
   1.581 +                    ) 1>&2
   1.582 +                fi
   1.583 +                if [ ".$s_output" = .yes ]; then
   1.584 +                    #   accumulate script output for later display
   1.585 +                    cat $outfile >>$allfile
   1.586 +                fi
   1.587 +            fi
   1.588 +        fi
   1.589 +    done
   1.590 +
   1.591 +    #   post-processing for each command
   1.592 +    if [ ".$print" = .1 ]; then
   1.593 +        #   for --print just print the resulting script to stdout
   1.594 +        cat $tmpfile
   1.595 +    elif [ ".$eval" = .1 ]; then
   1.596 +        #   finish generation of temporary script by restoring stdout
   1.597 +        #   and printing the exported environment variables into a format
   1.598 +        #   suitable for evaluation by the callers shell.
   1.599 +        echo "exec 1<&3-" >>$tmpfile
   1.600 +        echo "unset PWD SHLVL" >>$tmpfile
   1.601 +        echo "env |\\" >>$tmpfile
   1.602 +        echo "egrep '^[A-Z_][A-Z0-9_]*=.' |\\" >>$tmpfile
   1.603 +        echo "sed -e '/^_=/d' -e 's/\\\\/\\\\\\\\/g' -e 's/\"/\\\\\"/g' \\" >>$tmpfile
   1.604 +        case $SHELL in
   1.605 +            csh|*/csh|tcsh|*/tcsh )
   1.606 +                echo "-e 's/^\\([^=]*\\)=\\(.*\\)\$/setenv \\1 \"\\2\"/'" >>$tmpfile
   1.607 +                ;;
   1.608 +            * )
   1.609 +                echo "-e 's/^\\([^=]*\\)=\\(.*\\)\$/\\1=\"\\2\"; export \\1/'" >>$tmpfile
   1.610 +                ;;
   1.611 +        esac
   1.612 +
   1.613 +        #   prepare temporary files
   1.614 +        rm -f $outfile $errfile
   1.615 +        touch $outfile $errfile
   1.616 +
   1.617 +        #   now replace temporary script with its output
   1.618 +        #   by executing it and capturing its output
   1.619 +        #   (let stderr pass unfiltered in case of debug mode)
   1.620 +        if [ ".$debug" = .1 ]; then
   1.621 +            env -i \
   1.622 +                HOME="$HOME" \
   1.623 +                USER="$USER" \
   1.624 +                LOGNAME="$LOGNAME" \
   1.625 +                TERM="$TERM" \
   1.626 +                PATH="$PATH_ORIG" \
   1.627 +                MANPATH="$MANPATH" \
   1.628 +                INFOPATH="$INFOPATH" \
   1.629 +                LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \
   1.630 +                $bash --norc --noprofile --posix \
   1.631 +                $tmpfile >$outfile
   1.632 +        else
   1.633 +            env -i \
   1.634 +                HOME="$HOME" \
   1.635 +                USER="$USER" \
   1.636 +                LOGNAME="$LOGNAME" \
   1.637 +                TERM="$TERM" \
   1.638 +                PATH="$PATH_ORIG" \
   1.639 +                MANPATH="$MANPATH" \
   1.640 +                INFOPATH="$INFOPATH" \
   1.641 +                LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \
   1.642 +                $bash --norc --noprofile --posix \
   1.643 +                $tmpfile >$outfile 2>/dev/null
   1.644 +        fi
   1.645 +        cp $outfile $tmpfile
   1.646 +
   1.647 +        #   for --eval we cannot just print the resulting script because
   1.648 +        #   not all Bourne-Shell implementations like to "eval" large
   1.649 +        #   multi-line outputs. Hence we output a little one-liner which
   1.650 +        #   "sources" the script instead and cleans up.
   1.651 +        case $SHELL in
   1.652 +            csh|*/csh|tcsh|*/tcsh )
   1.653 +                echo "source $tmpfile; rm -rf $tmpdir 2>/dev/null || true"
   1.654 +                ;;
   1.655 +            * )
   1.656 +                echo ". $tmpfile; rm -rf $tmpdir 2>/dev/null || true"
   1.657 +                ;;
   1.658 +        esac
   1.659 +    else
   1.660 +        #   for the execution situation just make sure we
   1.661 +        #   terminate the verbose message output.
   1.662 +        if [ ".$silent" = .0 -a $verbose_pos -gt 0 ]; then
   1.663 +            echo "." 1>&2
   1.664 +        fi
   1.665 +
   1.666 +        #   additionally, if a script wants its output to be displayed,
   1.667 +        #   now do it. In case there was no such request, do not bother
   1.668 +        #   -- we then just output an empty file and so can avoid an
   1.669 +        #   extra test surrounding the next command.
   1.670 +        cat $allfile
   1.671 +    fi
   1.672 +done
   1.673 +
   1.674 +#   cleanup temporary files except the result script in
   1.675 +#   case of --eval (which is then removed by the caller).
   1.676 +#   keep those files for debugging purposes if requested.
   1.677 +if [ ".$keep" = .0 ]; then
   1.678 +    rm -f $outfile $errfile $allfile >/dev/null 2>&1 || true
   1.679 +    if [ ".$eval" = .0 ]; then
   1.680 +        rm -f $tmpfile >/dev/null 2>&1 || true
   1.681 +        rm -rf $tmpdir >/dev/null 2>&1 || true
   1.682 +    fi
   1.683 +fi
   1.684 +
   1.685 +#   now clean the exit trap and exit with the global return value
   1.686 +#   indicating to the caller whether all scripts were executed
   1.687 +#   successfully or at least one failed.
   1.688 +trap - EXIT
   1.689 +exit $rv
   1.690 +

mercurial