a8f451d22b9df0b8c780b92c13c4b31465a445d5
[util-vserver.git] / scripts / functions
1 # $Id: functions,v 1.62 2005/07/03 17:42:49 ensc Exp $  --*- sh -*--
2
3 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 #  
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License.
8 #  
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #  
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 _VS_LOGFILE=
19 _VS_ERRFILE=
20
21 _VS_NEWLINE='
22 '
23 declare -r _VS_NEWLINE=${_VS_NEWLINE:0-1}
24 declare -r VS_ALLVSERVERS_ARGS=all,marked,unmarked,stopped,running
25
26 function findObject
27 {
28     local _fo_mod=$1
29     local _fo_var=$2
30     local _fo_file=
31     local _fo_i=X
32     shift 2
33     
34     for _fo_i; do
35         test -n "$_fo_i"         || continue
36         test ! $_fo_mod "$_fo_i" || { _fo_file=$_fo_i; break; }
37     done
38
39     test -z "$_fo_i" -o -n "$_fo_file" || {
40         echo "Can not find file for '$_fo_var'; aborting"
41         exit 1
42     } >&2
43
44     eval "$_fo_var=\"$_fo_file\""
45 }
46
47 function findFile
48 {
49     findObject -f "$@"
50 }
51
52 function findDir
53 {
54     findObject -d "$@"
55 }
56
57 function findAndCopy
58 {
59     local dst=$1
60     test ! -s "$dst"         || return 0
61     
62     local tmp
63     shift
64     findFile tmp "$@"
65
66     test -n "$tmp" -a -s "$tmp" || return 0
67     $_CP -af "$tmp" "$dst"
68 }
69
70 ## Usage: isRegularFile <filename> [<mod>]
71 function isRegularFile
72 {
73     test ${2:--f} "$1" || return 1
74
75     case $1 in
76         (*.rpmsave|*.rpmnew|*.rpmorig|*.cfsaved*|*.~*~) return 1;;
77     esac
78
79     return 0
80 }
81
82 function getPhysicalDir
83 {
84     ( set -P && cd "$1" && pwd )
85 }
86
87 ## Usage: logging <message>
88 function logging
89 {
90     if test -n "$_VS_LOGFILE"; then
91         echo "$@" >>"$_VS_LOGFILE"
92     else
93         echo "$@"
94     fi
95 }
96
97 ## Usage: warning <message>
98 function warning
99 {
100     if test -n "$_VS_ERRFILE"; then
101         echo "$@" >>"$_VS_ERRFILE"
102     else
103         echo "$@" >&2
104     fi
105 }
106
107 ## Usage: panic <message>
108 function panic
109 {
110     if test -n "$_VS_ERRFILE"; then
111         echo "$@" >>"$_VS_ERRFILE"
112     else
113         echo "$@" >&2
114     fi
115
116     exit 1
117 }
118
119 ## Usage: execute <message>
120 function execute
121 {
122     test -z "${DEBUG_EXEC:-}"       || echo "$@"
123     test "${DEBUG_EXEC:-}" = noexec || exec "$@"
124     exit 0
125 }
126
127
128 ## Usage: spawn <message>
129 function spawn
130 {
131     test -z "${DEBUG_EXEC:-}"       || echo  "$@"
132     test "${DEBUG_EXEC:-}" = noexec || "$@"
133 }
134
135 ## Usage: isNumber <arg>
136 function isNumber
137 {
138     local tmp
139     let tmp=$1+0 2>/dev/null || test -z "${1//0/}" -a -n "$1" || return 1
140     return 0
141 }
142
143 ## Usage: hasSubstring <haystack> <needle>+
144 function hasSubstring
145 {
146     local pat=$1
147     local i
148     
149     shift
150
151     for i; do
152         test x"${pat/*$i*/$i}" = x"$i" || continue
153         return 0
154     done
155
156     return 1
157 }
158
159 ## Usage: colorize <style> <command>
160 function colorize
161 {
162     local       style=$1
163     shift
164     
165     if ! $_TTY -s; then
166         "$@"
167     else
168         local   cfile
169         findFile cfile "$__CONFDIR"/.defaults/styles/"$style" ''
170         if test -n "$cfile"; then
171           $_CAT "$cfile"
172         else
173           case "$style" in
174             (bold)      echo -ne "\e[1m";;
175             (emph)      echo -ne "\e[34m";;
176             (info)      echo -ne "\e[0;34m";;
177             (warn*)     echo -ne "\e[1;31m";;
178             (error)     echo -ne "\e[1;33;41m";;
179             (*)         ;;
180           esac
181         fi
182             
183         "$@"
184         echo -ne "\e[m"
185     fi
186 }
187
188 ## Usage: xtermTitle <title>
189 function xtermTitle
190 {
191     $_TTY -s || return 0
192     echo -ne "\e]0;$@\007"
193 }
194
195 _VS_LOCKS=''
196 ## Usage: lock <lockfile> [<timeout>]
197 function lock
198 {
199     local tmp=$($_MKTEMP /tmp/vserver-lock.XXXXXX)
200     $_RM -f $tmp
201     $_MKFIFO -m600 $tmp
202
203     $_LOCKFILE "$1" $tmp $2 &
204     $_GREP -q true $tmp 2>/dev/null || return 1
205     
206     _VS_LOCKS="$! $_VS_LOCKS"
207 }
208
209 ## Usage: unlock [<num>]
210 function unlock
211 {
212     local num=$1
213     local i
214
215     set -- $_VS_LOCKS
216     while test "$#" -gt 0; do
217         kill -HUP "$1" >/dev/null || :
218         shift
219         test "$num" != 1 || break
220         test -z "$num"   || let --num
221     done
222     _VS_LOCKS="$@"
223 }
224
225 function _pkgMountBindDir()
226 {
227     test "$1" != "$2" || return 0
228
229     $_MOUNT -n --bind "$1" "$2"
230 }
231
232 function _pkgSetVarsBase
233 {
234     case "$vserver" in
235         ./*|/*)
236             if test -d "$vserver/vdir"; then
237                 BASEDIR=$vserver
238                 VDIR=$(getPhysicalDir "$vserver/vdir")
239                 
240                 PKGDIR=$BASEDIR/apps/pkgmgmt
241                 test -d "$PKGDIR" || {
242                     echo "Can not find configuration-directory for package-managment tools"
243                     exit 1
244                 } >&2
245                 findDir EXECDIR      $PKGDIR/execdir     /
246             else
247                 VDIR=$(getPhysicalDir "$vserver")
248                 PKGDIR=
249             fi
250             ;;
251         *)
252             BASEDIR=$__CONFDIR/$vserver
253             test -d "$BASEDIR" || {
254                 echo "Can not find configuration-directory"
255                 exit 1
256             } >&2
257             
258             VDIR=$BASEDIR/vdir
259             test -d "$VDIR"   || VDIR=$__DEFAULT_VSERVERDIR/$vserver
260             VDIR=$(getPhysicalDir "$VDIR")
261             
262             PKGDIR=$BASEDIR/apps/pkgmgmt
263             test -d "$PKGDIR" || {
264                 echo "Can not find configuration-directory for package-managment tools"
265                 exit 1
266             } >&2
267
268             findDir EXECDIR      $PKGDIR/execdir     /
269
270             ;;
271     esac
272
273     if test -z "$WORKAROUND_106057"; then
274         _rpmdb_mntpoint=/dev
275     else
276         _rpmdb_mntpoint=/.rpmdb
277     fi
278 }
279
280 function _pkgSetVarsRPM
281 {
282     if test -n "$PKGDIR"; then
283         findDir RPMETCDIR    $PKGDIR/rpmetc      $PKGDIR/base/rpm/etc       /etc/rpm
284         findDir RPMSTATEDIR  $PKGDIR/rpmstate    $PKGDIR/base/rpm/state
285
286         findDir RPMLIBDIR    $PKGDIR/rpmlib      /
287
288     else
289         findDir RPMETCDIR    "$VDIR"/etc/rpm     /etc/rpm
290         findDir RPMSTATEDIR  "$VDIR"/var/lib/rpm
291         RPMLIBDIR=/
292     fi
293     
294     RPMSTATEDIR=$(getPhysicalDir "$RPMSTATEDIR")
295     RPMETCDIR=$(getPhysicalDir "$RPMETCDIR")
296 }
297
298 function _pkgSetVarsApt
299 {
300     if test -n "$PKGDIR"; then
301         findDir APTETCDIR    $PKGDIR/aptetc      $PKGDIR/base/apt/etc       /etc/apt
302         findDir APTSTATEDIR  $PKGDIR/aptstate    $PKGDIR/base/apt/state
303         findDir APTCACHEDIR  $PKGDIR/aptcache    $PKGDIR/base/apt/cache
304         findDir APTARCHIVDIR $PKGDIR/aptarchives $PKGDIR/base/apt/archives  /var/cache/apt/archives
305     else
306         findDir APTETCDIR    "$VDIR"/etc/apt            /etc/apt
307         findDir APTSTATEDIR  "$VDIR"/var/state/apt
308         findDir APTCACHEDIR  "$VDIR"/var/cache/apt
309         findDir APTARCHIVDIR "$VDIR"/var/cache/apt/archives /var/cache/apt/archives
310     fi
311
312     findFile APT_CONFIG "$APTETCDIR"/apt.conf ""
313     test -z "$APT_CONFIG" || export APT_CONFIG
314 }
315
316 function _pkgSetVarsYum
317 {
318     if test -n "$PKGDIR"; then
319         findDir YUMETCDIR    $PKGDIR/yumetc      $PKGDIR/base/yum/etc       /etc
320         findDir YUMCACHEDIR  $PKGDIR/yumcache    $PKGDIR/base/yum/cache
321     else
322         findDir YUMETCDIR    "$VDIR"/etc         /etc
323         findDir YUMCACHEDIR  "$VDIR"/var/cache/yum
324     fi
325 }
326
327
328 function _pkgMountBase
329 {
330     :
331 }
332
333 function _pkgMountApt
334 {
335     :
336 }
337
338 function _pkgMountYum
339 {
340     :
341 }
342
343 function _pkgMountRPM
344 {
345     _pkgMountBindDir "$RPMETCDIR" /etc/rpm
346     test "$RPMLIBDIR" = "/" || _pkgMountBindDir "$RPMLIBDIR" /usr/lib/rpm
347
348     pushd "$VDIR" >/dev/null
349
350     $_SECURE_MOUNT --chroot -n --bind "$RPMSTATEDIR" "$_rpmdb_mntpoint"
351     test -z "$WORKAROUND_106057" || mount -n --bind "$RPMSTATEDIR" "$_rpmdb_mntpoint"
352
353     test -e "$VDIR"/proc/self/status || \
354         $_SECURE_MOUNT --chroot -n -t proc none /proc
355
356     popd >/dev/null
357 }
358
359 function _pkgSetEnvBase
360 {
361     test "$EXECDIR" = "/" || {
362         PATH=$EXECDIR:$PATH
363         LD_LIBRARY_PATH=$EXECDIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
364     }
365
366     export PATH LD_LIBRARY_PATH
367 }
368
369 function _pkgSetEnvApt
370 {
371     :
372 }
373
374 function _pkgSetEnvYum
375 {
376     :
377 }
378
379 function _pkgSetEnvRPM
380 {
381     CUR_VSERVER=$vserver
382     RPM_FAKE_NAMESPACE_MOUNTS=$_rpmdb_mntpoint
383     RPM_BINARY=$_VRPM_PRELOAD
384
385     export CUR_VSERVER RPM_FAKE_NAMESPACE_MOUNTS RPM_BINARY
386 }
387
388 function pkgInit
389 {
390     local i
391     local vserver=$1
392     shift
393     
394     _pkgSetVarsBase
395     for i; do
396         case "$i" in
397             rpm)        _pkgSetVarsRPM;;
398             apt)        _pkgSetVarsApt;;
399             yum)        _pkgSetVarsYum;;
400             *)          echo "Unknown packaging flavor" >&2; exit 1;;
401         esac
402     done
403
404     _pkgMountBase
405     for i; do
406         case "$i" in
407             rpm)        _pkgMountRPM;;
408             apt)        _pkgMountApt;;
409             yum)        _pkgMountYum;;
410         esac
411     done
412
413     _pkgSetEnvBase
414     for i; do
415         case "$i" in
416             rpm)        _pkgSetEnvRPM;;
417             apt)        _pkgSetEnvApt;;
418             yum)        _pkgSetEnvYum;;
419         esac
420     done
421
422     _PKG_FLAVORS="$@"
423     _PKG_VSERVER=$vserver
424 }
425
426 function isAvoidNamespace
427 {
428     local cfgdir
429
430     $_VSERVER_INFO - FEATURE namespace   || return 0
431     cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || return 0
432     test ! -e "$cfgdir"/namespace        || return 1
433     test -e "$__CONFDIR"/.defaults/nonamespace -o \
434          -e "$cfgdir"/nonamespace
435 }
436
437 ## Usage: getAllVservers <var> [<KIND>*]
438 function getAllVservers
439 {
440     local _ga_i
441     declare -a _ga_tmp=()
442
443     for _ga_i in $__CONFDIR/*; do
444         isRegularFile "$_ga_i" -d   || continue
445
446         test ! -e "$_ga_i"/disabled || continue
447         test   -d "$_ga_i"/vdir     || continue
448
449         local _ga_doadd=1
450         local _ga_markfile=$_ga_i/apps/init/mark
451         
452         case ${2:-ALL} in
453             (MARKED)    test   -s "$_ga_markfile" || _ga_doadd=;;
454             (UNMARKED)  test ! -s "$_ga_markfile" || _ga_doadd=;;
455             (STOPPED)   ! $_VSERVER "$_ga_i" running &>/dev/null || _ga_doadd=;;
456             (RUNNING)     $_VSERVER "$_ga_i" running &>/dev/null || _ga_doadd=;;
457             (ALL)       ;;
458             (*)         panic $"Unknown vserver tagging '$2'";;
459         esac
460
461         test -z "$_ga_doadd" || _ga_tmp=( "${_ga_tmp[@]}" "${_ga_i##$__CONFDIR/}")
462     done
463
464     eval $1='( "${_ga_tmp[@]}" )'
465 }
466
467 ## Usage: getAllVserversByArg <var> <arg>
468 function getAllVserversByArg
469 {
470     local _gav_mark=
471     
472     case $2 in
473         (--all)         _gav_mark=ALL;;
474         (--marked)      _gav_mark=MARKED;;
475         (--unmarked)    _gav_mark=UNMARKED;;
476         (--stopped)     _gav_mark=STOPPED;;
477         (--running)     _gav_mark=RUNNING;;
478         (*)             return 1;;
479     esac
480
481     getAllVservers "$1" "$_gav_mark"
482 }
483
484 ## Usage: _getProcNumberCount <ctx> <var>
485 function _getProcNumberCount
486 {
487     local _gp_var=$2
488     local _gp_procnr_cnt=0
489
490     # Use /proc/virtual from kernel 2.6 when possible
491     if test -d "/proc/virtual"; then
492         set -- $($_GREP '^PROC:' "/proc/virtual/$1/limit" 2>/dev/null)
493         _gp_procnr_cnt=$2
494     else
495         _gp_procnr_cnt=$($_VPS ax | $_AWK '{print $2}' | $_GREP -x "$1" | $_WC -l )
496     fi
497
498     let _gp_procnr_cnt=_gp_procnr_cnt+0
499     eval $_gp_var=\$_gp_procnr_cnt
500 }
501
502 ## Usage: getVserverCtx <vdir> <result-varname> [<procnumber-varname> [<do-cleanup>]]
503 ## Returns: 0 iff vserver is running
504 function getVserverStatus
505 {
506     test -r "$1"/run || return 1
507
508     local _gvs_ctx
509     read _gvs_ctx <"$1"/run
510     eval "$2"=\$_gvs_ctx
511
512     test -n "$3"     || return 0
513     local _gvs_tmp
514     _getProcNumberCount "$_gvs_ctx" _gvs_tmp
515     eval "$3"=\$_gvs_tmp
516
517     if test "$_gvs_tmp" = 0; then
518         local runfile=$($_READLINK "$1/run")
519         test -z "$4" || $_RM -f "$runfile"
520         return 1
521     fi
522
523     return 0
524 }
525
526 ## Usage: isCtxRunning <ctx>
527 function isCtxRunning
528 {
529     local _tmp
530     _getProcNumberCount "$1" _tmp
531     test $_tmp -gt 0
532 }
533
534 ## Usage: isVserverRunning <vdir> [<ctx-varname>]
535 function isVserverRunning
536 {
537     local _ivr_ctx _ivr_procnum
538
539     getVserverStatus "$1" _ivr_ctx _ivr_procnum 1 || return 1
540     test "$_ivr_procnum" != 0                     || return 1
541     test -z "$2" || eval "$2"=\$_ivr_ctx
542     return 0
543 }
544
545 ## Called as 'getFileValue <varname> <filename>+'
546 function getFileValue
547 {
548     local _gfv_var=$1
549     local _gfv_file
550     shift
551
552     findFile _gfv_file "$@" ''
553     test -n "$_gfv_file" -a -r "$_gfv_file" || return 0
554     eval read "$_gfv_var" <"$_gfv_file"
555 }
556
557 ## Called as 'getFileArray <varname> <filename>'
558 function getFileArray
559 {
560     test -r "$2" || return 1
561     
562     local IFS=$_VS_NEWLINE
563     eval "$1"='( $(< "$2") )'
564 }
565
566 function checkComponents
567 {
568     local       i
569     local       msg=$1
570     local       x_failed=
571
572     shift
573     
574     for i; do
575         local failed=
576         case "$i" in
577             (core)      test -x "$_CHBIND"           || failed=1;;
578             (build)     test -x "$_VSERVER_BUILD"    || failed=1;;
579             (sysv)      test -x "$__INITRDDIR/vserver"    || failed=1;;
580             (devel)     test -d "$__INCLUDEDIR/vserver.h" || failed=1;;
581             (*)         echo "Unknown component '$i'" >&2
582                         return false
583                         ;;
584         esac
585
586         test -z "$failed" || {
587             echo "$msg: $i"
588             x_failed=1
589         } >&2
590     done
591
592     test -z "$x_failed"
593 }
594
595 ## Usage: isKernelAPI <ver> [<cmp-modifier>]
596 function isKernelAPI
597 {
598     local api
599     api=$($_VSERVER_INFO - APIVER) || api=0
600     test $[ $api ] -${2:-ge} $[ $1 ]
601 }
602
603 ## Usage: callInNamespace <vserver> <command> <args>*
604 function callInNamespace
605 {
606     local ctx=
607     
608     isAvoidNamespace "$1" || \
609     ctx=$( $_VSERVER_INFO "$1" CONTEXT f ) || ctx=
610
611     shift
612     if test -n "$ctx"; then
613         $_VNAMESPACE --enter "$ctx" -- "$@"
614     else
615         "$@"
616     fi
617 }
618
619 ## Usage: setDefaultTTY <vdir> [<fallback-tty>]
620 function setDefaultTTY
621 {
622     local cfgdir ttyname
623
624     cfgdir=$($_VSERVER_INFO "$1" APPDIR init) || cfgdir=
625     findObject -e ttyname \
626         ${cfgdir:+"$cfgdir"/tty} \
627         "$__CONFDIR/.defaults/apps/init/tty" \
628         $2 /dev/null
629
630     exec   <$ttyname
631     exec  &>$ttyname
632 }
633
634 ## Usage: killContext <XID> [<SIG>]
635 function killContext
636 {
637     local sig=${2:-9}
638
639     #$_VKILL -s STOP   --xid "$1" 1 &>/dev/null || :
640     $_VKILL -s "$sig" --xid "$1" 1 &>/dev/null || :
641     $_VKILL -s "$sig" --xid "$1"   &>/dev/null || :
642     #$_VKILL -s "$sig" --xid "$1" 1 &>/dev/null || :
643     #$_VKILL -s CONT   --xid "$1" 1 &>/dev/null || :
644 }
645
646 ## Usage: pkgmgmt.guessStyle <vserver> <resultvar>
647 function pkgmgmt.guessStyle()
648 {
649     local _pgs_vdir
650     _pgs_vdir=$($_VSERVER_INFO "$1" VDIR) || {
651         echo $"Can not determine vserver-root" >&2
652         return 1
653     }
654     local _pgs_cfgdir=$($_VSERVER_INFO "$1" APPDIR pkgmgmt) || :
655
656     if test -n "$_pgs_cfgdir" -a -e "$_pgs_cfgdir"/style; then
657         read style <"$_pgs_cfgdir"/style
658     elif test -e "$_pgs_vdir"/etc/redhat-release -o -e "$_pgs_vdir"/etc/fedora-release; then
659         style=redhat
660     elif test -e "$_pgs_vdir"/etc/mandrake-release; then
661         style=mandrake
662     elif test -e "$_pgs_vdir"/etc/debian_version; then
663         style=debian
664     elif test -e "$_pgs_vdir"/etc/SuSE-release; then
665         style=suse
666     else
667         echo $"Can not determine packagemanagement style" >&2
668         return 1
669     fi
670
671     eval $2=\$style
672     return 0
673 }
674
675 ## Usage: pkgmgmt.isInternal <vserver>
676 ## returns true iff <vserver> is configured for internal packagemanagement
677 ## A typical application is
678 ## | is_external=
679 ## | pkgmgmt.isInternal "$vserver" || is_external=1
680 function pkgmgmt.isInternal
681 {
682     local cfgdir=$($_VSERVER_INFO "$1" APPDIR pkgmgmt) || :
683
684     test -z "$cfgdir" -o ! -d "$cfgdir" -o -e "$cfgdir"/internal
685 }
686
687 ## Usage: pkgmgmt.isAptAvailable <cfgdir> <vdir> [<is-internal>]
688 function pkgmgmt.isAptAvailable
689 {
690     local cfgdir="$1"
691     local vdir="$2"
692     local is_internal="$3"
693     
694     local have_apt i
695     if test -n "$is_internal"; then
696         have_apt=1
697         test -d "$cfgdir"/base/apt -o -d "$cfgdir"/aptetc || have_apt=
698     else
699         have_apt=
700         for i in /bin /usr/bin /usr/local/bin; do
701             test ! -x "$vdir$i"/apt-get || { have_apt=1; break; }
702         done
703     fi
704
705     test -n "$have_apt" && return 0 || return 1
706 }
707
708 ## Usage: pkgmgmt.isYumAvailable <cfgdir> <vdir> [<is-internal>]
709 function pkgmgmt.isYumAvailable
710 {
711     local cfgdir="$1"
712     local vdir="$2"
713     local is_internal="$3"
714     
715     local have_yum i
716     if test -n "$is_internal"; then
717         have_yum=1
718         test -d "$cfgdir"/base/yum -o -d "$cfgdir"/yumetc || have_yum=
719     else
720         have_yum=
721         for i in /bin /usr/bin /usr/local/bin; do
722             test ! -x "$vdir$i"/yum || { have_yum=1; break; }
723         done
724     fi
725
726     test -n "$have_yum" && return 0 || return 1
727 }
728
729
730 function vshelper.doSanityCheck
731 {
732     local vshelper this_xid i
733     declare -a warnings=()
734     local solution_disable=
735     local solution_sysctl=
736
737     vshelper.isEnabled && vshelper.isEnabled warning || return 0
738     
739     this_xid=$($_VSERVER_INFO - XID) ||
740         panic $"Failed to determine current context; aborting..."
741
742     ## Do nothing in other xid's; the helper will be executed in xid 0 only
743     test "$this_xid" = 0 || return 0
744
745     local proc_file=/proc/sys/kernel/vshelper
746
747     if ! test -r "$proc_file"; then
748         vshelper=
749         warnings=( "${warnings[@]}"
750                    $"File '$proc_file' does not exist but is required for vshelper setup" )
751         solution_disable=1
752     else
753         vshelper=$(cat "$proc_file")
754
755         $_CMP -s "$vshelper" "$_VSHELPER" || {
756             warnings=( "${warnings[@]}"
757                        $"The configured vshelper '$vshelper' does not match the 'vshelper'
758   script of the util-vserver package"
759                      )
760             solution_disable=1
761             solution_sysctl=1
762         }
763     fi
764
765     test -d "$__VSHELPERSTATEDIR" || {
766         warnings=( "${warnings[@]}"
767                    $"\
768 The vshelper state-directory '$__VSHELPERSTATEDIR' does not exist; since
769 it is created by 'make install', this indicates a serious problem with
770 your util-vserver installation" )
771         solution_disable=1
772     }
773
774     test "${#warnings[@]}" -eq 0 || {
775         warning $"\
776 The following problem(s) were encountered while verifying vshelper
777 functionality:"
778
779         for i in "${warnings[@]}"; do
780             warning "* $i"
781         done
782
783         warning $"\
784         
785 To fix this, you can:"
786
787         test -z "$solution_disable" || warning $"\
788 * disable vshelper entirely by executing
789   | touch \"$__CONFDIR/.defaults/apps/vshelper/disabled\"
790 * disable only this message by executing
791   | touch \"$__CONFDIR/.defaults/apps/vshelper/warning-disabled\""
792
793         test -x "$solution_sysctl" || warning $"\
794 * configure the util-vserver vshelper script, e.g. by adding
795   | kernel.vshelper = $_VSHELPER
796   to /etc/sysctl.conf and rebooting the machine, or by executing
797   | echo \"$_VSHELPER\" >$proc_file"
798
799         warning ""
800
801         return 1
802     }
803
804     return 0
805 }
806
807 ## Usage: vshelper.isEnabled [<style>] [<vserver>]
808 function vshelper.isEnabled
809 {
810     local f=${1:+$1-}disabled
811     test ! -e "$__CONFDIR"/.defaults/apps/vshelper/"$f"     || return 1
812     $_VSERVER_INFO - FEATURE vshelper                       || return 1
813     if test -n "$2"; then
814         local appdir
815         appdir=$($_VSERVER_INFO "$2" APPDIR vshelper)       || return 0
816         test -z "$2" -o ! -e "$appdir/$f"                   || return 1
817     fi
818
819     return 0
820 }
821
822 ## Usage: vshelper.isDebug [<vserver>]
823 function vshelper.isDebug
824 {
825     test ! -e "$__CONFDIR"/.defaults/apps/vshelper/debug    || return 0
826     $_VSERVER_INFO - FEATURE vshelper                       || return 1
827     if test -n "$1"; then
828         local appdir
829         appdir=$($_VSERVER_INFO "$1" APPDIR vshelper)       || return 1
830         test ! -e "$appdir/debug"                           || return 0
831     fi
832
833     return 1
834 }
835
836 function vshelper._getHandlerInternal
837 {
838     local _vghi_var=$1
839     local _vghi_tmp
840     shift
841     shift       ## HACK: see below the note about the 'set -u' mode
842     
843     while test "$#" -ge 2; do
844         local _vghi_mod=$1
845         local _vghi_obj=$2
846         shift 2
847
848         test "$_vghi_mod" "$_vghi_obj" || continue
849         case "$_vghi_mod" in
850             (-x)
851                 eval $_vghi_var=\$_vghi_obj
852                 ;;
853             (-e)
854                 read _vghi_tmp <"$_vghi_obj"
855                 eval $_vghi_var=:\$_vghi_tmp
856                 ;;
857             (*) panic $"Internal error, unexpected modifier '$_vghi_mod'"
858         esac
859         return 0
860     done
861     
862     return 1
863 }
864
865 ## Usage: vshelper.getHandler <result-var> <vserver> <action>
866 function vshelper.getHandler
867 {
868     local _vgh_appdir
869     _vgh_appdir=$($_VSERVER_INFO "$2" APPDIR vshelper) || _vgh_appdir=
870
871     declare -a _vgh_search_list=( X )
872     ## HACK: when we are in 'set -u' mode, empty lists are causing errors
873
874     test -z "$_vgh_appdir" || _vgh_search_list=( "${_vgh_search_list[@]}" -x "$_vgh_appdir/$3" )
875     test -z "$_vgh_appdir" || _vgh_search_list=( "${_vgh_search_list[@]}" -e "$_vgh_appdir/action" )
876     _vgh_search_list=( "${_vgh_search_list[@]}" -x "$__CONFDIR"/.defaults/apps/vshelper/"$3" )
877     _vgh_search_list=( "${_vgh_search_list[@]}" -e "$__CONFDIR"/.defaults/apps/vshelper/action )
878
879     ! vshelper._getHandlerInternal "$1" "${_vgh_search_list[@]}" || return 0
880     eval $1=':restart'
881 }
882
883 ## Usage: vshelper.init <vserver> [<method> <args>*]
884 function vshelper.doInit
885 {
886     vshelper.isEnabled || return 0
887     
888     local xid
889     xid=$($_VSERVER_INFO "$1" CONTEXT false) && test -n "$xid" || {
890         warning $"vshelper.init: can not determine xid of vserver '$vserver'; returned value was '$xid'"
891         return 1
892     }
893
894     local f="$__VSHELPERSTATEDIR/$xid"
895     
896     set -C
897     $_RM -f "$f"
898     echo "$1" >"$f"
899     set +C
900     
901     if test -n "$2"; then
902         shift 1
903         local i
904         for i; do
905             echo "$i" 
906         done
907     else
908         echo "default"
909     fi >>"$f"
910
911     return 0
912 }
913
914 ## Usage: vshelper.doDestroy <vserver> <xid>
915 function vshelper.doDestroy
916 {
917     vshelper.isEnabled || return 0
918
919     $_RM -f "$__VSHELPERSTATEDIR/$2"
920 }
921
922 ## Usage: vshelper.initSync <vserver> <pipe-varname> [<method>]
923 function vshelper.initSync
924 {
925     local _vis_tmpdir
926     _vis_tmpdir=$($_MKTEMPDIR /tmp/vserver-stop.XXXXXX) || {
927         warning $"Failed to generate temporary directory for vshelper sync"
928         return 1
929     }
930
931     local _vis_fifo="$_vis_tmpdir"/pipe
932     $_MKFIFO -m700 "$_vis_fifo"
933     vshelper.doInit "$1" "${3:-sync}" "$_vis_fifo"
934     eval $2=\$_vis_fifo
935 }
936
937 ## Usage: vshelper.getSyncTimeout <vserver> <varname>
938 function vshelper.getSyncTimeout
939 {
940     local _vgst_appdir _vgst_file _vgst_tmp
941     _vgst_appdir=$($_VSERVER_INFO "$1" APPDIR vshelper) || _vgst_appdir=
942
943     findFile _vgst_file ${_vgst_appdir:+"$_vgst_appdir"/sync-timeout} "$__CONFDIR"/.defaults/apps/vshelper/sync-timeout ''
944     test -n "$_vgst_file" || return 1
945     read _vgst_tmp <"$_vgst_file"
946     eval $2=\$_vgst_tmp
947 }
948
949
950 function _rpmFake.getCapFlags
951 {
952     local ctx=$1
953     
954     if test -n "$ctx" && ! $_VSERVER_INFO - FEATURE migrate; then
955         set -- $($_CHCONTEXT_COMPAT --xid 1 \
956             $_SH -c "$_CAT /proc/[0-9]*/status | $_EGREP '^(CapBset|s_context|ctxflags)'" | \
957             $_GREP -B 1 -A 1 "^s_context: $ctx " | \
958             $_SED -e '1,3p;d' | $_AWK '{ print $2 }')
959     else
960         set --
961     fi
962
963     if test -n "$3"; then
964         RPM_FAKE_CAP=$[ ~0x$1 ]
965         RPM_FAKE_FLAGS=$3
966     else
967         RPM_FAKE_CAP=$[ ~0xd40c04ff ]
968         RPM_FAKE_FLAGS=4
969     fi
970 }
971
972 function rpmFake.init
973 {
974     local vdir ctx
975     
976     vdir=$($_VSERVER_INFO "$1" VDIR)    || vdir="$1"
977     ctx=$($_VSERVER_INFO  "$1" CONTEXT) || ctx=
978
979     test -d "$vdir" ||
980         panic $"Can not find chroot environment at '$vdir' for '$1'"
981
982     _rpmFake.getCapFlags "$ctx"
983
984     RPM_FAKE_CHROOT=$vdir
985     RPM_FAKE_CTX=$ctx
986 }
987
988 function rpmFake.exec
989 {
990     export RPM_FAKE_CHROOT RPM_FAKE_CTX RPM_FAKE_CAP RPM_FAKE_FLAGS
991     
992     LD_PRELOAD=$_RPM_FAKE_SO${LD_PRELOAD:+:$LD_PRELOAD} \
993         exec "$@"
994 }