Thu, 04 Oct 2012 20:30:05 +0200
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 |