michael@13: #!@l_prefix@/lib/openpkg/bash --noprofile michael@13: ## michael@13: ## rc -- OpenPKG Run-Command Processor michael@13: ## Copyright (c) 2000-2007 OpenPKG Foundation e.V. michael@13: ## Copyright (c) 2000-2007 Ralf S. Engelschall michael@13: ## michael@13: ## Permission to use, copy, modify, and distribute this software for michael@13: ## any purpose with or without fee is hereby granted, provided that michael@13: ## the above copyright notice and this permission notice appear in all michael@13: ## copies. michael@13: ## michael@13: ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED michael@13: ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF michael@13: ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. michael@13: ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR michael@13: ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@13: ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@13: ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF michael@13: ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND michael@13: ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, michael@13: ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT michael@13: ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF michael@13: ## SUCH DAMAGE. michael@13: ## michael@13: michael@13: ## michael@13: ## configuration michael@13: ## michael@13: michael@13: # program name, version and date michael@13: progname="rc" michael@13: progvers="1.2.0" michael@13: progdate="28-Jul-2003" michael@13: michael@13: # path to OpenPKG instance michael@13: prefix="@l_prefix@" michael@13: michael@13: # path to GNU bash and GNU shtool michael@13: bash="$prefix/lib/openpkg/bash" michael@13: shtool="$prefix/lib/openpkg/shtool" michael@13: michael@13: # path to rc.d, rc.conf and rc.func michael@13: rcdir="$prefix/etc/rc.d" michael@13: rcconf="$prefix/etc/rc.conf" michael@13: rcfunc="$prefix/etc/rc.func" michael@13: michael@13: # helper variables michael@13: NL=" michael@13: " michael@13: michael@13: ## michael@13: ## command line option parsing michael@13: ## michael@13: michael@13: # default parameters michael@13: silent=0 michael@13: verbose=0 michael@13: debug=0 michael@13: help=0 michael@13: keep=0 michael@13: print=0 michael@13: eval=0 michael@13: config=0 michael@13: query=0 michael@13: michael@13: # iterate over argument line michael@13: while [ $# -gt 0 ]; do michael@13: opt=$1 michael@13: case $opt in michael@13: -*=*) arg=${opt/-*=/} ;; michael@13: *) arg='' ;; michael@13: esac michael@13: case $opt in michael@13: -s|--silent ) silent=1 ;; michael@13: -v|--verbose ) verbose=1 ;; michael@13: -d|--debug ) debug=1 ;; michael@13: -h|--help ) help="Usage" ;; michael@13: -k|--keep ) keep=1 ;; michael@13: -p|--print ) print=1 ;; michael@13: -e|--eval ) eval=1 ;; michael@13: -c|--config ) config=1 ;; michael@13: -q|--query ) query=1 ;; michael@13: -* ) help="Invalid option \`$opt'"; break ;; michael@13: * ) break ;; michael@13: esac michael@13: shift michael@13: done michael@13: michael@13: # display error or usage message michael@13: if [ ".$help" != .0 ]; then michael@13: if [ ".$help" != ".Usage" ]; then michael@13: echo "$progname:ERROR: $help" 1>&2 michael@13: fi michael@13: echo "Usage: $progname [-s|--silent] [-v|--verbose] [-d|--debug] [-k|--keep] [-h|--help]" 1>&2 michael@13: echo " [-p|--print] [-e|--eval] [-c|--config] [-q|--query]" 1>&2 michael@13: echo " [ ...]" 1>&2 michael@13: if [ ".$help" != ".Usage" ]; then michael@13: exit 1 michael@13: else michael@13: exit 0 michael@13: fi michael@13: fi michael@13: michael@13: # determine a reasonable default silent/verbose situation in case michael@13: # nothing was explicitly specified or a conflicting situation was michael@13: # specified. Else is silent either disabled by default or was michael@13: # explicitly enabled. michael@13: if [ $silent -eq $verbose ]; then michael@13: if [ -t 2 ]; then michael@13: # stdout connected to a terminal device, so no need to be silent michael@13: silent=0 michael@13: else michael@13: # stdout NOT connected to a terminal device, so be silent michael@13: silent=1 michael@13: fi michael@13: fi michael@13: michael@13: # extend run-time environment with local OpenPKG tools (shtool, rpmtool, etc) michael@13: PATH_ORIG="$PATH" michael@13: PATH="$prefix/bin:$PATH" michael@13: PATH="$prefix/sbin:$PATH" michael@13: PATH="$prefix/lib/openpkg:$PATH" michael@13: michael@13: # establish secure temporary directory michael@13: i=0 michael@13: while [ $i -lt 10 ]; do michael@13: tmpdir="/tmp/rc-`date '+%Y%m%d%H%M%S'`-$$" michael@13: (umask 022; mkdir $tmpdir >/dev/null 2>&1) && break michael@13: i=$(($i + 1)) michael@13: sleep 1 michael@13: done michael@13: if [ $i -eq 10 ]; then michael@13: echo "openpkg:rc:ERROR: unable to establish secure temporary directory" 1>&2 michael@13: exit 1 michael@13: fi michael@13: declare -r tmpdir michael@13: trap "trap - EXIT INT ABRT QUIT TERM; rm -rf $tmpdir >/dev/null 2>&1 || true" EXIT INT ABRT QUIT TERM michael@13: michael@13: # determine reasonable temporary files michael@13: tmpfile="$tmpdir/rc.tmp" michael@13: outfile="$tmpdir/rc.out" michael@13: errfile="$tmpdir/rc.err" michael@13: allfile="$tmpdir/rc.all" michael@13: michael@13: # handle --query option michael@13: if [ ".$query" = .1 ]; then michael@13: # suck in all %config sections of all scripts michael@13: # (rc.openpkg is special: has to be first and requires pre-inclusion of rc.conf) michael@13: touch $tmpfile michael@13: sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d' michael@13: echo ". $rcconf" >>$tmpfile michael@13: scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'` michael@13: for s_name in $scripts; do michael@13: sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d' michael@13: done michael@13: . $tmpfile michael@13: michael@13: # apply override values to get effective values michael@13: . $rcconf michael@13: michael@13: # display variable value michael@13: for var in $*; do michael@13: eval "echo \${$var}" michael@13: done michael@13: michael@13: # stop processing immediately michael@13: exit 0 michael@13: fi michael@13: michael@13: # handle --config option michael@13: if [ ".$config" = .1 ]; then michael@13: # suck in all %config sections of all scripts michael@13: # (rc.openpkg is special: has to be first and requires pre-inclusion of rc.conf) michael@13: touch $tmpfile michael@13: sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d' michael@13: echo ". $rcconf" >>$tmpfile michael@13: scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'` michael@13: for s_name in $scripts; do michael@13: sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d' michael@13: done michael@13: . $tmpfile michael@13: michael@13: # remember default values michael@13: vars="" michael@13: OIFS="$IFS"; IFS="$NL" michael@13: for assign in `egrep '[ ]*[a-zA-Z_][a-zA-Z_0-9]*=' $tmpfile | sort`; do michael@13: var=`echo "$assign" | sed -e 's;^[ ]*\([a-zA-Z_][a-zA-Z_0-9]*\)=.*;\1;'` michael@13: vars="$vars $var" michael@13: eval "${var}_def=\"\$$var\"" michael@13: done michael@13: IFS="$OIFS" michael@13: michael@13: # apply override values to get effective values michael@13: . $rcconf michael@13: michael@13: # determine how to print in bold mode in case output michael@13: # is connected to a terminal device michael@13: if [ -t 1 ]; then michael@13: begin_bold=`$shtool echo -e '%B'` michael@13: end_bold=`$shtool echo -e '%b'` michael@13: else michael@13: begin_bold="" michael@13: end_bold="" michael@13: fi michael@13: michael@13: # iterate over all variables and display name, default and effective value michael@13: echo "${begin_bold}Configuration Variable Effective Value Default Value${end_bold}" michael@13: echo "------------------------ ------------------------- -- -------------------------" michael@13: for var in . $vars; do michael@13: test ".$var" = .. && continue michael@13: eval "val=\"\$$var\"" michael@13: eval "def=\"\$${var}_def\"" michael@13: tag="!=" michael@13: begin="$begin_bold" michael@13: end="$end_bold" michael@13: if [ ".$val" = ".$def" ]; then michael@13: tag="==" michael@13: begin="" michael@13: end="" michael@13: fi michael@13: printf "%s%-24s %-25s %s %-25s%s\n" "$begin" "$var" "\"$val\"" "$tag" "\"$def\"" "$end" michael@13: done michael@13: michael@13: # stop processing immediately michael@13: exit 0 michael@13: fi michael@13: michael@13: # determine script(s) to use and make sure they exist michael@13: if [ $# -lt 1 ]; then michael@13: echo "openpkg:rc:ERROR: no package and command(s) specified" 1>&2 michael@13: exit 1 michael@13: fi michael@13: if [ $# -lt 2 ]; then michael@13: echo "openpkg:rc:ERROR: no command(s) specified for package" 1>&2 michael@13: exit 1 michael@13: fi michael@13: scripts="${1/*rc./}" michael@13: shift michael@13: isall=0 michael@13: if [ ".$scripts" = ".all" ]; then michael@13: isall=1 michael@13: . $rcconf michael@13: if [ ".$openpkg_runall" != . ]; then michael@13: # backward compatibility only michael@13: echo "openpkg:rc:WARNING: variable \"openpkg_runall\" was renamed to \"openpkg_rc_all\"." 1>&2 michael@13: echo "openpkg:rc:WARNING: value of deprecated variable \"openpkg_runall\" taken over for compatibility." 1>&2 michael@13: echo "openpkg:rc:WARNING: please update your local configuration in \"$rcconf\"." 1>&2 michael@13: openpkg_rc_all="$openpkg_runall" michael@13: fi michael@13: case "$openpkg_rc_all" in michael@13: [Nn][Oo] | [Ff][Aa][Ll][Ss][Ee] | [Oo][Ff][Ff] | 0 ) exit 0 ;; michael@13: esac michael@13: scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;"` michael@13: else michael@13: if [ ! -f "$rcdir/rc.$scripts" ]; then michael@13: echo "openpkg:rc:ERROR: package \"$scripts\" not found" 1>&2 michael@13: exit 1 michael@13: fi michael@13: fi michael@13: michael@13: # determine current run-time user michael@13: user=`(id -un) 2>/dev/null ||\ michael@13: (id | sed -e 's;^[^(]*(\([^)]*\)).*;\1;') 2>/dev/null ||\ michael@13: (whoami) 2>/dev/null ||\ michael@13: (who am i | cut "-d " -f1) 2>/dev/null ||\ michael@13: echo ${LOGNAME:-${USER}}` michael@13: if [ ".$user" = . ]; then michael@13: echo "openpkg:rc:ERROR: unable to determine current username" 1>&2 michael@13: exit 1 michael@13: fi michael@13: michael@13: # iterate over the specified commands michael@13: rv=0 michael@13: cmds="$*" michael@13: for cmd in $cmds; do michael@13: # create "all outputs" file for execution operation (i.e. not --print and --eval) michael@13: if [ ".$print" = .0 -a ".$eval" = .0 ]; then michael@13: rm -f $allfile michael@13: touch $allfile michael@13: fi michael@13: michael@13: # find scripts which contain the command and determine michael@13: # their individual user/priority settings michael@13: list='' michael@13: for s_name in $scripts; do michael@13: enable=yes michael@13: michael@13: # check for upgraded package with unresolved configuration file conflicts michael@13: if [ -d "$prefix/etc/$s_name" -a ".$eval" != .1 ]; then michael@13: 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 michael@13: case "$cmd" in michael@13: start|restart ) type="ERROR" ;; michael@13: * ) type="WARNING" ;; michael@13: esac michael@13: echo "openpkg:rc:${type}: package \"$s_name\" has unresolved configuration file conflicts" 1>&2 michael@13: echo "openpkg:rc:${type}: indicated by \"*.rpm(new|orig|save)\" files in or below the" 1>&2 michael@13: echo "openpkg:rc:${type}: directory \"$prefix/etc/$s_name\". Please resolve first!" 1>&2 michael@13: if [ ".$type" = .ERROR ]; then michael@13: continue michael@13: fi michael@13: fi michael@13: fi michael@13: michael@13: # check whether command exists in script at all michael@13: cmdline=`grep "^%$cmd" $rcdir/rc.$s_name | sed -e "s;^%$cmd[^ ].*;;"` michael@13: if [ ".$cmdline" != . ]; then michael@13: # parse local command options michael@13: cmdopts=`echo "$cmdline" | sed -e "s;^%$cmd *;;"` michael@13: s_user=$user michael@13: s_prio=500 michael@13: s_output=no michael@13: set -- $cmdopts michael@13: prev='' michael@13: for opt michael@13: do michael@13: if [ ".$prev" != . ]; then michael@13: opt="$prev$opt" michael@13: prev='' michael@13: fi michael@13: case $opt in michael@13: -*=* ) arg=${opt/-*=/} ;; michael@13: -[a-zA-Z]* ) arg=${opt/-[a-zA-Z0-9]/} ;; michael@13: *) arg='' ;; michael@13: esac michael@13: case $opt in michael@13: -u|-p ) prev=$opt ;; michael@13: -e|--enable ) enable=yes ;; michael@13: -d|--disable ) enable=no ;; michael@13: -o|--output ) s_output=yes ;; michael@13: -u*|--user=* ) s_user=$arg ;; michael@13: -p*|--prio=* ) s_prio=$arg ;; michael@13: * ) echo "openpkg:rc:WARNING: invalid local option \"$opt\" in \"$rcdir/rc.$s_name:%$cmd\""; break ;; michael@13: esac michael@13: shift michael@13: done michael@13: michael@13: # sanity check: is operation supported by current environment? michael@13: if [ ".$s_user" != ".$user" -a ".$user" != ".root" -a ".$print" = .0 ]; then michael@13: echo "openpkg:rc:ERROR: $s_name:%$cmd: require root privileges to run as user \"$s_user\"" 1>&2 michael@13: exit 1 michael@13: fi michael@13: michael@13: # skip this script if script is disabled michael@13: if [ ".$enable" != .yes ]; then michael@13: continue michael@13: fi michael@13: michael@13: # accumulate the determined information michael@13: list="$list,$s_prio:$s_name:$s_user:$s_output" michael@13: else michael@13: # command not found in script michael@13: if [ ".$isall" = .0 ]; then michael@13: echo "openpkg:rc:ERROR: $s_name: command \"$cmd\" not found" 1>&2 michael@13: exit 1 michael@13: fi michael@13: fi michael@13: done michael@13: michael@13: # if operating on all scripts, complain if a non-standard command michael@13: # was used and it was not found in any(!) script at all. The michael@13: # standard commands are accepted to perform no operation if no michael@13: # packages are currently installed which provide such commands. michael@13: if [ ".$list" = . -a ".$isall" = .1 ]; then michael@13: case "$cmd" in michael@13: start|stop|monthly|weekly|daily|hourly|quarterly ) michael@13: ;; michael@13: * ) michael@13: echo "openpkg:rc:ERROR: command \"$cmd\" not found in any script" 1>&2 michael@13: rv=1 michael@13: break michael@13: ;; michael@13: esac michael@13: fi michael@13: michael@13: # generate global (loop invariant) header for script in case of michael@13: # --print and --eval (for the execution approach we cannot do michael@13: # this, because there a new script is generated from scratch for michael@13: # each package. michael@13: if [ ".$print" = .1 -o ".$eval" = .1 ]; then michael@13: rm -f $tmpfile michael@13: touch $tmpfile michael@13: michael@13: # generate: optionally enable shell debugging michael@13: if [ ".$debug" = .1 ]; then michael@13: echo "set -x" >>$tmpfile michael@13: fi michael@13: michael@13: # generate: inclusion of the run-command helper functions michael@13: echo ". $rcfunc" >>$tmpfile michael@13: michael@13: # generate: all %config sections of all(!) scripts. We cannot michael@13: # just include those which have the current command in it michael@13: # because by design all command scripts see the %config michael@13: # section of all(!) scripts. Because of $openpkg_rc_def the michael@13: # variable, we place the %config section of "openpkg" to the front. michael@13: # And we have to extra pre-include the rc.conf to allow michael@13: # rc.conf to override the default of $openpkg_rc_def, too. michael@13: sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d' michael@13: echo ". $rcconf" >>$tmpfile michael@13: l_scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'` michael@13: for l_name in $l_scripts; do michael@13: sed <$rcdir/rc.$l_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d' michael@13: done michael@13: michael@13: # generate: inclusion of the application of override variables michael@13: echo ". $rcconf" >>$tmpfile michael@13: michael@13: # for --eval redirect stderr and stdout (but remember stdout) michael@13: # (let stderr pass unfiltered in case of debug mode) michael@13: if [ ".$eval" = .1 ]; then michael@13: if [ ".$debug" = .1 ]; then michael@13: echo "exec 3<&1- 1>/dev/null" >>$tmpfile michael@13: else michael@13: echo "exec 3<&1- 1>/dev/null 2>/dev/null" >>$tmpfile michael@13: fi michael@13: fi michael@13: fi michael@13: michael@13: # iterate over all packages (in priority order!) where the command michael@13: # was found in order to execute, print, or evaluate their scripts michael@13: verbose_pos=0 michael@13: for entry in `echo $list | tr ',' '\012' | sort -n`; do michael@13: [ ".$entry" = . ] && continue michael@13: michael@13: # re-determine the script name, script and whether to print output michael@13: eval `echo $entry | sed -e 's%^[0-9]*:\(.*\):\(.*\):\(.*\)$%s_name="\1"; s_user="\2"; s_output="\3";%'` michael@13: michael@13: # display verbose progress message parts michael@13: if [ ".$print" = .0 -a ".$eval" = .0 -a ".$silent" = .0 ]; then michael@13: # line break if we already have output more than 70 michael@13: # characters (notice that usually already more characters michael@13: # where printed, because of the name of the last script) michael@13: if [ $verbose_pos -gt 70 ]; then michael@13: verbose_pos=0 michael@13: echo "" 1>&2 michael@13: fi michael@13: michael@13: # display verbose message parts: prefix (on first), separator and package michael@13: if [ $verbose_pos -eq 0 ]; then michael@13: output=$(printf "OpenPKG: %s: " "$cmd") michael@13: echo -n "$output" 1>&2 michael@13: verbose_pos=$(($verbose_pos + ${#output})) michael@13: output_prefix="" michael@13: else michael@13: output_prefix=", " michael@13: fi michael@13: output=$(printf "%s%s" "$output_prefix" "$s_name") michael@13: echo -n "$output" 1>&2 michael@13: verbose_pos=$(($verbose_pos + ${#output})) michael@13: fi michael@13: michael@13: # now operate on the particular script michael@13: if [ ".$print" = .1 ]; then michael@13: # special case: under --print we just add the %common and michael@13: # command scripts to the generated output script and do michael@13: # not execute anything at this point. michael@13: sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d' michael@13: sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d' michael@13: elif [ ".$eval" = .1 ]; then michael@13: # special case: under --eval we just add the %common and michael@13: # command scripts to the generated output script and do michael@13: # not execute anything at this point. Additionally, we michael@13: # emulate a real sub-shell environment. michael@13: sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d' michael@13: echo "while [ 1 ]; do" >>$tmpfile michael@13: sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d' \ michael@13: -e 's/^exit[^;]*/break 99/' -e 's/\([^a-zA-Z0-9_]\)exit[^;]*/\1break 99/g' \ michael@13: -e 's/^return[^;]*/break 99/' -e 's/\([^a-zA-Z0-9_]\)return[^;]*/\1break 99/g' michael@13: echo "break" >>$tmpfile michael@13: echo "done" >>$tmpfile michael@13: else michael@13: # the regular case of executing the command script directly michael@13: michael@13: # prepare temporary files michael@13: rm -f $tmpfile $outfile $errfile michael@13: (umask 077; touch $tmpfile $outfile $errfile) michael@13: michael@13: # generate: optionally enable shell debugging michael@13: if [ ".$debug" = .1 ]; then michael@13: echo "set -x" >>$tmpfile michael@13: fi michael@13: michael@13: # generate: inclusion of the run-command helper functions michael@13: echo ". $rcfunc" >>$tmpfile michael@13: michael@13: # generate: all %config sections of all(!) scripts. We cannot michael@13: # just include those which have the current command in it michael@13: # because by design all command scripts see the %config michael@13: # section of all(!) scripts. Because of $openpkg_rc_def the michael@13: # variable, we place the %config section of "openpkg" to the front. michael@13: # And we have to extra pre-include the rc.conf to allow michael@13: # rc.conf to override the default of $openpkg_rc_def, too. michael@13: sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d' michael@13: echo ". $rcconf" >>$tmpfile michael@13: l_scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'` michael@13: for l_name in $l_scripts; do michael@13: sed <$rcdir/rc.$l_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d' michael@13: done michael@13: michael@13: # generate: inclusion of the application of override variables michael@13: echo ". $rcconf" >>$tmpfile michael@13: michael@13: # generate: %common section and particular command section michael@13: sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d' michael@13: sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d' michael@13: michael@13: # execute the generated script with GNU Bash michael@13: if [ ".$user" != ".$s_user" ]; then michael@13: # execute as different user michael@13: if [ ".$verbose" = .1 ]; then michael@13: echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: executing as user $s_user" michael@13: fi michael@13: if [ ".$user" = ".@l_susr@" -a ".@l_susr@" = ".root" ]; then michael@13: chown $s_user $tmpfile michael@13: if [ ".$debug" = .1 ]; then michael@13: su - $s_user -c "PATH=\"$PATH\"; $bash $tmpfile" >$outfile michael@13: rc=$? michael@13: else michael@13: su - $s_user -c "PATH=\"$PATH\"; $bash $tmpfile" >$outfile 2>$errfile michael@13: rc=$? michael@13: fi michael@13: elif [ ".@l_susr@" != ".root" ]; then michael@13: # do not complain if we would not have any chance michael@13: # at all to switch the user because we are running michael@13: # in a non-privileged instance. Else we would just michael@13: # trash the mailbox of the user receiving the michael@13: # output of periodic run-commands. michael@13: rc=0 michael@13: else michael@13: echo "openpkg:rc:WARNING: $prefix:$s_name:%$cmd: require root privileges to run as user \"$s_user\"" 1>&2 michael@13: rc=1 michael@13: fi michael@13: else michael@13: # execute as current user michael@13: if [ ".$verbose" = .1 ]; then michael@13: echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: executing as user $user" michael@13: fi michael@13: if [ ".$debug" = .1 ]; then michael@13: $bash $tmpfile >$outfile michael@13: rc=$? michael@13: else michael@13: $bash $tmpfile >$outfile 2>$errfile michael@13: rc=$? michael@13: fi michael@13: fi michael@13: if [ $rc -ne 0 ]; then michael@13: if [ ".$silent" = .0 ]; then michael@13: # indicate failure of execution on verbose message line michael@13: echo ":FAILED" 1>&2 michael@13: verbose_pos=0 michael@13: fi michael@13: # give details of execution failure michael@13: ( echo "openpkg:rc:WARNING: $prefix:$s_name:%$cmd: failed with return code $rc" michael@13: if [ ".`cat $outfile $errfile`" != . ]; then michael@13: echo "openpkg:rc:NOTICE: output from stdout/stderr is following:" michael@13: echo "+----------------------------------------------------------------------" michael@13: cat $outfile $errfile | sed -e 's;^;| ;' michael@13: echo "+----------------------------------------------------------------------" michael@13: else michael@13: echo "openpkg:rc:NOTICE: no output occurred on stdout/stderr" michael@13: fi michael@13: ) 1>&2 michael@13: michael@13: # enforce global return value michael@13: rv=1 michael@13: else michael@13: # give details of execution success in case verbose operation is requested michael@13: if [ ".$verbose" = .1 ]; then michael@13: ( echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: succeeded with return code $rc" michael@13: if [ ".`cat $outfile $errfile`" != . ]; then michael@13: echo "openpkg:rc:NOTICE: output from stdout/stderr is following:" michael@13: echo "+----------------------------------------------------------------------" michael@13: cat $outfile $errfile | sed -e 's;^;| ;' michael@13: echo "+----------------------------------------------------------------------" michael@13: else michael@13: echo "openpkg:rc:NOTICE: no output occurred on stdout/stderr" michael@13: fi michael@13: ) 1>&2 michael@13: fi michael@13: if [ ".$s_output" = .yes ]; then michael@13: # accumulate script output for later display michael@13: cat $outfile >>$allfile michael@13: fi michael@13: fi michael@13: fi michael@13: done michael@13: michael@13: # post-processing for each command michael@13: if [ ".$print" = .1 ]; then michael@13: # for --print just print the resulting script to stdout michael@13: cat $tmpfile michael@13: elif [ ".$eval" = .1 ]; then michael@13: # finish generation of temporary script by restoring stdout michael@13: # and printing the exported environment variables into a format michael@13: # suitable for evaluation by the callers shell. michael@13: echo "exec 1<&3-" >>$tmpfile michael@13: echo "unset PWD SHLVL" >>$tmpfile michael@13: echo "env |\\" >>$tmpfile michael@13: echo "egrep '^[A-Z_][A-Z0-9_]*=.' |\\" >>$tmpfile michael@13: echo "sed -e '/^_=/d' -e 's/\\\\/\\\\\\\\/g' -e 's/\"/\\\\\"/g' \\" >>$tmpfile michael@13: case $SHELL in michael@13: csh|*/csh|tcsh|*/tcsh ) michael@13: echo "-e 's/^\\([^=]*\\)=\\(.*\\)\$/setenv \\1 \"\\2\"/'" >>$tmpfile michael@13: ;; michael@13: * ) michael@13: echo "-e 's/^\\([^=]*\\)=\\(.*\\)\$/\\1=\"\\2\"; export \\1/'" >>$tmpfile michael@13: ;; michael@13: esac michael@13: michael@13: # prepare temporary files michael@13: rm -f $outfile $errfile michael@13: touch $outfile $errfile michael@13: michael@13: # now replace temporary script with its output michael@13: # by executing it and capturing its output michael@13: # (let stderr pass unfiltered in case of debug mode) michael@13: if [ ".$debug" = .1 ]; then michael@13: env -i \ michael@13: HOME="$HOME" \ michael@13: USER="$USER" \ michael@13: LOGNAME="$LOGNAME" \ michael@13: TERM="$TERM" \ michael@13: PATH="$PATH_ORIG" \ michael@13: MANPATH="$MANPATH" \ michael@13: INFOPATH="$INFOPATH" \ michael@13: LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \ michael@13: $bash --norc --noprofile --posix \ michael@13: $tmpfile >$outfile michael@13: else michael@13: env -i \ michael@13: HOME="$HOME" \ michael@13: USER="$USER" \ michael@13: LOGNAME="$LOGNAME" \ michael@13: TERM="$TERM" \ michael@13: PATH="$PATH_ORIG" \ michael@13: MANPATH="$MANPATH" \ michael@13: INFOPATH="$INFOPATH" \ michael@13: LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \ michael@13: $bash --norc --noprofile --posix \ michael@13: $tmpfile >$outfile 2>/dev/null michael@13: fi michael@13: cp $outfile $tmpfile michael@13: michael@13: # for --eval we cannot just print the resulting script because michael@13: # not all Bourne-Shell implementations like to "eval" large michael@13: # multi-line outputs. Hence we output a little one-liner which michael@13: # "sources" the script instead and cleans up. michael@13: case $SHELL in michael@13: csh|*/csh|tcsh|*/tcsh ) michael@13: echo "source $tmpfile; rm -rf $tmpdir 2>/dev/null || true" michael@13: ;; michael@13: * ) michael@13: echo ". $tmpfile; rm -rf $tmpdir 2>/dev/null || true" michael@13: ;; michael@13: esac michael@13: else michael@13: # for the execution situation just make sure we michael@13: # terminate the verbose message output. michael@13: if [ ".$silent" = .0 -a $verbose_pos -gt 0 ]; then michael@13: echo "." 1>&2 michael@13: fi michael@13: michael@13: # additionally, if a script wants its output to be displayed, michael@13: # now do it. In case there was no such request, do not bother michael@13: # -- we then just output an empty file and so can avoid an michael@13: # extra test surrounding the next command. michael@13: cat $allfile michael@13: fi michael@13: done michael@13: michael@13: # cleanup temporary files except the result script in michael@13: # case of --eval (which is then removed by the caller). michael@13: # keep those files for debugging purposes if requested. michael@13: if [ ".$keep" = .0 ]; then michael@13: rm -f $outfile $errfile $allfile >/dev/null 2>&1 || true michael@13: if [ ".$eval" = .0 ]; then michael@13: rm -f $tmpfile >/dev/null 2>&1 || true michael@13: rm -rf $tmpdir >/dev/null 2>&1 || true michael@13: fi michael@13: fi michael@13: michael@13: # now clean the exit trap and exit with the global return value michael@13: # indicating to the caller whether all scripts were executed michael@13: # successfully or at least one failed. michael@13: trap - EXIT michael@13: exit $rv michael@13: