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