7aae6083e40d984cefc5d6e7b5f68b03ee920234
[util-vserver.git] / scripts / vserver
1 #!/bin/bash
2
3 # Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 # based on vserver by Jacques Gelinas
5 #  
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2, or (at your option)
9 # any later version.
10 #  
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #  
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 # This is a script to control a virtual server
21
22 : ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars}
23 test -e "$UTIL_VSERVER_VARS" || {
24     echo "Can not find util-vserver installation; aborting..."
25     exit 1
26 }
27 . "$UTIL_VSERVER_VARS"
28
29 USR_SBIN=$SBINDIR
30 USR_LIB_VSERVER=$PKGLIBDIR
31
32 VSERVER_CMD=$USR_SBIN/vserver
33 WAITFOR_CMD="waitfor 60"
34 VINIT_CMD=/etc/rc.vinit
35 CHCONTEXT_CMD=$USR_SBIN/chcontext
36 SAVE_S_CONTEXT_CMD=$USR_LIB_VSERVER/save_s_context
37 CAPCHROOT_CMD=$USR_LIB_VSERVER/capchroot
38 VSERVERKILLALL_CMD=$USR_LIB_VSERVER/vserverkillall
39 DEFAULTPATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
40
41 vserver_mknod(){
42         mknod $1 $2 $3 $4
43         chmod $5 $1
44 }
45
46 mountproc()
47 {
48         mkdir -p $1/proc $1/dev/pts
49         if [ ! -d $1/proc/1 ] ; then
50                 mount -t proc none $1/proc
51                 mount -t devpts -o gid=5,mode=0620 none $1/dev/pts
52         fi
53 }
54 umountproc()
55 {
56         umount $1/proc 2>/dev/null
57         umount $1/dev/pts 2>/dev/null
58 }
59
60 # Check that the vservers parent directory has permission 000
61 # This is the key to avoid chroot escape
62 testperm()
63 {
64         return
65         PERM=`$USR_LIB_VSERVER/showperm $VROOTDIR/$1/..`
66         if [ "$PERM" != 000 ] ; then
67                 echo
68                 echo "**********************************************************"
69                 echo $VROOTDIR/$1/.. has insecure permissions.
70                 echo A vserver administrator may be able to visit the root server.
71                 echo To fix this, do
72                 echo "  " chmod 000 $VROOTDIR/$1/..
73                 echo do it anytime you want, even if vservers are running.
74                 echo "**********************************************************"
75                 echo
76         fi
77 }
78
79 # Extract the initial runlevel from the vserver inittab
80 get_initdefault()
81 {
82         INITDEFAULT=`grep :initdefault $VROOTDIR/$1/etc/inittab | sed 's/:/ /g' | ( read a level b; echo $level)`
83 }
84
85 # Read the vserver configuration file, reusing the PROFILE value
86 # found in /var/run/vservers
87 readlastconf()
88 {
89         if [ -f /var/run/vservers/$1.ctx ] ; then
90                 . /var/run/vservers/$1.ctx
91                 if [ "$S_PROFILE" != "" ] ; then
92                         export PROFILE=$S_PROFILE
93                 fi
94         fi
95         export PROFILE
96         . /etc/vservers/$1.conf
97 }
98
99 # Wait for a process to finish for $1 seconds.
100 waitfor()
101 {
102         timeout=$1
103         shift
104         # Background the process.
105         $@ &
106         # Wait for it to finish.
107         while [ $timeout -gt 0 ] ; do
108                 sleep 1
109                 kill -0 $! 2>/dev/null || break
110                 timeout=$(($timeout - 1))
111         done
112         # Try nicely terminating it, then just kill it.
113         if [ $timeout -eq 0 ] ; then
114                 kill -TERM $! && kill -0 $! 2>/dev/null && kill -KILL $!
115         fi
116         # Cleanup.
117         wait
118 }
119
120 usage()
121 {
122         echo vserver [ options ] server-name command ...
123         echo
124         echo server-name is a directory in $VROOTDIR
125         echo
126         echo The commands are:
127         echo " build   : Create a virtual server by copying the packages"
128         echo "           of the root server"
129         echo " enter   : Enter in the virtual server context and starts a shell"
130         echo "           Same as \"vserver name exec /bin/sh\""
131         echo " exec    : Exec a command in the virtual server context"
132         echo " suexec  : Exec a command in the virtual server context uid"
133         echo " service : Control a service inside a vserver"
134         echo "           vserver name service service-name start/stop/restart/status"
135         echo " start   : Starts the various services in the vserver, runlevel 3"
136         echo " stop    : Ends all services and kills the remaining processes"
137         echo " running : Tells if a virtual server is running"
138         echo "           It returns proper exit code, so you can use it as a test"
139         echo " status  : Tells some information about a vserver"
140         echo " chkconfig : It turns a server on or off in a vserver"
141         echo
142         echo "--silent : No informative messages about vserver context and IP numbers"
143         echo "           Useful when you want to redirect the output"
144 }
145
146 calculateCaps()
147 {
148     local f
149     for f in "$@"; do
150         case $f in
151             !CAP_SYS_CHROOT)
152                 CHROOTOPT=--nochroot
153                 ;;
154             *)
155                 CAPS="$CAPS --cap $f"
156                 ;;
157         esac
158     done
159 }
160
161 SILENT=
162 while true
163 do
164         if [ "$1" = "--silent" ] ; then
165                 SILENT=--silent
166                 shift
167         else
168                 break
169         fi
170 done
171 # Setup the default ulimit for a vserver
172 setdefulimit(){
173         # File handle are limited to half of the current system limit
174         # Virtual memory is limited to the ram size
175         NFILE=`cat /proc/sys/fs/file-max`
176         NFILE=`expr $NFILE / 2`
177         VMEM=`cat /proc/meminfo  | grep MemTotal | (read a b c; echo $b)`
178         # Disabled for now, we need a different to set the security
179         # context limit than fiddling with ulimit
180         #ulimit -H -n $NFILE -v $VMEM
181 }
182 if [ $# -lt 2 ] ; then
183         usage
184 elif [ "$2" = "build" ] ; then
185         # Either the directory does not exist or is empty
186         NBSUB=`ls $VROOTDIR/$1 2>/dev/null | grep -v lost+found | wc -l` 
187         NBSUB=`expr $NBSUB`
188         if [ "$NBSUB" != 0 ] ; then
189                 echo Virtual server $VROOTDIR/$1 already exist
190         else
191                 if [ ! -d $VROOTDIR ] ; then
192                         mkdir $VROOTDIR || exit 1
193                         chmod 000 $VROOTDIR
194                         chattr +t $VROOTDIR
195                         echo Directory $VROOTDIR was created with permissions 000
196                 fi
197                 mkdir -p $VROOTDIR/$1 || exit 1
198                 chattr -t $VROOTDIR/$1
199                 chmod 755 $VROOTDIR/$1
200                 if test "$UTIL_VSERVER_AVOID_COPY"; then
201                     mkdir -p $VROOTDIR/$1/{etc/rc.d/init.d,sbin,var/run,var/log}
202                 else
203                     cp -ax /sbin /bin /etc /usr /var /lib $VROOTDIR/$1/. || exit 1
204                 fi
205                 cd $VROOTDIR/$1 || exit 1
206                 rm -fr lib/modules/*
207                 rm -f var/spool/mail/*
208                 rm -f `find var/run -type f`
209                 rm -f `find var/log -type f`
210                 touch var/log/wtmp
211                 rm -f var/lock/subsys/*
212                 rm -f etc/cron.d/kmod
213                 mkdir proc tmp home root boot
214                 test -f /root/.bashrc && cp -a /root/.bashrc root/.
215                 test -f /root/.bash_profile && cp -a /root/.bash_profile root/.
216                 chmod 1777 tmp
217                 chmod 750 root
218                 # Create a minimal dev so the virtual server can't grab
219                 # more privileges
220                 mkdir dev dev/pts
221                 vserver_mknod dev/null c 1 3 666
222                 vserver_mknod dev/zero c 1 5 666
223                 vserver_mknod dev/full c 1 7 666
224                 vserver_mknod dev/random c 1 8 644
225                 vserver_mknod dev/urandom c 1 9 644
226                 vserver_mknod dev/tty c 5 0 666
227                 vserver_mknod dev/ptmx c 5 2 666
228                 touch dev/hdv1
229                 # Create a dummy /etc/fstab and /etc/mtab to please
230                 # df and linuxconf. We use hdv1, which does not exist
231                 # to remind the admin that it is not the real drive
232                 echo /dev/hdv1 / ext2 defaults 1 1 >etc/fstab
233                 echo /dev/hdv1 / ext2 rw 0 0 >etc/mtab
234                 # Install the vreboot utility
235                 cp -a $USR_LIB_VSERVER/vreboot sbin/.
236                 ln -sf vreboot sbin/vhalt
237
238                 echo Directory $VROOTDIR/$1 has been populated
239                 if [ ! -d /etc/vservers ] ; then
240                         mkdir /etc/vservers
241                         chmod 600 /etc/vservers
242                         echo Directory /etc/vservers has been created
243                 fi
244                 if [ ! -f /etc/vservers/$1.conf ] ; then
245                         CONF=/etc/vservers/$1.conf
246                         cat >$CONF <<-EOF
247 if [ "$PROFILE" = "" ] ; then
248         PROFILE=prod
249 fi
250 # Select the IP number assigned to the virtual server
251 # This IP must be one IP of the server, either an interface
252 # or an IP alias
253 # A vserver may have more than one IP. Separate them with spaces.
254 # do not forget double quotes.
255 # Some examples:
256 # IPROOT="1.2.3.4 2.3.4.5"
257 # IPROOT="eth0:1.2.3.4 eth1:2.3.4.5"
258 # If the device is not specified, IPROOTDEV is used
259 case \$PROFILE in
260 prod)
261         IPROOT=1.2.3.4
262         # The netmask and broadcast are computed by default from IPROOTDEV
263         #IPROOTMASK=
264         #IPROOTBCAST=
265         # You can define on which device the IP alias will be done
266         # The IP alias will be set when the server is started and unset
267         # when the server is stopped
268         #IPROOTDEV=eth0
269         # You can set a different host name for the vserver
270         # If empty, the host name of the main server is used
271         S_HOSTNAME=
272         ;;
273 backup)
274         IPROOT=1.2.3.4
275         #IPROOTMASK=
276         #IPROOTBCAST=
277         #IPROOTDEV=eth0
278         S_HOSTNAME=
279         ;;
280 esac
281 # Uncomment the onboot line if you want to enable this
282 # virtual server at boot time
283 #ONBOOT=yes
284 # You can set a different NIS domain for the vserver
285 # If empty, the current on is kept
286 # Set it to "none" to have no NIS domain set
287 S_DOMAINNAME=
288 # You can set the priority level (nice) of all process in the vserver
289 # Even root won't be able to raise it
290 S_NICE=
291 # You can set various flags for the new security context
292 # lock: Prevent the vserver from setting new security context
293 # sched: Merge scheduler priority of all processes in the vserver
294 #        so that it acts a like a single one.
295 # nproc: Limit the number of processes in the vserver according to ulimit
296 #        (instead of a per user limit, this becomes a per vserver limit)
297 # private: No other process can join this security context. Even root
298 # Do not forget the quotes around the flags
299 S_FLAGS="lock nproc"
300 # You can set various ulimit flags and they will be inherited by the
301 # vserver. You enter here various command line argument of ulimit
302 # ULIMIT="-HS -u 200"
303 # The example above, combined with the nproc S_FLAGS will limit the
304 # vserver to a maximum of 200 processes
305 #ULIMIT="-HS -u 1000"
306 ULIMIT=""
307 # You can set various capabilities. By default, the vserver are run
308 # with a limited set, so you can let root run in a vserver and not
309 # worry about it. He can't take over the machine. In some cases
310 # you can to give a little more capabilities (such as CAP_NET_RAW)
311 # S_CAPS="CAP_NET_RAW"
312 S_CAPS=""
313 # Select an unused context (this is optional)
314 # The default is to allocate a free context on the fly
315 # In general you don't need to force a context
316 #S_CONTEXT=
317                         EOF
318                         echo $CONF has been created. Look at it\!
319                 fi
320                 # Turn off some service useless on a vserver
321                 #               vserver_turnoff apmd network autofs dhcpd gpm ipchains iptables \
322                 #                       irda isdn keytable kudzu linuxconf-setup netfs nfs nfslock \
323                 #                       pcmcia portmap pppoe random rawdevices rhnsd rstatd ruserd \
324                 #                       rwalld rwhod sendmail smb snmpd v_httpd h_xinetd v_sshd vservers \
325                 #                       xfs ypbind xinetd
326                 (
327                         cd etc/init.d 2>/dev/null || cd etc/rc.d/init.d
328                         for serv in *
329                         do
330                                 case $serv in
331                                 *.bak|*~|functions|killall|halt|single)
332                                         ;;
333                                 *)
334                                         #$USR_LIB_VSERVER/capchroot $VROOTDIR/$1 /sbin/chkconfig --level 2345 $serv off
335                                         $0 --silent $1 chkconfig --level 2345 $serv off
336                                         ;;
337                                 esac
338                         done
339                 )
340                 rm -f etc/rc.d/rc6.d/S*reboot
341         fi
342 elif [ ! -f /etc/vservers/$1.conf ] ; then
343         echo No configuration for this vserver: /etc/vservers/$1.conf
344         exit 1
345 elif [ ! -d $VROOTDIR/$1/. ] ; then
346         echo No directory for this vserver: $VROOTDIR/$1
347         exit 1
348 elif [ "$2" = "start" ] ; then
349         echo Starting the virtual server $1
350         testperm $1
351         if ! $VSERVER_CMD $1 running
352         then
353                 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1
354                 S_NICE=
355                 S_FLAGS=
356                 . /etc/vservers/$1.conf
357                 export PROFILE
358                 cd $VROOTDIR/$1 || exit 1
359
360                 if [ "$PROFILE" != "" ] ; then
361                         echo export PROFILE=$PROFILE >etc/PROFILE
362                 fi
363
364                 rm -f `find var/run -type f`
365                 touch var/run/utmp
366                 chgrp ${UTMP_GROUP:-utmp} var/run/utmp
367                 chmod 0664 var/run/utmp
368                 rm -f  var/lock/subsys/*
369                 mountproc $VROOTDIR/$1
370                 CTXOPT=
371                 HOSTOPT=
372                 DOMAINOPT=
373                 NICECMD=
374                 FLAGS=
375                 CAPS=
376                 get_initdefault $1
377                 STARTCMD="/etc/rc.d/rc $INITDEFAULT"
378                 if [ -x $VROOTDIR/$1/etc/init.d/rc ] ; then
379                         STARTCMD="/etc/init.d/rc $INITDEFAULT"
380                 elif [ -x $VROOTDIR/$1/usr/bin/emerge ] ; then
381                         STARTCMD="/sbin/rc default"
382                 elif [ -x $VROOTDIR/$1/etc/rc.d/rc.M ] ; then
383                         STARTCMD="/etc/rc.d/rc.M"                       
384                 fi
385
386                 DISCONNECT=
387                 FAKEINIT=
388                 for f in $S_FLAGS dummy
389                 do
390                         case $f in
391                         dummy)
392                                 ;;
393
394                         minit)
395                                 FAKEINIT=true
396                                 FLAGS="$FLAGS --flag fakeinit"
397                                 STARTCMD=/sbin/minit-start
398                                 DISCONNECT=--disconnect
399                                 ;;
400
401                         fakeinit)
402                                 FAKEINIT=true
403                                 FLAGS="$FLAGS --flag $f"
404                                 STARTCMD=/sbin/init
405                                 DISCONNECT=--disconnect
406                                 ;;
407                         *)
408                                 FLAGS="$FLAGS --flag $f"
409                                 ;;
410                         esac
411                 done
412                 if [ -n "$S_START" ] ; then
413                         STARTCMD=$S_START
414                 fi              
415                 if [ "$FAKEINIT" = "" ] ; then
416                         $USR_LIB_VSERVER/fakerunlevel $INITDEFAULT var/run/utmp
417                 fi
418
419                 calculateCaps $S_CAPS
420
421                 if [ "$S_CONTEXT" != "" ] ; then
422                         CTXOPT="--ctx $S_CONTEXT"
423                 fi
424                 if [ "$S_HOSTNAME" != "" ] ; then
425                         HOSTOPT="--hostname $S_HOSTNAME"
426                         export HOSTNAME=$S_HOSTNAME
427                 fi
428                 if [ "$S_DOMAINNAME" != "" ] ; then
429                         DOMAINOPT="--domainname $S_DOMAINNAME"
430                 fi
431                 if [ "$S_NICE" != "" ] ; then
432                         NICECMD="nice -$S_NICE"
433                 fi
434                 mkdir -p /var/run/vservers
435                 chmod 700 /var/run/vservers
436                 setdefulimit
437                 if [ "$ULIMIT" != "" ] ; then
438                         ulimit $ULIMIT
439                 fi
440                 #echo FLAGS=$FLAGS
441                 #echo CAPS=$CAPS
442                 # We switch to $VROOTDIR/$1 now, because after the
443                 # security context switch $VROOTDIR directory becomes a dead zone.
444                 cd $VROOTDIR/$1
445                 export PATH=$DEFAULTPATH
446                 # XXX execute /etc/rc.vinit first for backward compatibility
447                 for CMD in "$VINIT_CMD $2" "$STARTCMD" ; do
448                         $NICECMD \
449                                 $CHCONTEXT_CMD $SILENT $DISCONNECT $CAPS $FLAGS $CTXOPT $HOSTOPT $DOMAINOPT --secure \
450                                 $SAVE_S_CONTEXT_CMD /var/run/vservers/$1.ctx \
451                                 $CAPCHROOT_CMD $CHROOTOPT . $CMD
452                 done
453                 sleep 2
454                 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-start $1
455         fi
456 elif [ "$2" = "running" ] ; then
457         if [ ! -f /var/run/vservers/$1.ctx ] ; then
458                 echo Server $1 is not running
459                 exit 1
460         else
461                 . /var/run/vservers/$1.ctx
462                 NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
463                 #NB=`$CHCONTEXT_CMD --silent --ctx $S_CONTEXT ps ax | wc -l`
464                 #NB=`eval expr $NB + 0`
465                 if [ "$NB" -gt 0 ] ; then
466                         echo Server $1 is running
467                         exit 0
468                 else
469                         echo Server $1 is not running
470                         exit 1
471                 fi
472         fi
473 elif [ "$2" = "status" ] ; then
474         if $0 $1 running
475         then
476                 . /var/run/vservers/$1.ctx
477                 NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
478                 echo $NB processes running
479                 echo Vserver uptime: `$USR_LIB_VSERVER/filetime /var/run/vservers/$1.ctx`
480         fi
481 elif [ "$2" = "stop" ] ; then
482         echo Stopping the virtual server $1
483         CAPS=
484         IS_MINIT=
485         readlastconf $1
486         if $VSERVER_CMD $1 running
487         then
488                 test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-stop $1
489                 cd $VROOTDIR/$1
490                 mountproc $VROOTDIR/$1
491                 # The fakeinit flag tell us how to turn off the server
492                 get_initdefault $1
493                 export PREVLEVEL=$INITDEFAULT
494                 STOPCMD="/etc/rc.d/rc 6"
495                 if [ -x $VROOTDIR/$1/etc/init.d/rc ] ; then
496                         STOPCMD="/etc/init.d/rc 6"
497                 elif [ -x $VROOTDIR/$1/usr/bin/emerge ] ; then
498                         STOPCMD="/sbin/rc shutdown"
499                 elif [ -x $VROOTDIR/$1/etc/rc.d/rc.6 ] ; then
500                         STOPCMD="/etc/rc.d/rc.6"
501                 fi
502
503                 for f in $S_FLAGS dummy
504                 do
505                         case $f in
506                         minit)
507                                 IS_MINIT=1
508                                 FLAGS="$FLAGS --flag fakeinit"
509                                 STOPCMD="/sbin/minit-stop"
510                                 ;;
511
512                         fakeinit)
513                                 FLAGS="$FLAGS --flag $f"
514                                 STOPCMD="/sbin/init 6"
515                                 ;;
516                         *)
517                                 ;;
518                         esac
519                 done
520
521                 if [ -n "$S_STOP" ] ; then
522                         STOPCMD=$S_STOP
523                 fi
524                 
525                 calculateCaps $S_CAPS
526
527                 cd $VROOTDIR/$1
528                 export PATH=$DEFAULTPATH
529                 # XXX execute /etc/rc.vinit first for backward compatibility
530                 for CMD in "$VINIT_CMD $2" "$STOPCMD" ; do
531                         $WAITFOR_CMD $CHCONTEXT_CMD $SILENT $CAPS --secure --ctx $S_CONTEXT \
532                                 $CAPCHROOT_CMD . $CMD
533                 done
534
535                 if test "$IS_MINIT"; then
536                     echo "Waiting for minit finish-signal"
537                     dd if=var/run/minit-stop of=/dev/zero bs=1 count=1 &>/dev/null
538                     sleep 1
539                 else
540                     echo sleeping 5 seconds
541                     sleep 5
542                 fi
543
544                 echo Killing all processes
545                 $CHCONTEXT_CMD $CAPS --secure --silent --ctx $S_CONTEXT \
546                         $VSERVERKILLALL_CMD
547         fi
548         # We umount anyway, because "enter" establish the mount
549         # but when you exit, the server is considered not running
550         umountproc $VROOTDIR/$1
551         cd /
552         test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-stop $1
553 elif [ "$2" = "restart" ] ; then
554         if $0 $1 running
555         then
556                 $0 $1 stop
557                 $0 $1 start
558         fi
559 elif [ "$2" = "suexec" ] ; then
560         if [ -z "$3" ] ; then
561                 echo "Missing user!" >&2
562                 echo "vserver vserver-name suexec user command [ args ... ]" >&2
563                 exit 1
564         elif [ -z "$4" ] ; then
565                 echo "Missing command and arguments!" >&2
566                 echo "vserver vserver-name suexec user command [ args ... ]" >&2
567                 exit 1
568         else
569                 readlastconf $1
570                 . /etc/vservers/$1.conf
571                 cd $VROOTDIR/$1
572                 mountproc $VROOTDIR/$1
573                 PS1="[\u@vserver:$1 \W]"
574                 export PS1
575                 VSERVER=$1
576                 USERID=$3
577                 shift; shift; shift
578                 CAPS=
579                 for f in $S_CAPS dummy
580                 do
581                         case $f in
582                         dummy)
583                                 ;;
584                         !CAP_SYS_CHROOT)
585                                 CHROOTOPT=--nochroot
586                                 ;;
587                         *)
588                                 CAPS="$CAPS --cap $f"
589                                 ;;
590                         esac
591                 done
592                 FLAGS=
593                 for f in $S_FLAGS dummy
594                 do
595                         case $f in
596                         minit)
597                                 FLAGS="$FLAGS --flag fakeinit"
598                                 ;;
599
600                         dummy)
601                                 ;;
602                         *)
603                                 FLAGS="$FLAGS --flag $f"
604                                 ;;
605                         esac
606                 done
607                 setdefulimit
608                 if [ "$ULIMIT" != "" ] ; then
609                         ulimit $ULIMIT
610                 fi
611                 if $0 $VSERVER running >/dev/null
612                 then
613                         . /var/run/vservers/$VSERVER.ctx
614                         cd $VROOTDIR/$VSERVER
615                         export PATH=$DEFAULTPATH
616                         exec $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure --ctx $S_CONTEXT \
617                                 $CAPCHROOT_CMD --suid $USERID . "$@"
618                 else
619                         test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1
620                         CTXOPT=
621                         HOSTOPT=
622                         DOMAINOPT=
623                         if [ "$S_CONTEXT" != "" ] ; then
624                                 CTXOPT="--ctx $S_CONTEXT"
625                         fi
626                         if [ "$S_HOSTNAME" != "" ] ; then
627                                 HOSTOPT="--hostname $S_HOSTNAME"
628                                 export HOSTNAME=$S_HOSTNAME
629                         fi
630                         if [ "$S_DOMAINNAME" != "" ] ; then
631                                 DOMAINOPT="--domainname $S_DOMAINNAME"
632                         fi
633                         mkdir -p /var/run/vservers
634                         cd $VROOTDIR/$VSERVER
635                         export PATH=$DEFAULTPATH
636                         exec $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \
637                                 $SAVE_S_CONTEXT_CMD /var/run/vservers/$VSERVER.ctx \
638                                 $CAPCHROOT_CMD --suid $USERID $CHROOTOPT . "$@"
639                 fi
640         fi
641 elif [ "$2" = "exec" ] ; then
642         VSERV=$1
643         shift; shift
644         exec $0 $SILENT $VSERV suexec root "$@"
645 elif [ "$2" = "enter" ] ; then
646         testperm $1
647         exec $0 $SILENT $1 exec /bin/bash -login
648 elif [ "$2" = "service" ] ; then
649         VSERVER=$1
650         shift
651         shift
652         exec $0 $SILENT $VSERVER exec /sbin/service "$@"
653 elif [ "$2" = "chkconfig" ] ; then
654         VSERVER=$1
655         LEVELS=()
656         shift
657         shift
658         if [ "$1" = "--level" ] ; then
659                 LEVELS=( --level "$2" )
660                 shift 2
661         fi
662         if [ $# != 2 -a ! -x $VROOTDIR/$VSERVER/sbin/chkconfig ] ; then
663                 echo Invalid argument, expected vserver name chkconfig [ --level nnn ] service on\|off
664         elif [ -x $VROOTDIR/$VSERVER/sbin/chkconfig ] ; then
665                 exec $0 --silent $VSERVER exec /sbin/chkconfig "${LEVELS[@]}" "$@"
666         elif [ -x $VROOTDIR/$VSERVER/usr/sbin/update-rc.d ] ; then
667                 if [ "$2" = "on" -o "$2" = "start" ] ; then
668                         $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
669                         exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 start 80 2 3 4 5 . stop 20 0 1 6 . >/dev/null
670                 elif [ "$2" = "off" -o "$2" = "stop" ] ; then
671                         $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
672                         exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 stop 20 0 1 2 3 4 5 6 . >/dev/null
673                 else
674                         echo vserver chkconfig: Expecting on or off
675                 fi
676         else
677                 echo chkconfig functionality is not available on this
678                 echo vserver distribution.
679                 echo Looked for /sbin/chkconfig and /usr/sbin/update-rc.d
680         fi
681 else
682         echo Command unknown $2
683         echo
684         usage
685 fi
686