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