openpkg/rc

Mon, 28 Jan 2013 17:37:18 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 28 Jan 2013 17:37:18 +0100
changeset 758
a2c6460cfb16
parent 469
65414bdd541c
permissions
-rw-r--r--

Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.

     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

mercurial