openpkg/rc

Thu, 04 Oct 2012 20:30:05 +0200

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 04 Oct 2012 20:30:05 +0200
changeset 715
c10fb90893b9
parent 469
65414bdd541c
permissions
-rw-r--r--

Correct out of date build configuration, porting to Solaris 11 network
link infrastructure and new libpcap logic. This additionally allows for
device drivers in subdirectories of /dev. Correct packaged nmap
personalities and signatures to work out of the box. Finally, hack
arpd logic to properly close sockets and quit on TERM by repeating
signaling in the run command script. Sadly, all this fails to correct
the run time behaviour of honeyd which fails to bind to the IP layer.

michael@13 1 #!@l_prefix@/lib/openpkg/bash --noprofile
michael@13 2 ##
michael@428 3 ## rc -- OpenPKG Run-Command Processor
michael@428 4 ## Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/>
michael@13 5 ##
michael@428 6 ## This software is property of the OpenPKG GmbH, DE MUC HRB 160208.
michael@428 7 ## All rights reserved. Licenses which grant limited permission to use,
michael@428 8 ## copy, modify and distribute this software are available from the
michael@428 9 ## OpenPKG GmbH.
michael@13 10 ##
michael@428 11 ## THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
michael@13 12 ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
michael@13 13 ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
michael@13 14 ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
michael@13 15 ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@13 16 ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@13 17 ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
michael@13 18 ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
michael@13 19 ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
michael@13 20 ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
michael@13 21 ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
michael@13 22 ## SUCH DAMAGE.
michael@13 23 ##
michael@13 24
michael@13 25 ##
michael@13 26 ## configuration
michael@13 27 ##
michael@13 28
michael@13 29 # program name, version and date
michael@13 30 progname="rc"
michael@428 31 progvers="1.2.1"
michael@428 32 progdate="2007-12-27"
michael@13 33
michael@13 34 # path to OpenPKG instance
michael@13 35 prefix="@l_prefix@"
michael@13 36
michael@13 37 # path to GNU bash and GNU shtool
michael@13 38 bash="$prefix/lib/openpkg/bash"
michael@13 39 shtool="$prefix/lib/openpkg/shtool"
michael@13 40
michael@13 41 # path to rc.d, rc.conf and rc.func
michael@13 42 rcdir="$prefix/etc/rc.d"
michael@13 43 rcconf="$prefix/etc/rc.conf"
michael@13 44 rcfunc="$prefix/etc/rc.func"
michael@13 45
michael@13 46 # helper variables
michael@13 47 NL="
michael@13 48 "
michael@13 49
michael@13 50 ##
michael@428 51 ## temporary file handling
michael@428 52 ##
michael@428 53
michael@428 54 # establish secure temporary directory
michael@428 55 i=0
michael@428 56 while [ $i -lt 10 ]; do
michael@428 57 tmpdir="/tmp/rc-`date '+%Y%m%d%H%M%S'`-$$"
michael@428 58 (umask 022; mkdir $tmpdir >/dev/null 2>&1) && break
michael@428 59 i=$(($i + 1))
michael@428 60 sleep 1
michael@428 61 done
michael@428 62 if [ $i -eq 10 ]; then
michael@428 63 echo "openpkg:rc:ERROR: unable to establish secure temporary directory" 1>&2
michael@428 64 exit 1
michael@428 65 fi
michael@428 66 declare -r tmpdir
michael@428 67 cleanup () {
michael@428 68 if [ ".$tmpdir" != . ]; then
michael@428 69 if [ -d $tmpdir ]; then
michael@428 70 rm -rf $tmpdir >/dev/null 2>&1 || true
michael@428 71 fi
michael@428 72 fi
michael@428 73 }
michael@428 74 trap "cleanup; trap - EXIT INT ABRT QUIT TERM" EXIT INT ABRT QUIT TERM
michael@428 75
michael@428 76 # determine reasonable temporary files
michael@428 77 tmpfile="$tmpdir/rc.tmp"
michael@428 78 outfile="$tmpdir/rc.out"
michael@428 79 errfile="$tmpdir/rc.err"
michael@428 80 allfile="$tmpdir/rc.all"
michael@428 81 deffile="$tmpdir/rc.def"
michael@428 82
michael@428 83 # initialize files
michael@428 84 cp /dev/null $deffile
michael@428 85
michael@428 86 ##
michael@13 87 ## command line option parsing
michael@13 88 ##
michael@13 89
michael@13 90 # default parameters
michael@13 91 silent=0
michael@13 92 verbose=0
michael@13 93 debug=0
michael@13 94 help=0
michael@13 95 keep=0
michael@13 96 print=0
michael@13 97 eval=0
michael@13 98 config=0
michael@13 99 query=0
michael@13 100
michael@13 101 # iterate over argument line
michael@13 102 while [ $# -gt 0 ]; do
michael@428 103 case "$1" in
michael@13 104 -s|--silent ) silent=1 ;;
michael@13 105 -v|--verbose ) verbose=1 ;;
michael@13 106 -d|--debug ) debug=1 ;;
michael@13 107 -h|--help ) help="Usage" ;;
michael@13 108 -k|--keep ) keep=1 ;;
michael@13 109 -p|--print ) print=1 ;;
michael@13 110 -e|--eval ) eval=1 ;;
michael@13 111 -c|--config ) config=1 ;;
michael@13 112 -q|--query ) query=1 ;;
michael@428 113 -D|--define ) echo "@$2" | \
michael@428 114 sed -e "s;';\\\\';g" | \
michael@428 115 sed -e "s;^@\\([a-z][a-zA-Z0-9_]*\\)=\\(.*\\)\$;\1='\2';" \
michael@428 116 -e "s;^@.*;;" >>$deffile; shift ;;
michael@428 117 -* ) help="Invalid option \`$1'"; break ;;
michael@428 118 * ) break ;;
michael@13 119 esac
michael@13 120 shift
michael@13 121 done
michael@13 122
michael@13 123 # display error or usage message
michael@13 124 if [ ".$help" != .0 ]; then
michael@13 125 if [ ".$help" != ".Usage" ]; then
michael@13 126 echo "$progname:ERROR: $help" 1>&2
michael@13 127 fi
michael@13 128 echo "Usage: $progname [-s|--silent] [-v|--verbose] [-d|--debug] [-k|--keep] [-h|--help]" 1>&2
michael@428 129 echo " [-p|--print] [-e|--eval] [-c|--config] [-q|--query] [-D|--define <name>=<value>]" 1>&2
michael@13 130 echo " <package> <command> [<command> ...]" 1>&2
michael@13 131 if [ ".$help" != ".Usage" ]; then
michael@13 132 exit 1
michael@13 133 else
michael@13 134 exit 0
michael@13 135 fi
michael@13 136 fi
michael@13 137
michael@13 138 # determine a reasonable default silent/verbose situation in case
michael@13 139 # nothing was explicitly specified or a conflicting situation was
michael@13 140 # specified. Else is silent either disabled by default or was
michael@13 141 # explicitly enabled.
michael@13 142 if [ $silent -eq $verbose ]; then
michael@13 143 if [ -t 2 ]; then
michael@13 144 # stdout connected to a terminal device, so no need to be silent
michael@13 145 silent=0
michael@13 146 else
michael@13 147 # stdout NOT connected to a terminal device, so be silent
michael@13 148 silent=1
michael@13 149 fi
michael@13 150 fi
michael@13 151
michael@471 152 # extend runtime environment with local OpenPKG tools (shtool, rpmtool, etc)
michael@13 153 PATH_ORIG="$PATH"
michael@428 154 PATH="$prefix/lib/openpkg/fallback:$PATH"
michael@13 155 PATH="$prefix/bin:$PATH"
michael@13 156 PATH="$prefix/sbin:$PATH"
michael@13 157 PATH="$prefix/lib/openpkg:$PATH"
michael@428 158 PATH="$prefix/lib/openpkg/override:$PATH"
michael@13 159
michael@13 160 # handle --query option
michael@13 161 if [ ".$query" = .1 ]; then
michael@13 162 # suck in all %config sections of all scripts
michael@471 163 # (rc.openpkg is special: has to be first and requires preinclusion of rc.conf)
michael@13 164 touch $tmpfile
michael@13 165 sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
michael@13 166 echo ". $rcconf" >>$tmpfile
michael@428 167 echo ". $deffile" >>$tmpfile
michael@13 168 scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'`
michael@13 169 for s_name in $scripts; do
michael@13 170 sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
michael@13 171 done
michael@13 172 . $tmpfile
michael@13 173
michael@13 174 # apply override values to get effective values
michael@13 175 . $rcconf
michael@428 176 . $deffile
michael@13 177
michael@13 178 # display variable value
michael@13 179 for var in $*; do
michael@13 180 eval "echo \${$var}"
michael@13 181 done
michael@13 182
michael@13 183 # stop processing immediately
michael@13 184 exit 0
michael@13 185 fi
michael@13 186
michael@13 187 # handle --config option
michael@13 188 if [ ".$config" = .1 ]; then
michael@13 189 # suck in all %config sections of all scripts
michael@471 190 # (rc.openpkg is special: has to be first and requires preinclusion of rc.conf)
michael@13 191 touch $tmpfile
michael@13 192 sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
michael@13 193 echo ". $rcconf" >>$tmpfile
michael@428 194 echo ". $deffile" >>$tmpfile
michael@13 195 scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'`
michael@13 196 for s_name in $scripts; do
michael@13 197 sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
michael@13 198 done
michael@13 199 . $tmpfile
michael@13 200
michael@13 201 # remember default values
michael@13 202 vars=""
michael@13 203 OIFS="$IFS"; IFS="$NL"
michael@13 204 for assign in `egrep '[ ]*[a-zA-Z_][a-zA-Z_0-9]*=' $tmpfile | sort`; do
michael@13 205 var=`echo "$assign" | sed -e 's;^[ ]*\([a-zA-Z_][a-zA-Z_0-9]*\)=.*;\1;'`
michael@13 206 vars="$vars $var"
michael@13 207 eval "${var}_def=\"\$$var\""
michael@13 208 done
michael@13 209 IFS="$OIFS"
michael@13 210
michael@13 211 # apply override values to get effective values
michael@13 212 . $rcconf
michael@428 213 . $deffile
michael@13 214
michael@13 215 # determine how to print in bold mode in case output
michael@13 216 # is connected to a terminal device
michael@13 217 if [ -t 1 ]; then
michael@13 218 begin_bold=`$shtool echo -e '%B'`
michael@13 219 end_bold=`$shtool echo -e '%b'`
michael@13 220 else
michael@13 221 begin_bold=""
michael@13 222 end_bold=""
michael@13 223 fi
michael@13 224
michael@13 225 # iterate over all variables and display name, default and effective value
michael@13 226 echo "${begin_bold}Configuration Variable Effective Value Default Value${end_bold}"
michael@13 227 echo "------------------------ ------------------------- -- -------------------------"
michael@13 228 for var in . $vars; do
michael@13 229 test ".$var" = .. && continue
michael@13 230 eval "val=\"\$$var\""
michael@13 231 eval "def=\"\$${var}_def\""
michael@13 232 tag="!="
michael@13 233 begin="$begin_bold"
michael@13 234 end="$end_bold"
michael@13 235 if [ ".$val" = ".$def" ]; then
michael@13 236 tag="=="
michael@13 237 begin=""
michael@13 238 end=""
michael@13 239 fi
michael@13 240 printf "%s%-24s %-25s %s %-25s%s\n" "$begin" "$var" "\"$val\"" "$tag" "\"$def\"" "$end"
michael@13 241 done
michael@13 242
michael@13 243 # stop processing immediately
michael@13 244 exit 0
michael@13 245 fi
michael@13 246
michael@13 247 # determine script(s) to use and make sure they exist
michael@13 248 if [ $# -lt 1 ]; then
michael@13 249 echo "openpkg:rc:ERROR: no package and command(s) specified" 1>&2
michael@13 250 exit 1
michael@13 251 fi
michael@13 252 if [ $# -lt 2 ]; then
michael@13 253 echo "openpkg:rc:ERROR: no command(s) specified for package" 1>&2
michael@13 254 exit 1
michael@13 255 fi
michael@13 256 scripts="${1/*rc./}"
michael@13 257 shift
michael@13 258 isall=0
michael@428 259 if [ ".$scripts" = ".cron" ]; then
michael@428 260 # "cron" is an "all" with a random delay (to ensure that multiple
michael@428 261 # OpenPKG instances do not all startup at exactly the same time)
michael@428 262 # plus a mutex lock to ensure that multiple OpenPKG cron tasks of
michael@428 263 # the same OpenPKG instance do not stumble over each other).
michael@428 264
michael@428 265 # determine delay range and timeout
michael@428 266 case "${1-quarterly}" in
michael@428 267 monthly ) delay=1800; timeout=28800 ;; # 30m / 8h
michael@428 268 weekly ) delay=1800; timeout=14400 ;; # 30m / 4h
michael@428 269 daily ) delay=900; timeout=7200 ;; # 15m / 2h
michael@428 270 hourly ) delay=600; timeout=3600 ;; # 5m / 1h
michael@428 271 quarterly|* ) delay=30; timeout=900 ;; # 30s / 15m
michael@428 272 esac
michael@428 273
michael@471 274 # apply random runtime delay
michael@428 275 # (hint: $RANDOM is a random value 0..32767)
michael@428 276 sleep $(( ($RANDOM * $delay) / 32767 ))
michael@428 277
michael@471 278 # wrap ourself for mutual exclusion runtime
michael@428 279 # and then perform the "all" command
michael@428 280 cleanup
michael@428 281 exec $prefix/lib/openpkg/mutex \
michael@428 282 -t $timeout $prefix/RPM/TMP/openpkg-rc-cron.mutex \
michael@428 283 sh -c "exec $0 all $*" || exit $?
michael@428 284 fi
michael@13 285 if [ ".$scripts" = ".all" ]; then
michael@13 286 isall=1
michael@13 287 . $rcconf
michael@428 288 . $deffile
michael@13 289 case "$openpkg_rc_all" in
michael@13 290 [Nn][Oo] | [Ff][Aa][Ll][Ss][Ee] | [Oo][Ff][Ff] | 0 ) exit 0 ;;
michael@13 291 esac
michael@13 292 scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;"`
michael@428 293
michael@428 294 # the "all" target is usually called from system startup scripts,
michael@428 295 # and we really want to ensure that no potentially corrupt
michael@428 296 # (because of an unclean shutdown of the system) RPM DB journal
michael@428 297 # files are staying around and preventing the startup of the
michael@428 298 # OpenPKG instance. When called manually it also doesn't hurt to
michael@428 299 # cleanup.
michael@428 300 rm -f $prefix/RPM/DB/__db.* >/dev/null 2>&1 || true
michael@13 301 else
michael@13 302 if [ ! -f "$rcdir/rc.$scripts" ]; then
michael@13 303 echo "openpkg:rc:ERROR: package \"$scripts\" not found" 1>&2
michael@13 304 exit 1
michael@13 305 fi
michael@13 306 fi
michael@13 307
michael@471 308 # determine current runtime user
michael@13 309 user=`(id -un) 2>/dev/null ||\
michael@13 310 (id | sed -e 's;^[^(]*(\([^)]*\)).*;\1;') 2>/dev/null ||\
michael@13 311 (whoami) 2>/dev/null ||\
michael@13 312 (who am i | cut "-d " -f1) 2>/dev/null ||\
michael@13 313 echo ${LOGNAME:-${USER}}`
michael@13 314 if [ ".$user" = . ]; then
michael@13 315 echo "openpkg:rc:ERROR: unable to determine current username" 1>&2
michael@13 316 exit 1
michael@13 317 fi
michael@13 318
michael@469 319 # Avoid handing control to OpenPKG binary logic until
michael@469 320 # the binary is is ready for prime time on all platforms.
michael@471 321 ## just call OpenPKG RPM to let it once perform the runtime integrity checks
michael@469 322 #$prefix/bin/openpkg rpm -q openpkg >/dev/null || exit $?
michael@428 323
michael@13 324 # iterate over the specified commands
michael@13 325 rv=0
michael@13 326 cmds="$*"
michael@13 327 for cmd in $cmds; do
michael@13 328 # create "all outputs" file for execution operation (i.e. not --print and --eval)
michael@13 329 if [ ".$print" = .0 -a ".$eval" = .0 ]; then
michael@13 330 rm -f $allfile
michael@13 331 touch $allfile
michael@13 332 fi
michael@13 333
michael@13 334 # find scripts which contain the command and determine
michael@13 335 # their individual user/priority settings
michael@13 336 list=''
michael@13 337 for s_name in $scripts; do
michael@13 338 enable=yes
michael@13 339
michael@13 340 # check for upgraded package with unresolved configuration file conflicts
michael@13 341 if [ -d "$prefix/etc/$s_name" -a ".$eval" != .1 ]; then
michael@13 342 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 343 case "$cmd" in
michael@13 344 start|restart ) type="ERROR" ;;
michael@13 345 * ) type="WARNING" ;;
michael@13 346 esac
michael@13 347 echo "openpkg:rc:${type}: package \"$s_name\" has unresolved configuration file conflicts" 1>&2
michael@13 348 echo "openpkg:rc:${type}: indicated by \"*.rpm(new|orig|save)\" files in or below the" 1>&2
michael@13 349 echo "openpkg:rc:${type}: directory \"$prefix/etc/$s_name\". Please resolve first!" 1>&2
michael@13 350 if [ ".$type" = .ERROR ]; then
michael@13 351 continue
michael@13 352 fi
michael@13 353 fi
michael@13 354 fi
michael@13 355
michael@13 356 # check whether command exists in script at all
michael@13 357 cmdline=`grep "^%$cmd" $rcdir/rc.$s_name | sed -e "s;^%$cmd[^ ].*;;"`
michael@13 358 if [ ".$cmdline" != . ]; then
michael@13 359 # parse local command options
michael@13 360 cmdopts=`echo "$cmdline" | sed -e "s;^%$cmd *;;"`
michael@13 361 s_user=$user
michael@13 362 s_prio=500
michael@13 363 s_output=no
michael@13 364 set -- $cmdopts
michael@13 365 prev=''
michael@13 366 for opt
michael@13 367 do
michael@13 368 if [ ".$prev" != . ]; then
michael@13 369 opt="$prev$opt"
michael@13 370 prev=''
michael@13 371 fi
michael@13 372 case $opt in
michael@13 373 -*=* ) arg=${opt/-*=/} ;;
michael@13 374 -[a-zA-Z]* ) arg=${opt/-[a-zA-Z0-9]/} ;;
michael@13 375 *) arg='' ;;
michael@13 376 esac
michael@13 377 case $opt in
michael@13 378 -u|-p ) prev=$opt ;;
michael@13 379 -e|--enable ) enable=yes ;;
michael@13 380 -d|--disable ) enable=no ;;
michael@13 381 -o|--output ) s_output=yes ;;
michael@13 382 -u*|--user=* ) s_user=$arg ;;
michael@13 383 -p*|--prio=* ) s_prio=$arg ;;
michael@13 384 * ) echo "openpkg:rc:WARNING: invalid local option \"$opt\" in \"$rcdir/rc.$s_name:%$cmd\""; break ;;
michael@13 385 esac
michael@13 386 shift
michael@13 387 done
michael@13 388
michael@13 389 # sanity check: is operation supported by current environment?
michael@13 390 if [ ".$s_user" != ".$user" -a ".$user" != ".root" -a ".$print" = .0 ]; then
michael@13 391 echo "openpkg:rc:ERROR: $s_name:%$cmd: require root privileges to run as user \"$s_user\"" 1>&2
michael@13 392 exit 1
michael@13 393 fi
michael@13 394
michael@13 395 # skip this script if script is disabled
michael@13 396 if [ ".$enable" != .yes ]; then
michael@13 397 continue
michael@13 398 fi
michael@13 399
michael@13 400 # accumulate the determined information
michael@13 401 list="$list,$s_prio:$s_name:$s_user:$s_output"
michael@13 402 else
michael@13 403 # command not found in script
michael@13 404 if [ ".$isall" = .0 ]; then
michael@13 405 echo "openpkg:rc:ERROR: $s_name: command \"$cmd\" not found" 1>&2
michael@13 406 exit 1
michael@13 407 fi
michael@13 408 fi
michael@13 409 done
michael@13 410
michael@471 411 # if operating on all scripts, complain if a nonstandard command
michael@13 412 # was used and it was not found in any(!) script at all. The
michael@13 413 # standard commands are accepted to perform no operation if no
michael@13 414 # packages are currently installed which provide such commands.
michael@13 415 if [ ".$list" = . -a ".$isall" = .1 ]; then
michael@13 416 case "$cmd" in
michael@13 417 start|stop|monthly|weekly|daily|hourly|quarterly )
michael@13 418 ;;
michael@13 419 * )
michael@13 420 echo "openpkg:rc:ERROR: command \"$cmd\" not found in any script" 1>&2
michael@13 421 rv=1
michael@13 422 break
michael@13 423 ;;
michael@13 424 esac
michael@13 425 fi
michael@13 426
michael@13 427 # generate global (loop invariant) header for script in case of
michael@13 428 # --print and --eval (for the execution approach we cannot do
michael@13 429 # this, because there a new script is generated from scratch for
michael@13 430 # each package.
michael@13 431 if [ ".$print" = .1 -o ".$eval" = .1 ]; then
michael@13 432 rm -f $tmpfile
michael@13 433 touch $tmpfile
michael@13 434
michael@13 435 # generate: optionally enable shell debugging
michael@13 436 if [ ".$debug" = .1 ]; then
michael@13 437 echo "set -x" >>$tmpfile
michael@13 438 fi
michael@13 439
michael@471 440 # generate: inclusion of the runcommand helper functions
michael@13 441 echo ". $rcfunc" >>$tmpfile
michael@13 442
michael@13 443 # generate: all %config sections of all(!) scripts. We cannot
michael@13 444 # just include those which have the current command in it
michael@13 445 # because by design all command scripts see the %config
michael@13 446 # section of all(!) scripts. Because of $openpkg_rc_def the
michael@13 447 # variable, we place the %config section of "openpkg" to the front.
michael@471 448 # And we have to extra preinclude the rc.conf to allow
michael@13 449 # rc.conf to override the default of $openpkg_rc_def, too.
michael@13 450 sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
michael@13 451 echo ". $rcconf" >>$tmpfile
michael@428 452 echo ". $deffile" >>$tmpfile
michael@13 453 l_scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'`
michael@13 454 for l_name in $l_scripts; do
michael@13 455 sed <$rcdir/rc.$l_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
michael@13 456 done
michael@13 457
michael@13 458 # generate: inclusion of the application of override variables
michael@13 459 echo ". $rcconf" >>$tmpfile
michael@428 460 echo ". $deffile" >>$tmpfile
michael@13 461
michael@13 462 # for --eval redirect stderr and stdout (but remember stdout)
michael@13 463 # (let stderr pass unfiltered in case of debug mode)
michael@13 464 if [ ".$eval" = .1 ]; then
michael@13 465 if [ ".$debug" = .1 ]; then
michael@13 466 echo "exec 3<&1- 1>/dev/null" >>$tmpfile
michael@13 467 else
michael@13 468 echo "exec 3<&1- 1>/dev/null 2>/dev/null" >>$tmpfile
michael@13 469 fi
michael@13 470 fi
michael@13 471 fi
michael@13 472
michael@13 473 # iterate over all packages (in priority order!) where the command
michael@13 474 # was found in order to execute, print, or evaluate their scripts
michael@13 475 verbose_pos=0
michael@13 476 for entry in `echo $list | tr ',' '\012' | sort -n`; do
michael@13 477 [ ".$entry" = . ] && continue
michael@13 478
michael@471 479 # redetermine the script name, script and whether to print output
michael@13 480 eval `echo $entry | sed -e 's%^[0-9]*:\(.*\):\(.*\):\(.*\)$%s_name="\1"; s_user="\2"; s_output="\3";%'`
michael@13 481
michael@13 482 # display verbose progress message parts
michael@13 483 if [ ".$print" = .0 -a ".$eval" = .0 -a ".$silent" = .0 ]; then
michael@13 484 # line break if we already have output more than 70
michael@13 485 # characters (notice that usually already more characters
michael@13 486 # where printed, because of the name of the last script)
michael@13 487 if [ $verbose_pos -gt 70 ]; then
michael@13 488 verbose_pos=0
michael@13 489 echo "" 1>&2
michael@13 490 fi
michael@13 491
michael@13 492 # display verbose message parts: prefix (on first), separator and package
michael@13 493 if [ $verbose_pos -eq 0 ]; then
michael@13 494 output=$(printf "OpenPKG: %s: " "$cmd")
michael@13 495 echo -n "$output" 1>&2
michael@13 496 verbose_pos=$(($verbose_pos + ${#output}))
michael@13 497 output_prefix=""
michael@13 498 else
michael@13 499 output_prefix=", "
michael@13 500 fi
michael@13 501 output=$(printf "%s%s" "$output_prefix" "$s_name")
michael@13 502 echo -n "$output" 1>&2
michael@13 503 verbose_pos=$(($verbose_pos + ${#output}))
michael@13 504 fi
michael@13 505
michael@13 506 # now operate on the particular script
michael@13 507 if [ ".$print" = .1 ]; then
michael@13 508 # special case: under --print we just add the %common and
michael@13 509 # command scripts to the generated output script and do
michael@13 510 # not execute anything at this point.
michael@13 511 sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d'
michael@13 512 sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d'
michael@13 513 elif [ ".$eval" = .1 ]; then
michael@13 514 # special case: under --eval we just add the %common and
michael@13 515 # command scripts to the generated output script and do
michael@13 516 # not execute anything at this point. Additionally, we
michael@471 517 # emulate a real subshell environment.
michael@13 518 sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d'
michael@13 519 echo "while [ 1 ]; do" >>$tmpfile
michael@13 520 sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d' \
michael@13 521 -e 's/^exit[^;]*/break 99/' -e 's/\([^a-zA-Z0-9_]\)exit[^;]*/\1break 99/g' \
michael@13 522 -e 's/^return[^;]*/break 99/' -e 's/\([^a-zA-Z0-9_]\)return[^;]*/\1break 99/g'
michael@13 523 echo "break" >>$tmpfile
michael@13 524 echo "done" >>$tmpfile
michael@13 525 else
michael@13 526 # the regular case of executing the command script directly
michael@13 527
michael@13 528 # prepare temporary files
michael@13 529 rm -f $tmpfile $outfile $errfile
michael@13 530 (umask 077; touch $tmpfile $outfile $errfile)
michael@13 531
michael@13 532 # generate: optionally enable shell debugging
michael@13 533 if [ ".$debug" = .1 ]; then
michael@13 534 echo "set -x" >>$tmpfile
michael@13 535 fi
michael@13 536
michael@471 537 # generate: inclusion of the runcommand helper functions
michael@13 538 echo ". $rcfunc" >>$tmpfile
michael@13 539
michael@13 540 # generate: all %config sections of all(!) scripts. We cannot
michael@13 541 # just include those which have the current command in it
michael@13 542 # because by design all command scripts see the %config
michael@13 543 # section of all(!) scripts. Because of $openpkg_rc_def the
michael@13 544 # variable, we place the %config section of "openpkg" to the front.
michael@471 545 # And we have to extra preinclude the rc.conf to allow
michael@13 546 # rc.conf to override the default of $openpkg_rc_def, too.
michael@13 547 sed <$rcdir/rc.openpkg >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
michael@13 548 echo ". $rcconf" >>$tmpfile
michael@428 549 echo ". $deffile" >>$tmpfile
michael@13 550 l_scripts=`/bin/ls $rcdir/rc.* | sed -e "s;^$rcdir/rc\.;;" | egrep -v '^openpkg$'`
michael@13 551 for l_name in $l_scripts; do
michael@13 552 sed <$rcdir/rc.$l_name >>$tmpfile -e "1,/^%config/d" -e '/^%.*/,$d'
michael@13 553 done
michael@13 554
michael@13 555 # generate: inclusion of the application of override variables
michael@13 556 echo ". $rcconf" >>$tmpfile
michael@428 557 echo ". $deffile" >>$tmpfile
michael@13 558
michael@13 559 # generate: %common section and particular command section
michael@13 560 sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%common/d" -e '/^%.*/,$d'
michael@13 561 sed <$rcdir/rc.$s_name >>$tmpfile -e "1,/^%$cmd/d" -e '/^%.*/,$d'
michael@13 562
michael@13 563 # execute the generated script with GNU Bash
michael@13 564 if [ ".$user" != ".$s_user" ]; then
michael@13 565 # execute as different user
michael@13 566 if [ ".$verbose" = .1 ]; then
michael@13 567 echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: executing as user $s_user"
michael@13 568 fi
michael@13 569 if [ ".$user" = ".@l_susr@" -a ".@l_susr@" = ".root" ]; then
michael@13 570 chown $s_user $tmpfile
michael@13 571 if [ ".$debug" = .1 ]; then
michael@13 572 su - $s_user -c "PATH=\"$PATH\"; $bash $tmpfile" >$outfile
michael@13 573 rc=$?
michael@13 574 else
michael@13 575 su - $s_user -c "PATH=\"$PATH\"; $bash $tmpfile" >$outfile 2>$errfile
michael@13 576 rc=$?
michael@13 577 fi
michael@13 578 elif [ ".@l_susr@" != ".root" ]; then
michael@13 579 # do not complain if we would not have any chance
michael@13 580 # at all to switch the user because we are running
michael@471 581 # in a unprivileged instance. Else we would just
michael@13 582 # trash the mailbox of the user receiving the
michael@471 583 # output of periodic runcommands.
michael@13 584 rc=0
michael@13 585 else
michael@13 586 echo "openpkg:rc:WARNING: $prefix:$s_name:%$cmd: require root privileges to run as user \"$s_user\"" 1>&2
michael@13 587 rc=1
michael@13 588 fi
michael@13 589 else
michael@13 590 # execute as current user
michael@13 591 if [ ".$verbose" = .1 ]; then
michael@13 592 echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: executing as user $user"
michael@13 593 fi
michael@13 594 if [ ".$debug" = .1 ]; then
michael@13 595 $bash $tmpfile >$outfile
michael@13 596 rc=$?
michael@13 597 else
michael@13 598 $bash $tmpfile >$outfile 2>$errfile
michael@13 599 rc=$?
michael@13 600 fi
michael@13 601 fi
michael@13 602 if [ $rc -ne 0 ]; then
michael@13 603 if [ ".$silent" = .0 ]; then
michael@13 604 # indicate failure of execution on verbose message line
michael@13 605 echo ":FAILED" 1>&2
michael@13 606 verbose_pos=0
michael@13 607 fi
michael@13 608 # give details of execution failure
michael@13 609 ( echo "openpkg:rc:WARNING: $prefix:$s_name:%$cmd: failed with return code $rc"
michael@13 610 if [ ".`cat $outfile $errfile`" != . ]; then
michael@13 611 echo "openpkg:rc:NOTICE: output from stdout/stderr is following:"
michael@13 612 echo "+----------------------------------------------------------------------"
michael@13 613 cat $outfile $errfile | sed -e 's;^;| ;'
michael@13 614 echo "+----------------------------------------------------------------------"
michael@13 615 else
michael@13 616 echo "openpkg:rc:NOTICE: no output occurred on stdout/stderr"
michael@13 617 fi
michael@13 618 ) 1>&2
michael@13 619
michael@13 620 # enforce global return value
michael@13 621 rv=1
michael@13 622 else
michael@13 623 # give details of execution success in case verbose operation is requested
michael@13 624 if [ ".$verbose" = .1 ]; then
michael@13 625 ( echo "openpkg:rc:NOTICE: $prefix:$s_name:%$cmd: succeeded with return code $rc"
michael@13 626 if [ ".`cat $outfile $errfile`" != . ]; then
michael@13 627 echo "openpkg:rc:NOTICE: output from stdout/stderr is following:"
michael@13 628 echo "+----------------------------------------------------------------------"
michael@13 629 cat $outfile $errfile | sed -e 's;^;| ;'
michael@13 630 echo "+----------------------------------------------------------------------"
michael@13 631 else
michael@13 632 echo "openpkg:rc:NOTICE: no output occurred on stdout/stderr"
michael@13 633 fi
michael@13 634 ) 1>&2
michael@13 635 fi
michael@13 636 if [ ".$s_output" = .yes ]; then
michael@13 637 # accumulate script output for later display
michael@13 638 cat $outfile >>$allfile
michael@13 639 fi
michael@13 640 fi
michael@13 641 fi
michael@13 642 done
michael@13 643
michael@471 644 # postprocessing for each command
michael@13 645 if [ ".$print" = .1 ]; then
michael@13 646 # for --print just print the resulting script to stdout
michael@13 647 cat $tmpfile
michael@13 648 elif [ ".$eval" = .1 ]; then
michael@13 649 # finish generation of temporary script by restoring stdout
michael@13 650 # and printing the exported environment variables into a format
michael@13 651 # suitable for evaluation by the callers shell.
michael@13 652 echo "exec 1<&3-" >>$tmpfile
michael@13 653 echo "unset PWD SHLVL" >>$tmpfile
michael@13 654 echo "env |\\" >>$tmpfile
michael@13 655 echo "egrep '^[A-Z_][A-Z0-9_]*=.' |\\" >>$tmpfile
michael@13 656 echo "sed -e '/^_=/d' -e 's/\\\\/\\\\\\\\/g' -e 's/\"/\\\\\"/g' \\" >>$tmpfile
michael@13 657 case $SHELL in
michael@13 658 csh|*/csh|tcsh|*/tcsh )
michael@13 659 echo "-e 's/^\\([^=]*\\)=\\(.*\\)\$/setenv \\1 \"\\2\"/'" >>$tmpfile
michael@13 660 ;;
michael@13 661 * )
michael@13 662 echo "-e 's/^\\([^=]*\\)=\\(.*\\)\$/\\1=\"\\2\"; export \\1/'" >>$tmpfile
michael@13 663 ;;
michael@13 664 esac
michael@13 665
michael@13 666 # prepare temporary files
michael@13 667 rm -f $outfile $errfile
michael@13 668 touch $outfile $errfile
michael@13 669
michael@13 670 # now replace temporary script with its output
michael@13 671 # by executing it and capturing its output
michael@13 672 # (let stderr pass unfiltered in case of debug mode)
michael@13 673 if [ ".$debug" = .1 ]; then
michael@13 674 env -i \
michael@13 675 HOME="$HOME" \
michael@13 676 USER="$USER" \
michael@13 677 LOGNAME="$LOGNAME" \
michael@13 678 TERM="$TERM" \
michael@13 679 PATH="$PATH_ORIG" \
michael@13 680 MANPATH="$MANPATH" \
michael@13 681 INFOPATH="$INFOPATH" \
michael@13 682 LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \
michael@13 683 $bash --norc --noprofile --posix \
michael@13 684 $tmpfile >$outfile
michael@13 685 else
michael@13 686 env -i \
michael@13 687 HOME="$HOME" \
michael@13 688 USER="$USER" \
michael@13 689 LOGNAME="$LOGNAME" \
michael@13 690 TERM="$TERM" \
michael@13 691 PATH="$PATH_ORIG" \
michael@13 692 MANPATH="$MANPATH" \
michael@13 693 INFOPATH="$INFOPATH" \
michael@13 694 LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \
michael@13 695 $bash --norc --noprofile --posix \
michael@13 696 $tmpfile >$outfile 2>/dev/null
michael@13 697 fi
michael@13 698 cp $outfile $tmpfile
michael@13 699
michael@13 700 # for --eval we cannot just print the resulting script because
michael@471 701 # not all Bourne Shell implementations like to "eval" large
michael@471 702 # multiline outputs. Hence we output a little one liner which
michael@13 703 # "sources" the script instead and cleans up.
michael@13 704 case $SHELL in
michael@13 705 csh|*/csh|tcsh|*/tcsh )
michael@13 706 echo "source $tmpfile; rm -rf $tmpdir 2>/dev/null || true"
michael@13 707 ;;
michael@13 708 * )
michael@13 709 echo ". $tmpfile; rm -rf $tmpdir 2>/dev/null || true"
michael@13 710 ;;
michael@13 711 esac
michael@13 712 else
michael@13 713 # for the execution situation just make sure we
michael@13 714 # terminate the verbose message output.
michael@13 715 if [ ".$silent" = .0 -a $verbose_pos -gt 0 ]; then
michael@13 716 echo "." 1>&2
michael@13 717 fi
michael@13 718
michael@13 719 # additionally, if a script wants its output to be displayed,
michael@13 720 # now do it. In case there was no such request, do not bother
michael@13 721 # -- we then just output an empty file and so can avoid an
michael@13 722 # extra test surrounding the next command.
michael@13 723 cat $allfile
michael@13 724 fi
michael@13 725 done
michael@13 726
michael@13 727 # cleanup temporary files except the result script in
michael@13 728 # case of --eval (which is then removed by the caller).
michael@13 729 # keep those files for debugging purposes if requested.
michael@13 730 if [ ".$keep" = .0 ]; then
michael@13 731 rm -f $outfile $errfile $allfile >/dev/null 2>&1 || true
michael@13 732 if [ ".$eval" = .0 ]; then
michael@13 733 rm -f $tmpfile >/dev/null 2>&1 || true
michael@13 734 rm -rf $tmpdir >/dev/null 2>&1 || true
michael@13 735 fi
michael@13 736 fi
michael@13 737
michael@13 738 # now clean the exit trap and exit with the global return value
michael@13 739 # indicating to the caller whether all scripts were executed
michael@13 740 # successfully or at least one failed.
michael@13 741 trap - EXIT
michael@13 742 exit $rv
michael@13 743

mercurial