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