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