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