initial checkin
authorEnrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
Mon, 29 Sep 2003 22:01:59 +0000 (22:01 +0000)
committerEnrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
Mon, 29 Sep 2003 22:01:59 +0000 (22:01 +0000)
git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2 94cd875c-1c1d-0410-91d2-eb244daf1a30

109 files changed:
util-vserver/.cvsignore [new file with mode: 0644]
util-vserver/AUTHORS [new file with mode: 0644]
util-vserver/Makefile.am [new file with mode: 0644]
util-vserver/NEWS [new file with mode: 0644]
util-vserver/README [new file with mode: 0644]
util-vserver/THANKS [new file with mode: 0644]
util-vserver/configure.ac [new file with mode: 0644]
util-vserver/distrib/Makefile-files [new file with mode: 0644]
util-vserver/distrib/install-mdk8.2 [new file with mode: 0644]
util-vserver/distrib/install-post.sh [new file with mode: 0644]
util-vserver/distrib/install-pre.sh [new file with mode: 0644]
util-vserver/distrib/install-rh7.2 [new file with mode: 0644]
util-vserver/distrib/install-rh7.3 [new file with mode: 0644]
util-vserver/distrib/install-rh8.0 [new file with mode: 0644]
util-vserver/distrib/install-rh9.0 [new file with mode: 0644]
util-vserver/distrib/mdk8.2-minimum [new file with mode: 0644]
util-vserver/distrib/rh7.3-minimum [new file with mode: 0644]
util-vserver/distrib/rh8.0-minimum [new file with mode: 0644]
util-vserver/distrib/rh9.0-minimum [new file with mode: 0644]
util-vserver/distrib/sample.conf [new file with mode: 0644]
util-vserver/distrib/sample.sh [new file with mode: 0755]
util-vserver/doc/FAQ.txt [new file with mode: 0644]
util-vserver/doc/Makefile-files [new file with mode: 0644]
util-vserver/doc/changelog.txt [new file with mode: 0644]
util-vserver/doc/intro.txt [new file with mode: 0644]
util-vserver/lib/Makefile-files [new file with mode: 0644]
util-vserver/lib/syscall.c [new file with mode: 0644]
util-vserver/lib/vserver.h [new file with mode: 0644]
util-vserver/m4/changelog.am [new file with mode: 0644]
util-vserver/m4/ensc_cflags.m4 [new file with mode: 0644]
util-vserver/m4/gpgsig.am [new file with mode: 0644]
util-vserver/m4/validate.am [new file with mode: 0644]
util-vserver/man/Makefile-files [new file with mode: 0644]
util-vserver/man/chbind.8 [new file with mode: 0644]
util-vserver/man/chcontext.8 [new file with mode: 0644]
util-vserver/man/distrib-info.8 [new file with mode: 0644]
util-vserver/man/newvserver.8 [new file with mode: 0644]
util-vserver/man/rebootmgr.8 [new file with mode: 0644]
util-vserver/man/reducecap.8 [new file with mode: 0644]
util-vserver/man/vps.8 [new file with mode: 0644]
util-vserver/man/vpstree.8 [new file with mode: 0644]
util-vserver/man/vrpm.8 [new file with mode: 0644]
util-vserver/man/vserver-copy.8 [new file with mode: 0644]
util-vserver/man/vserver-stat.8 [new file with mode: 0644]
util-vserver/man/vserver.8 [new file with mode: 0644]
util-vserver/man/vtop.8 [new file with mode: 0644]
util-vserver/newvserver.defaults [new file with mode: 0644]
util-vserver/scripts/Makefile-files [new file with mode: 0644]
util-vserver/scripts/distrib-info [new file with mode: 0755]
util-vserver/scripts/rootshell [new file with mode: 0755]
util-vserver/scripts/save_s_context [new file with mode: 0755]
util-vserver/scripts/util-vserver-vars.subst [new file with mode: 0644]
util-vserver/scripts/vkill [new file with mode: 0755]
util-vserver/scripts/vprofile [new file with mode: 0755]
util-vserver/scripts/vps [new file with mode: 0755]
util-vserver/scripts/vpstree [new file with mode: 0755]
util-vserver/scripts/vrpm [new file with mode: 0755]
util-vserver/scripts/vserver [new file with mode: 0755]
util-vserver/scripts/vserver-copy [new file with mode: 0755]
util-vserver/scripts/vserverkillall [new file with mode: 0755]
util-vserver/scripts/vservers.grabinfo.sh [new file with mode: 0644]
util-vserver/scripts/vsysvwrapper [new file with mode: 0755]
util-vserver/scripts/vtop [new file with mode: 0755]
util-vserver/scripts/vunify.old.sh [new file with mode: 0755]
util-vserver/src/Makefile-files [new file with mode: 0644]
util-vserver/src/capchroot.c [new file with mode: 0644]
util-vserver/src/chbind.c [new file with mode: 0644]
util-vserver/src/chcontext.c [new file with mode: 0644]
util-vserver/src/fakerunlevel.c [new file with mode: 0644]
util-vserver/src/filetime.c [new file with mode: 0644]
util-vserver/src/ifspec.c [new file with mode: 0644]
util-vserver/src/listdevip.c [new file with mode: 0644]
util-vserver/src/parserpmdump.c [new file with mode: 0644]
util-vserver/src/readlink.c [new file with mode: 0644]
util-vserver/src/rebootmgr.c [new file with mode: 0644]
util-vserver/src/reducecap.c [new file with mode: 0644]
util-vserver/src/setctxlimit.c [new file with mode: 0644]
util-vserver/src/showattr.c [new file with mode: 0644]
util-vserver/src/showperm.c [new file with mode: 0644]
util-vserver/src/vbuild.cc [new file with mode: 0644]
util-vserver/src/vcheck.cc [new file with mode: 0644]
util-vserver/src/vdu.c [new file with mode: 0644]
util-vserver/src/vfiles.cc [new file with mode: 0644]
util-vserver/src/vreboot.c [new file with mode: 0644]
util-vserver/src/vserver-stat.c [new file with mode: 0644]
util-vserver/src/vunify.cc [new file with mode: 0644]
util-vserver/src/vutil.cc [new file with mode: 0644]
util-vserver/src/vutil.h [new file with mode: 0644]
util-vserver/src/vutil.p [new file with mode: 0644]
util-vserver/sysv/Makefile-files [new file with mode: 0644]
util-vserver/sysv/rebootmgr.subst [new file with mode: 0755]
util-vserver/sysv/v_gated.subst [new file with mode: 0755]
util-vserver/sysv/v_httpd.subst [new file with mode: 0755]
util-vserver/sysv/v_named.subst [new file with mode: 0755]
util-vserver/sysv/v_portmap.subst [new file with mode: 0755]
util-vserver/sysv/v_sendmail.subst [new file with mode: 0755]
util-vserver/sysv/v_smb.subst [new file with mode: 0755]
util-vserver/sysv/v_sshd.subst [new file with mode: 0755]
util-vserver/sysv/v_xinetd.subst [new file with mode: 0755]
util-vserver/sysv/vservers.conf [new file with mode: 0644]
util-vserver/sysv/vservers.subst [new file with mode: 0755]
util-vserver/tests/Makefile-files [new file with mode: 0644]
util-vserver/tests/chrootsafe.cc [new file with mode: 0644]
util-vserver/tests/escaperoot.cc [new file with mode: 0644]
util-vserver/tests/forkbomb.cc [new file with mode: 0644]
util-vserver/tests/testipc.cc [new file with mode: 0644]
util-vserver/tests/testlimit.cc [new file with mode: 0644]
util-vserver/tests/testopenf.cc [new file with mode: 0644]
util-vserver/vserver.spec.in [new file with mode: 0644]

diff --git a/util-vserver/.cvsignore b/util-vserver/.cvsignore
new file mode 100644 (file)
index 0000000..ffa3457
--- /dev/null
@@ -0,0 +1,22 @@
+.X_usr_local_etc-up-to-date
+.deps
+COPYING
+ChangeLog
+INSTALL
+aclocal.m4
+autom4te.cache
+compile
+config.h
+config.h.in
+config.log
+config.status
+depcomp
+install-sh
+missing
+mkinstalldirs
+stamp-h1
+stamp-h2
+util-vserver-*.tar.bz2*
+util-vserver-*.tar.gz
+vserver.spec
+vserverx-*.tar.*
diff --git a/util-vserver/AUTHORS b/util-vserver/AUTHORS
new file mode 100644 (file)
index 0000000..db53813
--- /dev/null
@@ -0,0 +1 @@
+Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
diff --git a/util-vserver/Makefile.am b/util-vserver/Makefile.am
new file mode 100644 (file)
index 0000000..8c34f66
--- /dev/null
@@ -0,0 +1,75 @@
+## $Id$
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#  
+
+ACLOCAL_AMFLAGS                =  -I m4
+
+sysvdir                        =  $(sysconfdir)/init.d
+vservercfgdir          =  $(sysconfdir)/vservers
+
+include_HEADERS                =  $(lib_HDRS)
+noinst_HEADERS         =  $(src_HDRS)
+
+lib_LIBRARIES          =  $(lib_lib_LIBS)
+
+pkglib_SCRIPTS         =  $(distrib_SCRPTS) $(scripts_SCRPTS)
+pkglib_DATA            =  $(distrib_DAT) $(scriptscfg_DATA)
+pkglib_PROGRAMS                =  $(src_pkglib_PRGS)
+
+sbin_SCRIPTS           =  $(scripts_PRGS)
+sbin_PROGRAMS          =  $(src_sbin_PRGS)
+noinst_PROGRAMS                =  $(test_PRGS)
+
+sysv_SCRIPTS           =  $(sysv_SCRPTS)
+sysconf_DATA           =  $(sysv_CFG)
+vservercfg_DATA                =  newvserver.defaults
+
+BUILT_SOURCES          =  linuxcaps.h
+
+man_MANS               =  $(man_DATMAN)
+
+EXTRA_DIST             =  $(distrib_SCRPTS) $(distrib_DAT) \
+                          $(sysv_XTRAS) $(sysv_CFG) \
+                           $(doc_DAT) $(man_DATMAN) \
+                          $(scripts_SCRPTS) $(scripts_PRGS) $(scripts_XTRAS) \
+                          vserver.spec newvserver.defaults \
+                           m4/ensc_cflags.m4 \
+                          THANKS
+
+AM_CPPFLAGS            =  -I $(top_srcdir)/lib -D VERSION=\"$(VERSION)\" -D PKGLIBDIR=\"$(pkglibdir)\" -D _GNU_SOURCE
+AM_CFLAGS              =  -Wall -pedantic
+
+CLEANFILES             =  $(sysv_GENSCRPTS) $(scripts_GENSCRPTS) linuxcaps.h
+
+
+linuxcaps.h:
+               ln -sf ${kernelincludedir}/linux/capability.h linuxcaps.h
+
+
+include $(top_srcdir)/lib/Makefile-files
+include $(top_srcdir)/src/Makefile-files
+include $(top_srcdir)/distrib/Makefile-files
+include $(top_srcdir)/doc/Makefile-files
+include $(top_srcdir)/man/Makefile-files
+include $(top_srcdir)/scripts/Makefile-files
+include $(top_srcdir)/tests/Makefile-files
+include $(top_srcdir)/sysv/Makefile-files
+
+include $(top_srcdir)/m4/gpgsig.am
+include $(top_srcdir)/m4/validate.am
+include $(top_srcdir)/m4/changelog.am
diff --git a/util-vserver/NEWS b/util-vserver/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/util-vserver/README b/util-vserver/README
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/util-vserver/THANKS b/util-vserver/THANKS
new file mode 100644 (file)
index 0000000..65b51e9
--- /dev/null
@@ -0,0 +1,7 @@
+I want to thank
+
+Jacques Gelinas <jack@solucorp.qc.ca>,
+    who wrote and maintains the 'vserver' package on which util-vserver
+    is based on
+
+all the other people, who contributed to the original 'vserver' package
diff --git a/util-vserver/configure.ac b/util-vserver/configure.ac
new file mode 100644 (file)
index 0000000..5e7b319
--- /dev/null
@@ -0,0 +1,69 @@
+dnl $Id$
+
+dnl Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+dnl  
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl  
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl  
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl  
+dnl  
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+dnl  
+
+AC_PREREQ(2.57)
+AC_INIT(util-vserver, 0.23.5, enrico.scholz@informatik.tu-chemnitz.de)
+AC_CONFIG_SRCDIR([src/capchroot.c])
+AC_CONFIG_HEADER([config.h])
+
+AM_INIT_AUTOMAKE([gnu dist-bzip2 subdir-objects])
+AM_MAINTAINER_MODE
+
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_RANLIB
+AM_PROG_CC_C_O
+
+ENSC_CHECK_CC_FLAG([-std=c99])
+
+AC_ARG_VAR(CC, [The C compiler])
+AC_MSG_CHECKING([for linux kernel headers])
+AC_ARG_WITH([kerneldir],
+           [AC_HELP_STRING([--with-kerneldir=DIR],
+                            [assume top-kernelsources in DIR (default: /lib/modules/<current>/build)])],
+            [case "$withval" in
+               yes|no) AC_MSG_ERROR(['$withval' is not a valid value for kerneldir]);;
+               *)      kerneldir=$withval;;
+            esac],
+           [kerneldir=
+            for i in /lib/modules/$(uname -r)/build /usr/src/linux /usr; do
+               test -e $i/include/linux/version.h && { kerneldir=$i; break; }
+            done])
+
+test "$kerneldir" -a -e $i/include/linux/version.h || {
+       AC_MSG_ERROR([Can not find kernelsources])
+}
+
+kernelincludedir=$kerneldir/include
+AC_SUBST(kernelincludedir)
+AC_MSG_RESULT($kernelincludedir/linux)
+               
+
+AC_CONFIG_FILES([vserver.spec Makefile])
+AC_OUTPUT
diff --git a/util-vserver/distrib/Makefile-files b/util-vserver/distrib/Makefile-files
new file mode 100644 (file)
index 0000000..0b73f26
--- /dev/null
@@ -0,0 +1,33 @@
+## $Id$  -*- makefile -*-
+
+## Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+distrib_SCRPTS         = distrib/install-mdk8.2 \
+                         distrib/install-post.sh \
+                         distrib/install-pre.sh \
+                         distrib/install-rh7.2 \
+                         distrib/install-rh7.3 \
+                         distrib/install-rh8.0 \
+                         distrib/install-rh9.0 \
+                         distrib/sample.sh
+
+distrib_DAT            = distrib/mdk8.2-minimum \
+                         distrib/rh7.3-minimum \
+                         distrib/rh8.0-minimum \
+                         distrib/rh9.0-minimum \
+                         distrib/sample.conf
+
diff --git a/util-vserver/distrib/install-mdk8.2 b/util-vserver/distrib/install-mdk8.2
new file mode 100644 (file)
index 0000000..5212ca4
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/sh
+# $Id$  --*- sh -*--
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on install-mdk8.2 by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+# This script creates a vserver from Mandrake 8.2 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-mdk8.2 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# -lt 1 ] ; then
+       echo install-mdk8.2 vserver-id [ type ]
+       echo type minimum means, minimum package for a server
+       echo type large means, all packages on the first CD
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+       echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/Mandrake/RPMS ] ; then
+       echo No rpms in /mnt/cdrom/Mandrake/RPMS. Is the CD mounted \?
+else
+       VROOT=/vservers/$1
+       $USR_LIB_VSERVER/install-pre.sh $1
+       mkdir -p $VROOT/proc
+       mount -t proc none $VROOT/proc
+       mkdir -p $VROOT/var/lib/rpm
+       rpm --root $VROOT --initdb
+       if [ "$2" = "minimum" ] ; then
+               echo `cat $USR_LIB_VSERVER/mdk8.2-minimum | wc -l` packages to install
+               cd /mnt/cdrom/Mandrake/RPMS
+               rpm --root $VROOT -Uvh `cat $USR_LIB_VSERVER/mdk8.2-minimum`
+       else
+               PKGS=`ls /mnt/cdrom/Mandrake/RPMS/*.i586.rpm | grep -v LPRng- \
+                       | grep -v lpr-`
+
+               echo `(ls /mnt/cdrom/Mandrake/RPMS/*.noarch.rpm \
+                       ;echo $PKGS) | wc -w` packages to install
+               rpm --root $VROOT -Uvh \
+                       /mnt/cdrom/Mandrake/RPMS/*.noarch.rpm \
+                       $PKGS --nodeps
+       fi
+       $USR_LIB_VSERVER/install-post.sh $1
+       umount $VROOT/proc
+fi
+
+
diff --git a/util-vserver/distrib/install-post.sh b/util-vserver/distrib/install-post.sh
new file mode 100644 (file)
index 0000000..d877321
--- /dev/null
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-post by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Complete the installation of a vserver
+USR_LIB_VSERVER=$(dirname $0)
+vserver_mknod()
+{
+       mknod $1 $2 $3 $4
+       chmod $5 $1
+}
+
+if [ $# != 1 ] ; then
+       echo install-post.sh vserver
+else
+       VROOT=/vservers/$1
+       rm -fr $VROOT/dev
+       mkdir $VROOT/dev && chmod 755 $VROOT/dev
+       mkdir $VROOT/dev/pts
+       vserver_mknod $VROOT/dev/null c 1 3 666
+       vserver_mknod $VROOT/dev/zero c 1 5 666
+       vserver_mknod $VROOT/dev/full c 1 7 666
+       vserver_mknod $VROOT/dev/random c 1 8 644
+       vserver_mknod $VROOT/dev/urandom c 1 9 644
+       vserver_mknod $VROOT/dev/tty c 5 0 666
+       vserver_mknod $VROOT/dev/ptmx c 5 2 666
+       test -f /etc/vservers/$1.conf || cp $USR_LIB_VSERVER/sample.conf /etc/vservers/$1.conf
+       test -f /etc/vservers/$1.sh   || cp $USR_LIB_VSERVER/sample.sh /etc/vservers/$1.sh
+       echo NETWORKING=yes >$VROOT/etc/sysconfig/network
+       echo HOSTNAME=$1 >>$VROOT/etc/sysconfig/network
+       (
+               cd $VROOT/etc/rc.d/init.d || cd $VROOT/etc/init.d
+               for serv in *
+               do
+                       case $serv in
+                       *.bak|*~|functions|killall|halt|single)
+                               ;;
+                       *)
+                               $USR_LIB_VSERVER/capchroot /vservers/$1 /sbin/chkconfig --level 2345 $serv off
+                               ;;
+                       esac
+               done
+               rm -f $VROOT/etc/rc.d/rc6.d/S*reboot
+       )
+       if [ ! -f $VROOT/etc/fstab ] ; then
+               echo /dev/hdv1  /       ext2    defaults        1       1 >$VROOT/etc/fstab
+               echo /dev/hdv1  /       ext2    rw      1       1 >$VROOT/etc/mtab
+       fi
+       cp -a $USR_LIB_VSERVER/vreboot $VROOT/sbin/.
+       ln -sf vreboot $VROOT/sbin/vhalt
+       if [ -x /etc/vservers/install-post.sh ]; then
+               /etc/vservers/install-post.sh $VROOT
+       fi
+fi
+
diff --git a/util-vserver/distrib/install-pre.sh b/util-vserver/distrib/install-pre.sh
new file mode 100644 (file)
index 0000000..262a5f6
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-pre by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+vserver_mknod()
+{
+       mknod $1 $2 $3 $4
+       chmod $5 $1
+}
+
+if [ $# != 1 ] ; then
+       echo install-pre.sh vserver
+else
+       mkdir -p /etc/vservers
+       mkdir -p /vservers 2>/dev/null
+       VROOT=/vservers/$1
+       rm -fr $VROOT/dev
+       mkdir -p $VROOT/dev && chmod 755 $VROOT/dev
+       mkdir $VROOT/dev/pts
+       vserver_mknod $VROOT/dev/null c 1 3 666
+       vserver_mknod $VROOT/dev/zero c 1 5 666
+       vserver_mknod $VROOT/dev/full c 1 7 666
+       vserver_mknod $VROOT/dev/random c 1 8 644
+       vserver_mknod $VROOT/dev/urandom c 1 9 644
+       vserver_mknod $VROOT/dev/tty c 5 0 666
+       vserver_mknod $VROOT/dev/ptmx c 5 2 666
+       # We fake this device to help some package managers
+       touch $VROOT/dev/hdv1
+fi
+
diff --git a/util-vserver/distrib/install-rh7.2 b/util-vserver/distrib/install-rh7.2
new file mode 100644 (file)
index 0000000..b3bd0ca
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/sh
+# $Id$ --*- sh -*--
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-rh7.2 by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This script creates a vserver from RedHat 7.2 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-rh7.2 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# != 1 ] ; then
+       echo install-rh7.2 vserver-id
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+       echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/RedHat/RPMS ] ; then
+       echo No rpms in /mnt/cdrom/RedHat/RPMS. Is the CD mounted \?
+else
+       echo `ls /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+               /mnt/cdrom/RedHat/RPMS/*.i386.rpm | wc -l` packages to install
+       VROOT=/vservers/$1
+       mkdir -p $VROOT/proc
+       mount -t proc none $VROOT/proc
+       mkdir -p $VROOT/var/lib/rpm
+       rpm --root $VROOT --initdb
+       rpm --root $VROOT -Uvh \
+               /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+               /mnt/cdrom/RedHat/RPMS/*.i386.rpm
+       $USR_LIB_VSERVER/install-post.sh $1
+       umount $VROOT/proc
+fi
+
+
diff --git a/util-vserver/distrib/install-rh7.3 b/util-vserver/distrib/install-rh7.3
new file mode 100644 (file)
index 0000000..b50d14a
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+# $Id$ --*- sh -*--
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-rh7.3 by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This script creates a vserver from RedHat 7.3 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-rh7.3 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# -lt 1 ] ; then
+       echo install-rh7.3 vserver-id [ type ]
+       echo type minimum means, minimum package for a server
+       echo type large means, all packages on the first CD
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+       echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/RedHat/RPMS ] ; then
+       echo No rpms in /mnt/cdrom/RedHat/RPMS. Is the CD mounted \?
+else
+       VROOT=/vservers/$1
+       mkdir -p $VROOT/proc
+       mount -t proc none $VROOT/proc
+       mkdir -p $VROOT/var/lib/rpm
+       rpm --root $VROOT --initdb
+       if [ "$2" = "minimum" ] ; then
+               echo `cat $USR_LIB_VSERVER/rh7.3-minimum | wc -l` packages to install
+               cd /mnt/cdrom/RedHat/RPMS
+               rpm --root $VROOT -Uvh `cat $USR_LIB_VSERVER/rh7.3-minimum`
+       else
+               echo `ls        /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+                       /mnt/cdrom/RedHat/RPMS/*.i386.rpm | wc -l` packages to install
+               rpm --root $VROOT -Uvh \
+                       /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+                       /mnt/cdrom/RedHat/RPMS/*.i386.rpm --nodeps
+       fi
+       $USR_LIB_VSERVER/install-post.sh $1
+       umount $VROOT/proc
+fi
+
+
diff --git a/util-vserver/distrib/install-rh8.0 b/util-vserver/distrib/install-rh8.0
new file mode 100644 (file)
index 0000000..625c3a8
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-rh8.0 by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This script creates a vserver from RedHat 8.0 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-rh8.0 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# -lt 1 ] ; then
+       echo install-rh8.0 vserver-id [ type ]
+       echo type minimum means, minimum package for a server
+       echo type large means, all packages on the first CD
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+       echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/RedHat/RPMS ] ; then
+       echo No rpms in /mnt/cdrom/RedHat/RPMS. Is the CD mounted \?
+else
+       VROOT=/vservers/$1
+       $USR_LIB_VSERVER/install-pre.sh $1
+       mkdir -p $VROOT/proc
+       mount -t proc none $VROOT/proc
+       mount -t devpts none $VROOT/dev/pts
+       mkdir -p $VROOT/var/lib/rpm
+       rpm --root $VROOT --initdb
+       if [ "$2" = "minimum" ] ; then
+               echo `cat $USR_LIB_VSERVER/rh8.0-minimum | wc -l` packages to install
+               cd /mnt/cdrom/RedHat/RPMS
+               rpm --root $VROOT -Uvh `cat $USR_LIB_VSERVER/rh8.0-minimum`
+       else
+               PKGS=`ls /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+                        /mnt/cdrom/RedHat/RPMS/*.i386.rpm`
+               for except in control-center iptables kernel-pcmcia-cs\
+                       nfs-utils pciutils quota rp-pppoe tcpdump \
+                       lokkit kudzu-devel pciutils-devel
+               do
+                       PKGS=`ls $PKGS | grep -v $except`
+               done
+               echo `echo $PKGS | wc -w` packages to install
+               rpm --root $VROOT -Uvh $PKGS
+       fi
+       umount $VROOT/proc
+       umount $VROOT/dev/pts
+       $USR_LIB_VSERVER/install-post.sh $1
+fi
+
+
diff --git a/util-vserver/distrib/install-rh9.0 b/util-vserver/distrib/install-rh9.0
new file mode 100644 (file)
index 0000000..6aa639b
--- /dev/null
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-rh9.0 by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This script creates a vserver from RedHat 9.0 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-rh9.0 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# -lt 1 ] ; then
+       echo install-rh9.0 vserver-id [ type ]
+       echo type minimum means, minimum package for a server
+       echo type large means, all packages on the first CD
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+       echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/RedHat/RPMS ] ; then
+       echo No rpms in /mnt/cdrom/RedHat/RPMS. Is the CD mounted \?
+else
+       VROOT=/vservers/$1
+       $USR_LIB_VSERVER/install-pre.sh $1
+       mkdir -p $VROOT/proc
+       mount -t proc none $VROOT/proc
+       mount -t devpts none $VROOT/dev/pts
+       mkdir -p $VROOT/var/lib/rpm
+       rpm --root $VROOT --initdb
+       if [ "$2" = "minimum" ] ; then
+               echo `cat $USR_LIB_VSERVER/rh9.0-minimum | wc -l` packages to install
+               cd /mnt/cdrom/RedHat/RPMS
+               rpm --root $VROOT -Uvh `cat $USR_LIB_VSERVER/rh9.0-minimum`
+       else
+               PKGS=`ls /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+                        /mnt/cdrom/RedHat/RPMS/*.i386.rpm`
+               for except in control-center iptables kernel-pcmcia-cs\
+                       nfs-utils pciutils quota rp-pppoe tcpdump \
+                       lokkit kudzu-devel pciutils-devel \
+                       redhat-config-securitylevel redhat-config-nfs
+               do
+                       PKGS=`ls $PKGS | grep -v $except`
+               done
+               echo `echo $PKGS | wc -w` packages to install
+               rpm --root $VROOT -Uvh $PKGS --nodeps
+       fi
+       umount $VROOT/proc
+       umount $VROOT/dev/pts
+       $USR_LIB_VSERVER/install-post.sh $1
+fi
+
+
diff --git a/util-vserver/distrib/mdk8.2-minimum b/util-vserver/distrib/mdk8.2-minimum
new file mode 100644 (file)
index 0000000..344325d
--- /dev/null
@@ -0,0 +1,179 @@
+4Suite-0.11.1-8.i386.rpm
+Canna-3.5b2-62.i386.rpm
+Canna-libs-3.5b2-62.i386.rpm
+Distutils-1.0.2-2.noarch.rpm
+MAKEDEV-3.3-4.i386.rpm
+PyXML-0.7-4.i386.rpm
+SysVinit-2.84-2.i386.rpm
+a2ps-4.13b-19.i386.rpm
+alchemist-1.0.23-1.i386.rpm
+anacron-2.3-17.i386.rpm
+ash-0.3.7-2.i386.rpm
+at-3.1.8-23.i386.rpm
+audiofile-0.2.3-1.i386.rpm
+authconfig-4.2.8-4.i386.rpm
+basesystem-7.0-2.noarch.rpm
+bash-2.05a-13.i386.rpm
+bdflush-1.5-17.i386.rpm
+bzip2-1.0.2-2.i386.rpm
+bzip2-libs-1.0.2-2.i386.rpm
+chkconfig-1.3.5-3.i386.rpm
+cpio-2.4.2-26.i386.rpm
+cracklib-2.7-15.i386.rpm
+cracklib-dicts-2.7-15.i386.rpm
+crontabs-1.10-1.noarch.rpm
+cyrus-sasl-1.5.24-25.i386.rpm
+cyrus-sasl-md5-1.5.24-25.i386.rpm
+cyrus-sasl-plain-1.5.24-25.i386.rpm
+db1-1.85-8.i386.rpm
+db2-2.4.14-10.i386.rpm
+db3-3.3.11-6.i386.rpm
+dev-3.3-4.i386.rpm
+diffutils-2.7.2-5.i386.rpm
+dosfstools-2.8-1.i386.rpm
+e2fsprogs-1.27-3.i386.rpm
+ed-0.2-25.i386.rpm
+fam-2.6.7-6.i386.rpm
+file-3.37-5.i386.rpm
+filesystem-2.1.6-2.noarch.rpm
+fileutils-4.1-10.i386.rpm
+findutils-4.1.7-4.i386.rpm
+freetype-2.0.9-2.i386.rpm
+gawk-3.1.0-4.i386.rpm
+gdbm-1.8.0-14.i386.rpm
+glib-1.2.10-5.i386.rpm
+glib2-2.0.1-2.i386.rpm
+glibc-2.2.5-34.i386.rpm
+glibc-common-2.2.5-34.i386.rpm
+gnupg-1.0.6-5.i386.rpm
+grep-2.5.1-1.i386.rpm
+groff-1.17.2-12.i386.rpm
+groff-perl-1.17.2-12.i386.rpm
+gzip-1.3.3-1.i386.rpm
+htdig-3.2.0-2.011302.i386.rpm
+indexhtml-7.3-3.noarch.rpm
+info-4.1-1.i386.rpm
+initscripts-6.67-1.i386.rpm
+iputils-20020124-3.i386.rpm
+less-358-24.i386.rpm
+libcap-1.10-8.i386.rpm
+libghttp-1.0.9-2.i386.rpm
+libjpeg-6b-19.i386.rpm
+libmng-1.0.3-2.i386.rpm
+libogg-1.0rc3-1.i386.rpm
+libpng-1.0.12-2.i386.rpm
+libstdc++-2.96-110.i386.rpm
+libtermcap-2.0.8-28.i386.rpm
+libtiff-3.5.7-2.i386.rpm
+libtool-libs-1.4.2-7.i386.rpm
+libunicode-0.4-6.i386.rpm
+libuser-0.50.2-1.i386.rpm
+libvorbis-1.0rc3-1.i386.rpm
+libxml-1.8.17-3.i386.rpm
+libxml2-2.4.19-4.i386.rpm
+libxslt-1.0.15-1.i386.rpm
+logrotate-3.6.4-1.i386.rpm
+losetup-2.11n-12.i386.rpm
+m4-1.4.1-7.i386.rpm
+mailcap-2.1.9-2.noarch.rpm
+mailx-8.1.1-22.i386.rpm
+make-3.79.1-8.i386.rpm
+man-1.5j-6.i386.rpm
+man-pages-1.48-2.noarch.rpm
+mktemp-1.5-14.i386.rpm
+mount-2.11n-12.i386.rpm
+mpage-2.5.1-9.i386.rpm
+ncurses-5.2-26.i386.rpm
+netpbm-9.24-3.i386.rpm
+netpbm-progs-9.24-3.i386.rpm
+newt-0.50.35-1.i386.rpm
+nhpf-1.42-2.i386.rpm
+ntsysv-1.3.5-3.i386.rpm
+openldap-2.0.23-4.i386.rpm
+openssh-3.1p1-3.i386.rpm
+openssh-clients-3.1p1-3.i386.rpm
+openssl-0.9.6b-18.i386.rpm
+pam-0.75-32.i386.rpm
+passwd-0.67-1.i386.rpm
+patch-2.5.4-12.i386.rpm
+pcre-3.9-2.i386.rpm
+perl-5.6.1-34.99.6.i386.rpm
+perl-CGI-2.752-34.99.6.i386.rpm
+perl-CPAN-1.59_54-34.99.6.i386.rpm
+perl-DB_File-1.75-34.99.6.i386.rpm
+perl-DateManip-5.40-15.i386.rpm
+perl-Digest-MD5-2.16-15.i386.rpm
+perl-File-MMagic-1.13-14.i386.rpm
+perl-HTML-Parser-3.26-2.i386.rpm
+perl-HTML-Tagset-3.03-14.i386.rpm
+perl-MIME-Base64-2.12-14.i386.rpm
+perl-NDBM_File-1.75-34.99.6.i386.rpm
+perl-NKF-1.71-2.i386.rpm
+perl-Parse-Yapp-1.05-15.i386.rpm
+perl-Storable-1.0.14-15.i386.rpm
+perl-URI-1.17-16.i386.rpm
+perl-XML-Dumper-0.4-12.noarch.rpm
+perl-XML-Encoding-1.01-9.noarch.rpm
+perl-XML-Grove-0.46alpha-11.noarch.rpm
+perl-XML-Parser-2.30-15.i386.rpm
+perl-XML-Twig-2.02-9.noarch.rpm
+perl-libnet-1.0901-17.i386.rpm
+perl-libwww-perl-5.63-9.i386.rpm
+perl-libxml-enno-1.02-15.i386.rpm
+perl-libxml-perl-0.07-14.noarch.rpm
+pnm2ppa-1.04-2.i386.rpm
+popt-1.6.4-7x.18.i386.rpm
+portmap-4.0-41.i386.rpm
+procmail-3.22-5.i386.rpm
+procps-2.0.7-12.i386.rpm
+psmisc-20.2-2.i386.rpm
+pspell-0.12.2-8.i386.rpm
+psutils-1.17-13.i386.rpm
+pwdb-0.61.2-2.i386.rpm
+python-1.5.2-38.i386.rpm
+python-clap-1.0.0-3.noarch.rpm
+python-popt-0.8.8-7.x.2.i386.rpm
+python-xmlrpc-1.5.1-7.x.3.i386.rpm
+python2-2.2-16.i386.rpm
+readline-4.2a-4.i386.rpm
+redhat-release-7.3-1.noarch.rpm
+rootfiles-7.2-1.noarch.rpm
+rpm-4.0.4-7x.18.i386.rpm
+rpm-python-4.0.4-7x.18.i386.rpm
+sed-3.02-11.i386.rpm
+sendmail-8.11.6-15.i386.rpm
+setup-2.5.12-1.noarch.rpm
+sgml-common-0.6.3-9.noarch.rpm
+sh-utils-2.0.11-14.i386.rpm
+shadow-utils-20000902-7.i386.rpm
+slang-1.4.5-2.i386.rpm
+slocate-2.6-1.i386.rpm
+specspo-7.3-4.noarch.rpm
+sysklogd-1.4.1-8.i386.rpm
+tar-1.13.25-4.i386.rpm
+tcl-8.3.3-67.i386.rpm
+tcsh-6.10-6.i386.rpm
+termcap-11.0.1-10.noarch.rpm
+textutils-2.0.21-1.i386.rpm
+time-1.7-16.i386.rpm
+tmpwatch-2.8.3-1.i386.rpm
+umb-scheme-3.2-21.i386.rpm
+unzip-5.50-2.i386.rpm
+usermode-1.53-2.i386.rpm
+utempter-0.5.2-6.i386.rpm
+util-linux-2.11n-12.i386.rpm
+vim-common-6.1-2.i386.rpm
+vim-minimal-6.1-2.i386.rpm
+vixie-cron-3.0.1-64.i386.rpm
+which-2.13-3.i386.rpm
+words-2-18.noarch.rpm
+xinetd-2.3.4-0.8.i386.rpm
+xml-common-0.6.3-9.noarch.rpm
+zip-2.3-12.i386.rpm
+zlib-1.1.3-25.7.i386.rpm
+mingetty-1.00-1.i386.rpm
+iproute-2.4.7-1.i386.rpm
+modutils-2.4.14-3.i386.rpm
+gmp-4.0.1-3.i386.rpm
+expat-1.95.2-2.i386.rpm 
+net-tools-1.60-4.i386.rpm 
diff --git a/util-vserver/distrib/rh7.3-minimum b/util-vserver/distrib/rh7.3-minimum
new file mode 100644 (file)
index 0000000..344325d
--- /dev/null
@@ -0,0 +1,179 @@
+4Suite-0.11.1-8.i386.rpm
+Canna-3.5b2-62.i386.rpm
+Canna-libs-3.5b2-62.i386.rpm
+Distutils-1.0.2-2.noarch.rpm
+MAKEDEV-3.3-4.i386.rpm
+PyXML-0.7-4.i386.rpm
+SysVinit-2.84-2.i386.rpm
+a2ps-4.13b-19.i386.rpm
+alchemist-1.0.23-1.i386.rpm
+anacron-2.3-17.i386.rpm
+ash-0.3.7-2.i386.rpm
+at-3.1.8-23.i386.rpm
+audiofile-0.2.3-1.i386.rpm
+authconfig-4.2.8-4.i386.rpm
+basesystem-7.0-2.noarch.rpm
+bash-2.05a-13.i386.rpm
+bdflush-1.5-17.i386.rpm
+bzip2-1.0.2-2.i386.rpm
+bzip2-libs-1.0.2-2.i386.rpm
+chkconfig-1.3.5-3.i386.rpm
+cpio-2.4.2-26.i386.rpm
+cracklib-2.7-15.i386.rpm
+cracklib-dicts-2.7-15.i386.rpm
+crontabs-1.10-1.noarch.rpm
+cyrus-sasl-1.5.24-25.i386.rpm
+cyrus-sasl-md5-1.5.24-25.i386.rpm
+cyrus-sasl-plain-1.5.24-25.i386.rpm
+db1-1.85-8.i386.rpm
+db2-2.4.14-10.i386.rpm
+db3-3.3.11-6.i386.rpm
+dev-3.3-4.i386.rpm
+diffutils-2.7.2-5.i386.rpm
+dosfstools-2.8-1.i386.rpm
+e2fsprogs-1.27-3.i386.rpm
+ed-0.2-25.i386.rpm
+fam-2.6.7-6.i386.rpm
+file-3.37-5.i386.rpm
+filesystem-2.1.6-2.noarch.rpm
+fileutils-4.1-10.i386.rpm
+findutils-4.1.7-4.i386.rpm
+freetype-2.0.9-2.i386.rpm
+gawk-3.1.0-4.i386.rpm
+gdbm-1.8.0-14.i386.rpm
+glib-1.2.10-5.i386.rpm
+glib2-2.0.1-2.i386.rpm
+glibc-2.2.5-34.i386.rpm
+glibc-common-2.2.5-34.i386.rpm
+gnupg-1.0.6-5.i386.rpm
+grep-2.5.1-1.i386.rpm
+groff-1.17.2-12.i386.rpm
+groff-perl-1.17.2-12.i386.rpm
+gzip-1.3.3-1.i386.rpm
+htdig-3.2.0-2.011302.i386.rpm
+indexhtml-7.3-3.noarch.rpm
+info-4.1-1.i386.rpm
+initscripts-6.67-1.i386.rpm
+iputils-20020124-3.i386.rpm
+less-358-24.i386.rpm
+libcap-1.10-8.i386.rpm
+libghttp-1.0.9-2.i386.rpm
+libjpeg-6b-19.i386.rpm
+libmng-1.0.3-2.i386.rpm
+libogg-1.0rc3-1.i386.rpm
+libpng-1.0.12-2.i386.rpm
+libstdc++-2.96-110.i386.rpm
+libtermcap-2.0.8-28.i386.rpm
+libtiff-3.5.7-2.i386.rpm
+libtool-libs-1.4.2-7.i386.rpm
+libunicode-0.4-6.i386.rpm
+libuser-0.50.2-1.i386.rpm
+libvorbis-1.0rc3-1.i386.rpm
+libxml-1.8.17-3.i386.rpm
+libxml2-2.4.19-4.i386.rpm
+libxslt-1.0.15-1.i386.rpm
+logrotate-3.6.4-1.i386.rpm
+losetup-2.11n-12.i386.rpm
+m4-1.4.1-7.i386.rpm
+mailcap-2.1.9-2.noarch.rpm
+mailx-8.1.1-22.i386.rpm
+make-3.79.1-8.i386.rpm
+man-1.5j-6.i386.rpm
+man-pages-1.48-2.noarch.rpm
+mktemp-1.5-14.i386.rpm
+mount-2.11n-12.i386.rpm
+mpage-2.5.1-9.i386.rpm
+ncurses-5.2-26.i386.rpm
+netpbm-9.24-3.i386.rpm
+netpbm-progs-9.24-3.i386.rpm
+newt-0.50.35-1.i386.rpm
+nhpf-1.42-2.i386.rpm
+ntsysv-1.3.5-3.i386.rpm
+openldap-2.0.23-4.i386.rpm
+openssh-3.1p1-3.i386.rpm
+openssh-clients-3.1p1-3.i386.rpm
+openssl-0.9.6b-18.i386.rpm
+pam-0.75-32.i386.rpm
+passwd-0.67-1.i386.rpm
+patch-2.5.4-12.i386.rpm
+pcre-3.9-2.i386.rpm
+perl-5.6.1-34.99.6.i386.rpm
+perl-CGI-2.752-34.99.6.i386.rpm
+perl-CPAN-1.59_54-34.99.6.i386.rpm
+perl-DB_File-1.75-34.99.6.i386.rpm
+perl-DateManip-5.40-15.i386.rpm
+perl-Digest-MD5-2.16-15.i386.rpm
+perl-File-MMagic-1.13-14.i386.rpm
+perl-HTML-Parser-3.26-2.i386.rpm
+perl-HTML-Tagset-3.03-14.i386.rpm
+perl-MIME-Base64-2.12-14.i386.rpm
+perl-NDBM_File-1.75-34.99.6.i386.rpm
+perl-NKF-1.71-2.i386.rpm
+perl-Parse-Yapp-1.05-15.i386.rpm
+perl-Storable-1.0.14-15.i386.rpm
+perl-URI-1.17-16.i386.rpm
+perl-XML-Dumper-0.4-12.noarch.rpm
+perl-XML-Encoding-1.01-9.noarch.rpm
+perl-XML-Grove-0.46alpha-11.noarch.rpm
+perl-XML-Parser-2.30-15.i386.rpm
+perl-XML-Twig-2.02-9.noarch.rpm
+perl-libnet-1.0901-17.i386.rpm
+perl-libwww-perl-5.63-9.i386.rpm
+perl-libxml-enno-1.02-15.i386.rpm
+perl-libxml-perl-0.07-14.noarch.rpm
+pnm2ppa-1.04-2.i386.rpm
+popt-1.6.4-7x.18.i386.rpm
+portmap-4.0-41.i386.rpm
+procmail-3.22-5.i386.rpm
+procps-2.0.7-12.i386.rpm
+psmisc-20.2-2.i386.rpm
+pspell-0.12.2-8.i386.rpm
+psutils-1.17-13.i386.rpm
+pwdb-0.61.2-2.i386.rpm
+python-1.5.2-38.i386.rpm
+python-clap-1.0.0-3.noarch.rpm
+python-popt-0.8.8-7.x.2.i386.rpm
+python-xmlrpc-1.5.1-7.x.3.i386.rpm
+python2-2.2-16.i386.rpm
+readline-4.2a-4.i386.rpm
+redhat-release-7.3-1.noarch.rpm
+rootfiles-7.2-1.noarch.rpm
+rpm-4.0.4-7x.18.i386.rpm
+rpm-python-4.0.4-7x.18.i386.rpm
+sed-3.02-11.i386.rpm
+sendmail-8.11.6-15.i386.rpm
+setup-2.5.12-1.noarch.rpm
+sgml-common-0.6.3-9.noarch.rpm
+sh-utils-2.0.11-14.i386.rpm
+shadow-utils-20000902-7.i386.rpm
+slang-1.4.5-2.i386.rpm
+slocate-2.6-1.i386.rpm
+specspo-7.3-4.noarch.rpm
+sysklogd-1.4.1-8.i386.rpm
+tar-1.13.25-4.i386.rpm
+tcl-8.3.3-67.i386.rpm
+tcsh-6.10-6.i386.rpm
+termcap-11.0.1-10.noarch.rpm
+textutils-2.0.21-1.i386.rpm
+time-1.7-16.i386.rpm
+tmpwatch-2.8.3-1.i386.rpm
+umb-scheme-3.2-21.i386.rpm
+unzip-5.50-2.i386.rpm
+usermode-1.53-2.i386.rpm
+utempter-0.5.2-6.i386.rpm
+util-linux-2.11n-12.i386.rpm
+vim-common-6.1-2.i386.rpm
+vim-minimal-6.1-2.i386.rpm
+vixie-cron-3.0.1-64.i386.rpm
+which-2.13-3.i386.rpm
+words-2-18.noarch.rpm
+xinetd-2.3.4-0.8.i386.rpm
+xml-common-0.6.3-9.noarch.rpm
+zip-2.3-12.i386.rpm
+zlib-1.1.3-25.7.i386.rpm
+mingetty-1.00-1.i386.rpm
+iproute-2.4.7-1.i386.rpm
+modutils-2.4.14-3.i386.rpm
+gmp-4.0.1-3.i386.rpm
+expat-1.95.2-2.i386.rpm 
+net-tools-1.60-4.i386.rpm 
diff --git a/util-vserver/distrib/rh8.0-minimum b/util-vserver/distrib/rh8.0-minimum
new file mode 100644 (file)
index 0000000..c96370f
--- /dev/null
@@ -0,0 +1,163 @@
+4Suite-[0-9]*.i386.rpm
+Canna-[0-9]*.i386.rpm
+Canna-libs-[0-9]*.i386.rpm
+Distutils-*.noarch.rpm
+MAKEDEV-[0-9]*.i386.rpm
+PyXML-[0-9]*.i386.rpm
+SysVinit-[0-9]*.i386.rpm
+a2ps-[0-9]*.i386.rpm
+alchemist-[0-9]*.i386.rpm
+anacron-[0-9]*.i386.rpm
+ash-[0-9]*.i386.rpm
+at-[0-9]*.i386.rpm
+audiofile-[0-9]*.i386.rpm
+authconfig-[0-9]*.i386.rpm
+basesystem-*.noarch.rpm
+bash-[0-9]*.i386.rpm
+bdflush-[0-9]*.i386.rpm
+bzip2-[0-9]*.i386.rpm
+bzip2-libs-[0-9]*.i386.rpm
+chkconfig-[0-9]*.i386.rpm
+cpio-[0-9]*.i386.rpm
+cracklib-[0-9]*.i386.rpm
+cracklib-dicts-[0-9]*.i386.rpm
+crontabs-*.noarch.rpm
+cyrus-sasl-[0-9]*.i386.rpm
+cyrus-sasl-md5-[0-9]*.i386.rpm
+db1-[0-9]*.i386.rpm
+db2-[0-9]*.i386.rpm
+db3-[0-9]*.i386.rpm
+db4-[0-9]*.i386.rpm
+libelf-[0-9]*.i386.rpm
+dev-[0-9]*.i386.rpm
+diffutils-[0-9]*.i386.rpm
+dosfstools-[0-9]*.i386.rpm
+e2fsprogs-[0-9]*.i386.rpm
+ed-[0-9]*.i386.rpm
+fam-[0-9]*.i386.rpm
+file-[0-9]*.i386.rpm
+filesystem-[0-9]*.noarch.rpm
+fileutils-[0-9]*.i386.rpm
+findutils-[0-9]*.i386.rpm
+libacl-[0-9]*.i386.rpm
+libgcc-[0-9]*.i386.rpm
+freetype-[0-9]*.i386.rpm
+gawk-[0-9]*.i386.rpm
+gdbm-[0-9]*.i386.rpm
+glib-[0-9]*.i386.rpm
+glib2-[0-9]*.i386.rpm
+glibc-[0-9]*.i386.rpm
+glibc-common-[0-9]*.i386.rpm
+gnupg-[0-9]*.i386.rpm
+grep-[0-9]*.i386.rpm
+groff-[0-9]*.i386.rpm
+groff-perl-[0-9]*.i386.rpm
+gzip-[0-9]*.i386.rpm
+htdig-[0-9]*.i386.rpm
+indexhtml-*.noarch.rpm
+info-[0-9]*.i386.rpm
+initscripts-[0-9]*.i386.rpm
+iputils-[0-9]*.i386.rpm
+less-[0-9]*.i386.rpm
+libcap-[0-9]*.i386.rpm
+libghttp-[0-9]*.i386.rpm
+libjpeg-[0-9]*.i386.rpm
+libmng-[0-9]*.i386.rpm
+libogg-[0-9]*.i386.rpm
+libpng-[0-9]*.i386.rpm
+libstdc++-[0-9]*.i386.rpm
+libtermcap-[0-9]*.i386.rpm
+libtiff-[0-9]*.i386.rpm
+libtool-libs-[0-9]*.i386.rpm
+libunicode-[0-9]*.i386.rpm
+libuser-[0-9]*.i386.rpm
+libvorbis-[0-9]*.i386.rpm
+libxml-[0-9]*.i386.rpm
+libxml2-[0-9]*.i386.rpm
+libxslt-[0-9]*.i386.rpm
+logrotate-[0-9]*.i386.rpm
+losetup-[0-9]*.i386.rpm
+m4-[0-9]*.i386.rpm
+mailcap-*.noarch.rpm
+mailx-[0-9]*.i386.rpm
+make-[0-9]*.i386.rpm
+man-[0-9]*.i386.rpm
+man-pages-*.noarch.rpm
+mktemp-[0-9]*.i386.rpm
+mount-[0-9]*.i386.rpm
+mpage-[0-9]*.i386.rpm
+ncurses-[0-9]*.i386.rpm
+netpbm-[0-9]*.i386.rpm
+newt-[0-9]*.i386.rpm
+nhpf-[0-9]*.i386.rpm
+ntsysv-[0-9]*.i386.rpm
+openldap-[0-9]*.i386.rpm
+openssh-[0-9]*.i386.rpm
+openssh-clients-[0-9]*.i386.rpm
+openssh-server-[0-9]*.i386.rpm
+openssl-[0-9]*.i386.rpm
+pam-[0-9]*.i386.rpm
+passwd-[0-9]*.i386.rpm
+patch-[0-9]*.i386.rpm
+pcre-[0-9]*.i386.rpm
+perl-[0-9]*.i386.rpm
+perl-Filter-[0-9]*.i386.rpm
+krb5-libs-[0-9]*.i386.rpm
+libattr-[0-9]*.i386.rpm
+hesiod-[0-9]*.i386.rpm
+pnm2ppa-[0-9]*.i386.rpm
+popt-[0-9]*.i386.rpm
+portmap-[0-9]*.i386.rpm
+procmail-[0-9]*.i386.rpm
+procps-[0-9]*.i386.rpm
+psmisc-[0-9]*.i386.rpm
+pspell-[0-9]*.i386.rpm
+psutils-[0-9]*.i386.rpm
+pwdb-[0-9]*.i386.rpm
+python-[0-9]*.i386.rpm
+python-clap-*.noarch.rpm
+python-popt-[0-9]*.i386.rpm
+python-xmlrpc-[0-9]*.i386.rpm
+python2-[0-9]*.i386.rpm
+readline-[0-9]*.i386.rpm
+redhat-release-*.noarch.rpm
+rootfiles-*.noarch.rpm
+rpm-[0-9]*.i386.rpm
+sed-[0-9]*.i386.rpm
+sendmail-[0-9]*.i386.rpm
+setup-*.noarch.rpm
+sgml-common-*.noarch.rpm
+sh-utils-[0-9]*.i386.rpm
+shadow-utils-[0-9]*.i386.rpm
+slang-[0-9]*.i386.rpm
+slocate-[0-9]*.i386.rpm
+specspo-*.noarch.rpm
+sysklogd-[0-9]*.i386.rpm
+tar-[0-9]*.i386.rpm
+tcl-[0-9]*.i386.rpm
+tcsh-[0-9]*.i386.rpm
+termcap-*.noarch.rpm
+textutils-[0-9]*.i386.rpm
+time-[0-9]*.i386.rpm
+tmpwatch-[0-9]*.i386.rpm
+umb-scheme-[0-9]*.i386.rpm
+unzip-[0-9]*.i386.rpm
+usermode-[0-9]*.i386.rpm
+utempter-[0-9]*.i386.rpm
+util-linux-[0-9]*.i386.rpm
+vim-common-[0-9]*.i386.rpm
+vim-minimal-[0-9]*.i386.rpm
+vixie-cron-[0-9]*.i386.rpm
+which-[0-9]*.i386.rpm
+words-*.noarch.rpm
+xinetd-[0-9]*.i386.rpm
+xml-common-*.noarch.rpm
+zip-[0-9]*.i386.rpm
+zlib-[0-9]*.i386.rpm
+mingetty-[0-9]*.i386.rpm
+iproute-[0-9]*.i386.rpm
+modutils-[0-9]*.i386.rpm
+gmp-[0-9]*.i386.rpm
+expat-[0-9]*.i386.rpm
+net-tools-[0-9]*.i386.rpm
+
diff --git a/util-vserver/distrib/rh9.0-minimum b/util-vserver/distrib/rh9.0-minimum
new file mode 100644 (file)
index 0000000..c96370f
--- /dev/null
@@ -0,0 +1,163 @@
+4Suite-[0-9]*.i386.rpm
+Canna-[0-9]*.i386.rpm
+Canna-libs-[0-9]*.i386.rpm
+Distutils-*.noarch.rpm
+MAKEDEV-[0-9]*.i386.rpm
+PyXML-[0-9]*.i386.rpm
+SysVinit-[0-9]*.i386.rpm
+a2ps-[0-9]*.i386.rpm
+alchemist-[0-9]*.i386.rpm
+anacron-[0-9]*.i386.rpm
+ash-[0-9]*.i386.rpm
+at-[0-9]*.i386.rpm
+audiofile-[0-9]*.i386.rpm
+authconfig-[0-9]*.i386.rpm
+basesystem-*.noarch.rpm
+bash-[0-9]*.i386.rpm
+bdflush-[0-9]*.i386.rpm
+bzip2-[0-9]*.i386.rpm
+bzip2-libs-[0-9]*.i386.rpm
+chkconfig-[0-9]*.i386.rpm
+cpio-[0-9]*.i386.rpm
+cracklib-[0-9]*.i386.rpm
+cracklib-dicts-[0-9]*.i386.rpm
+crontabs-*.noarch.rpm
+cyrus-sasl-[0-9]*.i386.rpm
+cyrus-sasl-md5-[0-9]*.i386.rpm
+db1-[0-9]*.i386.rpm
+db2-[0-9]*.i386.rpm
+db3-[0-9]*.i386.rpm
+db4-[0-9]*.i386.rpm
+libelf-[0-9]*.i386.rpm
+dev-[0-9]*.i386.rpm
+diffutils-[0-9]*.i386.rpm
+dosfstools-[0-9]*.i386.rpm
+e2fsprogs-[0-9]*.i386.rpm
+ed-[0-9]*.i386.rpm
+fam-[0-9]*.i386.rpm
+file-[0-9]*.i386.rpm
+filesystem-[0-9]*.noarch.rpm
+fileutils-[0-9]*.i386.rpm
+findutils-[0-9]*.i386.rpm
+libacl-[0-9]*.i386.rpm
+libgcc-[0-9]*.i386.rpm
+freetype-[0-9]*.i386.rpm
+gawk-[0-9]*.i386.rpm
+gdbm-[0-9]*.i386.rpm
+glib-[0-9]*.i386.rpm
+glib2-[0-9]*.i386.rpm
+glibc-[0-9]*.i386.rpm
+glibc-common-[0-9]*.i386.rpm
+gnupg-[0-9]*.i386.rpm
+grep-[0-9]*.i386.rpm
+groff-[0-9]*.i386.rpm
+groff-perl-[0-9]*.i386.rpm
+gzip-[0-9]*.i386.rpm
+htdig-[0-9]*.i386.rpm
+indexhtml-*.noarch.rpm
+info-[0-9]*.i386.rpm
+initscripts-[0-9]*.i386.rpm
+iputils-[0-9]*.i386.rpm
+less-[0-9]*.i386.rpm
+libcap-[0-9]*.i386.rpm
+libghttp-[0-9]*.i386.rpm
+libjpeg-[0-9]*.i386.rpm
+libmng-[0-9]*.i386.rpm
+libogg-[0-9]*.i386.rpm
+libpng-[0-9]*.i386.rpm
+libstdc++-[0-9]*.i386.rpm
+libtermcap-[0-9]*.i386.rpm
+libtiff-[0-9]*.i386.rpm
+libtool-libs-[0-9]*.i386.rpm
+libunicode-[0-9]*.i386.rpm
+libuser-[0-9]*.i386.rpm
+libvorbis-[0-9]*.i386.rpm
+libxml-[0-9]*.i386.rpm
+libxml2-[0-9]*.i386.rpm
+libxslt-[0-9]*.i386.rpm
+logrotate-[0-9]*.i386.rpm
+losetup-[0-9]*.i386.rpm
+m4-[0-9]*.i386.rpm
+mailcap-*.noarch.rpm
+mailx-[0-9]*.i386.rpm
+make-[0-9]*.i386.rpm
+man-[0-9]*.i386.rpm
+man-pages-*.noarch.rpm
+mktemp-[0-9]*.i386.rpm
+mount-[0-9]*.i386.rpm
+mpage-[0-9]*.i386.rpm
+ncurses-[0-9]*.i386.rpm
+netpbm-[0-9]*.i386.rpm
+newt-[0-9]*.i386.rpm
+nhpf-[0-9]*.i386.rpm
+ntsysv-[0-9]*.i386.rpm
+openldap-[0-9]*.i386.rpm
+openssh-[0-9]*.i386.rpm
+openssh-clients-[0-9]*.i386.rpm
+openssh-server-[0-9]*.i386.rpm
+openssl-[0-9]*.i386.rpm
+pam-[0-9]*.i386.rpm
+passwd-[0-9]*.i386.rpm
+patch-[0-9]*.i386.rpm
+pcre-[0-9]*.i386.rpm
+perl-[0-9]*.i386.rpm
+perl-Filter-[0-9]*.i386.rpm
+krb5-libs-[0-9]*.i386.rpm
+libattr-[0-9]*.i386.rpm
+hesiod-[0-9]*.i386.rpm
+pnm2ppa-[0-9]*.i386.rpm
+popt-[0-9]*.i386.rpm
+portmap-[0-9]*.i386.rpm
+procmail-[0-9]*.i386.rpm
+procps-[0-9]*.i386.rpm
+psmisc-[0-9]*.i386.rpm
+pspell-[0-9]*.i386.rpm
+psutils-[0-9]*.i386.rpm
+pwdb-[0-9]*.i386.rpm
+python-[0-9]*.i386.rpm
+python-clap-*.noarch.rpm
+python-popt-[0-9]*.i386.rpm
+python-xmlrpc-[0-9]*.i386.rpm
+python2-[0-9]*.i386.rpm
+readline-[0-9]*.i386.rpm
+redhat-release-*.noarch.rpm
+rootfiles-*.noarch.rpm
+rpm-[0-9]*.i386.rpm
+sed-[0-9]*.i386.rpm
+sendmail-[0-9]*.i386.rpm
+setup-*.noarch.rpm
+sgml-common-*.noarch.rpm
+sh-utils-[0-9]*.i386.rpm
+shadow-utils-[0-9]*.i386.rpm
+slang-[0-9]*.i386.rpm
+slocate-[0-9]*.i386.rpm
+specspo-*.noarch.rpm
+sysklogd-[0-9]*.i386.rpm
+tar-[0-9]*.i386.rpm
+tcl-[0-9]*.i386.rpm
+tcsh-[0-9]*.i386.rpm
+termcap-*.noarch.rpm
+textutils-[0-9]*.i386.rpm
+time-[0-9]*.i386.rpm
+tmpwatch-[0-9]*.i386.rpm
+umb-scheme-[0-9]*.i386.rpm
+unzip-[0-9]*.i386.rpm
+usermode-[0-9]*.i386.rpm
+utempter-[0-9]*.i386.rpm
+util-linux-[0-9]*.i386.rpm
+vim-common-[0-9]*.i386.rpm
+vim-minimal-[0-9]*.i386.rpm
+vixie-cron-[0-9]*.i386.rpm
+which-[0-9]*.i386.rpm
+words-*.noarch.rpm
+xinetd-[0-9]*.i386.rpm
+xml-common-*.noarch.rpm
+zip-[0-9]*.i386.rpm
+zlib-[0-9]*.i386.rpm
+mingetty-[0-9]*.i386.rpm
+iproute-[0-9]*.i386.rpm
+modutils-[0-9]*.i386.rpm
+gmp-[0-9]*.i386.rpm
+expat-[0-9]*.i386.rpm
+net-tools-[0-9]*.i386.rpm
+
diff --git a/util-vserver/distrib/sample.conf b/util-vserver/distrib/sample.conf
new file mode 100644 (file)
index 0000000..7e1b7a6
--- /dev/null
@@ -0,0 +1,49 @@
+# Select an unused context (this is optional)
+# The default is to allocate a free context on the fly
+# In general you don't need to force a context
+#S_CONTEXT=
+# Select the IP number assigned to the virtual server
+# This IP must be one IP of the server, either an interface
+# or an IP alias
+IPROOT=1.2.3.4
+# The netmask and broadcast are computed by default from IPROOTDEV
+#IPROOTMASK=
+#IPROOTBCAST=
+# You can define on which device the IP alias will be done
+# The IP alias will be set when the server is started and unset
+# when the server is stopped
+IPROOTDEV=eth0
+# Uncomment the onboot line if you want to enable this
+# virtual server at boot time
+#ONBOOT=yes
+# You can set a different host name for the vserver
+# If empty, the host name of the main server is used
+S_HOSTNAME=somename.somedomain.com
+# You can set a different NIS domain for the vserver
+# If empty, the current on is kept
+# Set it to "none" to have no NIS domain set
+S_DOMAINNAME=
+# You can set the priority level (nice) of all process in the vserver
+# Even root won't be able to raise it
+S_NICE=
+# You can set various flags for the new security context
+# lock: Prevent the vserver from setting new security context
+# sched: Merge scheduler priority of all processes in the vserver
+#        so that it acts a like a single one.
+# nproc: Limit the number of processes in the vserver according to ulimit
+#        (instead of a per user limit, this becomes a per vserver limit)
+# private: No other process can join this security context. Even root
+# Do not forget the quotes around the flags
+S_FLAGS="lock nproc"
+# You can set various ulimit flags and they will be inherited by the
+# vserver. You enter here various command line argument of ulimit
+# ULIMIT="-H -u 200"
+# The example above, combined with the nproc S_FLAGS will limit the
+# vserver to a maximum of 200 processes
+ULIMIT="-H -u 1000"
+# You can set various capabilities. By default, the vserver are run
+# with a limited set, so you can let root run in a vserver and not
+# worry about it. He can't take over the machine. In some cases
+# you can to give a little more capabilities (such as CAP_NET_RAW)
+# S_CAPS="CAP_NET_RAW"
+S_CAPS=""
diff --git a/util-vserver/distrib/sample.sh b/util-vserver/distrib/sample.sh
new file mode 100755 (executable)
index 0000000..8e8c047
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+case $1 in
+pre-start)
+       ;;
+post-start)
+       ;;
+pre-stop)
+       ;;
+post-stop)
+       ;;
+*)
+       echo $0 pre-start
+       echo $0 pre-stop
+       echo $0 post-start
+       echo $0 post-stop
+       ;;
+esac
diff --git a/util-vserver/doc/FAQ.txt b/util-vserver/doc/FAQ.txt
new file mode 100644 (file)
index 0000000..fe4bd67
--- /dev/null
@@ -0,0 +1,20 @@
+
+                               Object not found!
+
+          The  requested URL was not found on this server. If you entered
+          the URL manually please check your spelling and try again.
+
+          If  you  think  this  is  a  server  error,  please contact the
+          [1]webmaster
+
+Error 404
+
+
+    [2]remtk
+    ven 18 jui 2003 11:41:32 EDT
+    Apache/2.0.40 (Red Hat Linux)
+
+Références
+
+   1. mailto:root@localhost
+   2. http://remtk/
diff --git a/util-vserver/doc/Makefile-files b/util-vserver/doc/Makefile-files
new file mode 100644 (file)
index 0000000..2975170
--- /dev/null
@@ -0,0 +1,22 @@
+## $Id$  -*- makefile -*-
+
+## Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+doc_DAT                        =  doc/FAQ.txt \
+                          doc/changelog.txt \
+                          doc/intro.txt
diff --git a/util-vserver/doc/changelog.txt b/util-vserver/doc/changelog.txt
new file mode 100644 (file)
index 0000000..fe4bd67
--- /dev/null
@@ -0,0 +1,20 @@
+
+                               Object not found!
+
+          The  requested URL was not found on this server. If you entered
+          the URL manually please check your spelling and try again.
+
+          If  you  think  this  is  a  server  error,  please contact the
+          [1]webmaster
+
+Error 404
+
+
+    [2]remtk
+    ven 18 jui 2003 11:41:32 EDT
+    Apache/2.0.40 (Red Hat Linux)
+
+Références
+
+   1. mailto:root@localhost
+   2. http://remtk/
diff --git a/util-vserver/doc/intro.txt b/util-vserver/doc/intro.txt
new file mode 100644 (file)
index 0000000..e649a75
--- /dev/null
@@ -0,0 +1,1430 @@
+
+   1. [1]Introduction [new.gif]
+   1.1 [2]Who needs that [new.gif]
+   2. [3]Principles [new.gif]
+   2.1 [4]Non reversible isolation [new.gif]
+   2.2 [5]Isolation areas [new.gif]
+   2.3 [6]New system calls [new.gif]
+   2.4 [7]Limiting super-user: The capabilities system [new.gif]
+   2.5 [8]Enhancing the capability system [new.gif]
+   2.6 [9]Playing with the new system calls [new.gif]
+   2.6.1 [10]Playing with /usr/sbin/chcontext [new.gif]
+   2.6.2 [11]Playing with /usr/sbin/chcontext as root [new.gif]
+   2.6.3 [12]Playing with /usr/sbin/chbind [new.gif]
+   2.6.4 [13]Playing with /usr/sbin/reducecap [new.gif]
+   2.7 [14]Unification [new.gif]
+   3. [15]Applications [new.gif]
+   3.1 [16]Virtual server [new.gif]
+   3.2 [17]Per user fire-wall [new.gif]
+   3.3 [18]Secure server/Intrusion detection [new.gif]
+   3.4 [19]Fail over servers [new.gif]
+   4. [20]Installation [new.gif]
+   4.1 [21]The packages [new.gif]
+   4.2 [22]Setting a virtual server [new.gif]
+   4.3 [23]Basic configuration of the virtual server [new.gif]
+   4.4 [24]Entering the virtual server [new.gif]
+   4.5 [25]Configuring the services [new.gif]
+   4.6 [26]Starting/Stopping the virtual server [new.gif]
+   4.7 [27]Starting/Stopping all the virtual servers [new.gif]
+   4.8 [28]Restarting a virtual server from inside [new.gif]
+   4.9 [29]Executing tasks at vserver start/stop time [new.gif]
+   4.10 [30]Issues [new.gif]
+   4.11 [31]How real is it ? [new.gif]
+   5. [32]Features [new.gif]
+   6. [33]Future directions [new.gif]
+   6.1 [34]User controlled security box [new.gif]
+   6.2 [35]Kernel enhancements [new.gif]
+   6.2.1 [36]Per context disk quota [new.gif]
+   6.2.2 [37]Global limits [new.gif]
+   6.2.3 [38]Scheduler [new.gif]
+   6.2.4 [39]Security issues [new.gif]
+   6.2.4.1 [40]/dev/random [new.gif]
+   6.2.4.2 [41]/dev/pts [new.gif]
+   6.2.4.3 [42]Network devices [new.gif]
+   7. [43]Alternative technologies [new.gif]
+   7.1 [44]Virtual machines [new.gif]
+   7.2 [45]Partitioning [new.gif]
+   7.3 [46]Limitation of those technologies [new.gif]
+   8. [47]Conclusion [new.gif]
+   9. [48]Download [new.gif]
+   10. [49]References [new.gif]
+
+               Virtual private servers and security contexts
+
+   Running independent Linux servers inside a single PC is now possible.
+   They offer many advantages, including higher security, flexibility and
+   cost reduction.
+
+   NEW
+
+Introduction
+
+   Linux computers are getting faster every day. So we should probably
+   end up with less, more powerful servers. Instead we are seeing more
+   and more servers. While there are many reasons for this trend (more
+   services offered), the major issue is more related to security and
+   administrative concerns.
+
+   Is it possible to split a Linux server into virtual ones with as much
+   isolation as possible between each one, looking like real servers, yet
+   sharing some common tasks (monitoring, backup, ups, hardware
+   configuration, ...) ?
+
+   We think so ... NEW
+
+Who needs that
+
+   The short answer is everybody, or everybody managing a server. Here
+   are some applications:
+
+     * Hosting: Complete general purpose hosting (Running many
+       independent servers in one box).
+     * Experimentation: You are toying with a new services and do not
+       want to impact the production services on the same machine.
+     * Education: Each student has its own server with root password.
+     * Personal security box: Run un-trusted applications with complete
+       control over their interaction with the rest of the computer and
+       the network.
+     * Managing several "versions" of the same server/project and turning
+       on/off each version independantly.
+
+   Just think about all the viruses and worms out there, you end up with
+   a big everybody using a computer needs this. :-) NEW
+
+Principles
+
+   NEW
+
+Non reversible isolation
+
+   Unix and Linux have always had the chroot() system call. This call was
+   used to trap a process into a sub-directory. After the system-call,
+   the process is led to believe that the sub-directory is now the root
+   directory. This system call can't be reversed. In fact, the only thing
+   a process can do is trap itself further and further in the file-system
+   (calling chroot() again).
+
+   The strategy is to introduce new system calls trapping the processes
+   in other areas within the server. NEW
+
+Isolation areas
+
+   A virtual server is isolated from the rest of the server in 5 areas:
+
+     * File system
+       The vserver is trapped into a sub-directory of the main server and
+       can't escape. This is done by the standard chroot() system call
+       found on all Unix and Linux boxes.
+     * Processes
+       The vserver can only see the processes in the same security
+       context. Even the root server can't see the processes in vservers,
+       making the root server less "dangerous" to use. A special
+       mechanism (context number 1) exists to view all processes though
+       (Limited to root in the root server).
+     * Networking
+       The vserver is assigned a host name and an IP number. The server
+       can only use this IP number to establish services and client
+       connection. Further, this restriction is transparent.
+     * Super user capabilities
+       The super user running in a vserver has less privileges than the
+       normal Linux root user. For example, it can't reconfigure the
+       networking and many aspect of the system. It can't mount devices,
+       can't access block devices and so on.
+       Roughly. the vserver super-user has full control over all files
+       and processes in the vserver and that's pretty much it.
+     * System V inter process communications
+       Sysv IPC resources are private to each vserver. The security
+       context is used as an extra key to select and assign resources.
+
+   Those facilities are used together to create a runtime environment for
+   virtual servers. But they can be used independently to achieve various
+   goals. NEW
+
+New system calls
+
+   The new system calls, as well as the existing chroot() system call are
+   sharing one common feature: Their effect can't be reversed. Once you
+   have executed one of those system call (chroot, new_s_context,
+   set_ipv4root), you can't get back. This affects the current process
+   and all the child processes. The parent process is not influenced.
+
+     * new_s_context (int ctx)
+       This system call sets a new security context for the current
+       process. It will be inherited by all child processes. The security
+       context is just an id, but the system call makes sure a new unused
+       one is allocated.
+       A process can only see other processes sharing the same security
+       context. When the system boot, the original security context is 0.
+       But this one is not privileged in anyway. Processes member of the
+       security context 0 can only interact (and see) processes member of
+       context 0.
+       This system call isolates the processes space.
+     * Setting the capabilities ceiling
+       This is handle by the new_s_context system call as well. This
+       reduces the ceiling capabilities of the current process. Even
+       setuid sub-process can't grab more capabilities. The capability
+       system found since Linux 2.2 is explained later in this document.
+     * set_ipv4root(unsigned long ip)
+       This system call locks the process (and children) into using a
+       single IP when they communicate and when they installs a service.
+       This system call is a one shot. Once a process have set its IPV4
+       (Internet Protocol Version 4) address to something different from
+       0.0.0.0, it can't change it anymore. Children can't change it
+       either.
+       If a process tries to bind a specific IP number, it will succeed
+       only if this corresponds to the ipv4root (if different from
+       0.0.0.0). If the process bind to any address, it will get the
+       ipv4root.
+       Basically, once a process is locked to a given ipv4root it is
+       forced to use this IP address to establish a service and
+       communicate. The restriction on services is handy: Most service
+       (Web servers, SQL servers) are binding to address 0.0.0.0. With
+       the ipv4root sets to a given IP you can have two virtual servers
+       using the exact same general/vanilla configuration for a given
+       services and running without any conflict.
+       This system calls isolate the IP network space.
+
+   Those system calls are not privileged. Any user may issue them. NEW
+
+Limiting super-user: The capabilities system
+
+   Once you have created a virtual environment where processes have a
+   limited view of the file-system, can't see processes outside of their
+   world and can only use a single IP number, you still must limit the
+   damages those processes can do. The goal is to run virtual
+   environments and provide some root privileges.
+
+   How do you limit those root processes from taking over the system, or
+   even just re-booting it. Enter the capability system. This is not new,
+   but we suspect many people have never heard of it.
+
+   In the old Unix/Linux days, user root (user ID 0) could do things
+   other user ID could not. All over the place in the kernel, system
+   calls were denying access to some resources unless the user ID of the
+   process (effective ID in fact) was 0. Plain zero.
+
+   The only way a process with user ID 0 could loose some privileges was
+   by changing to another ID. Unfortunately this was an all or nothing
+   deal. Enter the capabilities.
+
+   Today, the difference between root and the other users is the
+   capability set. User root has all capabilities and the other users
+   have none. The user ID 0 does not mean anything special anymore. There
+   are around 30 capabilities defined currently. A process may request to
+   loose a capability forever. It won't be able to get it back.
+
+   Capabilities allows a root process to diminish its power. This is
+   exactly what we need to create custom super-user. A super-user process
+   in a virtual server would have some privileges such as binding port
+   below 1024, but would not be able to reconfigure the network or reboot
+   the machine. Check the file /usr/include/linux/capability.h to learn
+   which one are available.
+
+   Note that the new system calls (new_s_context and set_ipv4root) are
+   not controlled by capabilities. They are by nature irreversible. Once
+   a virtual server is trapped in a chroot/s_context/ipv4root box, it
+   can't escape from the parameters of this trap.
+
+   NEW
+
+Enhancing the capability system
+
+   The Linux capability system, is still a work in progress. At some
+   point, we expect to see capabilities attached to programs,
+   generalizing the setuid concept. A setuid program would become a
+   program with all capability granted.
+
+   For now, this is not available. As explained above a process may
+   request to loose capabilities and its child process will be trapped
+   with a smaller capability set.
+
+   Well, ..., it does not work that way. Unfortunately, until
+   capabilities could be assigned to program, we still need a way to get
+   back capabilities even in a child process. So the irreversible logic
+   of the capabilities is kind of short circuited in the kernel.
+
+   To solve this, we have introduced a new per-process capability ceiling
+   (cap_bset). This one represents the capability set inherited by child
+   process, including setuid root child process. Lowering this ceiling is
+   irreversible for a process and all its child.
+
+   This ceiling is handled by the new_s_context system call and the
+   reducecap and chcontext utilities (part of the vserver package).
+
+   Using this, we can setup a virtual server environment where root has
+   less capabilities, so can't reconfigure the main server.
+
+   NEW
+
+Playing with the new system calls
+
+   The vserver package provides 3 utilities to make use of the new system
+   calls. We will describe shortly how they work and provide few example.
+   We invite the reader to try those example, so it has a better feel and
+   trust.
+
+   After re-booting with a kernel implementing the new system calls, and
+   installing the vserver package, one is ready to do experiment. You do
+   not need to be root to test those new utilities. None of them is
+   setuid either. NEW
+
+Playing with /usr/sbin/chcontext
+
+   The /usr/sbin/chcontext utility is used to enter into a new security
+   context. The utility switch the security context and execute a
+   program, specified on the command line. This program is now isolated
+   and can't see the other processes running on the server.
+
+   The experiment with this, start two command windows (xterm), as the
+   same user ID. In each window execute the following commands:
+
+                                   xterm
+
+   Using chcontext: first window
+
+/usr/sbin/chcontext /bin/sh
+pstree
+killall xterm
+exit
+
+   Using chcontext: second window
+   In  the  first window, you start the xterm command (or any command you
+   like).  In  the second window you execute chcontext. This starts a new
+   shell. You execute pstree and see very little. You attempt to kill the
+   xterm  and  you  fail. You exit this shell and you are back seeing all
+   processes.
+
+   Here  is  another example. You switch context and you get a new shell.
+   In  this  shell  you start an xterm. Then you switch context again and
+   start another sub-shell. Now the sub-shell is again isolated.
+
+/usr/sbin/chcontext /bin/sh
+pstree
+xterm &
+pstree
+# Ok now you see your xterm
+/usr/sbin/chcontext /bin/sh
+pstree
+# the xterm is not there, killall will fail
+killall xterm
+# Now we exit the shell
+exit
+pstree
+# the xterm is there
+killall xterm
+# Ok, it is gone
+exit
+# We are back to the initial security context
+
+   Using chcontext several times
+   Processes isolated using chcontext are doubly isolated: They can't see
+   the  other  processes on the server, but the other processes can't see
+   them  either.  The  original  security context (0) when you boot is no
+   better than the other: It sees only process in security context 0.
+
+   While  playing  with  chcontext,  you  will  notice  an exception. The
+   process  1  is  visible  from every security context. It is visible to
+   please  utilities  like  pstree.  But  only root processes in security
+   context 0 are allowed to interact with it. NEW
+
+Playing with /usr/sbin/chcontext as root
+
+   The  new_s_context  system  call  has  a  special  semantic  for  root
+   processes  running  in security context 0 and having the CAP_SYS_ADMIN
+   capability: They can switch to any context they want.
+
+   Normally,  new_s_context allocates a new security context by selecting
+   an  unused one. It walks all processes and find an ID (an integer) not
+   currently in use.
+
+   But  root  in  security  context 0 is allowed to select the context it
+   wants.  This  allow the main server to control the virtual server. The
+   chcontext  utility  has the --ctx option to specify the context ID you
+   want.
+
+   To help manage several virtual server, given that the security context
+   0  can't  see  processes in other security context, it is a good thing
+   root  in  the  main server (security context 0) is allowed to select a
+   specific  context.  Cool.  But  we  also  need  a way to have a global
+   picture  showing  all  processes in all security context. The security
+   context  1  is reserved for this. Security context 1 is allowed to see
+   all  processes  on the server but is not allowed to interact with them
+   (kill them).
+
+   This  special  feature  was  allocated to security context 1 and not 0
+   (the  default when you boot) to isolate virtual servers from the main.
+   This  way,  while  maintaining  services on the main server, you won't
+   kill service in vservers accidentally.
+
+   Here is an example showing those concepts:
+
+# You must be root, running X
+# We start an xterm in another security context
+/usr/sbin/chcontext xterm &
+# We check, there is no xterm running, yet we can
+# see it.
+ps ax | grep xterm
+# Are we running in security context 0
+# We check the s_context line in /proc/self/status
+cat /proc/self/status
+# Ok we in security context 0
+# Try the security context 1
+/usr/sbin/chcontext --ctx 1 ps ax | grep xterm
+# Ok, we see the xterm, we try to kill it
+/usr/sbin/chcontext --ctx 1 killall xterm
+# No, security context 1 can see, but can't kill
+# let's find out in which security context this
+# xterm is running
+/usr/sbin/chcontext --ctx 1 ps ax | grep xterm
+# Ok, this is PID XX. We need the security context
+/usr/sbin/chcontext --ctx 1 cat /proc/XX/status
+# We see the s_context, this is SS.
+# We want to kill this process
+/usr/sbin/chcontext --ctx SS killall xterm
+
+   chcontext as root
+   The  /usr/sbin/vpstree  and /usr/sbin/vps commands are supplied by the
+   vserver package. They simply runs ps and pstree in security context 1.
+   NEW
+
+Playing with /usr/sbin/chbind
+
+   The  chbind  utility  is  used to lock a process and its children into
+   using  a  specific  IP  number.  This  applies  to services and client
+   connection as well. Here are few examples. Execute them as root:
+
+# httpd is running
+netstat -atn | grep ":80 "
+# We see a line like this
+# tcp    0   0 0.0.0.0:80    0.0.0.0:*      LISTEN
+# Now we restart httpd, but we lock it so it
+# uses only the main IP of eth0
+/usr/sbin/chbind --ip eth0 /etc/rc.d/init.d/httpd restart
+netstat -atn | grep ":80 "
+# Now we see a line like
+# tcp    0   192.168.1.1:80    0.0.0.0:*      LISTEN
+# httpd.conf was not changed.
+# Now, restart it normally
+/etc/rc.d/init.d/httpd restart
+# Now we experiment with client socket
+# Log using telnet
+telnet localhost
+# Once logged in
+netstat -atn | grep ":23 "
+# You should see a line showing a connection from
+# 127.0.0.1 to 127.0.0.1 like this
+# tcp  0  0 127.0.0.1:23   127.0.0.1:32881     ESTABLISHED
+exit
+# Now we do the telnet again, bug forcing it to select a specific IP
+/usr/sbin/chbind --ip eth0 telnet localhost
+# Log in and then execute
+netstat -atn | grep ":23 "
+# You will get something like
+# tcp  0  0 127.0.0.1:23   192.168.3.9:32883   ESTABLISHED
+
+   Using /usr/sbin/chbind
+   NEW
+
+Playing with /usr/sbin/reducecap
+
+   The  reducecap  utility  is  used to lower the capability ceiling of a
+   process  and  child process. Even setuid program won't be able to grab
+   more capabilities.
+
+# You are not root now
+# What is the current capability ceiling
+cat /proc/self/status
+# The capBset line presents mostly 1s.
+/usr/sbin/reducecap --secure /bin/sh
+cat /proc/self/status
+# The capBset now shows many more 0s.
+# The capEff shows all 0s, you have no privilege now
+# We su to root
+su
+cat /proc/self/status
+# capEff is much better now, but there are still many 0s
+# Now we try to see if we are really root
+tail /var/log/messages
+# So far so good, we see the content
+/sbin/ifconfig eth0
+/sbin/ifconfig eth0 down
+# No way, we can't configure the interface. In fact
+# we have lost most privilege normally assigned to root
+exit
+
+   Using /usr/sbin/reducecap
+   NEW
+
+Unification
+
+   Installing a virtual private server copies a linux installation inside
+   a  sub-directory.  It  is  a  linux inside linux. If you intend to run
+   several  vservers  on the same box (which you will certainly do :-) ),
+   you  will end up using a lot of disk space needlessly: Each vserver is
+   made  up  hundreds of megabytes of the same stuff. This is a big waste
+   of disk space.
+
+   A  solution  is  to  use  hard links to connect together common files.
+   Using  the  package information, we can tell which packages are shared
+   between  various  vservers,  which  files  are configuration files and
+   which   are  not  (binaries,  libraries,  resource  files,  ...).  Non
+   configuration  files  may  be  linked together saving a huge amount of
+   disk space: A 2 GIG rh7.2 installation shrinks to 38megs.
+
+   Using  hard  links  is  cool,  but  may  be  a problem. If one vserver
+   overwrite  one file, say /bin/ls, then every vserver will inherit that
+   change.  Not  fun!  The  solution is to set the immutable bit on every
+   linked  file.  A  file  with  such a bit on can't be modified, even by
+   root.  The  only  way  to  modify it is to turn off the bit first. But
+   within a vserver environment, even root is not allowed to perform this
+   task.  So  linked  file,  turned  immutable, are now safe: They can be
+   shared between vservers without side effects: Cool!
+
+   Well,  there is still another side effect. All vservers are now locked
+   with  the  same files. We are saving a lot of disk space, but we pay a
+   very heavy price for that: Vservers can't evolve independantly.
+
+   A  solution  was  found.  A  new bit call immutable-linkage-invert was
+   added.  Combined  with  the immutable bit, a file may not be modified,
+   but   may   be   unlinked.   Unlinking  a  file  in  Unix/Linux  means
+   disconnecting  the  name  from the data and removing the name from the
+   directory. If the data is still referenced by one or more vservers, it
+   continue to exist on disk. So doing "rm /bin/ls" on a vserver, removes
+   the  file  /bin/ls  for  that  vserver and that's all. If all vservers
+   perform this task, then /bin/ls (the data) will be forgotten completly
+   and the disk space will be recovered.
+
+   Using  this  trick,  a  vserver gets back its independance. It becomes
+   possible  to  update  packages  by  using  the unlink/update sequence:
+   Unlink  /bin/ls  first  and  then  put  a  new copy in place. Luckily,
+   package manager works this way.
+
+   To keep this story short (probably too late :-) ), a unified vserver:
+     * Uses little disk space
+     * Can't interfere with other vservers by changing one of its file.
+     * Can   perform  package  update/deletion  normally  using  standard
+       practice.
+
+   NEW
+
+Applications
+
+   NEW
+
+Virtual server
+
+   The  first  goal  of this project is to create virtual servers sharing
+   the same machine. A virtual server operate like a normal Linux server.
+   It runs normal services such as telnet, mail servers, web servers, SQL
+   servers. In most cases, the services run using standard configuration:
+   The services are running unaware of the virtual server concept.
+
+   Normal  system  administration  is performed with ordinary admin tool.
+   Virtual servers have users account and a root account.
+
+   Packages are installed using standard packages (RPMs for example).
+
+   There  are  few  exceptions. Some configuration can't be done inside a
+   virtual  server. Notably the network configuration and the file-system
+   (mount/umount) can't be performed from a virtual server.
+
+   NEW
+
+Per user fire-wall
+
+   The  set_ipv4root()  system  call  may  be  used  to differentiate the
+   various users running on an application server. If you want to setup a
+   fire-wall  limiting what each user is doing, you have to assign one IP
+   per user, even if they are running application on the same server. The
+   chbind utility may be used to achieve that. NEW
+
+Secure server/Intrusion detection
+
+   While it can be interesting to run several virtual servers in one box,
+   there  is  one  concept  potentially  more generally useful. Imagine a
+   physical  server  running a single virtual server. The goal is isolate
+   the  main  environment  from any service, any network. You boot in the
+   main  environment,  start  very  few services and then continue in the
+   virtual server. The service in the main environment could be
+
+     * Un-reachable from the network.
+     * The  system  log  daemon. While virtual server could log messages,
+       they  would  be unable to change/erase the logs. So even a cracked
+       virtual server would not be able the edit the log.
+     * Some  intrusion detection facilities, potentially spying the state
+       of the virtual server. For example tripwire could run there and it
+       would be impossible to circumvent its operation or trick it.
+
+   NEW
+
+Fail over servers
+
+   One  key  feature  of  a  virtual  server is the independence from the
+   actual  hardware.  Most hardware issues are irrelevant for the virtual
+   server installation. For example:
+
+     * Disk  layout,  partitions  and  the  /etc/fstab configuration. The
+       virtual server has a dummy /etc/fstab.
+     * Network devices.
+     * Processor type, number of processor (kernel selection).
+
+   The  main  server  acts as a host and takes care of all those details.
+   The  virtual  server  is just a client and ignores all the details. As
+   such, the client can be moved to another physical server will very few
+   manipulations.  For  example,  to  move the virtual server v1 from one
+   physical one computer to another, you do
+
+     * Turn it off
+       /usr/sbin/vserver v1 stop
+     * Copy the file /etc/vservers/v1.conf to the new server.
+     * Copy all files in /vservers/v1 to the new server
+     * On the new server, start the vserver v1
+       /usr/sbin/vserver v1 start
+
+   As you see, there is no adjustment to do:
+
+     * No user account merging.
+     * No hardware configuration to fix.
+
+   This  opens  the  door  to  fail over servers. Imagine a backup server
+   having  a  copy  of many virtual servers. It can take over their tasks
+   with a single command. Various options exists for managing this backup
+   server:
+
+     * rsync to synchronize the data.
+     * Network block devices to synchronize the data in real time.
+     * Sharing the installation over a SAN (storage area network).
+     * Heartbeat for automatic monitoring/fail over.
+
+   NEW
+
+Installation
+
+   NEW
+
+The packages
+
+     * The kernel
+       We  are  supplying a patched 2.4.20 kernel. You will find [50]here
+       the kernel, the .config and the patch.
+       To  install  the  kernel,  just  untar it. This will create a file
+       /boot/kernel-2.4.20ctx-17  (ctx stands for security context) and a
+       directory /lib/modules/2.4.20ctx-17.
+       Then,  you  need  to  update your boot loader. For lilo, you add a
+       section like this at the end of the file /etc/lilo.conf
+
+
+image=/boot/vmlinuz-2.4.20ctx-17
+        label=linux2.4.20ctx-17
+        read-only
+        root=current
+
+       lilo.conf section to add
+       Change   the  /dev/XXXX  to  your  root  partition.  Then  execute
+       /sbin/lilo.
+       Reboot  and  select  the  proper  kernel.  This  kernel  is  fully
+       compatible  with  a normal 2.4.20 and will perform without any new
+       configuration.  Note  that  the supplied kernel does not carry all
+       the features and modules found on the various distributions.
+     * The vserver package
+       This  package  provides the various utilities to make use of those
+       new system calls. The package also provides a complete solution to
+       implement virtual servers. We describe the major components here.
+          + /usr/sbin/chcontext
+            This is the utility to request a new security context. It can
+            be  used to lower the capability ceiling. Execute it to learn
+            more.
+          + /usr/sbin/chbind
+            This  is the utility to select one IP number and assign it to
+            a process and its children.
+          + /usr/sbin/newvserver (in vserver-admin)
+            Front-end to help create new virtual servers.
+          + /usr/sbin/reducecap
+            This  utility  is  used  to  lower  the capability ceiling of
+            children processes.
+          + /usr/sbin/vdu
+            A  trimmed  down  "du" command reporting space usage of files
+            with  a  single link. Useful to tell how much space a unified
+            vserver is using.
+          + /usr/sbin/vkill
+            Locate  the security context associated with a process, enter
+            it  and  kill  the  process.  Generally  used  after you have
+            located a process with vtop, vpstree or vps.
+          + /usr/sbin/vps
+            Execute the ps command in security context 1 so all processes
+            in  all  vservers are shown. The security context and vserver
+            name are mapped inside the report.
+          + /usr/sbin/vpstree
+            Execute  the  pstree  command  in  security  context 1 so all
+            processes in all vservers are shown.
+          + /usr/sbin/vrpm
+            Apply  an  rpm  command  in several (or all) vservers. Useful
+            when you wish to update many vservers with the same package.
+        /usr/sbin/vrpm server1 server2 -- -Uvh /tmp/*.rpm
+        /usr/sbin/vrpm ALL -- -Uvh /tmp/*.rpm
+            After  updating  many  packages in different vservers you may
+            want  to  re-unify  them  to recover disk space (and increase
+            cache effectivity). You can do this using the vunify command,
+            or  simply  by  using the --unify option to the vrpm command.
+            After  performing  the  rpm  updates,  vrpm  will trigger the
+            vunify utility on the vservers for the updated packages.
+        /usr/sbin/vrpm --unify server1 server2 -- -Uvh /tmp/*.rpm
+          + /usr/sbin/vserver
+            This  is  the  wrapper  to start, stop and administer virtual
+            servers.
+          + /usr/sbin/vserver-stat
+            Produce  a  small  report  showing  the  activity  in  active
+            security  context.  The report presents the number of process
+            in  each  active  security context as well as the name of the
+            vserver associated with this context.
+          + /usr/sbin/vtop
+            Execute  the  top  command  in  security  context  1  so  all
+            processes in all vservers are shown.
+          + /etc/rc.d/init.d/vservers
+            This  is  an init script used to start all virtual servers at
+            boot  time  and  stop  them  at  shutdown  time. Only virtual
+            servers  with  ONBOOT=yes  are  started  at  boot  time.  All
+            vservers are stopped at shutdown time.
+          + /etc/rc.d/init.d/rebootmgr
+            This  is a daemon listening to requests from virtual servers.
+            It   can  either  restart  or  stop  a  virtual  server.  The
+            /sbin/vreboot  and  /sbin/vhalt  utilities  are  used to send
+            request to the reboot manager.
+          + /sbin/vreboot and /sbin/vhalt
+            Those  utilities  are  copied  in  each  virtual server. They
+            connect  to  the  reboot manager (rebootmgr) server using the
+            /dev/reboot  Unix  domain socket and request either a restart
+            or  a  stop  of  the virtual server. The reboot manager issue
+            either    a    "/usr/sbin/vserver    vserver    restart"   or
+            "/usr/sbin/vserver  vserver  stop"  command.  This allows the
+            virtual server administrator to test if all automatic service
+            are properly restarted at boot time.
+          + /usr/lib/vserver/vdu
+            This is a limited clone of the du command. It skips file with
+            more  than one link. It is used to evaluate the disk usage of
+            an  unified  vserver.  Using  the  normal du for this task is
+            misleading since it will count all unified files.
+
+   NEW
+
+Setting a virtual server
+
+   To  set  a virtual server, you need to copy in a sub-directory a Linux
+   installation. One way to achieve that is to copy some parts of the the
+   current  server  by  issuing the command vserver XX build, where XX is
+   the  name of the virtual server (pick one). This basically does (Well,
+   it does a little more than that, but this give you an idea):
+
+mkdir /vservers/XX
+cd /vservers/XX
+cp -ax /sbin /bin /etc /usr /var /dev /lib .
+mkdir proc tmp home
+chmod 1777 tmp
+
+   Building a virtual server
+
+   This  is normally done using the command /usr/sbin/newvserver. This is
+   a  text mode/graphical front-end allowing to setup the vserver runtime
+   and configure it. NEW
+
+Basic configuration of the virtual server
+
+   A  virtual  private server has a few settings. They are defined in the
+   file /etc/vservers/XX.conf where XX is the name of the virtual server.
+   This  is  a  simple  script  like  configuration. Here are the various
+   parameters:
+
+     * IPROOT
+       In  general,  each  virtual server is tied to one IP using the new
+       set_ipv4root  system  call.  This  way several servers may run the
+       same  services  without  conflict.  Enter the IP number (a name is
+       also valid if defined in the DNS).
+       Since  kernel  ctx-12, you can assign more than one IP number to a
+       vserver.  Enter  them  separated  by  spaces  and  don't forget to
+       enclose them with quotes.
+       Bu default, all IPs are configured as an IP alias on the IPROOTDEV
+       device  (if defined). If you want to attach the various IP numbers
+       to  different  devices,  specify  the device as a prefix to the IP
+       number like this:
+
+IPROOT="eth0:192.168.1.2 eth1:192.168.3.1 192.168.1.4"
+
+       IPROOT using multiple devices
+       In  the  example above, the IP 192.168.1.4 will be installed as an
+       IP alias on the device IPROOTDEV.
+       Use  "IPROOT=0.0.0.0"  or  "IPROOT=" if you do not want to tie the
+       vserver  at all. It will be allowed to use any IP available on the
+       server.
+     * IPROOTDEV
+       This  is  the  network device use to setup the IP alias defined by
+       IPROOT.  This  is generally eth0. If you define this variable, the
+       IP  alias will be configured when you start the virtual server and
+       un-configure when you stop it.
+     * IPROOTMASK
+       Netmask  used  to  setup  the  IP  alias.  Uses the netmask of the
+       IPROOTDEV device by default. Seldom used.
+       If  you have several IPs on one vserver and want to have different
+       netmask for each, use the following syntax:
+
+IPROOT="eth0:192.168.1.2 eth1:192.168.3.1/255.255.255.192"
+
+       IPROOT using different netmask
+       192.168.1.2  will  use the netmask of eth0, while 192.168.3.1 will
+       use the specified netmask: 255.255.255.192.
+     * IPROOTBCAST
+       Broadcast  address  used to setup the IP alias. Uses the broadcast
+       of the IPROOTDEV device by default. Seldom used.
+     * ONBOOT
+       The vserver package supplies the vservers service. This service is
+       installed  in  the  main  server. It is used to start and stop the
+       virtual server at boot and shutdown time.
+       Virtual  server  with  ONBOOT=yes  will  be  started  and  stopped
+       properly like any other services of the main server.
+       Once a virtual server is properly configured, it is a good idea to
+       set this parameter to yes.
+     * S_CAPS
+       You  enter  here  the  various capability you want to grant to the
+       vserver. By default, a vserver is left with much less capabilities
+       than the root server. For example, a vserver is not allowed to use
+       raw  socket. This explains why the ping command fails. S_CAPS lets
+       you  enumerate  the  capability  you  want to keep in the vserver.
+       CAP_NET_RAW will give back ping ability for example.
+     * S_CONTEXT
+       This  is  optional. In general the security context ID is selected
+       by  the kernel. An unused one is selected. If you select an ID (an
+       integer  greater than 1), make sure you select a different one for
+       each  server. Again, in most cases, you do not need to select one.
+       Leave the line commented.
+     * S_DOMAINNAME
+       A virtual server may have a different NIS domainname than the main
+       server. You set it here. If you leave the field empty, the vserver
+       will  inherit the same NIS domain as the root server. Enter "none"
+       to reset the NIS domain name for this vserver.
+     * S_HOSTNAME
+       Many  services  (Apache  for  one) use the host name to setup some
+       defaults. A virtual server may have a different host name than the
+       main server. It is a good idea to fill this line.
+     * S_NICE
+       The  is  an  optional  priority  level.  It  is an integer ranging
+       between  from -20 to 19. Well it is the nice level in fact, so -20
+       means  the  highest  priority  and 19 the lowest (the highest nice
+       level). All processes in the virtual server will be locked to this
+       level (or higher niceness).
+       Event root is locked and can't get more priority.
+       Note  that  this  has  limited  usefulness.  The  kernel  does not
+       differentiate  processes running in different security context for
+       scheduling  (for  now  :-)  ).  This  means that a virtual servers
+       running many low priority processes may nevertheless claim a large
+       share of CPU.
+     * S_FLAGS
+       This is used to set various flags. Here are the supported flags:
+          + lock
+            This  flags  prevents  the  vserver from setting new security
+            contexts.
+          + sched
+            It  kind  of  unifies  the  processes  in  a  vserver  from a
+            scheduler  view  point.  All processes are weighted as single
+            one when compared to other processes in the real server. This
+            prevents a vserver from taking to much CPU resources.
+          + nproc
+            Make the ulimit maximum user process global to the vserver.
+          + private
+            Once  set on a vserver security context, no other process can
+            enter  it.  Even  the  root  server  is  unable  to enter the
+            context.  It  can see the process list using security context
+            1, but can't signal or trace the process.
+          + fakeinit
+            This  assigned  the  current  process  so  it  works like the
+            process  number  1. Using this trick, a normal /sbin/init may
+            be  run  in a vserver. The /usr/sbin/vserver command will use
+            /sbin/init to start and stop a vserver. A properly configured
+            /etc/inittab is needed though.
+               o Processes  loosing  their  parent  are  reparent to this
+                 process.
+               o getppid()  done by child process of this process returns
+                 1.
+               o getpid() done by this process returns 1.
+               o This  process is not shown in /proc since process number
+                 1 is always shown.
+               o An  "initpid"  entry  is  available in /proc/*/status to
+                 tell which process is the fake init process.
+     * ULIMIT
+       This contains the command line option to the ulimit shell command.
+       You enter here whatever parameters accepted by ulimit. Here is the
+       default when you create a new vserver:
+
+ULIMIT="-H -u 1000"
+
+       Default vserver ulimit
+       Normally  ulimit  settings  only  affects  users independantly. So
+       limiting   a   vserver   this   way,  limit  each  user  processes
+       independantly  in  the vserver. Using special flags in the S_FLAGS
+       option,  you can make those ulimit settings global to the vserver.
+       The  example  above used with the nproc parameter make the maximum
+       number  of  process  global.  In  this  case,  a  maximum  of 1000
+       processes is available to all users in the vserver.
+
+   NEW
+
+Entering the virtual server
+
+   It  is possible to enter a virtual server context from the main server
+   just  by executing /usr/sbin/vserver XX enter (where XX is the virtual
+   server name).
+
+   This   creates   a   shell.   From  there  you  can  execute  anything
+   administrative you normally do on a Linux server.
+
+   NEW
+
+Configuring the services
+
+   The  virtual  server  can  run  pretty  much any services. Many pseudo
+   services,  such  as  network  configuration are useless (the server is
+   already configured). After building the environment, enter it (without
+   starting  the  virtual  server)  using the vserver name enter command.
+   Then  using a tool like Linuxconf (control/control service activity) ,
+   or ntsysv, browse all service and keep only the needed ones.
+
+   So  after building the server, you enter it and you select the service
+   you  need  in that server. Many services such as network, and apmd are
+   either  useless  or  won't run at all in the virtual server. They will
+   fail to start completely. NEW
+
+Starting/Stopping the virtual server
+
+   Virtual  server  with  ONBOOT=yes will be started and stopped like any
+   other  services  of  the  main  server.  But  you can stop and start a
+   virtual  server  at  any  time.  Starting  a  server  means  that  all
+   configured  service  will  be  started.  Stopping  it  means  that all
+   configured  services  will  be  stopped and then all remaining process
+   will be killed.
+
+   Oddly,  starting  a  virtual  server  does  not mean much. There is no
+   overhead.  No  monitoring  process  or  proxy  or emulator. Starting a
+   virtual server with 4 services is the same as running those 4 services
+   in  the  main  server, at least performance wise (the service inside a
+   virtual server are locked inside the security context).
+
+   The following commands may be used to control a virtual server:
+
+     * /usr/sbin/vserver server start
+     * /usr/sbin/vserver server stop
+     * /usr/sbin/vserver server restart
+     * /usr/sbin/vserver server running
+     * /usr/sbin/vserver server enter
+     * /usr/sbin/vserver server exec some commands ...
+     * /usr/sbin/vserver server suexec user some commands ...
+     * /usr/sbin/vserver        server        service        service-name
+       start/stop/restart/status
+     * /usr/sbin/vserver server status
+
+   The  running  command prints if there are any processes running in the
+   virtual server context.
+
+   Please note
+
+   The  processes running in a virtual server are invisible from the main
+   server.  The  opposite  is  true. This is very important. Managing the
+   main  server  must  not cause problems to the various virtual servers.
+   For  example, doing killall httpd will kill all the httpd processes in
+   the current context ( the main server or a virtual one).
+
+   NEW
+
+Starting/Stopping all the virtual servers
+
+   The sysv script /etc/rc.d/init.d/vserver is used to start and stop the
+   virtual  server  at boot and shutdown time. It may be used at any time
+   to operate all virtual servers. The following commands are supported:
+
+     * /etc/rc.d/init.d/vservers start
+     * /etc/rc.d/init.d/vservers stop
+     * /etc/rc.d/init.d/vservers restart
+     * /etc/rc.d/init.d/vservers status
+
+   The status command reports the running status of every virtual server.
+   NEW
+
+Restarting a virtual server from inside
+
+   A  virtual  server  administrator is not allowed to reboot the machine
+   (the  kernel).  But  it  is  useful to restart his virtual server from
+   scratch.  This  allow  him  to make sure all the services are properly
+   configured to start at boot time.
+
+   The  /sbin/vreboot  and  /sbin/vhalt  utilities  are installed in each
+   virtual server so they can request a restart or stop.
+
+   The rebootmgr service must be enabled in the main server.
+
+   NEW
+
+Executing tasks at vserver start/stop time
+
+   You can setup a script called /etc/vservers/XX.sh where XX is the name
+   of the virtual server. This script will be called four time:
+
+     * Before starting the vserver
+     * After starting it.
+     * Before stopping it.
+     * After stopping it.
+
+   You generally perform tasks such as mounting file system (mapping some
+   directory in the vserver root using "mount --bind").
+
+   Here  is  an  example where you map the /home directory as the vserver
+   /home directory.
+
+#!/bin/sh
+case $1 in
+pre-start)
+        mount --bind /home /vservers/$2/home
+        ;;
+post-start)
+        ;;
+pre-stop)
+        ;;
+post-stop)
+        umount /vservers/$2/home
+        ;;
+esac
+
+   /etc/vservers/XX.sh
+   NEW
+
+Issues
+
+   There are some common problem you may encounter. Here they are.
+
+     * The  main  server  is not tied (by default) to any ipv4root. So if
+       the main server has already some service running they are probably
+       binding  some  UDP  or TCP ports using the address 0.0.0.0. Once a
+       process  has  bound  a  service  with the address 0.0.0.0 (see the
+       LISTEN  lines  when  executing the "netstat -a" command), no other
+       process can bind the same port, even with a specific address.
+       The solution is to start the services of the main server using the
+       chbind utility to trap them in one ipv4root. For example
+
+/sbin/chbind --ip eth0 /etc/rc.d/init.d/httpd start
+
+       Assigning on IP to a service
+       will limit Apache to the IP address of the eth0 interface. without
+       configuration  changes (in httpd.conf). It is probably a good idea
+       to  start  the  following  services  in  the main server this way,
+       because they will be run by virtual servers as well.
+
+     * httpd
+     * sshd
+     * xinetd
+
+   To  ease  this,  the  vserver package supplies the following services:
+   v_httpd,   v_sshd,  v_smb  and  v_xinetd.  Disable  the  corresponding
+   services  and  enable the v_ services and you will lock those services
+   on a single IP.
+
+     Cleanup rc.local. This is probably not doing anything useful.
+
+   NEW
+
+How real is it ?
+
+   The  project  is  new.  So  far,  experiments  have  shown very little
+   restrictions.  Service  works  the  same in a virtual server. Further,
+   performance  is  the  same.  And  there  is  a high level of isolation
+   between the various virtual servers and the main server. NEW
+
+Features
+
+   There  are various tricks one can use to make the virtual servers more
+   secure.
+
+     * Putting  a  fire-wall  on the box and limiting access to a virtual
+       services from another one.
+     * Using  port  redirection  to allow one virtual server to logically
+       bind several IPs. One virtual server could run several web virtual
+       host this way.
+
+   NEW
+
+Future directions
+
+   NEW
+
+User controlled security box
+
+   By  combining  the  capabilities,  the s_context, the ipv4root and the
+   AclFS  (component of the [51]virtualfs package), we can produce a user
+   level  tool  allowing controlled access to the user own resources. For
+   example  the  user  may download any program he wants and execute them
+   under  control.  Whenever  the  program  tries to access something not
+   specified by the user, a popup is presented and the user may choose to
+   terminate the program or allow the access.
+
+   NEW
+
+Kernel enhancements
+
+   We  expect  to  see  some wider usage of the virtual servers. As usage
+   grow, we expect to see needs for more control. Here are some ideas.
+
+   NEW
+
+Per context disk quota
+
+   If  one  installs  virtual  servers  and  grant access to less trusted
+   users,  he  may  want  to  limit  the disk space used. Since a virtual
+   server may create new user accounts and run processes with any user ID
+   it wants, the current kernel disk quota is not powerful enough. First,
+   it  can't  differentiate between user ID 100 in one virtual server and
+   user ID 100 in another one.
+
+   Further,  the  main  administrator  may  want  to  control  disk space
+   allocated  to  the  virtual  server  on  a  server  per  server basis,
+   unrelated to the various user ID in use in those virtual servers.
+
+   The  kernel  has  already  user  and group disk quota. Adding security
+   context disk quota should be easily done.
+
+   To differentiate between user IDs in virtual servers, the kernel could
+   coin  together the security context and the user id to create a unique
+   ID.  The  kernel  2.4  now  supports 32 user ID, so combining security
+   context and user ID in a single 32 bits number should be acceptable.
+
+   NEW
+
+Global limits
+
+   The  kernel  has  supports  for  user  limit  (memory,  processes file
+   handles). With virtual server, we may want to limit the resources used
+   by  all processes in the virtual server. The security context would be
+   used  as  the  key here. The following resources could be limited on a
+   security context basis (as opposed to user or process basis)
+
+     * Memory used
+     * Processes number
+       (Done:  This  is  now  supported with the nproc flag in the kernel
+       2.4.16ctx-4. By default a new vserver is limited to 1000 processes
+       maximum, configurable).
+     * File handles
+
+   NEW
+
+Scheduler
+
+   The  scheduler may become security context aware. It could potentially
+   use  this  to  provide  some  fairness  and  control priority based on
+   context.  Currently  the  scheduler  is  process oriented and does not
+   group  process  together  to  qualify their priorities. For example, a
+   user  running  10  compilations  will  get  more CPU than another user
+   running a single compilation.
+
+   Currently,  it  is possible to raise the nice (lower priority) for all
+   processes  in  a  virtual  server.  This can't be reversed, so you are
+   setting  an  upper  limit on priority (Just set the S_NICE variable in
+   the  vserver configuration file). Note that a virtual server may still
+   start  many low priority processes and this can grab significant share
+   of  the  CPU.  A global per security context might be needed to really
+   provide more control and fairness between the various virtual servers.
+
+   Done:  The  sched security context flag group all process in a vserver
+   so their priority is kind of unified. If you have 50 processes running
+   full  speed in one vserver, they will take as much CPU resource than a
+   single process in the root server. A vserver can't starve the other...
+   NEW
+
+Security issues
+
+   The  current kernel + patch provides a fair level of isolation between
+   the  virtual  servers.  User  root can't take over the system: He sees
+   only  his  processes,  has  only access to his area of the file system
+   (chroot)  and  can't  reconfigure  the  kernel.  Yet  there  are  some
+   potential  problems. They are fixable. As usage grows, we will know if
+   they are real problems. Comments are welcome:
+
+   NEW
+
+/dev/random
+
+   Writing to /dev/random is not limited by any capability. Any root user
+   (virtual included) is allowed to write there. Is this a problem ?
+
+   (kernel expert think it is ok) NEW
+
+/dev/pts
+
+   /dev/pts  is  a  virtual  file-system  used to allocate pseudo-tty. It
+   presents  all  the  pseudo-tty  in  use  on  the server (including all
+   virtual  server).  User  root  is  allowed  to  read  and write to any
+   pseudo-tty, potentially causing problems on other vservers.
+
+   Starting  with  the ctx-6 patch, /dev/pts is virtualised. Although the
+   file  numbers are allocated from a single pool, a vserver only see the
+   pseudo-tty it owns. NEW
+
+Network devices
+
+   Anyone  can list the network devices configurations. This may inform a
+   virtual  user  that another vserver is on the same physical server. By
+   using  as  much resources as possible in his own vservers, a malicious
+   user  could  slow down the other server. Modification to the scheduler
+   explained above could stop this.
+
+   Starting  with  the  ctx-6  patch,  a  vserver  only  see  the  device
+   corresponding to its IP number. NEW
+
+Alternative technologies
+
+   Using  virtual  servers may be a cost effective alternative to several
+   independent  real  servers. You get the administrative independence of
+   independent servers, but share some costs including operation costs.
+
+   Other  technologies  exist  offering  some of the advantages talked in
+   this  document  as  well  as  other. Two technologies are available on
+   various hardware platform: Virtual machines and partitioning, NEW
+
+Virtual machines
+
+   This  has  been available for mainframes for a while now. You can boot
+   several  different  OS at once on the same server. This is mainly used
+   to  isolate environments. For example, you can install the new version
+   of  an  OS  on  the  same server, even while the server is running the
+   current version. This allows you to test and do a roll-out gracefully.
+
+   The advantages of virtual machines are:
+
+     * Total  flexibility.  You  can  run many different OS and different
+       version of the same OS, all at once.
+     * Robustness.  You  have  total  isolation. One OS may crash without
+       affecting the other.
+     * Resource management. You can effectively limit the resources taken
+       by one OS.
+     * Hardware  Independence.  The  client  OS  is  using  virtual disks
+       provided by the host OS.
+
+   This  technology  is  not  directly  available  on  PCs. The Intel x86
+   architecture  does  not  support visualization natively. Some products
+   nevertheless  have appeared and provide this. You can run Linux inside
+   Linux,  or this other OS (Which BTW has a logo showing a window flying
+   in pieces, which quite frankly tells everything about it).
+
+   The  solutions  available  on  PCs carry most of the advantages of the
+   virtual machines found on mainframe, except for performance. You can't
+   run  that  many virtual Linux's using this technology and expect it to
+   fly.  One  example  of  this  technology is [52]vmware, which is quite
+   useful, especially if you must run this other OS... vmware may be used
+   to  run Linux inside Linux, even test Linux installation while running
+   linux... NEW
+
+Partitioning
+
+   Partitioning  (domains  ?)  is a way to split the resources of a large
+   server  so  you  end up with independent servers. For example, you can
+   take  a  20  CPUs server and create 3 servers, two with 4 CPUs and one
+   with  12.  You  can  very easily re-assign CPUs to servers in case you
+   need more for a given tasks.
+
+   This technology provides full Independence, but much less flexibility.
+   If  your  12  CPUs  server  is  not working much, the 4 CPUs one can't
+   borrow some CPUs for 5 minutes. NEW
+
+Limitation of those technologies
+
+   Oddly,  one  disadvantage  of  those  technologies is a side effect of
+   their  major  advantage:  Total  Independence.  Each virtual server is
+   running  its  own  kernel.  Cool.  This makes the following tasks more
+   difficult or impossible:
+
+     * Sharing  administrative  tasks such as backup. The virtual servers
+       are using volumes in the host server. The host server can't handle
+       the  files  in those volumes directly without interfering with the
+       client  OS. It has to use some services of the client OS to access
+       the file.
+       The  vserver  solution  does  not  have  this limitation since the
+       virtual  servers  are  living in the same file-system, sharing the
+       same kernel.
+     * Task  monitoring.  The  virtual  servers  run their own kernel. As
+       such,  the  host OS can't spy on the tasks and check for intrusion
+       for example.
+     * Disk  space.  Virtual  servers  are  using  either volumes or full
+       devices  in  the  host  server. This space is pre-allocated to the
+       maximum needed by the server. You end up with a lot of wasted disk
+       space. Imagine running 100 virtual servers this way and allocating
+       say  10 gigs to each. You get the picture. The vserver solution is
+       sharing  a  common file-system so the free disk space is available
+       to all.
+       Further,  if  you  are  running the same Linux distribution in the
+       virtual  servers, you can unify the disk space using hard link and
+       immutable  attributes.  The /usr/lib/vserver/vunify was created to
+       test  that.  Using information found in the rpm package the script
+       links the files, except configuration ones.
+       Testing   vunify   on  a  vserver  installed  with  a  RedHat  6.2
+       distribution,  unifying  the  packages  glibc, binutils, perl, and
+       bash  saved  60  megs. Quite a few packages are not changing often
+       and could be unified.
+       Vservers  do  not  need kernel packages and hardware configuration
+       tools. This also contribute to save disk space.
+     * File system sharing
+       A  little  the  same  as above. You can't share file system easily
+       between  vservers  unless you use network services (often slower).
+       Using  "mount  --bind",  it is very easy to "map" any directory of
+       the  root  server  in several vservers, providing raw speed access
+       (and even sharing the disk cache).
+
+   NEW
+
+Conclusion
+
+   Virtual  servers  are  interesting  because  they can provide a higher
+   level  of security while potentially reducing the administration task.
+   Common  operation  such  as  backup,  are  shared between all servers.
+   Services such as monitoring may be configured once.
+
+   A  Linux  server  can  run  many services at once with a high level of
+   reliability.  As  servers  are  evolving,  more  and more services are
+   added,  often  unrelated. Unfortunately there are few details here and
+   there,  making the server more complex than it is in reality. When one
+   wants  to  move  one  service to another server, it is always a little
+   pain:  Some  user  accounts  have  to  be moved and some configuration
+   files. A lot of hand tweaking.
+
+   By  installing  services  in separate virtual servers, it becomes much
+   easier  to move services around (just by moving a directory although a
+   big one).
+
+   Virtual  servers  may  become  a preferred way to install common Linux
+   servers. NEW
+
+Download
+
+   The ftp site for this project is
+   [53]ftp://ftp.solucorp.qc.ca/pub/vserver  .  You  will  find there the
+   following components.
+
+     * [54]kernel-2.4.20ctx-17.tar.gz
+       [55]kernel-2.4.20ctxsmp-17.tar.gz
+       A  pre-compiled  kernel  for  Pentium class machine and up. An SMP
+       kernel is also supplied.
+     * [56]vserver-0.22-1.src.rpm
+       The source RPM for the vserver utilities
+     * [57]vserver-0.22-1.i386.rpm
+       A  compiled  rpm  for RedHat 7.x and up. Should work on any recent
+       distribution  (glibc  2.2).  You  need  a  recent  distribution to
+       operate a kernel 2.4 anyway.
+     * [58]vserver-admin-0.22-1.i386.rpm
+       Contains  the  command /usr/sbin/newvserver. It is a GUI to create
+       vservers.   It  requires  the  linuxconf-utils  and  linuxconf-lib
+       packages.  You can get them from [59]here. linuxconf itself is not
+       needed though.
+     * [60]vserver-0.22.src.tar.gz
+       The vserver utilities source
+     * [61]patch-2.4.20ctx-17.gz
+       The patch against Linux 2.4.20
+     * [62]patches
+       The various relative patches (ctxN-ctxN+1)
+
+   NEW
+
+References
+
+   This project is maintained by Jacques Gelinas [63]jack@solucorp.qc.ca
+
+   The vserver package is licensed under the GNU PUBLIC LICENSE.
+
+   A FAQ can be found at
+   [64]http://www.solucorp.qc.ca/howto.hc?projet=vserver 
+
+   A  mailing list has been created to exchange about this project. It is
+   [65]vserver@solucorp.qc.ca .You can subscribe [66]here 
+
+   The mailing list is archived [67]here.
+
+   The change logs for the vserver package are [68]here .
+
+   The    official    copy    of    this    document    is    found    at
+   [69]http://www.solucorp.qc.ca/miscprj/s_context.hc 
+
+   This document was produced using the [70]TLMP documentation system 
+
+   [71]Top
+   [72]Back to project page
+   [73]About tlmpdoc and cookies
+   Document maintained by Jacques Gélinas ([74]jack@solucorp.qc.ca)
+   Last update: Wed Apr 16 11:22:22 2003
+
+Références
+
+   1. http://remtk/solucor/miscprj/s_context.hc?s1=1&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+   2. http://remtk/solucor/miscprj/s_context.hc?s1=1&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+   3. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+   4. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+   5. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+   6. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=3&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+   7. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=4&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+   8. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=5&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+   9. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  10. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=1&s4=0&full=0&prjstate=1&nodoc=0
+  11. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=2&s4=0&full=0&prjstate=1&nodoc=0
+  12. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=3&s4=0&full=0&prjstate=1&nodoc=0
+  13. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=4&s4=0&full=0&prjstate=1&nodoc=0
+  14. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=7&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  15. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  16. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  17. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  18. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=3&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  19. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=4&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  20. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  21. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  22. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  23. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=3&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  24. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=4&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  25. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=5&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  26. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=6&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  27. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=7&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  28. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=8&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  29. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=9&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  30. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=10&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  31. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=11&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  32. http://remtk/solucor/miscprj/s_context.hc?s1=5&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  33. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  34. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  35. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  36. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=1&s4=0&full=0&prjstate=1&nodoc=0
+  37. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=2&s4=0&full=0&prjstate=1&nodoc=0
+  38. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=3&s4=0&full=0&prjstate=1&nodoc=0
+  39. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=4&s4=0&full=0&prjstate=1&nodoc=0
+  40. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=4&s4=1&full=0&prjstate=1&nodoc=0
+  41. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=4&s4=2&full=0&prjstate=1&nodoc=0
+  42. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=4&s4=3&full=0&prjstate=1&nodoc=0
+  43. http://remtk/solucor/miscprj/s_context.hc?s1=7&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  44. http://remtk/solucor/miscprj/s_context.hc?s1=7&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  45. http://remtk/solucor/miscprj/s_context.hc?s1=7&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  46. http://remtk/solucor/miscprj/s_context.hc?s1=7&s2=3&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  47. http://remtk/solucor/miscprj/s_context.hc?s1=8&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  48. http://remtk/solucor/miscprj/s_context.hc?s1=9&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  49. http://remtk/solucor/miscprj/s_context.hc?s1=10&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  50. ftp://ftp.solucorp.qc.ca/pub/vserver
+  51. http://www.solucorp.qc.ca/virtualfs
+  52. http://www.vmware.com/
+  53. ftp://ftp.solucorp.qc.ca/pub/vserver
+  54. ftp://ftp.solucorp.qc.ca/pub/vserver/kernel-2.4.20ctx-17.tar.gz
+  55. ftp://ftp.solucorp.qc.ca/pub/vserver/kernel-2.4.20ctxsmp-17.tar.gz
+  56. ftp://ftp.solucorp.qc.ca/pub/vserver/vserver-0.22-1.src.rpm
+  57. ftp://ftp.solucorp.qc.ca/pub/vserver/vserver-0.22-1.i386.rpm
+  58. ftp://ftp.solucorp.qc.ca/pub/vserver/vserver-admin-0.22-1.i386.rpm
+  59. http://www.solucorp.qc.ca/linuxconf/download.hc
+  60. ftp://ftp.solucorp.qc.ca/pub/vserver/vserver-0.22.src.tar.gz
+  61. ftp://ftp.solucorp.qc.ca/pub/vserver/patch-2.4.20ctx-17.gz
+  62. ftp://ftp.solucorp.qc.ca/pub/vserver/patches
+  63. mailto:jack@solucorp.qc.ca
+  64. http://www.solucorp.qc.ca/howto.hc?projet=vserver
+  65. mailto:vserver@solucorp.qc.ca
+  66. http://www.solucorp.qc.ca/mlist/index.hc?list=vserver
+  67. http://www.paul.sladen.org/vserver/archives/
+  68. http://www.solucorp.qc.ca/changes.hc?projet=vserver
+  69. http://www.solucorp.qc.ca/miscprj/s_context.hc
+  70. http://www.solucorp.qc.ca/tlmp
+  71. http://remtk/solucor/miscprj/s_context.hc?s1=0&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+  72. http://remtk/solucor/miscprj/s_context.hc
+  73. http://www.solucorp.qc.ca/tlmp/tlmpdoc.hc
+  74. mailto:jack@solucorp.qc.ca
diff --git a/util-vserver/lib/Makefile-files b/util-vserver/lib/Makefile-files
new file mode 100644 (file)
index 0000000..15dfea2
--- /dev/null
@@ -0,0 +1,26 @@
+## $Id$  -*- makefile -*-
+
+## Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+lib_SRCS                       =  lib/syscall.c
+lib_HDRS                       =  lib/vserver.h
+
+lib_lib_LIBS                   =  lib/libvserver.a
+
+lib_libvserver_a_SOURCES       =  lib/syscall.c
+lib_libvserver_a_CPPFLAGS      =  -I$(kernelincludedir)
diff --git a/util-vserver/lib/syscall.c b/util-vserver/lib/syscall.c
new file mode 100644 (file)
index 0000000..ebf96da
--- /dev/null
@@ -0,0 +1,220 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on syscall.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       This tells the system call number for new_s_context and set_ipv4root
+       using /proc/self/status. This helps until the vserver project is
+       included officially in the kernel (and has its own syscall).
+
+       We rely on /proc/self/status to find the syscall number.
+
+       If it is not there, we rely on adm/unistd.h.
+
+       If this file does not have those system calls (not a patched kernel source)
+       we rely on static values in this file.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <syscall.h>
+#include <asm/unistd.h>
+
+#include "vserver.h"
+
+// Here is the trick. We keep a copy of the define, then undef it
+// and then later, we try to locate the value reading /proc/self/status
+// If this fails, we have the old preserved copy.
+static int def_NR_set_ipv4root = 227;
+#undef __NR_set_ipv4root
+
+static int __NR_set_ipv4root_rev0;
+static int __NR_set_ipv4root_rev1;
+static int __NR_set_ipv4root_rev2;
+static int __NR_set_ipv4root_rev3;
+static int rev_ipv4root=0;
+
+
+static _syscall1(int, set_ipv4root_rev0, unsigned long, ip)
+static _syscall2(int, set_ipv4root_rev1, unsigned long, ip, unsigned long, bcast)
+static _syscall3(int, set_ipv4root_rev2, unsigned long *, ip, int, nb, unsigned long, bcast)
+static _syscall4(int, set_ipv4root_rev3, unsigned long *, ip, int, nb, unsigned long, bcast, unsigned long *, mask)
+
+static int def_NR_new_s_context = 226;
+#undef __NR_new_s_context
+static int __NR_new_s_context_rev0;
+static int __NR_new_s_context_rev1;
+static int rev_s_context=0;
+
+static _syscall3(int, new_s_context_rev0, int, newctx, int, remove_cap, int, flags)
+static _syscall4(int, new_s_context_rev1, int, nbctx, int *, ctxs, int, remove_cap, int, flags)
+
+#undef __NR_set_ctxlimit
+static int __NR_set_ctxlimit=-1;
+static int rev_set_ctxlimit=-1;
+
+static _syscall2 (int, set_ctxlimit, int, resource, long, limit)
+
+#undef __NR_chrootsafe
+static int __NR_chrootsafe=-1;
+static int rev_chrootsafe=-1;
+
+static _syscall1 (int, chrootsafe, const char *, dir)
+
+static void init()
+{
+       static int is_init = 0;
+       if (!is_init){
+               FILE *fin = fopen ("/proc/self/status","r");
+               __NR_set_ipv4root_rev0 = def_NR_set_ipv4root;
+               __NR_set_ipv4root_rev1 = def_NR_set_ipv4root;
+               __NR_set_ipv4root_rev2 = def_NR_set_ipv4root;
+               __NR_set_ipv4root_rev3 = def_NR_set_ipv4root;
+               __NR_new_s_context_rev1 = def_NR_new_s_context;
+               if (fin != NULL){
+                       char line[100];
+                       while (fgets(line,sizeof(line)-1,fin)!=NULL){
+                               int num;
+                               char title[100],rev[100];
+                               rev[0] = '\0';
+                               if (sscanf(line,"%s %d %s",title,&num,rev)>=2){
+                                       if (strcmp(title,"__NR_set_ipv4root:")==0){
+                                               __NR_set_ipv4root_rev0 = num;
+                                               __NR_set_ipv4root_rev1 = num;
+                                               __NR_set_ipv4root_rev2 = num;
+                                               __NR_set_ipv4root_rev3 = num;
+                                               if (strncmp(rev,"rev",3)==0){
+                                                       rev_ipv4root = atoi(rev+3);
+                                               }
+                                       }else if (strcmp(title,"__NR_set_ctxlimit:")==0){
+                                               __NR_set_ctxlimit = num;
+                                               if (strncmp(rev,"rev",3)==0){
+                                                       rev_set_ctxlimit = atoi(rev+3);
+                                               }
+                                       }else if (strcmp(title,"__NR_chrootsafe:")==0){
+                                               __NR_chrootsafe = num;
+                                               if (strncmp(rev,"rev",3)==0){
+                                                       rev_chrootsafe = atoi(rev+3);
+                                               }
+                                       }else if (strcmp(title,"__NR_new_s_context:")==0){
+                                               __NR_new_s_context_rev0 = num;
+                                               __NR_new_s_context_rev1 = num;
+                                               if (strncmp(rev,"rev",3)==0){
+                                                       rev_s_context = atoi(rev+3);
+                                               }
+                                       }
+                               }
+                       }
+                       fclose (fin);
+               }
+               is_init = 1;
+       }
+}
+
+void vserver_init()
+{
+        init();
+}
+
+int call_new_s_context(int nbctx, int ctxs[], int remove_cap, int flags)
+{
+       int ret = -1;
+       init();
+       if (rev_s_context == 0){
+               if (nbctx > 1){
+                       errno = EINVAL;
+                       fprintf (stderr,"The current kernel does not support new_s_context revision 1\n");
+               }else if (nbctx == 0){
+                       ret = new_s_context_rev0(-2,remove_cap,flags);
+               }else if (nbctx == 1){
+                       ret = new_s_context_rev0(ctxs[0],remove_cap,flags);
+               }
+       }else{
+fprintf (stderr,"new_s_context rev1 %d %d\n",nbctx,ctxs[0]);
+               ret = new_s_context_rev1(nbctx,ctxs,remove_cap,flags);
+       }
+       return ret;
+}
+
+int call_set_ipv4root (
+       unsigned long ip[],
+       int nb,
+       unsigned long bcast,
+       unsigned long mask[])
+{
+       init();
+       if (rev_ipv4root == 0){
+               if (nb > 1){
+                       fprintf (stderr,"set_ipv4root: Several IP number specified, but this kernel only supports one. Ignored\n");
+               }
+               return set_ipv4root_rev0 (ip[0]);
+       }else if (rev_ipv4root == 1){
+               if (nb > 1){
+                       fprintf (stderr,"set_ipv4root: Several IP number specified, but this kernel only supports one. Ignored\n");
+               }
+               return set_ipv4root_rev1 (ip[0],bcast);
+       }else if (rev_ipv4root == 2){
+               return set_ipv4root_rev2 (ip,nb,bcast);
+       }else if (rev_ipv4root == 3){
+               return set_ipv4root_rev3 (ip,nb,bcast,mask);
+       }
+       errno = EINVAL;
+       return -1;
+}
+
+int call_chrootsafe (const char *dir)
+{
+       init();
+       if (rev_chrootsafe == -1){
+               fprintf (stderr,"chrootsafe: Unsupported system call, update kernel\n");
+       }else if (rev_chrootsafe == 0){
+               return chrootsafe (dir);
+       }else{
+               fprintf (stderr,"chrootsafe: kernel support version %d, application expects version 0\n"
+                       ,rev_chrootsafe);
+       }
+       errno = EINVAL;
+       return -1;
+}
+
+/*
+       Return != 0 if chrootsafe is available
+*/
+int has_chrootsafe()
+{
+       init();
+       return rev_chrootsafe != -1;
+}
+
+int call_set_ctxlimit (int res, long limit)
+{
+       init();
+       if (rev_set_ctxlimit == -1){
+               fprintf (stderr,"set_ctxlimit: Unsupported system call, update kernel\n");
+       }else if (rev_set_ctxlimit == 0){
+               return set_ctxlimit (res,limit);
+       }else{
+               fprintf (stderr,"set_ctxlimit: kernel support version %d, application expects version 0\n"
+                       ,rev_set_ctxlimit);
+       }
+       errno = EINVAL;
+       return -1;
+}
+
+
diff --git a/util-vserver/lib/vserver.h b/util-vserver/lib/vserver.h
new file mode 100644 (file)
index 0000000..5485446
--- /dev/null
@@ -0,0 +1,39 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef H_VSERVER_SYSCALL_H
+#define H_VSERVER_SYSCALL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int call_new_s_context(int nbctx, int ctxs[], int remove_cap, int flags);
+int call_set_ipv4root (unsigned long ip[], int nb,
+                      unsigned long bcast, unsigned long mask[]);
+int call_chrootsafe (const char *dir);
+int has_chrootsafe();
+int call_set_ctxlimit (int res, long limit);
+
+void   vserver_init();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/util-vserver/m4/changelog.am b/util-vserver/m4/changelog.am
new file mode 100644 (file)
index 0000000..b35ee08
--- /dev/null
@@ -0,0 +1,27 @@
+## $Id$        ---*- makefile -*---
+
+## Copyright (C) 2002 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+ChangeLog.sed:
+                               test "$(srcdir)" != "."
+
+ChangeLog:                     ChangeLog.sed Makefile
+                               if test "$(srcdir)" = "." -a -d CVS; then       \
+                                       rcs2log -l 0 -c /dev/stdout | sed -f $< >$@;    \
+                               fi
+
+.PHONY:        ChangeLog
diff --git a/util-vserver/m4/ensc_cflags.m4 b/util-vserver/m4/ensc_cflags.m4
new file mode 100644 (file)
index 0000000..f6089cf
--- /dev/null
@@ -0,0 +1,111 @@
+dnl $Id$
+
+dnl Copyright (C) 2002 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+dnl  
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; version 2 of the License.
+dnl  
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl  
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+AC_DEFUN([__ENSC_CHECK_WARNFLAGS],
+[
+       warn_flags="-Werror -W"
+       AC_MSG_CHECKING([whether the $1-compiler accepts ${warn_flags}])
+       AC_LANG_PUSH($1)
+       old_CFLAGS="${$3}"
+       $3="$warn_flags"
+       AC_TRY_COMPILE([inline static void f(){}],
+                      [],
+                      [ensc_sys_compilerwarnflags_$2=${warn_flags}],
+                      [ensc_sys_compilerwarnflags_$2=])
+       AC_LANG_POP($1)
+       $3="$old_CFLAGS"
+
+       if test x"${ensc_sys_compilerwarnflags_$2}" = x; then
+               AC_MSG_RESULT([no])
+       else
+               AC_MSG_RESULT([yes])
+       fi
+])
+
+AC_DEFUN([__ENSC_CHECK_WARNFLAGS_C],
+[
+       __ENSC_CHECK_WARNFLAGS(C, C, CFLAGS)
+])
+
+AC_DEFUN([__ENSC_CHECK_WARNFLAGS_CXX],
+[
+       __ENSC_CHECK_WARNFLAGS(C++, CXX, CXXFLAGS)
+])
+
+
+# --------------------------------------------------------------------------
+# Check whether the C++ compiler accepts a certain flag
+# If it does it adds the flag to CXXFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+#   ENSC_CHECK_CXX_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN(ENSC_CHECK_CXX_FLAG,
+[
+       AC_REQUIRE([__ENSC_CHECK_WARNFLAGS_CXX])
+
+  echo 'void f(){}' > conftest.cc
+  for i in $1
+  do
+    AC_MSG_CHECKING([whether $CXX accepts $i])
+    if test -z "`${CXX} ${ensc_sys_compilerwarnflags_CXX} $i -c conftest.cc 2>&1`"
+    then
+      CXXFLAGS="${CXXFLAGS} $i"
+      AC_MSG_RESULT(yes)
+    else
+      AC_MSG_RESULT(no)
+    fi
+  done
+  rm -f conftest.cc conftest.o
+])
+
+# --------------------------------------------------------------------------
+# Check whether the C compiler accepts a certain flag
+# If it does it adds the flag to CFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+#  ENSC_CHECK_CC_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN(ENSC_CHECK_CC_FLAG,[
+       AC_REQUIRE([__ENSC_CHECK_WARNFLAGS_C])
+
+echo 'void f(){}' > conftest.c
+  for i in $1
+  do
+    AC_MSG_CHECKING([whether $CC accepts $i])
+    if test -z "`${CC} ${ensc_sys_compilerwarnflags_C} $i -c conftest.c 2>&1`"
+    then
+      CFLAGS="${CFLAGS} $i"
+      AC_MSG_RESULT(yes)
+    else
+      AC_MSG_RESULT(no)
+    fi
+  done
+  rm -f conftest.c conftest.o
+])
+
+AC_DEFUN(ENSC_CHECK_DEFAULT_FLAG,
+[
+       if test x"${ensc_sys_default_flag}" = x; then
+               ENSC_CHECK_CC_FLAG([-fmessage-length=0])
+               ENSC_CHECK_CXX_FLAG([-fmessage-length=0])
+
+               ensc_sys_default_flag=set
+       fi
+])
diff --git a/util-vserver/m4/gpgsig.am b/util-vserver/m4/gpgsig.am
new file mode 100644 (file)
index 0000000..6fbd407
--- /dev/null
@@ -0,0 +1,19 @@
+## $Id$
+
+## Copyright (C) 2002 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+gpgsig:
+                       gpg --armor --detach-sign $(distdir).tar.bz2
diff --git a/util-vserver/m4/validate.am b/util-vserver/m4/validate.am
new file mode 100644 (file)
index 0000000..b6c3a23
--- /dev/null
@@ -0,0 +1,29 @@
+## $Id$        ---*- makefile -*---
+
+## Copyright (C) 2002 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+$(BUILT_SOURCES) config.h:     .X$(subst /,_,$(sysconfdir))-up-to-date
+
+distclean-local:       distclean-uptodate
+
+distclean-uptodate:
+                       @rm -f  .*-up-to-date
+
+.%-up-to-date:
+                       @rm -f  .*-up-to-date
+                       @touch -t 197001020000 '$@'
+                       @$(MAKE)  clean
diff --git a/util-vserver/man/Makefile-files b/util-vserver/man/Makefile-files
new file mode 100644 (file)
index 0000000..8407ae4
--- /dev/null
@@ -0,0 +1,32 @@
+## $Id$  -*- makefile -*-
+
+## Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+man_DATMAN             =  man/chbind.8 \
+                          man/chcontext.8 \
+                          man/distrib-info.8 \
+                          man/newvserver.8 \
+                          man/rebootmgr.8 \
+                          man/reducecap.8 \
+                          man/vps.8 \
+                          man/vpstree.8 \
+                          man/vrpm.8 \
+                          man/vserver-copy.8 \
+                          man/vserver-stat.8 \
+                          man/vserver.8 \
+                          man/vtop.8
diff --git a/util-vserver/man/chbind.8 b/util-vserver/man/chbind.8
new file mode 100644 (file)
index 0000000..ca7783a
--- /dev/null
@@ -0,0 +1,43 @@
+.TH "chbind" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+chbind \- The chbind utility is used to lock a process and its children into using a specific IP number/Interface. 
+.SH "SYNTAX"
+.LP 
+chbind [\fI\-\-silent\fP] [\fI\-\-ip ip_number/interface\fP] <\fIcommand arguments\fP>
+.SH "DESCRIPTION"
+.LP 
+The chbind utility executes a command, and locks the resulting process and its children into using a specific IP number/Interface, no matter what it is told in it's configuration. This applies to services and client connection as well.
+.SH "OPTIONS"
+.LP 
+.TP 
+\fB\-\-ip\fR ip_number/interface
+Binds the process to the given IP number or Interface. If an interface
+is supplied (for example eth0), both the IP number and broadcast address
+are extracted.
+.TP 
+\fB\-\-bcast\fR broadcast address
+Binds the process to the given broadcast IP number.
+.TP 
+\fB\-\-silent\fR
+Do not complain.
+
+.SH "FILES"
+.LP 
+\fI/usr/sbin/chbind\fP 
+
+
+.SH "EXAMPLES"
+.LP 
+If I wanted to ensure my httpd listened only on my eth0 interface, I could do:
+chbind \-\-ip eth0 /etc/rc.d/init.d/httpd start
+.LP 
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chcontext(8) rebootmgr(8) reducecap(8)
+vps(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
diff --git a/util-vserver/man/chcontext.8 b/util-vserver/man/chcontext.8
new file mode 100644 (file)
index 0000000..63bd721
--- /dev/null
@@ -0,0 +1,103 @@
+.TH "chcontext" "1" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+chcontext \- chcontext allocates a new security context and executes a command in that context.
+.SH "SYNTAX"
+.LP 
+chcontext [\fIoptions\fP] <\fIcommand arguments\fP>
+.SH "DESCRIPTION"
+.LP 
+chcontext allocates a new security context and executes a command in that context.
+By default, a new/unused context is allocated
+.SH "OPTIONS"
+.LP 
+.TP 
+\fB\-\-cap\fR CAP_NAME
+Add a capability from the command. This option may be repeated several time. See /usr/include/linux/capability.h In general, this option is used with the \-\-secure option. \-\-secure removes most critical capabilities and \-\-cap adds specific ones.
+.TP 
+\fB\-\-cap\fR !CAP_NAME
+Remove a capability from the command. This option may be repeated several time. See /usr/include/linux/capability.h
+.TP 
+\fB\-\-ctx\fR num
+Select the context. Only root in context 0 is allowed to select a specific context.
+Context number 1 is special. It can see all processes in any contexts, but can't kill them though.
+.TP 
+\fB\-\-disconnect\fR
+Start the command in background and make the process a child of process 1.
+.TP 
+\fB\-\-domainname\fR new_domainname
+Set the domainname (NIS) in the new security context.
+Use "none" to unset the domainname.
+.TP 
+\fB\-\-flag\fR
+Set one flag in the new or current security context. The following flags are supported. The option may be used several time.
+   lock: The new process is trapped and can't use
+         chcontext anymore.
+   sched: The new process and its children will
+          share a common execution priority.
+   nproc: Limit the number of process in the 
+          vserver according to ulimit setting.
+          Normally, ulimit is a per user thing.
+          With this flag, it becomes a per vserver
+          thing.
+   private: No one can join this security context
+            once created.
+.TP 
+\fB\-\-hostname\fR new_hostname
+Set the hostname in the new security context.
+This is needed because if you create a less privileged security context, it may be unable to change its hostname.
+.TP 
+\fB\-\-secure\fR
+Remove all the capabilities to make a virtual server trustable.
+.TP 
+\fB\-\-silent\fR
+Do not print the allocated context number.
+.LP 
+Information about context is found in /proc/self/status
+.SH "FILES"
+.LP 
+\fI/usr/sbin/chcontext\fP 
+
+
+.SH "EXAMPLES"
+.LP 
+# You must be root, running X.              
+# We start an xterm in another security context   
+/usr/sbin/chcontext xterm &
+
+# We check, there is no xterm running, yet we can
+# see it.
+ps ax | grep xterm
+
+# Are we running in security context 0
+# We check the s_context line in /proc/self/status
+cat /proc/self/status
+
+# Ok we in security context 0
+# Try the security context 1
+/usr/sbin/chcontext \-\-ctx 1 ps ax | grep xterm
+
+# Ok, we see the xterm, we try to kill it
+/usr/sbin/chcontext \-\-ctx 1 killall xterm
+
+# No, security context 1 can see, but can't kill
+# let's find out in which security context this
+# xterm is running
+/usr/sbin/chcontext \-\-ctx 1 ps ax | grep xterm
+
+# Ok, this is PID XX. We need the security context
+/usr/sbin/chcontext \-\-ctx 1 cat /proc/XX/status
+
+# We see the s_context, this is SS.
+# We want to kill this process
+/usr/sbin/chcontext \-\-ctx SS killall xterm
+.LP 
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chbind(8) rebootmgr(8) reducecap(8)
+vps(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
diff --git a/util-vserver/man/distrib-info.8 b/util-vserver/man/distrib-info.8
new file mode 100644 (file)
index 0000000..5a7d867
--- /dev/null
@@ -0,0 +1,50 @@
+.TH "distrib-info" "8" "0.1.0" "Jacques Gelinas <jack@solucorp.qc.ca>" "System Administration"
+.SH "NAME"
+.LP 
+distrib-info \- A distribution independant utility to retrieve package information.
+.SH "SYNTAX"
+.LP 
+distrib-info vserver-name command [options]
+
+.SH "DESCRIPTION"
+.LP 
+distrib-info \- This utility provides a solution to hide some differences
+between Linux distributions. The various utilities (vunify, vbuild, ...)
+need package information to perform their task. They call distrib-info
+to retrieve this information. distrib-info is the only one understanding
+the various distribution out there.
+.TP
+This utility is only used as a back-end for other utilities such as
+vunify and vbuild.
+.SH "OPTIONS"
+.LP 
+.TP 
+\fBdumpfiles\fR reports all files owned by a package.
+.TP
+\fBpkgversion\fR reports all packages and version.
+.TP
+\fBunifiles\fR reports the files of a package which may be shared by
+several virtual servers. Generally, this excludes all configuration files.
+
+.SH "EXAMPLES"
+.LP 
+The following command will report all packages in the vserver ref80.
+The package will be presented with the version/release.
+
+       distrib-info ref80 pkgversion
+
+To get the list of unify-able (sharable) file in package sendmail
+of the vserver ref80, we do
+
+       distrib-info ref80 unifiles sendmail
+.SH "FILES"
+.LP
+       /usr/lib/vservers/distrib-info
+.SH "AUTHORS"
+.LP 
+This Man page was written by Jacques Gelinas <jack@solucorp.qc.ca>.
+.SH "SEE ALSO"
+.LP 
+vbuild(8) vfiles(8) vunify(8)
+newvserver(8)
+
diff --git a/util-vserver/man/newvserver.8 b/util-vserver/man/newvserver.8
new file mode 100644 (file)
index 0000000..46bbfd8
--- /dev/null
@@ -0,0 +1,82 @@
+.TH "newvserver" "8" "0.1.0" "Jacques Gelinas <jack@solucorp.qc.ca>" "System Administration"
+.SH "NAME"
+.LP 
+newvserver \- The newvserver is an interactive tool to create new vservers.
+.SH "SYNTAX"
+.LP 
+newvserver [ options ]
+
+.SH "DESCRIPTION"
+.LP 
+newvserver \- The newvserver creates new vservers interactivly. It provides
+a graphical user interface as well as a text user interface. You can
+configure most aspect of the vserver (name, description, hostname, IP number,
+root password, ...), select a source and then perform the creation.
+
+A vserver may be created by cloning another one, cloning the root server
+or by performing a minimal installation from a distribution CD (RedHat
+supported so far).
+
+.SH "Default values"
+.LP
+The file /etc/vservers/newvserver.defaults is sourced to get default
+input value for many fields. If you are creating many vservers
+(you will :-) ), you may want to edit this file and enter suitable
+values such as your domain name, IP network, etc...
+
+
+.SH "OPTIONS"
+.LP 
+.TP
+.I --help:
+Presents a summary of the options.
+.TP
+.I --name:
+Set the name of the new vserver.
+.TP
+.I --desc:
+Set the description.
+.TP
+.I --unify 1/0:
+Turn on unification on and off.
+.TP
+.I --hostname:
+Set the host name of the new vserver
+.TP
+.I --ip:
+Set the IP number(s)
+.TP
+.I --ondev:
+Install the IP numbers as IP aliases on device.
+.TP
+.I --clone:
+Create the vserver from another one or a distribution CD.
+.TP
+The distribution CD are identified by special strings:
+    #rh8.0m: RedHat 8 minimal
+    #rh8.0f: RedHat 8 complete first CD
+    #rh7.3m: RedHat 7.3 minimal
+    #rh7.3f: RedHat 7.3 complete first CD
+    #rh7.2m: RedHat 7.2 minimal
+    #rh7.2f: RedHat 7.2 complete first CD
+
+.SH "FILES"
+.LP 
+\fI/etc/vservers/*.conf\fP 
+.P
+\fI/etc/vservers/*.sh\fP 
+.P
+\fI/etc/vservers/newvserver.defaults\fP 
+.P
+\fI/vservers/*\fP 
+
+.SH "AUTHORS"
+.LP 
+This Man page was written by Jacques Gelinas.
+.SH "SEE ALSO"
+.LP 
+vserver(8)
+vserver\-stat(8)
+distrib-info(8)
+vbuild(8)
+
diff --git a/util-vserver/man/rebootmgr.8 b/util-vserver/man/rebootmgr.8
new file mode 100644 (file)
index 0000000..4ccfe5b
--- /dev/null
@@ -0,0 +1,38 @@
+.TH "rebootmgr" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+rebootmgr \- rebootmgr stops and starts one or more vservers at your command.
+.SH "SYNTAX"
+.LP 
+rebootmgr \fIvserver\-name\fP [\fIvserver\-name\fP ...] \fICommand\fP
+.SH "DESCRIPTION"
+.LP 
+The chbind utility executes a command, and locks the resulting process and its children into using a specific IP number/Interface, no matter what it is told in it's configuration. This applies to services and client connection as well.
+.SH "OPTIONS"
+.LP 
+.TP 
+\fB\-\-ip\fR ip_number/interface
+Binds the process to the given IP number or Interface.
+.TP 
+\fB\-\-silent\fR
+Do not complain.
+
+.SH "FILES"
+.LP 
+\fI/usr/sbin/rebootmgr\fP 
+
+
+.SH "EXAMPLES"
+.LP 
+If I wanted to ensure my httpd listened only on my eth0 interface, I could do:
+chbind \-\-ip eth0 /etc/rc.d/init.d/httpd start
+.LP 
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chcontext(8) chbind(8) reducecap(8)
+vps(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
diff --git a/util-vserver/man/reducecap.8 b/util-vserver/man/reducecap.8
new file mode 100644 (file)
index 0000000..96e485e
--- /dev/null
@@ -0,0 +1,124 @@
+.TH "reducecap" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+reducecap \- The reducecap utility is used to lower the capability ceiling of a process and child process.
+.SH "SYNTAX"
+.LP 
+reducecap [\fIoptions\fP] <\fIcommand arguments\fP>
+.SH "DESCRIPTION"
+.LP 
+The reducecap utility is used to lower the capability ceiling of a process and child process. Even setuid program won't be able to grab more capabilities.
+.SH "OPTIONS"
+.LP 
+.TP 
+\fB\-\-secure\fR Removes all dangerous capabilities from the process executed.Specificly it removes:
+CAP_LINUX_IMMUTABLE CAP_NET_BROADCAST CAP_NET_ADMIN, CAP_NET_RAW CAP_IPC_LOCK CAP_IPC_OWNER CAP_SYS_MODULE CAP_SYS_RAWIO CAP_SYS_PACCT CAP_SYS_ADMIN CAP_SYS_BOOT CAP_SYS_NICE CAP_SYS_RESOURCE CAP_SYS_TIME CAP_MKNOD.
+
+Leaving the following capabilities:
+CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_FSETID CAP_KILL CAP_SETGID CAP_SETUID CAP_NET_BIND_SERVICE CAP_SYS_CHROOT CAP_SYS_PTRACE CAP_SYS_TTY_CONFIG CAP_LEASE CAP_OPENDEV
+.TP 
+\fB\-\-show\fR Shows the current process capabilities.
+.TP 
+\fB\-\-flag\fR
+sets the security context flags. The option may be repeated
+several times. Here are the values:
+
+lock: The security context can't be changed. The process is trapped
+         in this context. This is generally used for vservers because yoy
+         do not want them to hide in new security context.
+
+sched: Each process in a security context contribute (lower) to the general
+       priority of every processes in the context. Mostly, all processes
+       in a security context take as much CPU together as one process
+       not bound to this flag. Said again differently, a vserver having
+       100 active processes won't get more CPU than another vserver
+       with a single active process.
+
+
+nproc: The "ulimit -u N" setting becomes global to the security context. It means
+       the security context is not allowed to have more than N processes.
+
+private: No other processes, even root in security context 0, is allowed to
+       enter this security context. Once a security context is setup
+       with this flag, it is on its own. This also means that root
+       in security context 0 won't be able to kill or interact with those
+       processes.
+
+hideinfo: Hides various information in /proc.
+
+.TP 
+\fB--LINUX_IMMUTABLE\fR
+.TP 
+\fB--NET_BIND_SERVICE\fR
+.TP 
+\fB--NET_BROADCAST\fR
+.TP 
+\fB--NET_ADMIN\fR
+.TP 
+\fB--NET_RAW\fR
+.TP 
+\fB--IPC_LOCK\fR
+.TP 
+\fB--IPC_OWNER\fR
+.TP 
+\fB--SYS_MODULE\fR
+.TP 
+\fB--SYS_RAWIO\fR
+.TP 
+\fB--SYS_PACCT\fR
+.TP 
+\fB--SYS_ADMIN\fR
+.TP 
+\fB--SYS_BOOT\fR
+.TP 
+\fB--SYS_NICE\fR
+.TP 
+\fB--SYS_RESOURCE\fR
+.TP 
+\fB--SYS_TIME\fR
+.TP 
+\fB--MKNOD\fR
+
+All these options remove one capability. These options may be used
+after the
+\fB--secure\fR
+option to remove more capabilities.
+
+
+.SH "FILES"
+.LP 
+\fI/usr/sbin/reducecap\fP 
+
+
+.SH "EXAMPLES"
+.LP 
+# You are not root now
+# What is the current capability ceiling
+cat /proc/self/status
+# The capBset line presents mostly 1s.
+/usr/sbin/reducecap \-\-secure /bin/sh
+cat /proc/self/status
+# The capBset now shows many more 0s.
+# The capEff shows all 0s, you have no privilege now
+# We su to root
+su
+cat /proc/self/status
+# capEff is much better now, but there are still many 0s
+# Now we try to see if we are really root
+tail /var/log/messages
+# So far so good, we see the content
+/sbin/ifconfig eth0
+/sbin/ifconfig eth0 down
+# No way, we can't configure the interface. In fact
+# we have lost most privilege normally assigned to root
+exit
+.LP 
+Please contribute some more, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chcontext(8) rebootmgr(8) chbind(8)
+vps(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
diff --git a/util-vserver/man/vps.8 b/util-vserver/man/vps.8
new file mode 100644 (file)
index 0000000..4b653f0
--- /dev/null
@@ -0,0 +1,31 @@
+.TH "vps" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+vps \- The vps utility is simply a wrapper for the ps program.
+.SH "SYNTAX"
+.LP 
+vps [\fIoptions\fP]
+
+.SH "DESCRIPTION"
+.LP 
+vps \- The vps utility is simply a wrapper for the ps program, that enables ps to show you the all the processes on the system, instead of only the ones in the current s_context (see cat /proc/self/status).
+.SH "OPTIONS"
+.LP 
+.TP 
+See man ps.
+.SH "FILES"
+.LP 
+\fI/usr/sbin/vps\fP 
+
+
+.SH "EXAMPLES"
+.LP 
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
diff --git a/util-vserver/man/vpstree.8 b/util-vserver/man/vpstree.8
new file mode 100644 (file)
index 0000000..27c1b24
--- /dev/null
@@ -0,0 +1,31 @@
+.TH "vpstree" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+vpstree \- The vpstree utility is simply a wrapper for the pstree program.
+.SH "SYNTAX"
+.LP 
+vpstree [\fIoptions\fP]
+
+.SH "DESCRIPTION"
+.LP 
+vpstree \- The vpstree utility is simply a wrapper for the pstree program, that enables pstree to show you the all the processes on the system, instead of only the ones in the current s_context (see cat /proc/self/status).
+.SH "OPTIONS"
+.LP 
+.TP 
+See man pstree.
+.SH "FILES"
+.LP 
+\fI/usr/sbin/vpstree\fP 
+
+
+.SH "EXAMPLES"
+.LP 
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vps(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
diff --git a/util-vserver/man/vrpm.8 b/util-vserver/man/vrpm.8
new file mode 100644 (file)
index 0000000..e6eb456
--- /dev/null
@@ -0,0 +1,48 @@
+.TH "vrpm" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+vrpm \- is simply a wrapper for the rpm utility.
+.SH "SYNTAX"
+.LP 
+vrpm [--unify] [ALL | vserver1 vserver2 ...] \-\- [rpm options]
+
+.SH "DESCRIPTION"
+.LP 
+vrpm \- is simply a wrapper for the rpm utility. It enables rpm to manage a specific, several or all virtual server(s) with one command.
+vrpm is executed in the root server.
+.SH "OPTIONS"
+.LP 
+.TP 
+\fB\-\-\fR All commands after this, is given to the rpm utility (see man rpm).
+.TP
+The
+\fB--unify\fR option triggers the vunify utility on the vservers and the
+supplied packages.
+.SH "FILES"
+.LP 
+\fI/usr/sbin/vrpm\fP 
+
+
+.SH "EXAMPLES"
+.TP 
+verifies the gcc package on all vservers.
+.LP
+vrpm ALL \-\- \-\-verify gcc
+.TP
+Updates package.rpm on vserver1 and vserver2 if
+the package exists in a earlier version 
+(the F flag for rpm).
+.LP
+vrpm vserver1 vserver2 \-\- \-Fvh package.rpm
+.TP
+vrpm is executed in the root server
+.LP 
+Please contribute some more, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vps(8) vtop(8) vserver(8)
+vserver\-stat(8) vpstree(8)
diff --git a/util-vserver/man/vserver-copy.8 b/util-vserver/man/vserver-copy.8
new file mode 100644 (file)
index 0000000..9481c49
--- /dev/null
@@ -0,0 +1,93 @@
+.TH "vserver-copy" "8" "0.3" "Mark Lawrence <nomad@null.net>" "System Administration"
+.SH "NAME"
+.LP 
+vserver-copy \- copy/move a virtual server.
+.SH "SYNTAX"
+.LP 
+vserver-copy [\fIoptions\fP] \fIvserver\fP \fInewname\fP 
+.LP 
+vserver-copy [\fIoptions\fP] \fIvserver\fP \fIhost\fP:[\fInewname\fP]
+.SH "DESCRIPTION"
+.LP 
+vserver-copy makes a copy of a virtual server using rsync. It will
+rewrite the vserver.conf configuration file with the new hostname and
+IP information when given. If the destination name contains a host
+specification then ssh/rsh will be used for the data transfer.
+
+vserver-copy can used on a running vserver, although naturally the
+consistency of open database files and the like cannot be guaranteed.
+A running vserver can however be safely moved from one root host to another
+using the \-s flag.
+
+If downtime is an issue when moving a virtual server across hosts you
+should first run vserver without the \-s flag. This will pre\-populate the
+destination filesystem requiring only updates to be made on the next
+invocation.
+.SH "OPTIONS"
+.LP 
+.TP 
+\fB\-h\fR,\fB-\-help\fR
+output usage information and exit
+.TP 
+\fB\-V\fR,\fB-\-version\fR
+output version information and exit
+.TP 
+\fB\-v\fR,\fB-\-verbose\fR
+show all output (normally only informational messages and warnings)
+.TP 
+\fB\-q\fR,\fB-\-quiet\fR
+suppress all output
+.TP 
+\fB\-d\fR,\fB-\-domain\fR domain
+the new DNS domain when changing name. Overwrites /etc/hosts. Must be
+used with \-i
+.TP 
+\fB\-i\fR,\fB-\-ip\fR address
+the new IP address when changing name. Overwrites /etc/hosts. Must be
+used with \-d
+.TP 
+\fB\-r\fR,\fB-\-vsroot\fR
+directory containing virtual servers. Defaults to "/vserver"
+.TP 
+\fB\-R\fR,\fB-\-rsh\fR
+use rsh instead of the default ssh for network transfer
+.TP
+\fB\-s\fR,\fB-\-stopstart\fR
+stop the virtual server before copying and start the new vserver afterwards.
+This really only makes sense if you are copying across root hosts and not
+changing names or IP addresses.
+.SH "FILES"
+.LP 
+\fI/etc/vservers/vserver.conf\fP 
+.SH "EXAMPLES"
+.LP 
+# Copy a template vserver (same IP addresses etc)
+
+/usr/sbin/vserver-copy template web01
+
+# Copy webserver with change in configuration
+
+/usr/sbin/vserver-copy -i 192.168.5.62 -d example.com template web62
+
+# Move a running vserver to another roothost
+
+/usr/sbin/vserver-copy -s web62 roothost02:
+
+.SH "BUGS"
+.LP 
+If a virtual server is moved from one root host to another a gratuitious
+ping should be sent to inform other devices on the local area network
+of the change in MAC address.
+
+Without this ping the devices will continue to attempt to reach the old
+MAC address for the length of their arp-cache timeout (10 minute default
+on Suns!).
+
+This functionality should probably be implmemented during the 
+"vserver <name> start" process.
+.SH "AUTHOR"
+.LP 
+Mark Lawrence <nomad@null.net>
+.SH "SEE ALSO"
+.LP 
+vserver(8)
diff --git a/util-vserver/man/vserver-stat.8 b/util-vserver/man/vserver-stat.8
new file mode 100644 (file)
index 0000000..4c1ac2d
--- /dev/null
@@ -0,0 +1,40 @@
+.TH "vserver-stat" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+vserver\-stat 
+.SH "SYNTAX"
+.LP 
+vserver\-stat 
+
+.SH "DESCRIPTION"
+.LP 
+vserver\-stat \- The vserver\-stat utility shows informations about all the active contexts.
+
+        CTX#            Context number
+                        #0 = root context
+                        #1 = monitoring context
+        PROC QTY        Quantity of processes in each
+                       context
+        VSZ             Number of pages of virtual
+                               memory
+        RSS             Resident set size
+        utime           User\-mode CPU time
+                               accumulated
+        ctime           Kernel\-mode CPU time
+                               accumulated
+.SH "FILES"
+.LP 
+\fI/usr/sbin/vserver\-stat\fP 
+
+
+.SH "EXAMPLES"
+.LP 
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vps(8) vrpm(8) vserver(8)
+vtop(8) vpstree(8)
diff --git a/util-vserver/man/vserver.8 b/util-vserver/man/vserver.8
new file mode 100644 (file)
index 0000000..6ea2052
--- /dev/null
@@ -0,0 +1,74 @@
+.TH "vserver" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+vserver \- The vserver utility enables you to control different aspects of your vservers.
+.SH "SYNTAX"
+.LP 
+vserver [ options ] [vserver name] [options]
+
+.SH "DESCRIPTION"
+.LP 
+vserver \- The vserver utility enables you to control different aspects of your vservers, such as stopping and starting them, and services within them.
+.SH "OPTIONS"
+.LP 
+.TP 
+\fBbuild\fR Create a virtual server by copying the packages of the root server
+.TP 
+\fBenter\fR Enter in the virtual server context and starts a shell. Same as "vserver name exec /bin/sh\".
+.TP 
+\fBexec\fR Exec a command in the virtual server context as root.
+syntax: vserver name exec command ...
+.TP 
+\fBsuexec\fR Exec a command in the virtual server context under some user id.
+syntax: vserver name suexec userid command ...
+.TP 
+\fBservice\fR Control a service inside a vserver. 
+syntax: vserver name service service\-name (start/stop/restart etc.)
+.TP 
+\fBstart\fR Starts the various services in the vserver.
+It uses the default runlevel found in the
+.B /etc/inittab
+file of the vserver.
+.TP 
+\fBstop\fR Ends all services and kills the remaining processes.
+.TP 
+\fBrunning\fR Tells if a virtual server is running. It returns proper exit code, so you can use it as a test.
+.TP
+\fBstatus\fR Tells various information about the state of a virtual server:
+running status, number of running processes and uptime.
+.TP
+.I --nodev
+do not configure the IP devices associated with the vserver. This
+is useful to execute some commands on the vserver (or enter it)
+without making it active on the network. Especially useful if you
+have an active copy of the vserver moved to another server on the
+network.
+.TP
+.I --silent
+cuts most informative messages.
+
+.SH "FILES"
+.LP 
+\fI/usr/sbin/vserver\fP 
+.P
+\fI/etc/vservers/*.conf\fP 
+.P
+\fI/etc/vservers/*.sh\fP 
+.P
+\fI/vservers/*\fP 
+
+.SH "EXAMPLES"
+.LP 
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chbind(8) chcontext(8)
+newvserver(8)
+rebootmgr(8) reducecap(8)
+vps(8) vpstree(8)
+vrpm(8)
+vserver\-stat(8) 
+vtop(8)
diff --git a/util-vserver/man/vtop.8 b/util-vserver/man/vtop.8
new file mode 100644 (file)
index 0000000..440bc27
--- /dev/null
@@ -0,0 +1,31 @@
+.TH "vtop" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP 
+vtop \- The vtop utility is simply a wrapper for the top program.
+.SH "SYNTAX"
+.LP 
+vtop [\fIoptions\fP]
+
+.SH "DESCRIPTION"
+.LP 
+vtop \- The vtop utility is simply a wrapper for the top program, that enables top to show you the all the processes on the system, instead of only the ones in the current s_context (see cat /proc/self/status).
+.SH "OPTIONS"
+.LP 
+.TP 
+See man top.
+.SH "FILES"
+.LP 
+\fI/usr/sbin/vtop\fP 
+
+
+.SH "EXAMPLES"
+.LP 
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP 
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP 
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vps(8) vrpm(8) vserver(8)
+vserver\-stat(8) vpstree(8)
diff --git a/util-vserver/newvserver.defaults b/util-vserver/newvserver.defaults
new file mode 100644 (file)
index 0000000..badfe64
--- /dev/null
@@ -0,0 +1,18 @@
+# This script is sourced by newvserver to set the dialog default values
+# Uncomment only the line you want to override.
+# Name of the vserver
+#      name=
+# Description
+#      desc=
+# Reference vserver to clone
+#      clone=/
+# Use unification
+#      unify=1
+# Host name. Put the default domain if you want
+#      hostname=.mydomain.com
+# List of IP
+# Put the prefix of your network to save some typing
+#      ip=
+# Network device for IP aliases setup
+#      ondev=eth0
+
diff --git a/util-vserver/scripts/Makefile-files b/util-vserver/scripts/Makefile-files
new file mode 100644 (file)
index 0000000..da8e692
--- /dev/null
@@ -0,0 +1,50 @@
+## $Id$  -*- makefile -*-
+
+## Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+scriptscfgdir          =  $(sbindir)
+
+scripts_SCRPTS         =  scripts/distrib-info \
+                          scripts/rootshell \
+                          scripts/save_s_context \
+                          scripts/vprofile \
+                          scripts/vserverkillall \
+                          scripts/vservers.grabinfo.sh \
+                          scripts/vsysvwrapper \
+                          scripts/vunify.old.sh
+
+scripts_PRGS           =  scripts/vkill \
+                          scripts/vps \
+                          scripts/vpstree \
+                          scripts/vrpm \
+                          scripts/vserver \
+                          scripts/vserver-copy \
+                          scripts/vtop
+
+scriptscfg_DATA                =  scripts/util-vserver-vars
+
+scripts_XTRAS          =  scripts/util-vserver-vars.subst
+scripts_GENSCRPTS      =  scripts/util-vserver-vars
+
+scripts/%:             scripts/%.subst
+                       @mkdir -p $$(dirname '$@')
+                       sed -e 's!@'PKGLIBDIR'@!$(pkglibdir)!g; \
+                               s!@'SBINDIR'@!$(sbindir)!g' '$<' >'$@.tmp'
+                       @-rm -f '$@'
+                       mv '$@.tmp' '$@'
+                       @chmod a-w '$@'
diff --git a/util-vserver/scripts/distrib-info b/util-vserver/scripts/distrib-info
new file mode 100755 (executable)
index 0000000..6bbddfb
--- /dev/null
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib-info by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  
+
+# This scripts knows about every possible distribution (well, it should)
+# It is passed a vserver name and a key (a command). The key represent a task.
+# It executes the command and output on stdout.
+# For example
+# distrib-info vserver1 pkgversion
+# If vserver1 is a redhat system, it executes
+# rpm -qa --queryformat "%{name}=%{version}-%{release}
+USR_LIB_VSERVER=$(dirname $0)
+
+if [ "$1" = "" ] ; then
+       echo distrib-info vserver-name command [ args ... ] >&2
+       echo Commands are: >&2
+       echo dumpfiles: Shows all files owned by a package >&2
+       echo pkgversion: reports all packages and their version/release >&2
+       echo unifiles: reports all unify-able file of a package >&2
+       exit 1
+fi
+if [ "$1" = "/" ] ; then
+       DISTDIR=/
+       CHROOTCMD=
+elif [ -d "$1" ] ; then
+       DISTDIR=$1
+       CHROOTCMD="/usr/sbin/chroot $DISTDIR"
+else
+       DISTDIR=/vservers/$1
+       CHROOTCMD="/usr/sbin/chroot $DISTDIR"
+fi
+KEY=$2
+shift
+shift
+if [ -f $DIRDIR/etc/redhat-release -o -f $DISTDIR/etc/mandrake-release ] ; then
+       case $KEY in
+       pkgversion)
+               $CHROOTCMD /bin/rpm -qa --queryformat "%{name}=%{version}-%{release}\n"
+               ;;
+       unifiles)
+               # We remove /etc and /var/log to make sure no special file
+               # there will be unified
+               $CHROOTCMD /bin/rpm -ql --dump $* \
+                       | $USR_LIB_VSERVER/parserpmdump /etc/
+               ;;
+       dumpfiles)
+               $CHROOTCMD /bin/rpm -ql $*
+               ;;
+       *)
+               echo unknown request $KEY >&2
+               ;;
+       esac
+else
+       echo Distribution not supported yet >&2
+fi
+
diff --git a/util-vserver/scripts/rootshell b/util-vserver/scripts/rootshell
new file mode 100755 (executable)
index 0000000..7586d46
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on rootshell by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+echo $* >/tmp/log
+OPTIONS=$@
+if [ "$OPTIONS" = "" ] ; then
+       OPTIONS=--login
+fi
+exec /usr/sbin/chbind --silent --ip 0.0.0.0 /bin/bash $OPTIONS
+
diff --git a/util-vserver/scripts/save_s_context b/util-vserver/scripts/save_s_context
new file mode 100755 (executable)
index 0000000..535c14e
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on save_s_context by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+if [ $# -lt 1 ] ;then
+       echo save_s_context file command
+       echo Save the security context in file and execute a command
+else
+       CTX=`grep ^s_context: /proc/self/status | sed s/s_context:// | (read a b; echo $a)`
+       CTX=`eval expr $CTX + 0`
+       echo S_CONTEXT=$CTX >$1
+       echo S_PROFILE=$PROFILE >>$1
+       shift
+       exec "$@"
+fi
+
+
diff --git a/util-vserver/scripts/util-vserver-vars.subst b/util-vserver/scripts/util-vserver-vars.subst
new file mode 100644 (file)
index 0000000..8600058
--- /dev/null
@@ -0,0 +1,2 @@
+PKGLIBDIR='@PKGLIBDIR@'
+SBINDIR='@SBINDIR@'
diff --git a/util-vserver/scripts/vkill b/util-vserver/scripts/vkill
new file mode 100755 (executable)
index 0000000..cbf3fb1
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vkill by Philip Snyder
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# kill wrapper for vserver. 
+# Philip Snyder <psnyder@vizional.com>
+# 2002/02/06 19:00 PST
+
+
+$PROC = $ARGV[0];
+
+# Grab the output from a context query against this process id
+open(PH, "/usr/sbin/chcontext --silent --ctx 1 cat /proc/$PROC/status 2>&1 |");
+
+# Loop through the output
+while (<PH>) {
+
+  # Searching for a line that looks like this:
+  # s_context: #
+  if (/^s_context: ([0-9]+)/) {
+
+    print "Process id $PROC was found in security context $1.\n";
+
+    # Make sure the process is in a vserver context
+    if ($1 > 0) {
+
+      # Since we have the context and the process id, we can kill it
+      print " + Killing... ";
+      `/usr/sbin/chcontext --ctx $1 kill $PROC`;
+      print "[done]\n";
+
+    } else {
+
+      # Not in vserver context, so its a process on the actual server
+      print " + Killing... ";
+      `kill $PROC`;
+      print "[done]\n";
+
+    }
+    exit;
+  }
+}
+
+print "Process id $PROC not found.\n";
+exit
diff --git a/util-vserver/scripts/vprofile b/util-vserver/scripts/vprofile
new file mode 100755 (executable)
index 0000000..26fe562
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vprofile by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Prints or select the active profile for a vserver
+if [ $# != 1 -a $# != 2 ] ; then
+       echo vprofile vserver [ profile-name ]
+else
+       if [ ! -f /etc/vservers/$1.conf ] ; then
+               echo vserver $1 does not exist >&2
+       else
+               unset PROFILE
+               . /etc/vservers/$1.conf
+               if [ $# = 1 ] ; then
+                       echo PROFILE=$PROFILE
+               elif [ $# = 2 ] ; then
+                       grep .\*\) /etc/vservers/$1.conf
+               fi
+       fi
+fi
+
+
diff --git a/util-vserver/scripts/vps b/util-vserver/scripts/vps
new file mode 100755 (executable)
index 0000000..0287bde
--- /dev/null
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vps by Krischan Jodies
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Wrapper for ps. Adds security context number and name
+# to the PID column.
+#
+# (c) 2002 krischan.jodies@sernet.de
+# version 1.0
+
+# 1.1        Added error messages
+
+if ($ARGV[0] eq "--help") {
+   exec("ps @ARGV");
+   exit;
+} 
+
+
+$lockdir = "/var/run/vservers";
+
+$pid_length = 5;
+get_server_names();
+$context=get_context("self");
+
+if ($context == -1) {
+   print "Can not find my security context. Is this a ctx kernel?\n";
+   exit;
+}
+if ($context != 1) {
+   exec("/usr/sbin/chcontext --silent --ctx 1 $0 @ARGV");
+   print "Can not execute chcontext\n";
+   exit; # not reached
+} 
+
+
+if (! open PS, "ps $ARGV[0]|") {
+   print "Can not execute ps\n";
+   exit;
+}
+while (<PS>) {
+  chomp;
+  push @ps,$_;
+}
+
+$header = shift @ps;
+$header =~ /(.*)  PID(.+)/;
+$left = $1;
+$right = $2;
+$left_length  = length($left);
+print "${left}  PID CONTEXT       ${right}\n";
+foreach $line (@ps) {
+   $pid =  substr $line,$left_length,$pid_length;
+   print   substr $line,0,$left_length;
+   print "$pid";
+   $context = get_context($pid);
+   $context_name = getcontextname($context);
+   printf " %-3s %-10s",$context,$context_name;
+   print   substr $line,$left_length + $pid_length;
+   print "\n";
+   
+}
+
+exit;
+
+sub get_context
+{
+   my $pid = $_[0];
+   $pid =~ s/ //g;
+   open STATUS, "/proc/$pid/status";
+   while (<STATUS>)
+   {
+      chomp;
+      if (/s_context: (\d+)/) {
+         close STATUS;   
+         return $1;
+      }
+   }
+   close STATUS;
+   return -1;
+}
+
+sub getcontextname {
+   if (exists $name{$_[0]}) {
+      return $name{$_[0]};
+   }
+   if    ($_[0] == 1) {
+      return "ALL_PROCS";
+   }
+   elsif ($_[0] == 0) {
+      return "MAIN";
+   }
+   return "UNKNOWN";
+}
+
+
+sub get_server_names 
+{
+    opendir LOCKDIR, "$lockdir";
+    while ($file=readdir(LOCKDIR)) {
+       if (-f "$lockdir/$file") {
+          open FILE, "$lockdir/$file";
+          $file =~ s/(.+)\.ctx/$1/;
+          while (<FILE>) {
+             if (/S_CONTEXT=(\d+)/) {
+                $name{$1} = $file;
+             }
+          }
+       }
+    }
+}
diff --git a/util-vserver/scripts/vpstree b/util-vserver/scripts/vpstree
new file mode 100755 (executable)
index 0000000..e785a46
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vpstree by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#Presents the processes running in all virtual servers
+exec /usr/sbin/chcontext --silent --ctx 1 pstree $*
+
+
diff --git a/util-vserver/scripts/vrpm b/util-vserver/scripts/vrpm
new file mode 100755 (executable)
index 0000000..8c5e8d5
--- /dev/null
@@ -0,0 +1,105 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vrpm by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Wrapper to update/install package in many vservers at once
+
+: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+    echo "Can not find util-vserver installation; aborting..."
+    exit 1
+}
+. "$UTIL_VSERVER_VARS"
+
+usage(){
+       echo vrpm: Install/Updates packages in several vservers at once
+       echo vrpm vservers ... -- rpm options and packages
+       echo vrpm \[--unify\] ALL -- rpm options and packages
+       echo vrpm \[--unify\] server1 server2 -- -Uvh package.rpm
+       echo
+       echo vrpm is executed in the root server
+       echo "--unify run vunify on the vserver for the updated packages"
+}
+UNIFY=no
+if [ "$1" = "--unify" ] ; then
+       UNIFY=yes
+       shift
+fi
+if [ $# = 0 ] ; then
+       usage
+else
+       SERVERS=
+       while [ $# -gt 0 -a "$1" != "--" ]
+       do
+               if [ "$1" = "ALL" ] ; then
+                       SERVERS=`cd /vservers && ls`
+               else
+                       SERVERS="$SERVERS $1"
+               fi
+               shift
+       done
+       if [ "$1" != "--" ] ; then
+               usage
+       elif [ "$SERVERS" = "" ] ; then
+               echo no server specified
+               echo
+               usage
+       else
+               shift
+               for serv in $SERVERS
+               do
+                       # We try to run the rpm command in the same security
+                       # context than the vserver, if running.
+                       # This way, process operations will be done in the proper
+                       # context
+                       # If the vserver is not running, chcontext will
+                       # pick an unused one.
+                       CTXOPT=""
+                       CTXFILE=/var/run/vservers/$serv.ctx
+                       if [ -f $CTXFILE ] ; then
+                               source $CTXFILE
+                               CTXOPT="--ctx $S_CONTEXT"
+                       fi
+                       #echo rpm --root /vservers/$serv $*
+                       echo Updating server $serv
+                       /usr/sbin/chcontext --silent $CTXOPT rpm --root /vservers/$serv $*
+               done
+               if [ "$UNIFY" = "yes" ] ; then
+                       PACKAGES=
+                       for pkg in $*
+                       do
+                               case $pkg in
+                               -*)
+                                       # RPM options ?
+                                       ;;
+                               --*)
+                                       # RPM options ?
+                                       ;;
+                               *)
+                                       pkg=`rpm -qp $pkg --queryformat %{name}`
+                                       PACKAGES="$PACKAGES $pkg"
+                                       ;;
+                               esac
+                       done
+                       echo Unification
+                       $PKGLIBDIR/vunify --excldir /var/log $SERVERS -- $PACKAGES
+               fi
+       fi
+fi
+       
+
diff --git a/util-vserver/scripts/vserver b/util-vserver/scripts/vserver
new file mode 100755 (executable)
index 0000000..c40eaf1
--- /dev/null
@@ -0,0 +1,771 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vserver by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This is a script to control a virtual server
+
+: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+    echo "Can not find util-vserver installation; aborting..."
+    exit 1
+}
+. "$UTIL_VSERVER_VARS"
+
+USR_SBIN=$SBINDIR
+USR_LIB_VSERVER=$PKGLIBDIR
+
+VSERVER_CMD=$USR_SBIN/vserver
+CHBIND_CMD=$USR_SBIN/chbind
+CHCONTEXT_CMD=$USR_SBIN/chcontext
+SAVE_S_CONTEXT_CMD=$USR_LIB_VSERVER/save_s_context
+CAPCHROOT_CMD=$USR_LIB_VSERVER/capchroot
+VSERVERKILLALL_CMD=$USR_LIB_VSERVER/vserverkillall
+DEFAULTPATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
+vserver_mknod(){
+       mknod $1 $2 $3 $4
+       chmod $5 $1
+}
+
+mountproc()
+{
+       mkdir -p $1/proc $1/dev/pts
+       if [ ! -d $1/proc/1 ] ; then
+               mount -t proc none $1/proc
+               mount -t devpts none $1/dev/pts
+       fi
+}
+umountproc()
+{
+       umount $1/proc 2>/dev/null
+       umount $1/dev/pts 2>/dev/null
+}
+
+# Check that the vservers parent directory has permission 000
+# This is the key to avoid chroot escape
+testperm()
+{
+       return
+       PERM=`$USR_LIB_VSERVER/showperm /vservers/$1/..`
+       if [ "$PERM" != 000 ] ; then
+               echo
+               echo "**********************************************************"
+               echo /vservers/$1/.. has insecure permissions.
+               echo A vserver administrator may be able to visit the root server.
+               echo To fix this, do
+               echo "  " chmod 000 /vservers/$1/..
+               echo do it anytime you want, even if vservers are running.
+               echo "**********************************************************"
+               echo
+       fi
+}
+# Set the IP alias needed by a vserver
+ifconfig_iproot()
+{
+       if [ "$NODEV" = "" -a "$IPROOT" != "" -a "$IPROOT" != "0.0.0.0" -a "$IPROOT" != "ALL" ] ;then
+               # A vserver may have more than one IP
+               # The first alias is dev:vserver
+               # and the other are dev:vserver1,2,3 and so on
+               # An IP may hold the device. The following is valid
+               #       IPROOT="1.2.4.5 eth1:1.2.3.5"
+               #       IPROOTDEV=eth0
+               # The first IP 1.2.3.4 will go on eth0 and the other on eth1
+               # VLAN devices are also supported (eth0.231 for vlan 231)
+               SUFFIX=
+               for oneip in $IPROOT
+               do
+                       IPDEV=$IPROOTDEV
+                       MASK=$IPROOTMASK
+                       BCAST=$IPROOTBCAST
+                       # Split the device and IP if available
+                       case $oneip in
+                       *:*)
+                               eval `echo $oneip | tr : ' ' | (read dev ip; echo oneip=$ip; echo IPDEV=$dev)`
+                               ;;
+                       esac
+                       # Split the IP and the netmask if available
+                       case $oneip in
+                       */*)
+                               eval `echo $oneip | tr / ' ' | (read ip msk; echo oneip=$ip; echo MASK=$msk)`
+                               eval `$USR_LIB_VSERVER/ifspec "" "$oneip" "$MASK" "$BCAST"`
+                               ;;
+                       esac
+                       if [ "$IPDEV" != "" ] ; then
+                               case $IPDEV in
+                               *.*)
+                                       if [ ! -f /proc/net/vlan/$IPDEV ] ; then
+                                               /sbin/vconfig add `echo $IPDEV | tr . ' '`
+                                               # Put a dummy IP
+                                               /sbin/ifconfig $IPDEV 127.0.0.1
+                                       fi
+                                       ;;
+                               esac
+                               # Compute the default netmask, if missing
+                               eval `$USR_LIB_VSERVER/ifspec $IPDEV "$oneip" "$MASK" "$BCAST"`
+                               IPROOTMASK=$NETMASK
+                               IPROOTBCAST=$BCAST
+                               #echo /sbin/ifconfig $IPDEV:$1$SUFFIX $oneip netmask $IPROOTMASK broadcast $IPROOTBCAST
+                               /sbin/ifconfig $IPDEV:$1$SUFFIX $oneip netmask $IPROOTMASK broadcast $IPROOTBCAST
+                       fi
+                       if [ "$SUFFIX" = "" ] ; then
+                               SUFFIX=1
+                       else
+                               SUFFIX=`expr $SUFFIX + 1`
+                       fi
+               done
+       fi
+       if [ "$IPROOTBCAST" = "" ] ; then
+               IPROOTBCAST=255.255.255.255
+       fi
+}
+ifconfig_iproot_off()
+{
+       if [ "$NODEV" = "" -a "$IPROOT" != "" -a "$IPROOT" != "0.0.0.0" -a "$IPROOT" != "ALL"  -a "$IPROOTDEV" != "" ] ;then
+               SUFFIX=
+               for oneip in $IPROOT
+               do
+                       IPDEV=$IPROOTDEV
+                       # Split the device and IP if available
+                       case $oneip in
+                       *:*)
+                               eval `echo $oneip | tr : ' ' | (read dev ip; echo IPDEV=$dev)`
+                               ;;
+                       esac
+                       /sbin/ifconfig $IPDEV:$1$SUFFIX down 2>/dev/null
+                       if [ "$SUFFIX" = "" ] ; then
+                               SUFFIX=1
+                       else
+                               SUFFIX=`expr $SUFFIX + 1`
+                       fi
+               done
+       fi
+}
+# Split an IPROOT definition, trash the devices and
+# compose a set of --ip option for chbind
+setipopt(){
+       RET=
+       IPS="$*"
+       if [ "$IPS" = "" ] ; then
+               IPS=0.0.0.0
+       fi
+       if [ "$1" = "ALL" ] ; then
+               IPS=`$USR_LIB_VSERVER/listdevip`
+       fi
+       for oneip in $IPS
+       do
+               # Split the device and IP if available
+               case $oneip in
+               *:*)
+                       eval `echo $oneip | tr : ' ' | (read dev ip; echo oneip=$ip)`
+                       ;;
+               esac
+               #case $oneip in
+               #*/*)
+               #       eval `echo $oneip | tr / ' ' | (read ip msk; echo oneip=$ip)`
+               #       ;;
+               #esac
+               echo --ip $oneip
+       done
+}
+
+# Extract the initial runlevel from the vserver inittab
+get_initdefault()
+{
+       INITDEFAULT=`grep :initdefault /vservers/$1/etc/inittab | sed 's/:/ /g' | ( read a level b; echo $level)`
+}
+
+# Read the vserver configuration file, reusing the PROFILE value
+# found in /var/run/vservers
+readlastconf()
+{
+       if [ -f /var/run/vservers/$1.ctx ] ; then
+               . /var/run/vservers/$1.ctx
+               if [ "$S_PROFILE" != "" ] ; then
+                       export PROFILE=$S_PROFILE
+               fi
+       fi
+       export PROFILE
+       . /etc/vservers/$1.conf
+}
+usage()
+{
+       echo vserver [ options ] server-name command ...
+       echo
+       echo server-name is a directory in /vservers
+       echo
+       echo The commands are:
+       echo " build   : Create a virtual server by copying the packages"
+       echo "           of the root server"
+       echo " enter   : Enter in the virtual server context and starts a shell"
+       echo "           Same as \"vserver name exec /bin/sh\""
+       echo " exec    : Exec a command in the virtual server context"
+       echo " suexec  : Exec a command in the virtual server context uid"
+       echo " service : Control a service inside a vserver"
+       echo "           vserver name service service-name start/stop/restart/status"
+       echo " start   : Starts the various services in the vserver, runlevel 3"
+       echo " stop    : Ends all services and kills the remaining processes"
+       echo " running : Tells if a virtual server is running"
+       echo "           It returns proper exit code, so you can use it as a test"
+       echo " status  : Tells some information about a vserver"
+       echo " chkconfig : It turns a server on or off in a vserver"
+       echo
+       echo "--nodev  : Do not configure the IP aliases of the vserver"
+       echo "           Useful to enter a vserver without enabling its network"
+       echo "           and avoiding conflicts with another copy of this vserver"
+       echo "           running elsewhere"
+       echo "--silent : No informative messages about vserver context and IP numbers"
+       echo "           Useful when you want to redirect the output"
+}
+
+calculateCaps()
+{
+    local f
+    for f in "$@"; do
+       case $f in
+           !CAP_SYS_CHROOT)
+               CHROOTOPT=--nochroot
+               ;;
+           *)
+               CAPS="$CAPS --cap $f"
+               ;;
+       esac
+    done
+}
+
+SILENT=
+NODEV=
+while true
+do
+       if [ "$1" = "--silent" ] ; then
+               SILENT=--silent
+               shift
+       elif [ "$1" = "--nodev" ] ; then
+               NODEV=--nodev
+               shift
+       else
+               break
+       fi
+done
+# Setup the default ulimit for a vserver
+setdefulimit(){
+       # File handle are limited to half of the current system limit
+       # Virtual memory is limited to the ram size
+       NFILE=`cat /proc/sys/fs/file-max`
+       NFILE=`expr $NFILE / 2`
+       VMEM=`cat /proc/meminfo  | grep MemTotal | (read a b c; echo $b)`
+       # Disabled for now, we need a different to set the security
+       # context limit than fiddling with ulimit
+       #ulimit -H -n $NFILE -v $VMEM
+}
+if [ $# -lt 2 ] ; then
+       usage
+elif [ "$2" = "build" ] ; then
+       # Either the directory does not exist or is empty
+       NBSUB=`ls /vservers/$1 2>/dev/null | grep -v lost+found | wc -l` 
+       NBSUB=`expr $NBSUB`
+       if [ "$NBSUB" != 0 ] ; then
+               echo Virtual server /vservers/$1 already exist
+       else
+               if [ ! -d /vservers ] ; then
+                       mkdir /vservers || exit 1
+                       chmod 000 /vservers
+                       echo Directory /vservers was created with permissions 000
+               fi
+               mkdir -p /vservers/$1 || exit 1
+               chmod 755 /vservers/$1
+               mkdir -p /vservers/$1/{etc/rc.d/init.d,sbin,var/run,var/log}
+               cd /vservers/$1 || exit 1
+               rm -fr lib/modules/*
+               rm -f var/spool/mail/*
+               rm -f `find var/run -type f`
+               rm -f `find var/log -type f`
+               touch var/log/wtmp
+               rm -f var/lock/subsys/*
+               rm -f etc/cron.d/kmod
+               mkdir proc tmp home root boot
+               test -f /root/.bashrc && cp -a /root/.bashrc root/.
+               test -f /root/.bash_profile && cp -a /root/.bash_profile root/.
+               chmod 1777 tmp
+               chmod 750 root
+               # Create a minimal dev so the virtual server can't grab
+               # more privileges
+               mkdir dev dev/pts
+               vserver_mknod dev/null c 1 3 666
+               vserver_mknod dev/zero c 1 5 666
+               vserver_mknod dev/full c 1 7 666
+               vserver_mknod dev/random c 1 8 644
+               vserver_mknod dev/urandom c 1 9 644
+               vserver_mknod dev/tty c 5 0 666
+               vserver_mknod dev/ptmx c 5 2 666
+               touch dev/hdv1
+               # Turn off some service useless on a vserver
+               #               vserver_turnoff apmd network autofs dhcpd gpm ipchains iptables \
+               #                       irda isdn keytable kudzu linuxconf-setup netfs nfs nfslock \
+               #                       pcmcia portmap pppoe random rawdevices rhnsd rstatd ruserd \
+               #                       rwalld rwhod sendmail smb snmpd v_httpd h_xinetd v_sshd vservers \
+               #                       xfs ypbind xinetd
+               (
+                       cd etc/init.d 2>/dev/null || cd etc/rc.d/init.d
+                       for serv in *
+                       do
+                               case $serv in
+                               *.bak|*~|functions|killall|halt|single)
+                                       ;;
+                               *)
+                                       #$USR_LIB_VSERVER/capchroot /vservers/$1 /sbin/chkconfig --level 2345 $serv off
+                                       $0 --silent $1 chkconfig --level 2345 $serv off
+                                       ;;
+                               esac
+                       done
+               )
+               rm -f etc/rc.d/rc6.d/S*reboot
+               # Create a dummy /etc/fstab and /etc/mtab to please
+               # df and linuxconf. We use hdv1, which does not exist
+               # to remind the admin that it is not the real drive
+               echo /dev/hdv1 / ext2 defaults 1 1 >etc/fstab
+               echo /dev/hdv1 / ext2 rw 0 0 >etc/mtab
+               # Install the vreboot utility
+               cp -a $USR_LIB_VSERVER/vreboot sbin/.
+               ln -sf vreboot sbin/vhalt
+
+               echo Directory /vservers/$1 has been populated
+               if [ ! -d /etc/vservers ] ; then
+                       mkdir /etc/vservers
+                       chmod 600 /etc/vservers
+                       echo Directory /etc/vservers has been created
+               fi
+               if [ ! -f /etc/vservers/$1.conf ] ; then
+                       CONF=/etc/vservers/$1.conf
+                       cat >$CONF <<-EOF
+if [ "$PROFILE" = "" ] ; then
+       PROFILE=prod
+fi
+# Select the IP number assigned to the virtual server
+# This IP must be one IP of the server, either an interface
+# or an IP alias
+# A vserver may have more than one IP. Separate them with spaces.
+# do not forget double quotes.
+# Some examples:
+# IPROOT="1.2.3.4 2.3.4.5"
+# IPROOT="eth0:1.2.3.4 eth1:2.3.4.5"
+# If the device is not specified, IPROOTDEV is used
+case \$PROFILE in
+prod)
+       IPROOT=1.2.3.4
+       # The netmask and broadcast are computed by default from IPROOTDEV
+       #IPROOTMASK=
+       #IPROOTBCAST=
+       # You can define on which device the IP alias will be done
+       # The IP alias will be set when the server is started and unset
+       # when the server is stopped
+       #IPROOTDEV=eth0
+       # You can set a different host name for the vserver
+       # If empty, the host name of the main server is used
+       S_HOSTNAME=
+       ;;
+backup)
+       IPROOT=1.2.3.4
+       #IPROOTMASK=
+       #IPROOTBCAST=
+       #IPROOTDEV=eth0
+       S_HOSTNAME=
+       ;;
+esac
+# Uncomment the onboot line if you want to enable this
+# virtual server at boot time
+#ONBOOT=yes
+# You can set a different NIS domain for the vserver
+# If empty, the current on is kept
+# Set it to "none" to have no NIS domain set
+S_DOMAINNAME=
+# You can set the priority level (nice) of all process in the vserver
+# Even root won't be able to raise it
+S_NICE=
+# You can set various flags for the new security context
+# lock: Prevent the vserver from setting new security context
+# sched: Merge scheduler priority of all processes in the vserver
+#        so that it acts a like a single one.
+# nproc: Limit the number of processes in the vserver according to ulimit
+#        (instead of a per user limit, this becomes a per vserver limit)
+# private: No other process can join this security context. Even root
+# Do not forget the quotes around the flags
+S_FLAGS="lock nproc"
+# You can set various ulimit flags and they will be inherited by the
+# vserver. You enter here various command line argument of ulimit
+# ULIMIT="-H -u 200"
+# The example above, combined with the nproc S_FLAGS will limit the
+# vserver to a maximum of 200 processes
+ULIMIT="-H -u 1000"
+# You can set various capabilities. By default, the vserver are run
+# with a limited set, so you can let root run in a vserver and not
+# worry about it. He can't take over the machine. In some cases
+# you can to give a little more capabilities (such as CAP_NET_RAW)
+# S_CAPS="CAP_NET_RAW"
+S_CAPS=""
+# Select an unused context (this is optional)
+# The default is to allocate a free context on the fly
+# In general you don't need to force a context
+#S_CONTEXT=
+                       EOF
+                       echo $CONF has been created. Look at it\!
+               fi
+       fi
+elif [ ! -f /etc/vservers/$1.conf ] ; then
+       echo No configuration for this vserver: /etc/vservers/$1.conf
+       exit 1
+elif [ ! -d /vservers/$1/. ] ; then
+       echo No directory for this vserver: /vservers/$1
+       exit 1
+elif [ "$2" = "start" ] ; then
+       echo Starting the virtual server $1
+       testperm $1
+       if ! $VSERVER_CMD $1 running
+       then
+               test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1
+               IPROOT=
+               IPROOTMASK=
+               IPROOTBCAST=
+               IPROOTDEV=
+               S_NICE=
+               S_FLAGS=
+               . /etc/vservers/$1.conf
+               export PROFILE
+               ifconfig_iproot $1
+               cd /vservers/$1 || exit 1
+
+               if [ "$PROFILE" != "" ] ; then
+                       echo export PROFILE=$PROFILE >etc/PROFILE
+               fi
+
+               rm -f `find var/run -type f`
+               touch var/run/utmp
+               rm -f  var/lock/subsys/*
+               mountproc /vservers/$1
+               CTXOPT=
+               HOSTOPT=
+               DOMAINOPT=
+               NICECMD=
+               FLAGS=
+               CAPS=
+               get_initdefault $1
+               STARTCMD="/etc/rc.d/rc $INITDEFAULT"
+               if [ -x /vservers/$1/etc/init.d/rc ] ; then
+                       STARTCMD="/etc/init.d/rc $INITDEFAULT"
+               fi
+
+               DISCONNECT=
+               FAKEINIT=
+               for f in $S_FLAGS dummy
+               do
+                       case $f in
+                       dummy)
+                               ;;
+
+                        minit)
+                               FAKEINIT=true
+                                FLAGS="$FLAGS --flag fakeinit"
+                                STARTCMD=/sbin/minit-start
+                                DISCONNECT=--disconnect
+                               ;;
+
+                       fakeinit)
+                               FAKEINIT=true
+                               FLAGS="$FLAGS --flag $f"
+                               STARTCMD=/sbin/init
+                               DISCONNECT=--disconnect
+                               ;;
+                       *)
+                               FLAGS="$FLAGS --flag $f"
+                               ;;
+                       esac
+               done
+               if [ "$FAKEINIT" = "" ] ; then
+                       $USR_LIB_VSERVER/fakerunlevel $INITDEFAULT var/run/utmp
+               fi
+
+               calculateCaps $S_CAPS
+
+               if [ "$S_CONTEXT" != "" ] ; then
+                       CTXOPT="--ctx $S_CONTEXT"
+               fi
+               if [ "$S_HOSTNAME" != "" ] ; then
+                       HOSTOPT="--hostname $S_HOSTNAME"
+                       export HOSTNAME=$S_HOSTNAME
+               fi
+               if [ "$S_DOMAINNAME" != "" ] ; then
+                       DOMAINOPT="--domainname $S_DOMAINNAME"
+               fi
+               if [ "$S_NICE" != "" ] ; then
+                       NICECMD="nice -$S_NICE"
+               fi
+               mkdir -p /var/run/vservers
+               chmod 700 /var/run/vservers
+               setdefulimit
+               if [ "$ULIMIT" != "" ] ; then
+                       ulimit $ULIMIT
+               fi
+               #echo FLAGS=$FLAGS
+               #echo CAPS=$CAPS
+               # We switch to /vservers/$1 now, because after the
+               # security context switch /vservers directory becomes a dead zone.
+               cd /vservers/$1
+               IPOPT=`setipopt $IPROOT`
+               export PATH=$DEFAULTPATH
+               $NICECMD $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
+                       $CHCONTEXT_CMD $SILENT $DISCONNECT $CAPS $FLAGS $CTXOPT $HOSTOPT $DOMAINOPT --secure \
+                       $SAVE_S_CONTEXT_CMD /var/run/vservers/$1.ctx \
+                       $CAPCHROOT_CMD $CHROOTOPT . $STARTCMD
+               sleep 2
+               test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-start $1
+       fi
+elif [ "$2" = "running" ] ; then
+       if [ ! -f /var/run/vservers/$1.ctx ] ; then
+               echo Server $1 is not running
+               exit 1
+       else
+               . /var/run/vservers/$1.ctx
+               NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
+               #NB=`$CHCONTEXT_CMD --silent --ctx $S_CONTEXT ps ax | wc -l`
+               #NB=`eval expr $NB + 0`
+               if [ "$NB" -gt 0 ] ; then
+                       echo Server $1 is running
+                       exit 0
+               else
+                       echo Server $1 is not running
+                       exit 1
+               fi
+       fi
+elif [ "$2" = "status" ] ; then
+       if $0 $1 running
+       then
+               . /var/run/vservers/$1.ctx
+               NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
+               echo $NB processes running
+               echo Vserver uptime: `$USR_LIB_VSERVER/filetime /var/run/vservers/$1.ctx`
+       fi
+elif [ "$2" = "stop" ] ; then
+       echo Stopping the virtual server $1
+       IPROOT=
+       IPROOTMASK=
+       IPROOTBCAST=
+       IPROOTDEV=
+       CAPS=
+       IS_MINIT=
+       readlastconf $1
+       if $VSERVER_CMD $1 running
+       then
+               test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-stop $1
+               ifconfig_iproot $1
+               cd /vservers/$1
+               mountproc /vservers/$1
+               # The fakeinit flag tell us how to turn off the server
+               get_initdefault $1
+               export PREVLEVEL=$INITDEFAULT
+               STOPCMD="/etc/rc.d/rc 6"
+               if [ -x /vservers/$1/etc/init.d/rc ] ; then
+                       STOPCMD="/etc/init.d/rc 6"
+               fi
+               for f in $S_FLAGS dummy
+               do
+                       case $f in
+                        minit)
+                               IS_MINIT=1
+                               FLAGS="$FLAGS --flag fakeinit"
+                                STOPCMD="/sbin/minit-stop"
+                                ;;
+
+                       fakeinit)
+                               FLAGS="$FLAGS --flag $f"
+                               STOPCMD="/sbin/init 6"
+                               ;;
+                       *)
+                               ;;
+                       esac
+               done
+
+               calculateCaps $S_CAPS
+
+               cd /vservers/$1
+               IPOPT=`setipopt $IPROOT`
+               export PATH=$DEFAULTPATH
+               $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
+                       $CHCONTEXT_CMD $SILENT $CAPS --secure --ctx $S_CONTEXT \
+                       $CAPCHROOT_CMD . $STOPCMD
+
+               if test "$IS_MINIT"; then
+                   echo "Waiting for minit finish-signal"
+                   dd if=var/run/minit-stop of=/dev/zero bs=1 count=1 &>/dev/null
+                   sleep 1
+               else
+                   echo sleeping 5 seconds
+                   sleep 5
+               fi
+
+               echo Killing all processes
+               $CHBIND_CMD --silent $IPOPT --bcast $IPROOTBCAST \
+                       $CHCONTEXT_CMD $CAPS --secure --silent --ctx $S_CONTEXT \
+                       $VSERVERKILLALL_CMD
+       fi
+       # We umount anyway, because "enter" establish the mount
+       # but when you exit, the server is considered not running
+       umountproc /vservers/$1
+       cd /
+       test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-stop $1
+       ifconfig_iproot_off $1
+elif [ "$2" = "restart" ] ; then
+       if $0 $1 running
+       then
+               $0 $1 stop
+               $0 $1 start
+       fi
+elif [ "$2" = "suexec" ] ; then
+       if [ -z "$3" ] ; then
+               echo "Missing user!" >&2
+               echo "vserver vserver-name suexec user command [ args ... ]" >&2
+               exit 1
+       elif [ -z "$4" ] ; then
+               echo "Missing command and arguments!" >&2
+               echo "vserver vserver-name suexec user command [ args ... ]" >&2
+               exit 1
+       else
+               IPROOT=
+               IPROOTMASK=
+               IPROOTBCAST=
+               IPROOTDEV=
+               readlastconf $1
+               . /etc/vservers/$1.conf
+               cd /vservers/$1
+               ifconfig_iproot $1
+               mountproc /vservers/$1
+               PS1="[\u@vserver:$1 \W]"
+               export PS1
+               VSERVER=$1
+               USERID=$3
+               shift; shift; shift
+               CAPS=
+               for f in $S_CAPS dummy
+               do
+                       case $f in
+                       dummy)
+                               ;;
+                       !CAP_SYS_CHROOT)
+                               CHROOTOPT=--nochroot
+                               ;;
+                       *)
+                               CAPS="$CAPS --cap $f"
+                               ;;
+                       esac
+               done
+               FLAGS=
+               for f in $S_FLAGS dummy
+               do
+                       case $f in
+                        minit)
+                               FLAGS="$FLAGS --flag fakeinit"
+                                ;;
+
+                       dummy)
+                               ;;
+                       *)
+                               FLAGS="$FLAGS --flag $f"
+                               ;;
+                       esac
+               done
+               setdefulimit
+               if [ "$ULIMIT" != "" ] ; then
+                       ulimit $ULIMIT
+               fi
+               if $0 $VSERVER running >/dev/null
+               then
+                       . /var/run/vservers/$VSERVER.ctx
+                       cd /vservers/$VSERVER
+                       IPOPT=`setipopt $IPROOT`
+                       export PATH=$DEFAULTPATH
+                       $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
+                               $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure --ctx $S_CONTEXT \
+                               $CAPCHROOT_CMD --suid $USERID . "$@"
+               else
+                       test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1
+                       CTXOPT=
+                       HOSTOPT=
+                       DOMAINOPT=
+                       if [ "$S_CONTEXT" != "" ] ; then
+                               CTXOPT="--ctx $S_CONTEXT"
+                       fi
+                       if [ "$S_HOSTNAME" != "" ] ; then
+                               HOSTOPT="--hostname $S_HOSTNAME"
+                               export HOSTNAME=$S_HOSTNAME
+                       fi
+                       if [ "$S_DOMAINNAME" != "" ] ; then
+                               DOMAINOPT="--domainname $S_DOMAINNAME"
+                       fi
+                       mkdir -p /var/run/vservers
+                       cd /vservers/$VSERVER
+                       IPOPT=`setipopt $IPROOT`
+                       export PATH=$DEFAULTPATH
+                       $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
+                               $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \
+                               $SAVE_S_CONTEXT_CMD /var/run/vservers/$VSERVER.ctx \
+                               $CAPCHROOT_CMD --suid $USERID $CHROOTOPT . "$@"
+               fi
+       fi
+elif [ "$2" = "exec" ] ; then
+       VSERV=$1
+       shift; shift
+       exec $0 $NODEV $SILENT $VSERV suexec root "$@"
+elif [ "$2" = "enter" ] ; then
+       testperm $1
+       exec $0 $NODEV $SILENT $1 exec /bin/bash -login
+elif [ "$2" = "service" ] ; then
+       VSERVER=$1
+       shift
+       shift
+       exec $0 $NODEV $SILENT $VSERVER exec /sbin/service "$@"
+elif [ "$2" = "chkconfig" ] ; then
+       VSERVER=$1
+       shift
+       shift
+       if [ "$1" = "--level" ] ; then
+               shift
+               LEVELS=$1
+               shift
+       fi
+       if [ $# != 2 -a ! -x /vservers/$VSERVER/sbin/chkconfig ] ; then
+               echo Invalid argument, expected vserver name chkconfig [ --level nnn ] service on\|off
+       elif [ -x /vservers/$VSERVER/sbin/chkconfig ] ; then
+               exec $0 --silent $VSERVER exec /sbin/chkconfig "$@"
+       elif [ -x /vservers/$VSERVER/usr/sbin/update-rc.d ] ; then
+               if [ "$2" = "on" -o "$2" = "start" ] ; then
+                       $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
+                       exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 start 80 2 3 4 5 . stop 20 0 1 6 . >/dev/null
+               elif [ "$2" = "off" -o "$2" = "stop" ] ; then
+                       $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
+                       exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 stop 20 0 1 2 3 4 5 6 . >/dev/null
+               else
+                       echo vserver chkconfig: Expecting on or off
+               fi
+       else
+               echo chkconfig functionality is not available on this
+               echo vserver distribution.
+               echo Looked for /sbin/chkconfig and /usr/sbin/update-rc.d
+       fi
+else
+       echo Command unknown $2
+       echo
+       usage
+fi
+
diff --git a/util-vserver/scripts/vserver-copy b/util-vserver/scripts/vserver-copy
new file mode 100755 (executable)
index 0000000..deb6f9f
--- /dev/null
@@ -0,0 +1,373 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vserver-copy by Mark Lawrence <nomad@null.net>
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Copy/Sync a virtual host from one machine to another
+#
+# History:
+#
+# 2003-04-04: Version 0.4 - Mark lawrence
+# - Set "ONBOOT=no" in the destination .conf file when --startstop
+#   is not used, in case the destination roothost reboots. We don't
+#   want two copies of a vserver running at the same time.
+#
+# 2003-03-04: Version 0.3 - Mark lawrence
+# - Changed all checks for [ "" != "$var" ] into [ -n|-z "$var" ]. "" doesn't
+#   seem to work for bash on the Sparc architecture.
+# - Changed $ssh variable into $shcmd.
+#
+# 2003-02-23: Version 0.2 - Mark Lawrence
+# - Set ONBOOT to "no" in the original .conf file when the "-s" flag is 
+#   used so that if/when you reboot the source roothost you don't have the
+#   same vserver and IP address running on two machines.
+
+VERSION="0.4"
+umask 022
+me=${0##*/}
+
+
+### Helper functions ###
+
+# Save stdin and stdout for later use
+exec 3>&1
+exec 4>&2
+
+noninteractive () {
+       exec &> /dev/null
+}
+
+interactive () {
+       exec 1>&3
+       exec 2>&4
+}
+
+info () {
+       ! $quiet && echo "I: $me: $1" >&3
+}
+
+warn () {
+       ! $quiet && echo "W: $me: $1" >&4
+}
+
+error () {
+       ! $quiet && echo "E: $me: $2" >&4
+       exit $1
+}
+
+
+### Usage/Info functions ###
+
+usage () {
+    cat <<EOF 1>&2
+Usage: $me [-hVvqidrRs] vserver newname
+       $me [-hVvqidrRs] vserver host:[newname]
+EOF
+}
+
+full_usage () {
+       usage
+        cat <<EOF
+
+$me uses rsync to make a copy of a vserver. If the destination
+name contains a host specification the vserver will be synchronised to
+the remote destination over ssh/rsh.
+
+This can be used on a running vserver to make a warm backup. With the -s
+flag a vserver can even be operationally moved to different hardware within
+seconds.
+
+The -i and -d flags can be used to minimally reconfigure the destination
+vserver (rewrites /etc/vservers/newname.conf and /vservers/newname/etc/hosts)
+
+Options:
+       -h, --help              this help
+       -V, --version           copyright and version information
+       -v, --verbose           show all output
+       -q, --quiet             direct all output to /dev/null (no password
+                               prompt for logins on remote hosts!)
+       -d, --domain [string]   new dns domain (must be used with -i)
+       -i, --ip [addr]         new IP address (must be used with -d)
+       -r, --vsroot            location of "/vserver/" directory
+       -R, --rsh               use rsh (instead of default ssh) for
+                               network transport
+       -s, --stopstart         stop the local vserver before copying and start
+                               it on the destination host afterwards
+
+EOF
+}
+
+full_version () {
+    cat <<EOF
+$me version $VERSION
+Copyright (c) 2002 Mark Lawrence   <nomad@null.net>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+EOF
+}
+
+
+### Default values and Command line options ###
+
+stopstart=(false)
+verbose=(false)
+quiet=(false)
+shcmd="ssh"
+rsflag="-e"
+rsh=(false)
+colon=":"
+domain=""
+ip=""
+vsroot="/vservers"
+
+if [ $# -eq 0 ]; then  # Script invoked with no command-line args?
+       usage
+       exit 1
+fi  
+
+temp=$(getopt -o hVvqd:i:rRs --long help,version,verbose,quiet,domain:,ip:,vsroot,rsh,stopstart, -n $me -- "$@")
+
+if [ $? -ne 0 ]; then
+       echo "  (See -h for help)"
+        exit 1
+fi
+
+# Note the quotes around `$temp': they are essential!
+eval set -- "$temp"
+
+while true; do
+        case "$1" in
+               -h|--help)      full_usage
+                               exit 1
+                               ;;
+               -V|--version)   full_version
+                               exit 1
+                               ;;
+               -v|--verbose)   verbose=(true)
+                               shift
+                               ;;
+               -q|--quiet)     quiet=(true)
+                               shift
+                               ;;
+               -d|--domain)    domain="$2"
+                               shift 2
+                               ;;
+               -i|--ip)        ip="$2"
+                               shift 2
+                               ;;
+               -r|--vsroot)    vsroot="$2"
+                               shift 2
+                               ;;
+               -R|--rsh)       rsh=(true)
+                               shift
+                               ;;
+               -s|--stopstart) stopstart=(true)
+                               shift
+                               ;;
+                --)             shift
+                               break
+                               ;;
+               *)              echo "Internal error!"
+                               exit 1
+                               ;;
+       esac
+done
+
+if [ $# -ne 2 ]; then
+       usage
+       exit 1
+fi
+
+
+### ###
+
+# By default we are reasonably quiet (ouput only via info, warn & error)
+if $verbose; then
+       interactive
+else
+       noninteractive
+fi
+
+now=$(date)
+info "called on $(hostname) at $now"
+
+
+vserver=$1
+vconf=/etc/vservers/$vserver.conf
+vroot=$vsroot/$vserver
+
+if $rsh; then
+       shcmd="rsh"
+fi
+
+if (echo $2 | grep '^[a-z][a-z0-9]\+$'); then
+       dhost=""
+       newname=$2
+       shcmd=""
+       rsflag=""
+       colon=""
+       if $rsh; then
+               warn "rsh is set but not used for a local copy"
+       fi
+elif (echo $2 | grep '^[a-z].*[a-z0-9]:$'); then
+       dhost=${2/:/}
+       newname=$vserver
+elif (echo $2 | grep '^[a-z].*[a-z0-9]:[a-z].*[a-z0-9]$'); then
+       dhost=${2/:*/}
+       newname=${2/*:/}
+else
+       error 1 "Second argument must be of the form \"[host:]name\" or \"host:\""
+fi
+
+target=$vsroot/$newname
+targetconf=/etc/vservers/$newname.conf
+
+
+### Perform some sanity checks ###
+
+if [ ! -d $vroot ]; then
+       error 1 "Directory \"$vroot\" does not exist"
+fi
+
+if [ ! -e $vconf ]; then
+       error 1 "Vserver file \"$vconf\" does not exist"
+fi
+
+if [ -z "$dhost" ] && [ "$vserver" == "$newname" ]; then
+       error 1 "Source and destination names cannot be the same on the localhost"
+fi
+
+if [ -n "$dhost" ] && ! (host $dhost | grep 'has address'); then
+       warn "$dhost does not resolve into an IP address"
+fi
+
+if [ \( -n "$ip" -a -z "$domain" \) -o \
+     \( -z "$ip" -a -n "$domain" \) ]
+then
+       error 1 "Both IP address and domain must be specified together"
+fi
+
+if [ -n "$ip" ] && \
+! (echo $ip | grep '^[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}$' ); then
+       error 1 "\"$ip\" is not a valid IP address"
+fi
+
+# This works both locally and remote
+if ($shcmd $dhost /usr/sbin/vserver $newname running | grep 'is running'); then
+       warn "destination vserver \"$newname\" is running" 
+       error 1 "Cannot copy over a running vserver"
+fi
+
+
+### Do the copy ###
+
+info "Attempting to copy $vserver to $dhost$colon$newname"
+
+if $stopstart; then
+       info "Stopping virtual server \"$vserver\" on localhost"
+       /usr/sbin/vserver $vserver stop
+fi
+
+info "Syncing directories"
+# trailing slashes very important in the rsync!
+if ! rsync -avxz $rsflag $shcmd $vroot/ $dhost$colon$target/; then
+       error 1 "rsync failed"
+fi
+
+if [ -n "$ip" -a -n "$domain" ]; then
+       # Insert the new IPROOT/S_HOSTNAME values into the config file
+       info "Modifying $targetconf"
+       tmpf=$(tempfile)
+       if (sed -e "s/^S_HOSTNAME=.*/S_HOSTNAME=\"$newname\"/" \
+               -e "s/^IPROOT=.*/IPROOT=\"$ip\"/" $vconf > $tmpf)
+       then
+               if ! rsync -v $rsflag $shcmd $tmpf $dhost$colon$targetconf; then
+                       error $? "vserver config file copy/change failed"
+               fi
+
+       else
+               warn "Unable to reconfigure virtual server config file"
+       fi
+
+       # create a new /etc/hostname
+       info "Creating hostname file"
+       echo $newname > $tmpf
+       if ! rsync -v $rsflag $shcmd $tmpf $dhost$colon$target/etc/hostname; then
+               error 1 "vserver /etc/hostname copy failed"
+       fi
+
+       info "Creating /etc/hosts"
+       cat << EOF > $tmpf
+# /etc/hosts (automatically generated by $me)
+
+127.0.0.1       localhost
+$ip    $newname.$domain        $newname
+
+# The following lines are desirable for IPv6 capable hosts
+
+::1     ip6-localhost ip6-loopback
+fe00::0 ip6-localnet
+ff00::0 ip6-mcastprefix
+ff02::1 ip6-allnodes
+ff02::2 ip6-allrouters
+ff02::3 ip6-allhosts
+EOF
+
+       # copy /etc/hosts
+       if ! rsync -v $rsflag $shcmd $tmpf $dhost$colon$target/etc/hosts; then
+               error 1 "vserver /etc/hosts copy failed"
+       fi
+       rm -f $tmpf
+
+else
+       if ! $stopstart; then
+               # Make sure that this vserver doesn't start on the 
+               # destination host if it reboots
+               tmpf=$(tempfile)
+               sed -e 's/^ONBOOT=.*/ONBOOT=no/' $vconf > $tmpf
+               vconf=$tmpf
+       fi
+
+       # copy newname.conf unchanged
+       info "Copying $targetconf"
+       if ! rsync -v $rsflag $shcmd $vconf $dhost$colon$targetconf; then
+               error 1 "vserver config file copy/change failed"
+       fi
+
+       rm -f $tmpf
+fi
+
+
+if $stopstart; then
+       info "Starting virtual server \"$vserver\" on $dhost"
+       $shcmd $dhost /usr/sbin/vserver $vserver start
+       if ($shcmd $dhost /usr/sbin/vserver $vserver running | \
+       grep 'not running'); then
+               error 1 "Virtual server \"$vserver\" failed to start on $dhost"
+       fi
+
+       # Make sure that we don't start the original on next boot
+       tmpf=$(tempfile)
+       sed -e 's/^ONBOOT=.*/ONBOOT=no/' $vconf > $tmpf
+       mv $tmpf $vconf
+fi
+
+exit 0
diff --git a/util-vserver/scripts/vserverkillall b/util-vserver/scripts/vserverkillall
new file mode 100755 (executable)
index 0000000..f49f339
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vserverkillall by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This script kills all process it can finds
+# Only useful if you are using a security context.
+# It does nothing in context 0
+USR_LIB_VSERVER=$(dirname $0)
+CTX=`grep ^s_context /proc/self/status | sed s/s_context:// | (read a b; echo $a)`
+CTX=`eval expr $CTX + 0`
+if [ "$CTX" = 0 ] ; then
+       echo Running in security context 0, do nothing
+else
+       cd /proc
+       for SIG in -TERM -TERM -TERM -9
+       do
+               ONE=0
+               for dir in *
+               do
+                       case $dir in
+                       1)
+                               ;;
+                       $$)
+                               ;;
+                       [1-9]*)
+                               ONE=1
+                               echo kill $SIG "`$USR_LIB_VSERVER/readlink /proc/$dir/exe`"[$dir]
+                               kill $SIG $dir
+                               ;;
+                       *)
+                               ;;
+                       esac
+               done
+               if [ "$ONE" = 0 ] ; then
+                       break
+               fi
+               sleep 1
+       done
+       # Kill the fakeinit process. It is shown as process one, but can't
+       # be killed this way
+       INITPID=`cat /proc/self/status | grep initpid: | (read a b; expr $b)`
+       if [ "$INITPID" != "0" ] ; then
+               echo kill init, pid $INITPID
+               kill -9 $INITPID
+       fi
+fi
+
+
diff --git a/util-vserver/scripts/vservers.grabinfo.sh b/util-vserver/scripts/vservers.grabinfo.sh
new file mode 100644 (file)
index 0000000..21de103
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vservers.grabinfo.sh by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Produce some XML statistics about vservers
+
+: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+    echo "Can not find util-vserver installation; aborting..."
+    exit 1
+}
+. "$UTIL_VSERVER_VARS"
+
+cd /vservers
+for vserv in *
+do
+       if [ -f /etc/vservers/$vserv.conf ] ; then
+               . /etc/vservers/$vserv.conf
+               echo "<m:vserver name=\"$vserv\" onboot=\"$ONBOOT\" HOSTNAME=\"$S_HOSTNAME\">"
+               for ip in $IPROOT
+               do
+                       case $ip in
+                       *:*)
+                               echo $ip | tr ':' ' ' | (read a b; echo "  <m:ip num=\"$b\"/>")
+                               ;;
+                       *)
+                               echo "  <m:ip num=\"$ip\"/>"
+                               ;;
+                       esac
+               done
+               echo "  <status>"
+               $SBINDIR/vserver $vserv status
+               echo "  </status>"
+               echo "</m:vserver>"
+       fi
+done
+
diff --git a/util-vserver/scripts/vsysvwrapper b/util-vserver/scripts/vsysvwrapper
new file mode 100755 (executable)
index 0000000..309a9d1
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vsyswrapper by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Helper script for all the v_xxx scripts
+USR_SBIN=/usr/sbin
+if [ $# = 0 ] ; then
+       echo vsysvwrapper service_name >&2
+else
+       SERVICE=$1
+       shift
+       IP=eth0
+       if [ -f /etc/vservices/$SERVICE.conf ] ; then
+               . /etc/vservices/$SERVICE.conf
+       fi
+       IPOPT=
+       for oneip in $IP
+       do
+               IPOPT="$IPOPT --ip $oneip"
+       done
+       echo exec $USR_SBIN/chbind $IPOPT /etc/init.d/$SERVICE $*
+       exec $USR_SBIN/chbind $IPOPT /etc/init.d/$SERVICE $*
+fi
+
+
diff --git a/util-vserver/scripts/vtop b/util-vserver/scripts/vtop
new file mode 100755 (executable)
index 0000000..0b4585c
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vtop by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#Presents the processes running in all virtual servers
+exec /usr/sbin/chcontext --silent --ctx 1 top $*
+
+
diff --git a/util-vserver/scripts/vunify.old.sh b/util-vserver/scripts/vunify.old.sh
new file mode 100755 (executable)
index 0000000..50c960e
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vunify by Jacques Gelinas
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This scripts is used to unify the disk space used by vservers
+# It takes various RPM packages and hard link them together so all
+# vservers are sharing the same exact copy of the files.
+# After doing so, it set them immutable, so the vserver can't change them
+
+# This has the following advantages:
+#      -You save disk space. If you have 100 vservers, each using 500 megs
+#       (common linux server installation), you can unify 90% of that
+#      -Memory usage. Since the exact same binary are loaded, including
+#       the same shared object, you save some memory and this can increase
+#       performance, especially the memory cache usage.
+#
+# On the down side, you are loosing some flexibility. The vserver
+# administrators can't upgrade package as they see fit, since the
+# files are immutable. On the other end, just unifying glibc is probably
+# a win.
+if [ $# = 0 ] ; then
+       echo vunify [ --undo ] ref-vserver vservers -- packages
+else
+       undo=0
+       if [ "$1" == "--undo" ] ; then
+               undo=1
+               shift
+       fi
+       ref=$1
+       shift
+       servers=
+       while [ "$1" != "" -a "$1" != "--" ]
+       do
+               servers="$servers $1"
+               shift
+       done
+       if [ "$servers" = "" ] ; then
+               echo No vserver specified >&2
+               exit 1
+       elif [ "$1" != "--" ] ; then
+               echo Missing -- marker >&2
+               exit 1
+       else
+               shift
+               if [ $# = 0 ] ; then
+                       echo No package specified >&2
+                       exit 1
+               else
+                       if [ ! -d /vservers/$ref/. ] ; then
+                               echo No vserver $ref >&2
+                               exit 1
+                       else
+                               #echo ref=$ref
+                               #echo servers=$servers
+                               #echo packages=$*
+                               tmpfile=/var/run/vunifi.$$
+                               rm -f $tmpfile
+                               echo Extracting list of file to unify in $tmpfile
+                               for pkg in $*
+                               do
+                                       /vservers/$ref/bin/rpm --root /vservers/$ref -ql --dump $pkg | \
+                                       while read path size mtime md5 \
+                                               mode owner group isconfig isdoc rdev symlink
+                                       do
+                                               if [ "$isconfig" = 0 ] ; then
+                                                       echo $path >>$tmpfile
+                                               fi
+                                       done
+                               done
+                               for serv in $servers
+                               do
+                                       if [ "$undo" = 0 ] ; then
+                                               echo Unifying server $serv
+                                               cat $tmpfile | while read file
+                                               do
+                                                       if [ ! -d /vservers/$ref/$file -a ! -L /vservers/$ref/$file ] ; then
+                                                               ln -f /vservers/$ref/$file /vservers/$serv/$file
+                                                       fi
+                                               done
+                                               cat $tmpfile | while read file
+                                               do
+                                                       chattr +i /vservers/$ref/$file
+                                               done
+                                       else
+                                               echo Differencing server $serv
+                                               cat $tmpfile | while read file
+                                               do
+                                                       chattr -i /vservers/$ref/$file
+                                                       if [ ! -d /vservers/$ref/$file ] ; then
+                                                               rm -f /vservers/$serv/$file
+                                                               cp -a /vservers/$ref/$file /vservers/$serv/$file
+                                                       fi
+                                               done
+                                       fi
+                               done
+                               rm -f $tmpfile 
+                       fi
+               fi
+       fi
+fi
+
diff --git a/util-vserver/src/Makefile-files b/util-vserver/src/Makefile-files
new file mode 100644 (file)
index 0000000..54fbf47
--- /dev/null
@@ -0,0 +1,84 @@
+## $Id$  -*- makefile -*-
+
+## Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+src_HDRS               =  src/vutil.h src/vutil.p
+
+src_pkglib_PRGS                =  src/capchroot \
+                          src/fakerunlevel \
+                          src/filetime \
+                          src/ifspec \
+                          src/listdevip \
+                          src/parserpmdump \
+                          src/readlink \
+                          src/showattr \
+                          src/showperm \
+                          src/vbuild \
+                          src/vcheck \
+                          src/vreboot \
+                          src/vunify
+
+src_sbin_PRGS          =  src/chbind \
+                          src/chcontext \
+                          src/rebootmgr \
+                          src/reducecap \
+                          src/setctxlimit \
+                          src/vdu \
+                          src/vfiles \
+                          src/vserver-stat
+
+src_capchroot_SOURCES          =  src/capchroot.c
+src_capchroot_LDADD            =  lib/libvserver.a
+
+src_chbind_SOURCES             =  src/chbind.c
+src_chbind_LDADD               =  lib/libvserver.a
+
+src_chcontext_SOURCES          =  src/chcontext.c
+src_chcontext_LDADD            =  lib/libvserver.a
+
+src_fakerunlevel_SOURCES       =  src/fakerunlevel.c
+src_filetime_SOURCES           =  src/filetime.c
+src_ifspec_SOURCES             =  src/ifspec.c
+src_listdevip_SOURCES          =  src/listdevip.c
+src_parserpmdump_SOURCES       =  src/parserpmdump.c
+src_readlink_SOURCES           =  src/readlink.c
+src_rebootmgr_SOURCES          =  src/rebootmgr.c
+
+src_reducecap_SOURCES          =  src/reducecap.c
+src_reducecap_LDADD            =  lib/libvserver.a
+
+src_setctxlimit_SOURCES                =  src/setctxlimit.c
+src_setctxlimit_LDADD          =  lib/libvserver.a
+
+src_showattr_SOURCES           =  src/showattr.c
+src_showperm_SOURCES           =  src/showperm.c
+src_vbuild_SOURCES             =  src/vbuild.cc src/vutil.cc
+src_vdu_SOURCES                        =  src/vdu.c
+src_vfiles_SOURCES             =  src/vfiles.cc src/vutil.cc
+src_vreboot_SOURCES            =  src/vreboot.c
+
+src_vserver_stat_SOURCES       =  src/vserver-stat.c
+src_vserver_stat_LDADD         =  lib/libvserver.a
+
+src_vunify_SOURCES             =  src/vunify.cc src/vutil.cc
+src_vcheck_SOURCES             =  src/vcheck.cc src/vutil.cc
+
+
+## Local Variables:
+## compile-command: "make -C .. -k"
+## End:
diff --git a/util-vserver/src/capchroot.c b/util-vserver/src/capchroot.c
new file mode 100644 (file)
index 0000000..50f03bf
--- /dev/null
@@ -0,0 +1,118 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on capchroot.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       This chroot command does very little. Once the chroot
+       system call is executed, it (option) remove the CAP_SYS_CHROOT
+       capability. Then it executes its argument
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "linuxcaps.h"
+#include "vserver.h"
+
+static int my_chroot(const char *dir)
+{
+       int ret = -1;
+       if (has_chrootsafe()){
+               ret = call_chrootsafe(dir);
+       }else{
+           //fprintf (stderr,"Kernel do not support chrootsafe(), using chroot()\n");
+               ret = chroot (dir);
+       }
+       return ret;
+}
+
+int main (int argc, char *argv[])
+{
+       if (argc < 3){
+               fprintf (stderr,"capchroot version %s\n",VERSION);
+               fprintf (stderr
+                       ,"capchroot --nochroot directory [ --suid user ] command argument\n"
+                        "\n"
+                        "--nochroot remove the CAP_SYS_CHROOT capability\n"
+                        "           after the chroot system call.\n"
+                        "--suid switch to a different user (in the vserver context)\n"
+                        "       before executing the command.\n");
+       }else{
+               const char *uid = NULL;
+               bool nochroot = false;
+               int dir;
+               for (dir=1; dir<argc; dir++){
+                       const char *arg = argv[dir];
+                       if (arg[0] != '-' && arg[1] != '-'){
+                               break;
+                       }else if (strcmp(arg,"--nochroot")==0){
+                               nochroot = true;
+                       }else if (strcmp(arg,"--suid")==0){
+                               dir++;
+                               uid = argv[dir];
+                       }
+                       
+               }
+               // We resolve the UID before doing the chroot.
+               // If we do the getpwnam after the chroot, we will end
+               // up loading shared object from the vserver.
+               // This is causing two kind of problem: Incompatibilities
+               // and also a security flaw. The shared objects in the vserver
+               // may be tweaked to get control of the root server ...
+               getpwnam ("root");
+               if (my_chroot (argv[dir]) == -1){
+                       fprintf (stderr,"Can't chroot to directory %s (%s)\n",argv[dir]
+                               ,strerror(errno));
+               }else{
+                       struct passwd *p = NULL;
+                       int cmd          = dir + 1;
+
+                       if (nochroot){
+                               call_new_s_context (0,NULL,1<<CAP_SYS_CHROOT,0);
+                       }
+
+                       if (uid != NULL && strcmp(uid,"root")!=0){
+                               p = getpwnam(uid);
+                               if (p == NULL){
+                                       fprintf (stderr,"User not found: %s\n",uid);
+                                       exit (-1);
+                               }
+                       }
+                       if (p != NULL) {
+                               setgroups (0,NULL);
+                               setgid(p->pw_gid);
+                               setuid(p->pw_uid);
+                       }
+                       if (cmd >= argc){
+                               fprintf (stderr,"capchroot: No command to execute, do nothing\n");
+                       }else{
+                               execvp (argv[cmd],argv+cmd);
+                               fprintf (stderr,"Can't execute %s (%s)\n",argv[cmd]
+                                       ,strerror(errno));
+                       }
+               }
+       }
+       return -1;
+}
+
+
diff --git a/util-vserver/src/chbind.c b/util-vserver/src/chbind.c
new file mode 100644 (file)
index 0000000..e190c15
--- /dev/null
@@ -0,0 +1,229 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on chbind.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "vserver.h"
+
+static void usage()
+{
+       fprintf (stderr,"chbind version %s\n",VERSION);
+       fprintf (stderr,"chbind [ --silent ] [ --ip ip_num[/mask] ] [ --bcast broadcast ] command argument\n");
+       exit (-1);
+}
+
+/*
+       Check if a network device exist in /proc/net/dev.
+       This is used because ifconfig_ioctl triggers modprobe if requesting
+       information about non existant devices.
+
+       Return != 0 if the device exist.
+*/
+static int chbind_devexist (const char *dev)
+{
+       int ret = 0;
+       FILE *fin = fopen ("/proc/net/dev","r");
+       if (fin != NULL){
+               int len = strlen(dev);
+               char buf[1000];
+               fgets(buf,sizeof(buf)-1,fin);   // Skip one line
+               while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
+                       const char *pt = strstr(buf,dev);
+                       if (pt != NULL && pt[len] == ':'){
+                               ret = 1;
+                               break;
+                       }
+               }
+               fclose (fin);
+       }
+       return ret;
+}
+
+
+static int ifconfig_ioctl(
+       int fd,
+       const char *ifname,
+       int cmd,
+       struct ifreq *ifr)
+{
+       strcpy(ifr->ifr_name, ifname);
+       return ioctl(fd, cmd,ifr);
+}
+
+/*
+       Fetch the IP number of an interface from the kernel.
+       Assume the device is already available in the kernel
+       Return -1 if any error.
+*/
+int ifconfig_getaddr (
+       const char *ifname,
+       unsigned long *addr,
+       unsigned long *mask,
+       unsigned long *bcast)
+{
+       int ret = -1;
+       if (chbind_devexist(ifname)){
+               int skfd = socket(AF_INET, SOCK_DGRAM, 0);
+               *addr = 0;
+               *bcast = 0xffffffff;
+               if (skfd != -1){
+                       struct ifreq ifr;
+                       if (ifconfig_ioctl(skfd,ifname,SIOCGIFADDR, &ifr) >= 0){
+                               struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+                               *addr = sin->sin_addr.s_addr;
+                               ret = 0;
+                       }
+                       if (ifconfig_ioctl(skfd,ifname,SIOCGIFNETMASK, &ifr) >= 0){
+                               struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+                               *mask = sin->sin_addr.s_addr;
+                               ret = 0;
+                       }
+                       if (ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){
+                               struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+                               *bcast = sin->sin_addr.s_addr;
+                               ret = 0;
+                       }
+                       close (skfd);
+               }
+       }
+       return ret;
+}
+
+
+
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       int silent = 0;
+       int i;
+       unsigned long addrs[16],masks[16];
+       int nbaddrs = 0;
+       unsigned long bcast = 0xffffffff;
+       for (i=1; i<argc; i++){
+               const char *arg = argv[i];
+               const char *opt = argv[i+1];
+               if (strcmp(arg,"--ip")==0){
+                       unsigned long addr,mask;
+                       if (nbaddrs == 16){
+                               fprintf (stderr,"Too many IP numbers, max 16, ignored\n");
+
+                       }else if (ifconfig_getaddr(opt,&addr,&mask,&bcast)==-1){
+                               unsigned long mask = 0x00ffffff;
+                               const char *pt = strchr(opt,'/');
+                               char tmpopt[strlen(opt)+1];
+                               struct hostent *h;
+                               
+                               if (pt != NULL){
+                                       strcpy (tmpopt,opt);
+                                       tmpopt[pt-opt] = '\0';
+                                       opt = tmpopt;
+                                       pt++;
+                                       if (strchr(pt,'.')==NULL){
+                                               // Ok, we have a network size, not a netmask
+                                               int size = atoi(pt);
+                                               int i;
+                                               mask = 0;
+                                               for (i=0; i<size; i++){
+                                                       mask = mask >> 1;
+                                                       mask |= 0x80000000;
+                                               }
+                                               mask = ntohl(mask);
+                                       }else{
+                                               struct hostent *h = gethostbyname (pt);
+                                               if (h != NULL){
+                                                       memcpy (&mask,h->h_addr,sizeof(mask));
+                                               }else{
+                                                       fprintf (stderr,"Invalid netmask: %s\n",pt);
+                                                       usage();
+                                               }
+                                       }
+                                                       
+                               }
+
+                               h = gethostbyname (opt);
+                               if (h == NULL){
+                                       fprintf (stderr,"Invalid IP number or host name: %s\n",opt);
+                                       usage();
+                               }else{
+                                       memcpy (&addr,h->h_addr,sizeof(addr));
+                                       masks[nbaddrs] = mask;
+                                       addrs[nbaddrs++] = addr;
+                               }
+                       }else{
+                               masks[nbaddrs] = mask;
+                               addrs[nbaddrs++] = addr;
+                       }
+                       i++;
+               }else if (strcmp(arg,"--bcast")==0){
+                       unsigned long tmp;
+                       if (ifconfig_getaddr(opt,&tmp,&tmp,&bcast)==-1){
+                               struct hostent *h = gethostbyname (opt);
+                               if (h == NULL){
+                                       fprintf (stderr,"Invalid broadcast number: %s\n",opt);
+                                       usage();
+                               }else{
+                                       memcpy (&bcast,h->h_addr,sizeof(bcast));
+                               }
+                       }
+                       i++;
+               }else if (strcmp(arg,"--silent")==0){
+                       silent = 1;
+               }else{
+                       break;
+               }
+       }
+       if (i == argc){
+               usage();
+       }else if (argv[i][0] == '-'){
+               usage();
+       }else{
+               if (call_set_ipv4root(addrs,nbaddrs,bcast,masks)==0){
+                       if (!silent){
+                               int i;
+                               printf ("ipv4root is now");
+                               for (i=0; i<nbaddrs; i++){
+                                       unsigned long hostaddr = ntohl(addrs[i]);
+                                       printf (" %ld.%ld.%ld.%ld"
+                                               ,hostaddr>>24
+                                               ,(hostaddr>>16)&0xff
+                                               ,(hostaddr>>8)&0xff
+                                               ,hostaddr &0xff);
+                               }
+                               printf ("\n");
+                       }
+                       execvp (argv[i],argv+i);
+                       fprintf (stderr,"Can't exec %s (%s)\n",argv[i],strerror(errno));
+               }else{
+                       fprintf (stderr,"Can't set the ipv4 root (%s)\n",strerror(errno));
+               }
+       }
+       return ret;
+}
+
+
diff --git a/util-vserver/src/chcontext.c b/util-vserver/src/chcontext.c
new file mode 100644 (file)
index 0000000..af60dec
--- /dev/null
@@ -0,0 +1,283 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on chcontext.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       chcontext is a wrapper to user the new_s_context system call. It
+       does little more than mapping command line option to the system call
+       arguments.
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "linuxcaps.h"
+#include "vserver.h"
+
+static void usage()
+{
+       fprintf (stderr,"chcontext version %s\n",VERSION);
+       fprintf (stderr
+               ,"chcontext [ options ] command arguments ...\n"
+                "\n"
+                "chcontext allocate a new security context and executes\n"
+                "a command in that context.\n"
+                "By default, a new/unused context is allocated\n"
+                "\n"
+
+                "--cap CAP_NAME\n"
+                "\tAdd a capability from the command. This option may be\n"
+                "\trepeated several time.\n"
+                "\tSee /usr/include/linux/capability.h\n"
+                "\tIn general, this option is used with the --secure option\n"
+                "\t--secure removes most critical capabilities and --cap\n"
+                "\tadds specific ones.\n"
+                "\n"
+
+                "--cap !CAP_NAME\n"
+                "\tRemove a capability from the command. This option may be\n"
+                "\trepeated several time.\n"
+                "\tSee /usr/include/linux/capability.h\n"
+                "\n"
+                "--ctx num\n"
+                "\tSelect the context. On root in context 0 is allowed to\n"
+                "\tselect a specific context.\n"
+                "\tContext number 1 is special. It can see all processes\n"
+                "\tin any contexts, but can't kill them though.\n"
+                "\tOption --ctx may be repeated several times to specify up to 16 contexts.\n"
+
+                "--disconnect\n"
+                "\tStart the command in background and make the process\n"
+                "\ta child of process 1.\n"
+
+                "--domainname new_domainname\n"
+                "\tSet the domainname (NIS) in the new security context.\n"
+                "\tUse \"none\" to unset the domain name.\n"
+
+                "--flag\n"
+                "\tSet one flag in the new or current security context. The following\n"
+                "\tflags are supported. The option may be used several time.\n"
+                "\n"
+                "\tfakeinit: The new process will believe it is process number 1.\n"
+                "            Useful to run a real /sbin/init in a vserver.\n"
+                "\tlock: The new process is trapped and can't use chcontext anymore.\n"
+                "\tsched: The new process and its children will share a common \n"
+                "         execution priority.\n"
+                "\tnproc: Limit the number of process in the vserver according to\n"
+                "         ulimit setting. Normally, ulimit is a per user thing.\n"
+                "         With this flag, it becomes a per vserver thing.\n"
+                "\tprivate: No one can join this security context once created.\n"
+                "\tulimit: Apply the current ulimit to the whole context\n"
+
+                "--hostname new_hostname\n"
+                "\tSet the hostname in the new security context\n"
+                "\tThis is need because if you create a less privileged\n"
+                "\tsecurity context, it may be unable to change its hostname\n"
+
+                "--secure\n"
+                "\tRemove all the capabilities to make a virtual server trustable\n"
+
+                "--silent\n"
+                "\tDo not print the allocated context number.\n"
+                "\n"
+                "Information about context is found in /proc/self/status\n");
+}
+
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       int i;
+       int nbctx = 0;
+       int ctxs[16];
+       int disconnect = 0;
+       int fakeinit = 0;
+       int silent = 0;
+       int flags = 0;
+       unsigned remove_cap = 0;
+       unsigned add_cap = 0;
+       unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
+               |(1<<CAP_NET_BROADCAST)
+               |(1<<CAP_NET_ADMIN)
+               |(1<<CAP_NET_RAW)
+               |(1<<CAP_IPC_LOCK)
+               |(1<<CAP_IPC_OWNER)
+               |(1<<CAP_SYS_MODULE)
+               |(1<<CAP_SYS_RAWIO)
+               |(1<<CAP_SYS_PACCT)
+               |(1<<CAP_SYS_ADMIN)
+               |(1<<CAP_SYS_BOOT)
+               |(1<<CAP_SYS_NICE)
+               |(1<<CAP_SYS_RESOURCE)
+               |(1<<CAP_SYS_TIME)
+               |(1<<CAP_MKNOD);
+       const char *hostname=NULL, *domainname=NULL;
+
+       for (i=1; i<argc; i++){
+               const char *arg = argv[i];
+               const char *opt = argv[i+1];
+               if (strcmp(arg,"--ctx")==0){
+                       if (nbctx >= 16){
+                               fprintf (stderr,"Too many context, max 16, ignored.\n");
+                       }else{
+                               ctxs[nbctx++] = atoi(opt);
+                       }
+                       i++;
+               }else if (strcmp(arg,"--disconnect")==0){
+                       disconnect = 1;
+               }else if (strcmp(arg,"--silent")==0){
+                       silent = 1;
+               }else if (strcmp(arg,"--flag")==0){
+                       if (strcmp(opt,"lock")==0){
+                               flags |= 1;
+                       }else if (strcmp(opt,"sched")==0){
+                               flags |= 2;
+                       }else if (strcmp(opt,"nproc")==0){
+                               flags |= 4;
+                       }else if (strcmp(opt,"private")==0){
+                               flags |= 8;
+                       }else if (strcmp(opt,"fakeinit")==0){
+                               fakeinit = 1;
+                               flags |= 16;
+                       }else if (strcmp(opt,"hideinfo")==0){
+                               flags |= 32;
+                       }else if (strcmp(opt,"ulimit")==0){
+                               flags |= 64;
+                       }else{
+                               fprintf (stderr,"Unknown flag %s\n",opt);
+                       }
+                       i++;
+               }else if (strcmp(arg,"--cap")==0){
+                       static struct {
+                               const char *option;
+                               int bit;
+                       }tbcap[]={
+                               // The following capabilities are normally available
+                               // to vservers administrator, but are place for
+                               // completeness
+                               {"CAP_CHOWN",CAP_CHOWN},
+                               {"CAP_DAC_OVERRIDE",CAP_DAC_OVERRIDE},
+                               {"CAP_DAC_READ_SEARCH",CAP_DAC_READ_SEARCH},
+                               {"CAP_FOWNER",CAP_FOWNER},
+                               {"CAP_FSETID",CAP_FSETID},
+                               {"CAP_KILL",CAP_KILL},
+                               {"CAP_SETGID",CAP_SETGID},
+                               {"CAP_SETUID",CAP_SETUID},
+                               {"CAP_SETPCAP",CAP_SETPCAP},
+                               {"CAP_SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG},
+                               {"CAP_LEASE",CAP_LEASE},
+                               {"CAP_SYS_CHROOT",CAP_SYS_CHROOT},
+
+                               // Those capabilities are not normally available
+                               // to vservers because they are not needed and
+                               // may represent a security risk
+                               {"CAP_LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
+                               {"CAP_NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
+                               {"CAP_NET_BROADCAST",CAP_NET_BROADCAST},
+                               {"CAP_NET_ADMIN",       CAP_NET_ADMIN},
+                               {"CAP_NET_RAW", CAP_NET_RAW},
+                               {"CAP_IPC_LOCK",        CAP_IPC_LOCK},
+                               {"CAP_IPC_OWNER",       CAP_IPC_OWNER},
+                               {"CAP_SYS_MODULE",CAP_SYS_MODULE},
+                               {"CAP_SYS_RAWIO",       CAP_SYS_RAWIO},
+                               {"CAP_SYS_PACCT",       CAP_SYS_PACCT},
+                               {"CAP_SYS_ADMIN",       CAP_SYS_ADMIN},
+                               {"CAP_SYS_BOOT",        CAP_SYS_BOOT},
+                               {"CAP_SYS_NICE",        CAP_SYS_NICE},
+                               {"CAP_SYS_RESOURCE",CAP_SYS_RESOURCE},
+                               {"CAP_SYS_TIME",        CAP_SYS_TIME},
+                               {"CAP_MKNOD",           CAP_MKNOD},
+                               {NULL,0}
+                       };
+                       int j;
+                       unsigned *cap = &add_cap;
+                       if (opt[0] == '!'){
+                               cap = &remove_cap;
+                               opt++;
+                       }
+                       for (j=0; tbcap[j].option != NULL; j++){
+                               if (strcasecmp(tbcap[j].option,opt)==0){
+                                       *cap |= (1<<tbcap[j].bit);
+                                       break;
+                               }
+                       }
+                       if (tbcap[j].option == NULL){
+                               fprintf (stderr,"Unknown capability %s\n",opt);
+                       }
+                       i++;
+               }else if (strcmp(arg,"--secure")==0){
+                       remove_cap |= secure;
+               }else if (strcmp(arg,"--hostname")==0){
+                       hostname = opt;
+                       i++;
+               }else if (strcmp(arg,"--domainname")==0){
+                       if (opt != NULL && strcmp(opt,"none")==0) opt = "";
+                       domainname = opt;
+                       i++;
+               }else{
+                       break;
+               }
+       }
+       if (i == argc){
+               usage();
+       }else if (argv[i][0] == '-'){
+               usage();
+       }else{
+               /*
+                       We must fork early because fakeinit set the current
+                       process as the special init process
+               */
+               if (disconnect == 0 || fork()==0){
+                       int newctx;
+                       if (nbctx == 0) ctxs[nbctx++] = -1;
+                       newctx = call_new_s_context(nbctx,ctxs,0,flags);
+                       if (newctx != -1){
+                               if (hostname != NULL){
+                                       if (sethostname (hostname,strlen(hostname))==-1){
+                                               fprintf (stderr,"Can't set the host name (%s)\n"
+                                                       ,strerror(errno));
+                                       }else if (!silent){
+                                               printf ("Host name is now %s\n",hostname);
+                                       }
+                               }
+                               if (domainname != NULL){
+                                       setdomainname (domainname,strlen(domainname));
+                                       if (!silent){
+                                               printf ("Domain name is now %s\n",domainname);
+                                       }
+                               }
+                               remove_cap &= (~add_cap);
+                               if (remove_cap != 0) call_new_s_context (0,NULL,remove_cap,0);
+                               if (!silent){
+                                       printf ("New security context is %d\n"
+                                               ,ctxs[0] == -1 ? newctx : ctxs[0]);
+                               }
+                               execvp (argv[i],argv+i);
+                               fprintf (stderr,"Can't exec %s (%s)\n",argv[i]
+                                       ,strerror(errno));
+                       }else{
+                               perror ("Can't set the new security context\n");
+                       }
+                       if (disconnect != 0) _exit(0);
+               }
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/fakerunlevel.c b/util-vserver/src/fakerunlevel.c
new file mode 100644 (file)
index 0000000..b4f5898
--- /dev/null
@@ -0,0 +1,73 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on fakerunlevel.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       This program add a RUNLEVEL record in a utmp file.
+       This is used when a vserver lack a private init process
+       so runlevel properly report the fake runlevel.
+*/
+#include <utmp.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static void usage()
+{
+       fprintf (stderr,"fakerunlevel version %s\n",VERSION);
+       fprintf (stderr
+               ,"\n"
+                "fakerunlevel runlevel utmp_file\n"
+                "\n"
+                "Put a runlevel record in file utmp_file\n");
+}
+
+int main (int argc, char *argv[])
+{
+       if (argc != 3){
+               usage();
+       }else{
+               int runlevel = atoi(argv[1]);
+               const char *fname = argv[2];
+               if (runlevel < 1 || runlevel > 5){
+                       usage();
+               }else{
+                       // Make sure the file exist
+                       FILE *fout = fopen (fname,"a");
+                       if (fout == NULL){
+                               fprintf (stderr,"Can't open file %s (%s)\n",fname
+                                       ,strerror(errno));
+                       }else{
+                               struct utmp ut;
+
+                               fclose (fout);
+                               utmpname (fname);
+                               setutent();
+                               memset (&ut,0,sizeof(ut));
+                               ut.ut_type = RUN_LVL;
+                               ut.ut_pid = ('#' << 8) + runlevel+'0';
+                               pututline (&ut);
+                               endutent();
+                       }
+               }
+       }
+
+       return 0;
+}
+
diff --git a/util-vserver/src/filetime.c b/util-vserver/src/filetime.c
new file mode 100644 (file)
index 0000000..2c67835
--- /dev/null
@@ -0,0 +1,58 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on filetime.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/stat.h>
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc != 2){
+               fprintf (stderr
+                       ,"filetime version %s\n"
+                        "filetime file\n"
+                        "\n"
+                        "Prints the age of a file\n"
+                        "(how long since it was created or modified)\n"
+                       ,VERSION);
+       }else{
+               struct stat st;
+               if (stat(argv[1],&st)==-1){
+                       fprintf (stderr,"Can't stat file %s (%s)\n",argv[1]
+                               ,strerror(errno));
+               }else{
+                       time_t now = time(NULL);
+                       time_t since = now - st.st_mtime;
+                       int days = since / (24*60*60);
+                       int today = since % (24*60*60);
+                       int hours = today / (60*60);
+                       int minutes = (today % (60*60)) / 60;
+                       if (days > 0){
+                               printf ("%d days ",days);
+                       }
+                       printf ("%02d:%02d\n",hours,minutes);
+                       ret = 0;
+               }
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/ifspec.c b/util-vserver/src/ifspec.c
new file mode 100644 (file)
index 0000000..cebe4d0
--- /dev/null
@@ -0,0 +1,180 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on ifspec.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       Prints the specs of a network device in shell like form
+
+       ADDR=
+       NETMASK=
+       BCAST=
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+static void usage()
+{
+       fprintf (stderr,"ifspec version %s\n",VERSION);
+       fprintf (stderr
+               ,"ifspec network-device [ ipaddr netmask broadcast ]\n"
+                "prints device specification in a shell usable way\n");
+       exit (-1);
+}
+
+static int ifconfig_ioctl(
+       int fd,
+       const char *ifname,
+       int cmd,
+       struct ifreq *ifr)
+{
+       strcpy(ifr->ifr_name, ifname);
+       return ioctl(fd, cmd,ifr);
+}
+
+static unsigned long ip_cnv (const char *str)
+{
+       const char *start_str = str;
+       unsigned tb[4];
+       int no = 0;
+       unsigned long ret;
+         
+       memset (tb,-1,sizeof(tb));
+       while (*str != '\0' && no < 4){
+               if (isdigit(*str)){
+                       int val = atoi(str);
+                       if (val > 255) break;
+                       tb[no++] = val;
+                       while (isdigit(*str)) str++;
+                       if (*str == '.'){
+                               str++;
+                       }else{
+                               break;
+                       }
+               }else{
+                       break;
+               }
+       }
+
+       ret = (tb[0] << 24) | (tb[1]<<16) | (tb[2] << 8) | tb[3];
+       if (no != 4 || *str != '\0'){
+               fprintf (stderr,"Invalid IP number or netmask: %s\n",start_str);
+               ret = 0xffffffff;
+       }
+       return ret;
+}
+
+
+/*
+       Fetch the IP number of an interface from the kernel.
+       Assume the device is already available in the kernel
+       Return -1 if any error.
+*/
+int ifconfig_print (
+       const char *ifname,
+       const char *addrstr,
+       const char *maskstr,
+       const char *bcaststr)
+{
+       int ret = -1;
+       int skfd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (skfd != -1){
+               struct ifreq ifr;
+               struct {
+                       unsigned long addr;
+                       unsigned long mask;
+               } solved;
+               if (addrstr != NULL && addrstr[0] != '\0'){
+                       printf ("ADDR=%s\n",addrstr);
+                       solved.addr = ip_cnv (addrstr);
+               }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFADDR, &ifr) >= 0){
+                       struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+                       unsigned long addr = ntohl(sin->sin_addr.s_addr);
+                       printf ("ADDR=%lu.%lu.%lu.%lu\n"
+                               ,(addr>>24)&0xff
+                               ,(addr>>16)&0xff
+                               ,(addr>>8)&0xff
+                               ,addr&0xff);
+                       solved.addr = addr;
+                       ret = 0;
+               }
+               if (maskstr != NULL && maskstr[0] != '\0'){
+                       printf ("NETMASK=%s\n",maskstr);
+                       solved.mask = ip_cnv (maskstr);
+               }else           if (ifconfig_ioctl(skfd,ifname,SIOCGIFNETMASK, &ifr) >= 0){
+                       struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+                       unsigned long addr = ntohl(sin->sin_addr.s_addr);
+                       printf ("NETMASK=%lu.%lu.%lu.%lu\n"
+                               ,(addr>>24)&0xff
+                               ,(addr>>16)&0xff
+                               ,(addr>>8)&0xff
+                               ,addr&0xff);
+                       solved.mask = addr;
+                       ret = 0;
+               }
+               if (bcaststr != NULL && bcaststr[0] != '\0'){
+                       printf ("BCAST=%s\n",bcaststr);
+               }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){
+                       struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+                       unsigned long addr = ntohl(sin->sin_addr.s_addr);
+                       printf ("BCAST=%lu.%lu.%lu.%lu\n"
+                               ,(addr>>24)&0xff
+                               ,(addr>>16)&0xff
+                               ,(addr>>8)&0xff
+                               ,addr&0xff);
+                       ret = 0;
+               }else{
+                       // Can't get it from the kernel, compute it from the IP
+                       // and the netmask
+                       unsigned long addr = (solved.addr & solved.mask)
+                               | ~solved.mask;
+                       printf ("BCAST=%lu.%lu.%lu.%lu\n"
+                               ,(addr>>24)&0xff
+                               ,(addr>>16)&0xff
+                               ,(addr>>8)&0xff
+                               ,addr&0xff);
+                       
+               }
+               close (skfd);
+       }
+       return ret;
+}
+
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc < 2){
+               usage();
+       }else{
+               const char *addrstr = argc >= 3 ? argv[2] : NULL;
+               const char *maskstr = argc >= 4 ? argv[3] : NULL;
+               const char *bcaststr = argc >= 5 ? argv[4] : NULL;
+               ret = ifconfig_print (argv[1],addrstr,maskstr,bcaststr);
+       }
+       return ret;
+}
+
+
+
diff --git a/util-vserver/src/listdevip.c b/util-vserver/src/listdevip.c
new file mode 100644 (file)
index 0000000..b854495
--- /dev/null
@@ -0,0 +1,107 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on listdevip.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       Print the list of all network (IP) devices. Print the IP
+       in fact, including all aliases.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+
+static int ifconfig_ioctl(
+       int fd,
+       const char *ifname,
+       int cmd,
+       struct ifreq *ifr)
+{
+       strcpy(ifr->ifr_name, ifname);
+       return ioctl(fd, cmd,ifr);
+}
+
+
+static int devlist_read2_2()
+{
+       int ret = -1;
+       int skfd = socket (AF_INET,SOCK_DGRAM,0);
+       if (skfd < 0) {
+               perror ("socket");
+       }else{
+               struct ifconf ifc;
+               int numreqs = 30;
+               ifc.ifc_buf = NULL;
+               ret = 0;
+               while (1) {
+                       ifc.ifc_len = sizeof(struct ifreq) * numreqs;
+                       ifc.ifc_buf = (char*)realloc(ifc.ifc_buf, ifc.ifc_len);
+
+                       if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
+                               perror("SIOCGIFCONF");
+                               ret = -1;
+                               break;
+                       }
+                       if (ifc.ifc_len == (int)sizeof(struct ifreq) * numreqs) {
+                               /* assume it overflowed and try again */
+                               numreqs += 10;
+                               continue;
+                       }
+                       break;
+               }
+               if (ret == 0){
+                       struct ifreq *ifr = ifc.ifc_req;
+                       int             n;
+                       for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
+                               struct sockaddr_in *sin = (struct sockaddr_in*)&ifr->ifr_addr;
+                               unsigned long addr = ntohl(sin->sin_addr.s_addr);
+                               unsigned long mask = 0xffffff00;
+                               struct ifreq ifmask;
+                               if (ifconfig_ioctl(skfd,ifr->ifr_name,SIOCGIFNETMASK, &ifmask) >= 0){
+                                       struct sockaddr_in *sin = (struct sockaddr_in*)&ifmask.ifr_addr;
+                                       mask = ntohl(sin->sin_addr.s_addr);
+                               }
+
+                               printf ("%lu.%lu.%lu.%lu/%lu.%lu.%lu.%lu\n"
+                                       ,(addr>>24)&0xff
+                                       ,(addr>>16)&0xff
+                                       ,(addr>>8)&0xff
+                                       ,addr&0xff
+                                       ,(mask>>24)&0xff
+                                       ,(mask>>16)&0xff
+                                       ,(mask>>8)&0xff
+                                       ,mask&0xff);
+                               ifr++;
+                       }
+               }
+               free(ifc.ifc_buf);
+       }
+       return ret;
+}
+
+int main (int argc, char *argv[])
+{
+       devlist_read2_2();
+       return 0;
+}
+
diff --git a/util-vserver/src/parserpmdump.c b/util-vserver/src/parserpmdump.c
new file mode 100644 (file)
index 0000000..58a7608
--- /dev/null
@@ -0,0 +1,71 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on parserpmdump.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       Litte utility to extract non config file from
+       an rpm --dump command.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <alloca.h>
+
+
+int main (int argc, char *argv[])
+{
+       int     *tblen = alloca(argc * sizeof(int));
+       int     i;
+       char tmp[1000];
+
+       for (i=1; i<argc; i++) tblen[i] = strlen(argv[i]);
+       while (fgets(tmp,sizeof(tmp)-1,stdin)!=NULL){
+               int i;
+               // Check if the file is in an excluded directory
+               for (i=1; i<argc; i++){
+                       if (strncmp(argv[i],tmp,tblen[i])==0) break;
+               }
+               if (i == argc){
+                       // Ok no match
+                       int last = strlen(tmp)-1;
+                       mode_t  mode=-1;
+                       int type=-1;
+                       char *start = tmp;
+                       int     i;
+                       
+                       if (last >= 0 && tmp[last] == '\n') tmp[last] = '\0';
+
+                       for (i=0; i<8; i++){
+                               char *pt = start;
+                               while (*pt > ' ') pt++;
+                               if (*pt == ' ') *pt++ = '\0';
+                               if (i == 4){
+                                       sscanf(start,"%o",&mode);
+                               }else if (i==7){
+                                       type = atoi(start);
+                               }
+                               start = pt;
+                                       
+                       }                       
+                       if (S_ISREG(mode) && type == 0) printf ("%s\n",tmp);
+               }
+       }
+       return 0;
+}
+
diff --git a/util-vserver/src/readlink.c b/util-vserver/src/readlink.c
new file mode 100644 (file)
index 0000000..4f023ce
--- /dev/null
@@ -0,0 +1,51 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on readlink.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       Copyright Jacques Gelinas jack@solucorp.qc.ca
+       Distributed under the Gnu Public License, see the License file
+       in this package.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc != 2){
+               fprintf (stderr,"readlink symlink-file\n");
+               fprintf (stderr,"Prints the contents of a symlink\n");
+       }else{
+               char buf[PATH_MAX];
+               int len = readlink (argv[1],buf,sizeof(buf)-1);
+               if (len > 0){
+                       buf[len] = '\0';
+                       printf ("%s\n",buf);
+                       ret = 0;
+               }else{
+                       fprintf (stderr,"readlink failed for file %s (%s)\n"
+                               ,argv[1],strerror(errno));
+               }
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/rebootmgr.c b/util-vserver/src/rebootmgr.c
new file mode 100644 (file)
index 0000000..8e9570e
--- /dev/null
@@ -0,0 +1,240 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on rebootmgr.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       The reboot manager allow a virtual server administrator to request
+       a complete restart of his vserver. This means that all services
+       are terminated, all remaining processes are killed and then
+       all services are started.
+
+       This is done by issuing
+
+               /usr/sbin/vserver vserver restart
+
+
+       The rebootmgr installs a unix domain socket in each vservers
+       and listen for the reboot messages. All other message are discarded.
+
+       The unix domain socket is placed in /vservers/N/dev/reboot and is
+       turned immutable.
+
+       The vreboot utility is used to send the signal from the vserver
+       environment.
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <alloca.h>
+
+static void usage()
+{
+       fprintf (stderr,"rebootmgr version %s\n",VERSION);
+       fprintf (stderr,"\n");
+       fprintf (stderr,"rebootmgr [--pidfile file ] vserver-name [ vserver-name ...]\n");
+}
+
+static int rebootmgr_opensocket (const char *vname)
+{
+       int ret = -1;
+       char sockn[PATH_MAX];
+       int fd =  socket (AF_UNIX,SOCK_STREAM,0);
+       sprintf (sockn,"/vservers/%s/dev/reboot",vname);
+       unlink (sockn);
+       if (fd == -1){
+               fprintf (stderr,"Can't create a unix domain socket (%s)\n"
+                               ,strerror(errno));
+       }else{
+               struct sockaddr_un un;
+               un.sun_family = AF_UNIX;
+               strcpy (un.sun_path,sockn);
+               if (bind(fd,(struct sockaddr*)&un,sizeof(un))==-1){
+                       fprintf (stderr,"Can't bind to file %s (%s)\n",sockn
+                               ,strerror(errno));
+               }else{
+                       int code;
+                       chmod (sockn,0600);
+                       code = listen (fd,10);
+                       if (code == -1){
+                               fprintf (stderr,"Can't listen to file %s (%s)\n",sockn
+                                       ,strerror(errno));
+                       }else{
+                               ret = fd;
+                       }       
+               }
+       }
+       return ret;
+}
+
+static int rebootmgr_process (int fd, const char *vname)
+{
+       int ret = -1;
+       char buf[100];
+       int len = read (fd,buf,sizeof(buf)-1);
+       // fprintf (stderr,"process %d %s len %d\n",fd,vname,len);
+       if (len > 0){
+               buf[len] = '\0';
+               if (strcmp(buf,"reboot\n")==0){
+                       char cmd[1000];
+                       syslog (LOG_NOTICE,"reboot vserver %s\n",vname);
+                       snprintf (cmd,sizeof(cmd)-1,"/usr/sbin/vserver %s restart >>/var/log/boot.log 2>&1",vname);
+                       system (cmd);
+                       ret = 0;
+               }else if (strcmp(buf,"halt\n")==0){
+                       char cmd[1000];
+                       syslog (LOG_NOTICE,"halt vserver %s\n",vname);
+                       snprintf (cmd,sizeof(cmd)-1,"/usr/sbin/vserver %s stop >>/var/log/boot.log 2>&1",vname);
+                       system (cmd);
+                       ret = 0;
+               }else{
+                       syslog (LOG_ERR,"Invalid request from vserver %s",vname);
+               }
+       }
+       return ret;
+}
+
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc < 2){
+               usage();
+       }else{
+               int error = 0;
+               int start = 1;
+               int i;
+               int *sockets = alloca(argc * sizeof(int));
+
+               openlog ("rebootmgr",LOG_PID,LOG_DAEMON);
+               for (i=0; i<argc; i++){
+                       const char *arg = argv[i];
+                       if (strcmp(arg,"--pidfile")==0){
+                               const char *pidfile = argv[i+1];
+                               FILE *fout = fopen (pidfile,"w");
+                               if (fout == NULL){
+                                       fprintf (stderr,"Can't open pidfile %s (%s)\n"
+                                               ,pidfile,strerror(errno));
+
+                                       __extension__
+                                       syslog (LOG_ERR,"Can't open pidfile %s (%m)"
+                                               ,pidfile);
+                               }else{
+                                       fprintf (fout,"%d\n",getpid());
+                                       fclose (fout);
+                               }
+                               start = i+2;
+                               i++;
+                       }else if (strcmp(arg,"--")==0){
+                               start = i+1;
+                               break;
+                       }else if (arg[0] == '-'){
+                               fprintf (stderr,"Invalid argument %s\n",arg);
+                               syslog (LOG_ERR,"Invalid argument %s",arg);
+                       }
+               }
+               for (i=start; i<argc; i++){
+                       int fd = rebootmgr_opensocket (argv[i]);
+                       if (fd == -1){
+                               error = 1;
+                       }else{
+                               sockets[i] = fd;
+                       }
+               }
+               if (!error){
+                       int maxhandles = argc*2;
+                       struct {
+                               int handle;
+                               const char *vname;
+                       } handles[maxhandles];
+                       int nbhandles=0;
+                       while (1){
+                               int maxfd = 0;
+                               int i;
+                               int ok;
+                               
+                               fd_set fdin;
+                               FD_ZERO (&fdin);
+                               for (i=start; i<argc; i++){
+                                       int fd = sockets[i];
+                                       if (fd > maxfd) maxfd = fd;
+                                       FD_SET (fd,&fdin);
+                               }
+                               for (i=0; i<nbhandles; i++){
+                                       int fd = handles[i].handle;
+                                       if (fd > maxfd) maxfd = fd;
+                                       FD_SET (fd,&fdin);
+                               }
+                               ok = select (maxfd+1,&fdin,NULL,NULL,NULL);
+                               if (ok <= 0){
+                                       break;
+                               }else{
+                                       int i;
+                                       int dst = 0;
+
+                                       for (i=start; i<argc; i++){
+                                               int fd = sockets[i];
+                                               if (FD_ISSET(fd,&fdin)){
+                                                       struct sockaddr_un unc;
+                                                       size_t len = sizeof(unc);
+                                                       unc.sun_family = AF_UNIX;
+                                                       fd = accept (fd,(struct sockaddr*)&unc,&len);
+                                                       if (fd != -1){
+                                                               if (nbhandles == maxhandles){
+                                                                       int j;
+                                                                       // Overloaded, we close every handle
+                                                                       syslog (LOG_ERR,"%d sockets opened: Overloaded\n",nbhandles);
+                                                                       for (j=0; j<nbhandles; j++){
+                                                                               close (handles[j].handle);
+                                                                       }
+                                                                       nbhandles = 0;
+                                                               }
+                                                               handles[nbhandles].handle = fd;
+                                                               handles[nbhandles].vname = argv[i];
+                                                               nbhandles++;
+                                                               // fprintf (stderr,"accept %d\n",nbhandles);
+                                                       }
+                                               }
+                                       }
+                                       for (i=0; i<nbhandles; i++){
+                                               int fd = handles[i].handle;
+                                               if (FD_ISSET(fd,&fdin)){
+                                                       if (rebootmgr_process (fd,handles[i].vname)==-1){
+                                                               close (fd);
+                                                       }else{
+                                                               handles[dst++] = handles[i];
+                                                       }
+                                               }else{
+                                                       handles[dst++] = handles[i];
+                                               }
+                                       }
+                                       nbhandles = dst;
+                               }
+                       }
+               }
+       }
+       return ret;
+}
+
+
diff --git a/util-vserver/src/reducecap.c b/util-vserver/src/reducecap.c
new file mode 100644 (file)
index 0000000..0efcb35
--- /dev/null
@@ -0,0 +1,232 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on reducecap.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "linuxcaps.h"
+#include "vserver.h"
+
+extern int capget (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
+extern int capset (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
+
+static void usage()
+{
+       fprintf (stderr,"reducecap version %s\n",VERSION);
+       fprintf (stderr,"reducecap [ options ] command argument\n");
+       exit (-1);
+}
+
+static void reducecap_print(struct __user_cap_data_struct *user)
+{
+       static const char *tb[]={
+               "CAP_CHOWN",
+               "CAP_DAC_OVERRIDE",
+               "CAP_DAC_READ_SEARCH",
+               "CAP_FOWNER",
+               "CAP_FSETID",
+               "CAP_KILL",
+               "CAP_SETGID",
+               "CAP_SETUID",
+               "CAP_SETPCAP",
+               "CAP_LINUX_IMMUTABLE",
+               "CAP_NET_BIND_SERVICE",
+               "CAP_NET_BROADCAST",
+               "CAP_NET_ADMIN",
+               "CAP_NET_RAW",
+               "CAP_IPC_LOCK",
+               "CAP_IPC_OWNER",
+               "CAP_SYS_MODULE",
+               "CAP_SYS_RAWIO",
+               "CAP_SYS_CHROOT",
+               "CAP_SYS_PTRACE",
+               "CAP_SYS_PACCT",
+               "CAP_SYS_ADMIN",
+               "CAP_SYS_BOOT",
+               "CAP_SYS_NICE",
+               "CAP_SYS_RESOURCE",
+               "CAP_SYS_TIME",
+               "CAP_SYS_TTY_CONFIG",
+               "CAP_MKNOD",
+               "CAP_LEASE",
+               "CAP_OPENDEV",
+               NULL
+       };
+       int i;
+       printf ("%22s %9s %9s %9s\n","Capability","Effective","Permitted"
+               ,"Inheritable");
+       for (i=0; tb[i] != NULL; i++){
+               int bit = (1 << i);
+               printf ("%22s %9s %9s %9s\n"
+                       ,tb[i]
+                       ,(user->effective & bit) ? "X    " : " "
+                       ,(user->permitted & bit) ? "X    " : " "
+                       ,(user->inheritable & bit) ? "X    " : " ");
+       }
+}
+
+static void reducecap_show()
+{
+       struct __user_cap_header_struct header;
+       struct __user_cap_data_struct user;
+       header.version = _LINUX_CAPABILITY_VERSION;
+       header.pid = getpid();
+       if (capget(&header,&user)==-1){
+               perror ("capget");
+       }else{
+               reducecap_print (&user);
+       }
+}
+
+
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       unsigned long remove = 0;
+       int show = 0;
+       int flags = 0;
+       unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
+               |(1<<CAP_NET_BROADCAST)
+               |(1<<CAP_NET_ADMIN)
+               |(1<<CAP_NET_RAW)
+               |(1<<CAP_IPC_LOCK)
+               |(1<<CAP_IPC_OWNER)
+               |(1<<CAP_SYS_MODULE)
+               |(1<<CAP_SYS_RAWIO)
+               |(1<<CAP_SYS_PACCT)
+               |(1<<CAP_SYS_ADMIN)
+               |(1<<CAP_SYS_BOOT)
+               |(1<<CAP_SYS_NICE)
+               |(1<<CAP_SYS_RESOURCE)
+               |(1<<CAP_SYS_TIME)
+               |(1<<CAP_MKNOD);
+       int i;
+       for (i=1; i<argc; i++){
+               const char *arg = argv[i];
+               const char *opt = argv[i+1];
+               if (strcmp(arg,"--secure")==0){
+                       remove = secure;
+               }else if (strcmp(arg,"--show")==0){
+                       show = 1;
+               }else if (strcmp(arg,"--flag")==0){
+                       if (strcmp(opt,"lock")==0){
+                               flags |= 1;
+                       }else if (strcmp(opt,"sched")==0){
+                               flags |= 2;
+                       }else if (strcmp(opt,"nproc")==0){
+                               flags |= 4;
+                       }else if (strcmp(opt,"private")==0){
+                               flags |= 8;
+                       }else if (strcmp(opt,"hideinfo")==0){
+                               flags |= 32;
+                       }else{
+                               fprintf (stderr,"Unknown flag %s\n",opt);
+                       }
+                       i++;
+               }else if (arg[0] == '-' && arg[1] == '-'){
+                       static struct {
+                               const char *option;
+                               int bit;
+                       }tbcap[]={
+                               // The following capabilities are normally available
+                               // to vservers administrator, but are place for
+                               // completeness
+                               {"CAP_CHOWN",CAP_CHOWN},
+                               {"CAP_DAC_OVERRIDE",CAP_DAC_OVERRIDE},
+                               {"CAP_DAC_READ_SEARCH",CAP_DAC_READ_SEARCH},
+                               {"CAP_FOWNER",CAP_FOWNER},
+                               {"CAP_FSETID",CAP_FSETID},
+                               {"CAP_KILL",CAP_KILL},
+                               {"CAP_SETGID",CAP_SETGID},
+                               {"CAP_SETUID",CAP_SETUID},
+                               {"CAP_SETPCAP",CAP_SETPCAP},
+                               {"CAP_SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG},
+                               {"CAP_LEASE",CAP_LEASE},
+                               {"CAP_SYS_CHROOT",CAP_SYS_CHROOT},
+
+                               // Those capabilities are not normally available
+                               // to vservers because they are not needed and
+                               // may represent a security risk
+                               {"--LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
+                               {"--NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
+                               {"--NET_BROADCAST",CAP_NET_BROADCAST},
+                               {"--NET_ADMIN", CAP_NET_ADMIN},
+                               {"--NET_RAW",   CAP_NET_RAW},
+                               {"--IPC_LOCK",  CAP_IPC_LOCK},
+                               {"--IPC_OWNER", CAP_IPC_OWNER},
+                               {"--SYS_MODULE",CAP_SYS_MODULE},
+                               {"--SYS_RAWIO", CAP_SYS_RAWIO},
+                               {"--SYS_PACCT", CAP_SYS_PACCT},
+                               {"--SYS_ADMIN", CAP_SYS_ADMIN},
+                               {"--SYS_BOOT",  CAP_SYS_BOOT},
+                               {"--SYS_NICE",  CAP_SYS_NICE},
+                               {"--SYS_RESOURCE",CAP_SYS_RESOURCE},
+                               {"--SYS_TIME",  CAP_SYS_TIME},
+                               {"--MKNOD",             CAP_MKNOD},
+                               {NULL,0}
+                       };
+                       int j;
+                       for (j=0; tbcap[j].option != NULL; j++){
+                               if (strcasecmp(tbcap[j].option,arg)==0){
+                                       remove |= (1<<tbcap[j].bit);
+                                       break;
+                               }
+                       }
+                       if (tbcap[j].option != NULL){
+                               usage();
+                       }
+               }else{
+                       break;
+               }
+       }
+       if (i == argc){
+               if (show){
+                       reducecap_show();
+               }else{
+                       usage();
+               }
+       }else if (argv[i][0] == '-'){
+               usage();
+       }else{
+               struct __user_cap_header_struct header;
+               struct __user_cap_data_struct user;
+               header.version = _LINUX_CAPABILITY_VERSION;
+               header.pid = 0;
+               if (capget(&header,&user)==-1){
+                       perror ("capget");
+               }else{
+                       if (show){
+                               reducecap_print (&user);
+                       }
+                       if (call_new_s_context(0,NULL,remove,flags)==-1){
+                               perror ("new_s_context -2");
+                       }else{
+                               fprintf (stderr,"Executing\n");
+                               execvp (argv[i],argv+i);
+                               fprintf (stderr,"Can't execute command %s\n",argv[i]);
+                       }
+               }
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/setctxlimit.c b/util-vserver/src/setctxlimit.c
new file mode 100644 (file)
index 0000000..499e691
--- /dev/null
@@ -0,0 +1,86 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on setctxlimit.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       Set the global per context limit of a resource (memory, file handle).
+       This utility can do it either for the current context or a selected
+       one.
+
+       It uses the same options as ulimit, when possible
+*/
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+
+#include "vserver.h"
+
+static void set_ctxlim (int res, long lim, const char *msg)
+{
+       if (call_set_ctxlimit(res,lim)==-1){
+               fprintf (stderr,"Error setting limit \"%s\": %s\n"
+                       ,msg,strerror(errno));
+               exit (-1);
+       }
+}
+
+static void usage()
+{
+               fprintf (stderr,"setctxlimit version %s\n",VERSION);
+               fprintf (stderr
+                       ,"setctxlimit [ --ctx context ] limits\n"
+                        "\n"
+                        "-n nax opened files\n");
+}
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc < 2){
+               usage();
+       }else{
+               int i;
+               ret = 0;
+               for (i=1; i<argc; i++){
+                       const char *arg = argv[i];
+                       const char *narg = argv[i+1];
+                       int val;
+                       
+                       if (narg == NULL) narg = "";
+                       val = atoi(narg);
+                       if (strcmp(arg,"--help")==0){
+                               usage();
+                       }else if (strcmp(arg,"--ctx")==0){
+                               int tb[1];
+
+                               tb[0] = val;
+                               if (call_new_s_context (1,tb,0,0)==-1){
+                                       fprintf (stderr,"Can't select context %d (%s)\n"
+                                               ,val,strerror(errno));
+                                       exit (-1);
+                               }
+                       }else if (strcmp (arg,"-n")==0){
+                               set_ctxlim (RLIMIT_NOFILE,val,"Number of opened files");
+                       }
+               }
+       }
+       return ret;     
+}
+
diff --git a/util-vserver/src/showattr.c b/util-vserver/src/showattr.c
new file mode 100644 (file)
index 0000000..7e63289
--- /dev/null
@@ -0,0 +1,129 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on showattr.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/ext2_fs.h>
+
+// Patch to help compile this utility on unpatched kernel source
+#ifndef EXT2_IMMUTABLE_FILE_FL
+       #define EXT2_IMMUTABLE_FILE_FL  0x00000010
+       #define EXT2_IMMUTABLE_LINK_FL  0x00008000
+#endif
+
+/*
+       Get the extended attributes of a file
+*/
+static int getext2flags (const char *fname, long *flags)
+{
+       int ret = -1;
+       int fd = open (fname,O_RDONLY);
+       if (fd == -1){
+               fprintf (stderr,"Can't open file %s (%s)\n",fname,strerror(errno));
+       }else{
+               *flags = 0;
+               ret = ioctl (fd,EXT2_IOC_GETFLAGS,flags);
+               close (fd);
+               if (ret == -1){
+                       fprintf (stderr,"Can't get ext2 flags on file %s (%s)\n"
+                               ,fname,strerror(errno));
+               }
+       }
+       return ret;
+}
+
+/*
+       Set the extended attributes of a file
+*/
+static int setext2flags (const char *fname, long flags)
+{
+       int ret = -1;
+       int fd = open (fname,O_RDONLY);
+       if (fd == -1){
+               fprintf (stderr,"Can't open file %s (%s)\n",fname,strerror(errno));
+       }else{
+               ret = ioctl (fd,EXT2_IOC_SETFLAGS,&flags);
+               close (fd);
+               if (ret == -1){
+                       fprintf (stderr,"Can't set ext2 flags on file %s (%s)\n"
+                               ,fname,strerror(errno));
+               }
+       }
+       return ret;
+}
+
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc <= 1){
+               fprintf (stderr
+                       ,"showattr file ...\n"
+                        "\n"
+                        "Presents extended file attribute.\n"
+                        "\n"
+                        "setattr --immutable --immulink file ...\n"
+                        "\n"
+                        "Sets the extended file attributes.\n"
+                        "\n"
+                        "These utilities exist as an interim until lsattr and\n"
+                        "chattr are updated.\n"
+                       );
+       }else if (strstr(argv[0],"showattr")!=NULL){
+               int i;
+               for (i=1; i<argc; i++){
+                       long flags;
+                       ret = getext2flags (argv[i],&flags);
+                       if (ret == -1){
+                               break;
+                       }else{
+                               printf ("%s\t%08lx\n",argv[i],flags);
+                       }
+               }
+       }else if (strstr(argv[0],"setattr")!=NULL){
+               long flags = 0;
+               int  i;
+               ret = 0;
+               for (i=1; i<argc; i++){
+                       const char *arg = argv[i];
+                       if (strncmp(arg,"--",2)==0){
+                               if (strcmp(arg,"--immutable")==0){
+                                       flags |= EXT2_IMMUTABLE_FILE_FL;
+                               }else if (strcmp(arg,"--immulink")==0){
+                                       flags |= EXT2_IMMUTABLE_LINK_FL;
+                               }else{
+                                       fprintf (stderr,"Invalid option %s\n",arg);
+                                       ret = -1;
+                                       break;
+                               }
+                       }else{
+                               ret = setext2flags (arg,flags);
+                               if (ret == -1){
+                                       break;
+                               }
+                       }
+               }
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/showperm.c b/util-vserver/src/showperm.c
new file mode 100644 (file)
index 0000000..1710de4
--- /dev/null
@@ -0,0 +1,51 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on showperm.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc < 2){
+               fprintf (stderr,"showperm version %s\n",VERSION);
+               fprintf (stderr,
+                       "showperm file or directory ...\n"
+                       "prints permission bits for files\n"
+                       "A very stripped down stat utility\n"
+                       );
+       }else{
+               int i;
+               ret = 0;
+               for (i=1; i<argc; i++){
+                       struct stat st;
+                       if (lstat(argv[i],&st)==-1){
+                               fprintf (stderr,"can't lstat %s (%s)\n",argv[i]
+                                       ,strerror(errno));
+                               ret = -1;
+                       }else{
+                               printf ("%03o\n",(st.st_mode & 0777));
+                       }
+               }
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/vbuild.cc b/util-vserver/src/vbuild.cc
new file mode 100644 (file)
index 0000000..1ad79a9
--- /dev/null
@@ -0,0 +1,283 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vbuild.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       This utility is used to build a new vserver using a reference vserver.
+       It uses hard link whenever possible instead of duplicating files.
+       Once done, it sets the immutable bits.
+*/
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <set>
+#include "vutil.h"
+
+using namespace std;
+
+struct EXCLDIR{
+       string prefix;
+       int len;
+       EXCLDIR(const char *s)
+       {
+               prefix = s;
+               prefix += '/';
+               len = prefix.size();
+       }
+};
+static vector<EXCLDIR> excldirs;
+
+
+static int  ext2flags = EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL;
+static struct {
+       int nblink;
+       int nbcopy;
+       long size_copy;
+       int nbdir;
+       int nbsymlink;
+       int nbspc;
+} stats;
+
+
+static void usage()
+{
+       cerr <<
+               "vbuild version " << VERSION <<
+               "\n\n"
+               "vbuild [ options ] reference-server new-vservers\n"
+               "\n"
+               "--test: Show what will be done, do not do it.\n"
+               "--debug: Prints some debugging messages.\n"
+               "\n"
+               "--excldir: None of the files under a given directory will be copied\n"
+               "\tThe directory is expressed in absolute/logical form (relative\n"
+               "\tto the vserver root (ex: /var/log)\n"
+               "\n"
+               "\n"
+               "--noflags: Do not put any immutable flags on the file\n"
+               "--immutable: Set the immutable_file bit on the files.\n"
+               "--immutable-mayunlink: Sets the immutable_link flag on files.\n"
+               "--stats: Produce statistics on the number of file linked\n"
+               "         copied and so on.\n"
+               "\n"
+               "By default, the immutable_file and     immutable_link flags are\n"
+               "set on the files. So if you want no immutable flags, you must\n"
+               "use --noflags. If you want a single flag, you must use\n"
+               "--noflags first, then the --immutable or --immutable-mayunlink\n"
+               "flag.\n"
+               ;
+}
+
+/*
+       Return true if a directory lies inside a directory set
+*/
+static bool vbuild_inside (vector<EXCLDIR> &dirs, const char *path)
+{
+       bool found = false;
+       for (unsigned i=0; i<dirs.size(); i++){
+               if (strncmp(dirs[i].prefix.c_str(),path,dirs[i].len)==0){
+                       found = true;
+                       break;
+               }
+       }
+       return found;
+}
+
+
+
+static int vbuild_copy (
+       string refserv,
+       string newserv,
+       dev_t dev,                      // We stay on the same volume
+       string logical_dir,
+       set<string> &files)
+{
+       int ret = -1;
+       if (debug > 0) printf ("Copying directory %s\n",logical_dir.c_str());
+       DIR *dir = opendir (refserv.c_str());
+       if (dir == NULL){
+               fprintf (stderr,"Can't open directory %s (%s)\n",refserv.c_str()
+                       ,strerror(errno));
+       }else{
+               logical_dir += "/";
+               bool copy_files = !vbuild_inside(excldirs,logical_dir.c_str());
+               struct dirent *ent;
+               ret = 0;
+               while (ret == 0 && (ent=readdir(dir))!=NULL){
+                       if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0){
+                               continue;
+                       }
+                       string file = refserv + "/" + ent->d_name;
+                       struct stat st;
+                       if (vutil_lstat(file.c_str(),st) == -1){
+                               ret = -1;
+                       }else if (st.st_dev != dev){
+                               if (debug > 0) printf ("Ignore sub-directory %s\n",file.c_str());
+                       }else{
+                               string newfile = newserv + "/" + ent->d_name;
+                               if (S_ISDIR(st.st_mode)){
+                                       if (vbuild_mkdir (newfile.c_str(),st.st_mode)==-1){
+                                               fprintf (stderr,"Can't mkdir %s (%s)\n"
+                                                       ,newfile.c_str(),strerror(errno));
+                                               ret = -1;
+                                       }else{
+                                               stats.nbdir++;
+                                               if (vbuild_chown(newfile.c_str(),st.st_uid,st.st_gid)==-1){
+                                                       fprintf (stderr,"Can't chown %s (%s)\n"
+                                                               ,newfile.c_str(),strerror(errno));
+                                                       ret = -1;
+                                               }
+                                               ret |= vbuild_copy (file,newfile,dev
+                                                       ,logical_dir + ent->d_name,files);
+                                       }
+                               }else if (S_ISLNK(st.st_mode)){
+                                       char path[PATH_MAX];
+                                       int len = readlink(file.c_str(),path,sizeof(path)-1);
+                                       if (len < 0){
+                                               fprintf (stderr,"Can't readlink %s (%s)\n"
+                                                       ,file.c_str(),strerror(errno));
+                                               ret = -1;
+                                       }else{
+                                               path[len] = '\0';
+                                               stats.nbsymlink++;
+                                               if (vbuild_symlink (path,newfile.c_str())==-1){
+                                                       fprintf (stderr,"Can't symlink %s to %s (%s)\n",
+                                                               newfile.c_str(),path,strerror(errno));
+                                               }
+                                       }
+                               }else if (S_ISBLK(st.st_mode)
+                                       || S_ISCHR(st.st_mode)
+                                       || S_ISFIFO(st.st_mode)){
+                                       stats.nbspc++;
+                                       if (vbuild_mknod (newfile.c_str(),st.st_mode,st.st_rdev)==-1){
+                                               fprintf (stderr,"Can't mknod %s (%s)\n"
+                                                       ,newfile.c_str(),strerror(errno));
+                                               ret = -1;
+                                       }
+                               }else if (S_ISSOCK(st.st_mode)){
+                                       // Do nothing
+                               }else if (copy_files){
+                                       // Ok, this is a file. We either copy it or do a link
+                                       string logical_file = logical_dir + ent->d_name;
+                                       if (files.find (logical_file)==files.end()){
+                                               if (debug > 1) printf ("Copying file %s\n",file.c_str());
+                                               if (vbuild_file_copy (file.c_str(),newfile.c_str(),st)==-1){
+                                                       fprintf (stderr,"Can't copy %s to %s (%s)\n",
+                                                               file.c_str(),newfile.c_str(),strerror(errno));
+                                                       ret = -1;
+                                               }else{
+                                                       stats.size_copy += st.st_size;
+                                                       stats.nbcopy++;
+                                               }
+                                       }else{
+                                               if (debug > 2) printf ("Linking file %s\n",file.c_str());
+                                               setext2flag (file.c_str(),false,ext2flags);
+                                               stats.nblink++;
+                                               if (vbuild_link (file.c_str(),newfile.c_str())==-1){
+                                                       fprintf (stderr,"Can't link %s to %s (%s)\n",
+                                                               file.c_str(),newfile.c_str(),strerror(errno));
+                                                       ret = -1;
+                                               }
+                                               setext2flag (file.c_str(),true,ext2flags);
+                                       }
+                               }
+                       }
+               }
+               closedir(dir);
+       }
+       return ret;
+}
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       bool statistics = false;
+       int i;
+       for (i=1; i<argc; i++){
+               const char *arg = argv[i];
+               //const char *opt = argv[i+1];
+               if (strcmp(arg,"--test")==0){
+                       testmode = true;
+               }else if (strcmp(arg,"--debug")==0){
+                       debug++;
+               }else if (strcmp(arg,"--stats")==0){
+                       statistics = true;
+               }else if (strcmp(arg,"--noflags")==0){
+                       ext2flags = 0;
+               }else if (strcmp(arg,"--immutable")==0){
+                       ext2flags |= EXT2_IMMUTABLE_FILE_FL;
+               }else if (strcmp(arg,"--immutable-mayunlink")==0){
+                       ext2flags |= EXT2_IMMUTABLE_LINK_FL;
+               }else if (strcmp(arg,"--excldir")==0){
+                       i++;
+                       excldirs.push_back (EXCLDIR(argv[i]));
+               }else{
+                       break;
+               }
+       }
+       if (i!=argc-2){
+               usage();
+       }else{
+               string refserv = argv[i++];
+               string newserv = argv[i];
+               list<PACKAGE> packages;
+               // Load the files which are not configuration files from
+               // the packages
+               vutil_loadallpkg (refserv,packages);
+               set<string> files;
+               for (list<PACKAGE>::iterator it=packages.begin(); it!=packages.end(); it++){
+                       (*it).loadfiles(refserv,files);
+               }
+               // Now, we do a recursive copy of refserv into newserv
+               umask (0);
+               mkdir (newserv.c_str(),0755);
+               // Check if it is on the same volume
+               struct stat refst,newst;
+               if (vutil_lstat(refserv,refst)!=-1
+                       && vutil_lstat(newserv,newst)!=1){
+                       if (refst.st_dev != newst.st_dev){
+                               fprintf (stderr,"Can't vbuild %s because it is not on the same volume as %s\n"
+                                       ,newserv.c_str(),refserv.c_str());
+                       }else{
+                               stats.nbdir = stats.nblink = stats.nbcopy = stats.nbsymlink = 0;
+                               stats.nbspc = 0;
+                               stats.size_copy = 0;
+                               ret = vbuild_copy (refserv,newserv,refst.st_dev,"",files);
+                               if (statistics){
+                                       printf ("Directory created: %d\n",stats.nbdir);
+                                       printf ("Files copied     : %d\n",stats.nbcopy);
+                                       printf ("Bytes copied     : %ld\n",stats.size_copy);
+                                       printf ("Files linked     : %d\n",stats.nblink);
+                                       printf ("Files symlinked  : %d\n",stats.nbsymlink);
+                                       printf ("Special files    : %d\n",stats.nbspc);
+                               }
+                       }
+               }
+       }
+       return ret;
+}
+
+
diff --git a/util-vserver/src/vcheck.cc b/util-vserver/src/vcheck.cc
new file mode 100644 (file)
index 0000000..b2ff6e4
--- /dev/null
@@ -0,0 +1,237 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vcheck.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       This utility is used to compare two vservers. One is known to
+       be clean and the other is potentially corrupted (cracked). The
+       goal of this program is to run the rpm verify command, but using
+       the RPM database of the first vserver.
+*/
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <set>
+#include "vutil.h"
+
+using namespace std;
+
+
+static void usage()
+{
+       cerr <<
+               "vcheck version " << VERSION <<
+               "\n\n"
+               "vcheck [ options ] reference-server chk-vservers\n"
+               "\n"
+               "--diffpkgs: Shows which package differ.\n"
+               "            + means the package only exists in chk-server.\n"
+               "            - means the package does not exist in chk-server.\n"
+               "            ! means the servers have different version.\n"
+               "\n"
+               "--verify: Execute an RPM verify on common packages.\n"
+               "--debug: Turn on some (useless) debugging messages.\n"
+               ;
+}
+
+typedef list<PACKAGE> PACKAGES;
+
+/*
+       Delete a directory silently
+*/
+static int vcheck_deldir (const string &path)
+{
+       int ret = -1;
+       struct stat st;
+       if (lstat(path.c_str(),&st)==-1){
+               ret = 0;
+       }else{
+               if (!S_ISDIR(st.st_mode)){
+                       fprintf (stderr,"%s already exist and is not a directory\n"
+                               ,path.c_str());
+                       exit (-1);
+               }else{
+                       DIR *d = opendir (path.c_str());
+                       if (d != NULL){
+                               struct dirent *ent;
+                               ret = 0;
+                               while ((ent=readdir(d))!=NULL){
+                                       if (strcmp(ent->d_name,".")!=0
+                                               && strcmp(ent->d_name,"..")!=0){
+                                               string tmp = path + "/" + ent->d_name;
+                                               if (unlink(tmp.c_str())==-1){
+                                                       fprintf (stderr,"Can't delete file %s (%s)\n",tmp.c_str()
+                                                               ,strerror(errno));
+                                                       ret = -1;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               closedir (d);
+                               rmdir (path.c_str());
+                       }
+               }
+       }
+       return ret;
+}
+               
+
+static int vcheck_copydb (const string &refserv, const string &path)
+{
+       int ret = -1;
+       string refpath = refserv + "/var/lib/rpm";
+       DIR *d = opendir (refpath.c_str());
+       if (d == NULL){
+               fprintf (stderr,"Can't open directory %s (%s)\n",refpath.c_str()
+                       ,strerror(errno));
+       }else{
+               ret = 0;
+               struct dirent *ent;
+               while ((ent=readdir(d))!=NULL){
+                       if (strcmp(ent->d_name,".")!=0
+                               && strcmp(ent->d_name,"..")!=0){
+                               string srcpath = refpath + "/" + ent->d_name;
+                               const char *spath = srcpath.c_str();
+                               struct stat st;
+                               if (stat(spath,&st)!=-1){
+                                       string dstpath = path + "/" + ent->d_name;
+                                       if (file_copy (spath,dstpath.c_str(),st) == -1){
+                                               ret = -1;
+                                               break;
+                                       }
+                               }else{
+                                       ret = -1;
+                                       fprintf (stderr,"Can't stat %s (%s)\n",spath,strerror(errno));
+                                       break;
+                               }
+                       }
+               }
+               closedir (d);
+       }
+       return ret;
+}
+
+class cmp_name{
+public:
+       int operator()(const PACKAGE &p1, const PACKAGE &p2){
+               return strcmp(p1.name.c_str(),p2.name.c_str());
+       }
+};
+
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       bool diffpkg = false;
+       bool verify = false;
+       int i;
+       for (i=1; i<argc; i++){
+               const char *arg = argv[i];
+               //const char *opt = argv[i+1];
+               if (strcmp(arg,"--diffpkg")==0){
+                       diffpkg = true;
+               }else if (strcmp(arg,"--verify")==0){
+                       verify = true;
+               }else if (strcmp(arg,"--debug")==0){
+                       debug++;
+               }else{
+                       break;
+               }
+       }
+       if (i!=argc-2){
+               usage();
+       }else{
+               string refserv = argv[i++];
+               string chkserv = argv[i];
+               PACKAGES refpkgs,chkpkgs;
+               // Load the package list from both vservers
+               vutil_loadallpkg (refserv,refpkgs);
+               vutil_loadallpkg (chkserv,chkpkgs);
+               PACKAGES common, differ, added, removed;
+               // Find which package are different, missing and added
+               // to chkserv
+               for (PACKAGES::iterator it=refpkgs.begin(); it!=refpkgs.end(); it++){
+                       PACKAGES::iterator f = find_if(chkpkgs.begin(),chkpkgs.end(),same_name(*it));
+                       if (f == chkpkgs.end()){
+                               removed.push_back (*it);
+                       }else if (f->version != it->version){
+                               differ.push_back (*it);
+                       }else{
+                               common.push_back (*it);
+                       }
+               }
+               for (list<PACKAGE>::iterator it=chkpkgs.begin(); it!=chkpkgs.end(); it++){
+                       list<PACKAGE>::iterator f = find_if(refpkgs.begin(),refpkgs.end(),same_name(*it));
+                       if (f == refpkgs.end()){
+                               added.push_back (*it);
+                       }
+               }
+               differ.sort ();
+               added.sort();
+               removed.sort();
+               common.sort ();
+               bool something = false;
+               if (diffpkg){
+                       for (PACKAGES::iterator it=removed.begin(); it!=removed.end(); it++){
+                               printf ("- %s\n",it->name.c_str());
+                       }
+                       for (PACKAGES::iterator it=added.begin(); it!=added.end(); it++){
+                               printf ("+ %s\n",it->name.c_str());
+                       }
+                       for (PACKAGES::iterator it=differ.begin(); it!=differ.end(); it++){
+                               printf ("! %s\n",it->name.c_str());
+                       }
+                       something = true;
+               }
+               if (verify){
+                       // We copy the rpm database from the reference vserver to
+                       // the target vserver
+                       string dbpath = chkserv + "/tmp/vcheck.db";
+                       vcheck_deldir (dbpath);
+                       if (mkdir (dbpath.c_str(),0)==-1){
+                               fprintf (stderr,"Can't create directory %s (%s)\n"
+                                       ,dbpath.c_str(),strerror(errno));
+                       }else if (vcheck_copydb (refserv,dbpath) != -1){
+                               // We only compare the common package
+                               string cmd = "rpm --dbpath /tmp/vcheck.db --root " + chkserv + " -V";
+                               for (PACKAGES::iterator it=common.begin(); it!=common.end(); it++){
+                                       //printf ("compare %s\n",it->name.c_str());
+                                       cmd += " " + it->name;
+                               }
+                               if (debug) printf ("CMD: %s\n",cmd.c_str());
+                               system (cmd.c_str());
+                       }
+                       vcheck_deldir (dbpath);
+                       something = true;
+               }
+               if (!something){
+                       fprintf (stderr,"Nothing to do !!!\n\n");
+                       usage();
+               }
+       }
+       return ret;
+}
+
+
+
diff --git a/util-vserver/src/vdu.c b/util-vserver/src/vdu.c
new file mode 100644 (file)
index 0000000..96efd57
--- /dev/null
@@ -0,0 +1,114 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vdu.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+
+__extension__ typedef long long                longlong;
+
+static int vdu_onedir (char const *path, longlong *size)
+{
+       int ret = -1;
+       int dirfd = open (path,O_RDONLY);       // A handle to speed up
+                                                                                               // chdir
+       if (dirfd == -1){
+               fprintf (stderr,"Can't open directory %s (%s)\n",path
+                       ,strerror(errno));
+       }else{
+               DIR *dir;
+
+               fchdir (dirfd);
+               dir = opendir (".");
+               if (dir == NULL){
+                       fprintf (stderr,"Can't open (opendir) directory %s (%s)\n",path
+                               ,strerror(errno));
+               }else{
+                       struct stat dirst;
+                       struct dirent *ent;
+                       longlong dirsize = 0;
+
+                       ret = 0;
+                       lstat (".",&dirst);
+                       while ((ent=readdir(dir))!=NULL){
+                               struct stat st;
+                               if (lstat(ent->d_name,&st)==-1){
+                                       fprintf (stderr,"Can't stat %s/%s (%s)\n",path
+                                               ,ent->d_name,strerror(errno));
+                                       ret = -1;
+                                       break;
+                               }else if (S_ISREG(st.st_mode)){
+                                       if (st.st_nlink == 1){
+                                               dirsize += st.st_size;
+                                       }
+                               }else if (S_ISDIR(st.st_mode) && st.st_dev == dirst.st_dev){
+                                       if (strcmp(ent->d_name,".")!=0
+                                               && strcmp(ent->d_name,"..")!=0){
+                                               char    *tmp = malloc(strlen(path) + strlen(ent->d_name) + 2);
+                                               if (tmp==0) ret=-1;
+                                               else {
+                                                 strcpy(tmp, path);
+                                                 strcat(tmp, "/");
+                                                 strcat(tmp, ent->d_name);
+                                                 ret = vdu_onedir(tmp,&dirsize);
+                                                 free(tmp);
+                                                 fchdir (dirfd);
+                                               }
+                                       }
+                               }
+                       }
+                       closedir (dir);
+                       *size += dirsize;
+               }
+               close (dirfd);
+       }
+       return ret;
+}
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc < 2){
+               fprintf (stderr,"vdu version %s\n",VERSION);
+               fprintf (stderr,"vdu directory ...\n\n");
+               fprintf (stderr
+                       ,"Compute the size of a directory tree, ignoring files\n"
+                        "with more than one link.\n");
+       }else{
+               int i;
+
+               ret = 0;
+               for (i=1; i<argc && ret != -1; i++){
+                       longlong size = 0;
+                       long ksize;
+                       
+                       ret = vdu_onedir (argv[i],&size);
+                       ksize = size >> 10;
+                       printf ("%s\t%ldK\n",argv[i],ksize);
+               }
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/vfiles.cc b/util-vserver/src/vfiles.cc
new file mode 100644 (file)
index 0000000..00a85ac
--- /dev/null
@@ -0,0 +1,146 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vfiles.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       This utility is used to extract the list of non unified files in
+       a vserver.
+*/
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include <string>
+#include <list>
+#include <set>
+#include "vutil.h"
+
+using namespace std;
+
+static bool ignorelink = false;
+
+
+static void usage()
+{
+       cerr <<
+               "vfiles version " << VERSION <<
+               "\n\n"
+               "vfiles [ options ] reference-server vserver\n"
+               "\n"
+               "--debug: Prints some debugging messages.\n"
+               "--ignorelink: Do not print symbolic links (they are never unified)\n"
+               "\n"
+               ;
+}
+
+
+static int vfiles_walk (
+       string absdir,
+       dev_t dev,                      // We stay on the same volume
+       string logical_dir,
+       set<string> &files)
+{
+       int ret = -1;
+       if (debug > 0) printf ("Entering directory %s\n",logical_dir.c_str());
+       DIR *dir = opendir (absdir.c_str());
+       if (dir == NULL){
+               fprintf (stderr,"Can't open directory %s (%s)\n",absdir.c_str()
+                       ,strerror(errno));
+       }else{
+               struct dirent *ent;
+               ret = 0;
+               while (ret == 0 && (ent=readdir(dir))!=NULL){
+                       if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0){
+                               continue;
+                       }
+                       string file = absdir + "/" + ent->d_name;
+                       struct stat st;
+                       if (vutil_lstat(file,st) == -1){
+                               ret = -1;
+                       }else if (st.st_dev != dev){
+                               if (debug > 0) printf ("Ignore sub-directory %s\n",file.c_str());
+                       }else{
+                               if (S_ISDIR(st.st_mode)){
+                                       ret |= vfiles_walk (file,dev
+                                                       ,logical_dir + "/" + ent->d_name,files);
+                               }else if (S_ISLNK(st.st_mode)){
+                                       if (!ignorelink) printf ("%s\n",file.c_str());  
+                               }else if (S_ISBLK(st.st_mode)
+                                       || S_ISCHR(st.st_mode)
+                                       || S_ISFIFO(st.st_mode)){
+                                       printf ("%s\n",file.c_str());   
+                               }else if (S_ISSOCK(st.st_mode)){
+                                       // Do nothing
+                               }else{
+                                       // Ok, this is a file. We either copy it or do a link
+                                       string logical_file = logical_dir + "/" + ent->d_name;
+                                       if (files.find (logical_file)==files.end()){
+                                               printf ("%s\n",file.c_str());   
+                                       }
+                               }
+                       }
+               }
+               closedir(dir);
+       }
+       return ret;
+}
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       int i;
+       for (i=1; i<argc; i++){
+               const char *arg = argv[i];
+               //const char *opt = argv[i+1];
+               if (strcmp(arg,"--debug")==0){
+                       debug++;
+               }else if (strcmp(arg,"--ignorelink")==0){
+                       ignorelink=true;
+               }else{
+                       break;
+               }
+       }
+       if (i!=argc-2){
+               usage();
+       }else{
+               string refserv = argv[i++];
+               string newserv = argv[i];
+               list<PACKAGE> packages;
+               // Load the files which are not configuration files from
+               // the packages
+               vutil_loadallpkg (refserv,packages);
+               set<string> files;
+               for (list<PACKAGE>::iterator it=packages.begin(); it!=packages.end(); it++){
+                       (*it).loadfiles(refserv,files);
+               }
+               struct stat st;
+               if (vutil_lstat(newserv,st)!=-1){
+                       // Now, we do a recursive walk of newserv and prints
+                       // all files not unifiable
+                       ret = vfiles_walk (newserv,st.st_dev,"",files);
+               }
+       }
+       return ret;
+}
+
+
+
diff --git a/util-vserver/src/vreboot.c b/util-vserver/src/vreboot.c
new file mode 100644 (file)
index 0000000..62e2ee0
--- /dev/null
@@ -0,0 +1,105 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vreboot.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       Used to send a reboot message to the reboot manager. It opens /dev/reboot
+       and write "reboot\n".
+*/
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdbool.h>
+
+/*
+       Connect to a unix domain socket
+*/
+static int vreboot_connect (const char *sockpath, bool showerror)
+{
+       int ret = -1;
+       int fd =  socket (AF_UNIX,SOCK_STREAM,0);
+       if (fd == -1){
+               if (showerror) perror("socket client");
+       }else{
+               struct sockaddr_un un;
+               int s;
+               
+               un.sun_family = AF_UNIX;
+               strcpy (un.sun_path,sockpath);
+               s = connect(fd,(struct sockaddr*)&un,sizeof(un));
+               if (s == -1){
+                       if (showerror) fprintf (stderr,"connect %s (%s)\n"
+                               ,sockpath,strerror(errno));
+               }else{
+                       ret = fd;
+               }
+       }
+       return ret;
+}
+
+static void usage()
+{
+       fprintf (stderr,"vreboot version %s\n",VERSION);
+       fprintf (stderr,"\n");
+       fprintf (stderr,"vreboot [ --socket path ]\n");
+       fprintf (stderr,"vhalt   [ --socket path ]\n");
+       fprintf (stderr,"vreboot request a reboot or a halt of a virtual server\n");
+}
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       int i;
+       const char *sockpath = "/dev/reboot";
+       for (i=1; i<argc; i++){
+               const char *arg = argv[i];
+               const char *opt = argv[i+1];
+               if (strcmp(arg,"--socket")==0){
+                       sockpath = opt;
+                       i++;
+               }else if (strcmp(arg,"--help")==0){
+                       break;
+
+               }else{
+                       fprintf (stderr,"Invalid option %s\n",arg);
+                       break;
+               }
+       }
+       if (argc != i){
+               usage();
+       }else{
+               int fd = vreboot_connect (sockpath,true);
+               if (fd != -1){
+                       if (strstr(argv[0],"halt")!=NULL){
+                               write (fd,"halt\n",5);
+                       }else{
+                               write (fd,"reboot\n",7);
+                       }
+                       close (fd);
+                       ret = 0;
+               }
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/vserver-stat.c b/util-vserver/src/vserver-stat.c
new file mode 100644 (file)
index 0000000..a7737b3
--- /dev/null
@@ -0,0 +1,510 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vserver-stat.cc by Guillaum Dallaire and Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       vserver-stat help you to see all the active context currently in the kernel
+       with some useful stat
+
+       Changelog:
+
+       2003-01-08 Jacques Gelinas: Shows vserver description
+       2002-02-28 Jacques Gelinas: Use dynamic system call
+       2002-06-05 Martial Rioux : fix memory output error
+       2002-12-05 Martial Rioux : fix output glitch
+       2001-11-29 added uptime/ctx stat
+       2001-11-20 added vmsize, rss, stime and utime stat
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+#include <syscall.h>
+#include <time.h>
+
+#define PROC_DIR_NAME "/proc"
+#define CTX_DIR_NAME "/var/run/vservers/"
+#define CTX_NAME_MAX_LEN 50
+
+int call_new_s_context(int nbctx, int ctxs[], int remove_cap, int flags);
+
+
+struct ctx_list
+{
+       int ctx;
+       int process_count;
+       int VmSize_total;
+       int VmRSS_total;
+       long start_time_oldest;
+       long stime_total, utime_total;
+       char name[CTX_NAME_MAX_LEN];
+       struct ctx_list *next;
+} *my_ctx_list;
+
+struct process_info
+{
+       long VmSize;            // number of pages of virtual memory
+       long VmRSS;             // resident set size from /proc/#/stat
+       long start_time;        // start time of process -- seconds since 1-1-70
+       long stime, utime;      // kernel & user-mode CPU time accumulated by process
+       long cstime, cutime;    // cumulative time of process and reaped children
+       int s_context;
+};
+
+char *process_name;
+
+void usage()
+{
+       fprintf(stderr, "%s: from vserver kit version %s\n", process_name, VERSION);
+       fprintf(stderr, "(no argument needed)\n\n");
+       fprintf(stderr, "Show informations about all the active context.\n\n");
+       fprintf(stderr, "       CTX#            Context number\n");
+       fprintf(stderr, "                       #0 = root context\n");
+       fprintf(stderr, "                       #1 = monitoring context\n");
+       fprintf(stderr, "       PROC QTY        Quantity of processes in each context\n");
+       fprintf(stderr, "       VSZ             Number of pages of virtual memory\n");
+       fprintf(stderr, "       RSS             Resident set size\n");
+       fprintf(stderr, "       userTIME        User-mode CPU time accumulated\n");
+       fprintf(stderr, "       sysTIME         Kernel-mode CPU time accumulated\n");
+       fprintf(stderr, "       UPTIME          Uptime/context\n");
+       fprintf(stderr, "       NAME            Virtual server name\n");
+       fprintf(stderr, "\n");
+
+}
+
+// return uptime (in ms) from /proc/uptime
+long get_uptime()
+{
+       int fd;
+       double up;
+       char buffer[64];
+
+       // open the /proc/uptime file
+       if ((fd = open("/proc/uptime", O_RDONLY, 0)) == -1)
+               return 0;
+
+       if (read(fd, buffer, sizeof(buffer)) < 1)
+               return 0;
+
+       close(fd);
+
+       if (sscanf(buffer, "%lf", &up) < 1)
+       {
+               fprintf(stderr, "%s: bad data in /proc/uptime\n", process_name);
+               return 0;
+       }
+
+       return up * 100;
+}
+
+// insert a new record to the list
+struct ctx_list *insert_ctx(int ctx, struct ctx_list *next)
+{
+       struct ctx_list *new;
+
+       new = (struct ctx_list *)malloc(sizeof(struct ctx_list));
+       new->ctx = ctx;
+       new->process_count = 0;
+       new->VmSize_total = 0;
+       new->VmRSS_total = 0;
+       new->utime_total = 0;
+       new->stime_total = 0;
+       new->start_time_oldest = 0;
+       new->next = next;
+       new->name[0] = '\0';
+
+       return new;
+}
+
+// find the ctx record with the ctx number
+struct ctx_list *find_ctx(struct ctx_list *list, int ctx)
+{
+       // very simple search engine...
+       while(list != NULL)
+       {
+               // find
+               if (list->ctx == ctx)
+               {
+                       return list;
+               }
+               list = list->next;
+       }
+       return NULL;
+}
+
+// compute the process info into the list
+void add_ctx(struct ctx_list *list, struct process_info *process)
+{
+       list->process_count ++;
+       list->VmSize_total += process->VmSize;
+       list->VmRSS_total += process->VmRSS;
+       list->utime_total += process->utime + process->cutime;
+       list->stime_total += process->stime + process->cstime;
+
+       if (list->start_time_oldest == 0) // first entry
+               list->start_time_oldest = process->start_time;
+       else
+               if (list->start_time_oldest > process->start_time)
+                       list->start_time_oldest = process->start_time;
+}
+
+// increment the count number in the ctx record using ctx number
+void count_ctx(struct ctx_list *list, struct process_info *process)
+{
+       struct ctx_list *prev = list;
+
+       if (process == NULL) return;
+
+       // search
+       while(list != NULL)
+       {
+               // find
+               if (list->ctx == process->s_context)
+               {
+                       add_ctx(list, process);
+                       return;
+               }
+               // insert between
+               if (list->ctx > process->s_context)
+               {
+                       prev->next = insert_ctx(process->s_context, list);
+                       add_ctx(prev->next, process);
+                       return;
+               }
+               // ++
+               prev = list;
+               list = list->next;
+       }
+       // add at the end
+       prev->next = insert_ctx(process->s_context, NULL);
+       add_ctx(prev->next, process);
+}
+
+// free mem
+void free_ctx(struct ctx_list *list)
+{
+       struct ctx_list *prev;
+
+       for(;list != NULL; list = prev)
+       {
+               prev = list->next;              
+               free(list);
+       }
+}
+
+/*
+       Read the vserver description
+*/
+static void read_description(
+       const char *name,               // Vserver name
+       char descrip[1000])
+{
+       char conf[PATH_MAX];
+       FILE *fin;
+       descrip[0] = '\0';
+       snprintf (conf,sizeof(conf)-1,"/etc/vservers/%s.conf",name);
+       fin = fopen (conf,"r");
+       if (fin != NULL){
+               char line[1000];
+               while (fgets(line,sizeof(line)-1,fin)!=NULL){
+                       if (line[0] == '#'){
+                               char *pt = line+1;
+                               while (isspace(*pt)) pt++;
+                               if (strncmp(pt,"Description:",12)==0){
+                                       int last;
+                                       pt += 12;
+                                       while (isspace(*pt)) pt++;
+                                       strcpy (descrip,pt);
+                                       last = strlen(descrip)-1;
+                                       if (last >=0 && descrip[last] == '\n'){
+                                               descrip[last] = '\0';
+                                       }
+                               }
+                       }
+               }
+               fclose (fin);
+       }
+}
+
+// show the ctx_list with name from /var/run/servers/*.ctx
+void show_ctx(struct ctx_list *list)
+{
+       // fill the ctx_list using the /var/run/servers/*.ctx file(s)
+        __extension__ int bind_ctx_name(struct ctx_list *list)
+       {
+               // fetch the context number in /var/run/vservers/'filename'
+               int fetch_ctx_number(char *filename)
+               {
+                       int fd;
+                       int ctx;
+                       char buf[25];
+
+                       // open file
+                       if ((fd = open(filename, O_RDONLY, 0)) == -1)
+                               return -1;
+                       // put the file in a small buffer
+                       if (read(fd, buf, sizeof(buf)) < 1)
+                               return -1;
+
+                       close(fd);
+
+                       sscanf(buf, "S_CONTEXT=%d", &ctx);
+                       return ctx;
+               }
+
+               /* begin bind_ctx_name */
+
+               DIR *ctx_dir;
+               struct dirent *dir_entry;
+               char *p;
+               char ctx_name[CTX_NAME_MAX_LEN];
+               struct ctx_list *ctx;
+               int ctx_number;
+
+               // open the /var/run/vservers directory
+               if ((ctx_dir = opendir(CTX_DIR_NAME)) == NULL)
+               {
+                       fprintf(stderr, "%s: in openning %s: %s\n", process_name, CTX_DIR_NAME, strerror(errno));
+                       return -1;
+               }
+       
+               chdir(CTX_DIR_NAME);
+               while ((dir_entry = readdir(ctx_dir)) != NULL)
+               {
+                       strncpy(ctx_name, dir_entry->d_name, sizeof(ctx_name));
+                       p = strstr(ctx_name, ".ctx");
+                       if (p != NULL) // make sure that it is a .ctx file..
+                       {
+                               *p = '\0'; // remove the .ctx in the file name
+                               if ((ctx_number = fetch_ctx_number(dir_entry->d_name)) > 1)
+                               {
+                                       if ((ctx = find_ctx(list, ctx_number)) != NULL)
+                                               strncpy(ctx->name, ctx_name, CTX_NAME_MAX_LEN);
+                               }
+                       }
+                       // else fprintf(stderr, "invalid file %s in %s\n", dir_entry->d_name, CTX_DIR_NAME);
+               }
+               closedir(ctx_dir);      
+               return 0;
+       }
+
+        __extension__ char *convert_time(unsigned t, char *str)
+       {
+               unsigned hh, mm, ss, ms;
+
+               ms = t % 100;
+               t /= 100;
+
+               ss = t%60;
+               t /= 60;
+               mm = t%60;
+               t /= 60;
+               hh = t%60;
+               t /= 24;
+
+               if (t > 0)      // day > 0
+               {
+                               snprintf(str, 25, "%3.ud%02uh%02u", t, (hh%12) ? hh%12 : 12, mm);
+               }
+               else
+               {
+                       if (hh > 0) // hour > 0
+                               snprintf(str, 25, " %2.uh%02um%02u", hh, mm, ss);
+                       else
+                       {
+                               snprintf(str, 25, " %2.um%02u.%02u", mm, ss, ms);
+                       }
+               }
+               return str;
+       }
+
+        __extension__ char *convert_mem(unsigned long total, char *str)
+       {
+               // Byte
+               if (total < 1024)
+               {
+                       snprintf(str, 25, "%luB", total);
+                       return str;
+               }
+
+               total >>= 10; // kByte
+               if (total < 1024)
+               {
+                       snprintf(str, 25, "%lukB", total);
+                       return str;
+               }
+
+               total >>= 10; // MByte
+               if (total < 1024)
+               {
+                       snprintf(str, 25, "%luMB", total);
+                       return str;
+               }
+
+               total >>= 10; // GByte
+               if (total < 1024)
+               {
+                       snprintf(str, 25, "%luGB", total);
+                       return str;
+               }
+               total >>= 10; // TByte
+               snprintf(str, 25, "%luTB", total);
+               return str;
+       }
+
+       /* begin show_ctx */
+       char utime[25], stime[25], ctx_uptime[25];
+       char vmsize[25], vmrss[25];
+       long uptime = get_uptime();
+
+       // now we have all the active context, fetch the name
+       // from /var/run/vservers/*.ctx
+       bind_ctx_name(list);
+
+       printf("CTX  PROC    VSZ    RSS  userTIME   sysTIME    UPTIME NAME     DESCRIPTION\n");
+       while(list != NULL)
+       {
+               char descrip[1000];
+               if (list->ctx == 1)
+                       strncpy(list->name, "monitoring server", CTX_NAME_MAX_LEN);
+
+               read_description (list->name,descrip);
+
+               printf("%-4d %4d %6s %6s %9s %9s %9s %-8s %s\n", list->ctx, list->process_count,
+                       convert_mem(list->VmSize_total, vmsize), convert_mem(list->VmRSS_total, vmrss),
+                       convert_time(list->utime_total, utime), convert_time(list->stime_total, stime), convert_time(uptime - list->start_time_oldest, ctx_uptime)
+                       , list->name,descrip);
+               list = list->next;
+       }
+}
+
+// open the process's status file to get the ctx number, and other stat
+struct process_info *get_process_info(char *pid)
+{
+       int fd;
+       char buffer[1024];
+       char *p;
+       static struct process_info process;
+
+       // open the proc/#/status file
+       snprintf(buffer, sizeof(buffer),  "/proc/%s/status", pid);
+       if ((fd = open(buffer, O_RDONLY, 0)) == -1)
+               return NULL;
+       // put the file in a buffer
+       if (read(fd, buffer, sizeof(buffer)) < 1)
+               return NULL;
+
+       close(fd);
+
+       // find the s_context entry
+       if ((p = strstr(buffer, "s_context:")) == NULL)
+               return NULL;
+
+       sscanf(p, "s_context: %d", &process.s_context);
+
+       // open the /proc/#/stat file
+       snprintf(buffer, sizeof(buffer),  "/proc/%s/stat", pid);
+       if ((fd = open(buffer, O_RDONLY, 0)) == -1)
+               return NULL;
+       // put the file in a buffer
+       if (read(fd, buffer, sizeof(buffer)) < 1)
+               return NULL;
+
+       close(fd);
+
+       p = strchr(buffer, ')');                // go after the PID (process_name)
+       sscanf(p + 2,
+               "%*s "
+               "%*s %*s %*s %*s %*s "
+               "%*s %*s %*s %*s %*s %ld %ld "
+               "%ld %ld %*s %*s %*s %*s "
+               "%ld %ld "
+               "%ld ", &process.utime, &process.stime,
+                       &process.cutime, &process.cstime,
+                       &process.start_time,
+                       &process.VmSize, &process.VmRSS);
+
+       return &process;
+}
+
+int main(int argc, char **argv)
+{
+       DIR *proc_dir;
+       struct dirent *dir_entry;
+       pid_t my_pid;
+       static int ctx1[]={1};
+
+       // for error msg
+       process_name = argv[0];
+
+       if (argc > 1)
+       {
+               usage();
+               return 0;
+       }
+
+       // do not include own stat
+       my_pid = getpid();
+
+       // try to switch in context 1
+       if (call_new_s_context(1,ctx1, 0, 0) < 0)
+       {
+               fprintf(stderr, "%s: unable to switch in context security #1\n", process_name);
+               return -1;
+       }
+
+       // create the fist...
+       my_ctx_list = insert_ctx(0, NULL);
+       // init with the default name for the context 0
+       strncpy(my_ctx_list->name, "root server", CTX_NAME_MAX_LEN);
+
+       // open the /proc dir
+       if ((proc_dir = opendir(PROC_DIR_NAME)) == NULL)
+       {
+               fprintf(stderr, "%s: %s\n", process_name, strerror(errno));
+               return -1;
+       }
+       
+       chdir(PROC_DIR_NAME);
+       while ((dir_entry = readdir(proc_dir)) != NULL)
+       {
+               // select only process file
+               if (!isdigit(*dir_entry->d_name))
+                       continue;
+
+               if (atoi(dir_entry->d_name) != my_pid)
+                       count_ctx(my_ctx_list, get_process_info(dir_entry->d_name));
+               
+       }
+       closedir(proc_dir);
+
+       // output the ctx_list  
+       show_ctx(my_ctx_list);
+
+       // free the ctx_list
+       free_ctx(my_ctx_list);
+
+       return 0;
+}
diff --git a/util-vserver/src/vunify.cc b/util-vserver/src/vunify.cc
new file mode 100644 (file)
index 0000000..0faa03b
--- /dev/null
@@ -0,0 +1,388 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vunify.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+/*
+       This utility is used to unify (using hard links) two or more
+       virtual servers.
+       It compares the each vserver with the first one and for every
+       common package (RPM, same version), it does a hard link on non
+       configuration file. It turns the file immutable after that.
+*/
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <iostream>
+#include "vutil.h"
+
+using namespace std;
+
+static bool undo = false;
+
+static int  ext2flags = EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL;
+struct EXCLDIR{
+       string prefix;
+       int len;
+       EXCLDIR(const char *s)
+       {
+               prefix = s;
+               prefix += '/';
+               len = prefix.size();
+       }
+};
+static vector<EXCLDIR> excldirs;
+static vector<EXCLDIR> incldirs;
+
+
+static void usage()
+{
+       cerr <<
+               "vunify version " << VERSION <<
+               "\n\n"
+               "vunify [ options ] reference-server vservers ... -- packages\n"
+               "vunify [ options ] reference-server vservers ... -- ALL\n"
+               "\n"
+               "--test: Show what will be done, do not do it.\n"
+               "--undo: Put back the file in place, using copies from the\n"
+               "        reference server.\n"
+               "--debug: Prints some debugging messages.\n"
+               "--noflags: Do not put any immutable flags on the file\n"
+               "--immutable: Set the immutable_file bit on the files.\n"
+               "--immutable-mayunlink: Sets the immutable_link flag on files.\n"
+               "\n"
+               "--excldir: None of the files under a given directory will be unified\n"
+               "\tThe directory is expressed in absolute/logical form (relative\n"
+               "\tto the vserver root (ex: /var/log)\n"
+               "\n"
+               "--incldir: All the files under a given directory will be unified\n"
+               "\tThe directory is expressed in absolute/logical form (relative\n"
+               "\tto the vserver root (ex: /var/log)\n"
+               "\n"
+               "By default, the immutable_file and     immutable_link flags are\n"
+               "set on the files. So if you want no immutable flags, you must\n"
+               "use --noflags. If you want a single flag, you must use\n"
+               "--noflags first, then the --immutable or --immutable-mayunlink\n"
+               "flag.\n"
+               ;
+}
+
+static bool vunify_inside (vector<EXCLDIR> &dirs, const char *path)
+{
+       bool found = false;
+       for (unsigned i=0; i<dirs.size(); i++){
+               if (strncmp(dirs[i].prefix.c_str(),path,dirs[i].len)==0){
+                       found = true;
+                       break;
+               }
+       }
+       return found;
+}
+
+class PACKAGE_UNI: public PACKAGE{
+public:
+       list<string> files;             // Files to unify
+                                                       // This is loaded on demand
+       PACKAGE_UNI(string &_name, string &_version)
+               : PACKAGE(_name,_version)
+       {
+       }
+       PACKAGE_UNI(const char *_name, const char *_version)
+               : PACKAGE (_name,_version)
+       {
+       }
+       PACKAGE_UNI(const string &line)
+               : PACKAGE (line)
+       {
+       }
+       // Load the file member of the package, but exclude configuration file
+       void loadfiles(const string &ref)
+       {
+               if (files.empty()){
+                       if (debug) cout << "Loading files for package " << name << endl;
+                       string namever;
+                       namever = name + '-' + version;
+                       FILE *fin = vutil_execdistcmd (K_UNIFILES,ref,namever.c_str());
+                       if (fin != NULL){
+                               char tmp[1000];
+                               while (fgets(tmp,sizeof(tmp)-1,fin)!=NULL){
+                                       int last = strlen(tmp)-1;
+                                       if (last >= 0 && tmp[last] == '\n') tmp[last] = '\0';
+                                       bool must_unify = false;
+                                       int type = 0;   // K_UNIFILES only report unify-able files
+                                       if(type == 0 && !vunify_inside(excldirs,tmp)){
+                                               must_unify = true;
+                                       }else if(vunify_inside(incldirs,tmp)){
+                                               must_unify = true;
+                                       }
+                                       if (must_unify){
+                                               files.push_front (tmp);
+                                       }else if (debug){
+                                               cout << "Package " << name << " exclude " << tmp << endl;
+                                       }
+                               }
+                       }
+                       if (debug) cout << "Done\n";
+               }
+       }
+};
+
+
+static ostream & operator << (ostream &c, const PACKAGE_UNI &p)
+{
+       return c << p.name << "-" << p.version;
+}
+
+template<class T>
+       void printit(T a){
+               cout << "xx " << a << endl;
+       }
+
+template<class T>
+       class printer{
+               string title;
+               public:
+               printer (const char *_title): title(_title){}
+               void operator()(T a){
+                       cout << title << " " << a << endl;
+               }
+       };
+
+
+/*
+       Load the list of all packages in a vserver
+*/
+static void vunify_loadallpkg (string &refserver, list<PACKAGE_UNI> &packages)
+{
+       FILE *fin = vutil_execdistcmd (K_PKGVERSION,refserver,NULL);
+       if (fin != NULL){
+               char line[1000];
+               while (fgets(line,sizeof(line)-1,fin)!=NULL){
+                       // fprintf (stderr,"line: %s",line);
+                       int last = strlen(line)-1;
+                       if (last >= 0 && line[last] == '\n') line[last] = '\0';
+                       packages.push_back (PACKAGE_UNI(line));
+               }
+               pclose (fin);
+       }
+}
+
+/*
+       Object to unify a file
+       The file is first removed, then a hard link is made  and then
+       the immutable flag is done
+*/
+class file_unifier{
+       string &ref_server,&target_server;
+       int &ret;
+       public:
+       file_unifier(string &_ref, string &_target, int &_ret)
+               : ref_server(_ref),target_server(_target), ret(_ret)
+       {}
+       void operator()(const string &file)
+       {
+               string refpath = "/vservers/" + ref_server + file;
+               string dstpath = "/vservers/" + target_server + file;
+               if (debug) cout << "Unify " << refpath << " -> " << dstpath << endl;
+               struct stat st;
+               if (stat(refpath.c_str(),&st)==-1){
+                       if (debug) cout << "File " << refpath << " does not exist, ignored\n";
+               }else if (setext2flag(refpath.c_str(),false,ext2flags)==-1){
+                       ret = -1;
+               }else if (vbuild_unlink(dstpath.c_str())==-1){
+                       ret = -1;
+                       cerr << "Can't delete file " << dstpath
+                               << " (" << strerror(errno) << ")\n";
+               }else{
+                       if (undo){
+                               if (vbuild_file_copy(refpath.c_str(),dstpath.c_str(),st)==-1){
+                                       ret = -1;
+                                       cerr << "Can't copy file " << refpath << " to " << dstpath
+                                               << " (" << strerror(errno) << ")\n";
+                               }
+                       }else{
+                               if (vbuild_link(refpath.c_str(),dstpath.c_str())==-1){
+                                       ret = -1;
+                                       cerr << "Can't link file " << refpath << " to " << dstpath
+                                               << " (" << strerror(errno) << ")\n";
+                               }
+                       }
+                       // We put back the original immutable because other vservers
+                       // may be unified on it.
+                       if (setext2flag(refpath.c_str(),true,ext2flags)==-1){
+                               ret = -1;
+                       }
+               }
+       }
+};
+#if 0
+// Check if two package have the same name (but potentially different version)
+class same_name{
+       PACKAGE_UNI &pkg;
+public:
+       same_name(PACKAGE_UNI &_pkg) : pkg(_pkg) {}
+       bool operator()(const PACKAGE_UNI &p)
+       {
+               return pkg.name == p.name;
+       }
+};
+#endif
+// Predicate to decide if a package must be unified
+class package_unifier{
+public:
+       string &ref_server,&target_server;
+       list<PACKAGE_UNI> &target_packages;
+       int &ret;
+       package_unifier(string &_ref,
+                       string &_target,
+                       list<PACKAGE_UNI> &_target_packages,
+                       int &_ret)
+               : ref_server(_ref),target_server(_target)
+               , target_packages(_target_packages) , ret(_ret)
+       {}
+       void operator()(PACKAGE_UNI &pkg)
+       {
+               if (find(target_packages.begin(),target_packages.end(),pkg)
+                       !=target_packages.end()){
+                       // Ok, the package is also in the target vserver
+                       cout << "Unify pkg " << pkg << " from " << ref_server << " to "
+                               << target_server << endl;
+
+                       if (!testmode || debug){
+                               pkg.loadfiles(ref_server);
+                               for_each (pkg.files.begin(),pkg.files.end()
+                                       ,file_unifier(ref_server,target_server,ret));
+                       }
+               }else if (testmode){
+                       // The package is missing, in test mode we provide more information
+                       if (find_if(target_packages.begin(),target_packages.end(),same_name(pkg))
+                               !=target_packages.end()){
+                               cout << pkg << " exist in server " << target_server << " not unified\n";
+                       }else{
+                               cout << pkg << " does not exist in server " << target_server << endl;
+                       }
+               }
+       }
+};
+
+// For each vserver, find the common packages and unify them
+class server_unifier{
+public:
+       list<PACKAGE_UNI> &ref_packages;
+       string &ref_server;
+       int &ret;
+       server_unifier(string _ref_server, list<PACKAGE_UNI> &_packages, int &_ret)
+               : ref_packages(_packages),ref_server(_ref_server), ret(_ret)
+               {}
+       void operator()(string serv)
+       {
+               list<PACKAGE_UNI> pkgs;
+               vunify_loadallpkg (serv,pkgs);
+               for_each(ref_packages.begin(),ref_packages.end()
+                       ,package_unifier(ref_server,serv,pkgs,ret));
+       }
+};
+class deleteif{
+public:
+       char **argv0,**argvn;
+       deleteif(char **_argv0, char **_argvn): argv0(_argv0),argvn(_argvn){}
+       bool operator()(const PACKAGE_UNI &pkg)
+       {
+               bool found = false;
+               for (char **pt = argv0; pt < argvn; pt++){
+                       if (pkg.name == *pt){
+                               found = true;
+                               break;
+                       }
+               }
+               return !found;
+       }
+};
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       int i;
+       for (i=1; i<argc; i++){
+               const char *arg = argv[i];
+               //const char *opt = argv[i+1];
+               if (strcmp(arg,"--test")==0){
+                       testmode = true;
+               }else if (strcmp(arg,"--undo")==0){
+                       undo = true;
+               }else if (strcmp(arg,"--debug")==0){
+                       debug++;
+               }else if (strcmp(arg,"--noflags")==0){
+                       ext2flags = 0;
+               }else if (strcmp(arg,"--immutable")==0){
+                       ext2flags |= EXT2_IMMUTABLE_FILE_FL;
+               }else if (strcmp(arg,"--immutable-mayunlink")==0){
+                       ext2flags |= EXT2_IMMUTABLE_LINK_FL;
+               }else if (strcmp(arg,"--excldir")==0){
+                       i++;
+                       //excldirs[excldirs.size()] = EXCLDIR(argv[i]);
+                       excldirs.push_back (EXCLDIR(argv[i]));
+               }else if (strcmp(arg,"--incldir")==0){
+                       i++;
+                       incldirs.push_back (EXCLDIR(argv[i]));
+               }else{
+                       break;
+               }
+       }
+       if (i==argc){
+               usage();
+       }else{
+               string refserv = argv[i++];
+               list<string> vservers;
+               for (; i<argc && strcmp(argv[i],"--")!=0; i++){
+                       vservers.push_front (argv[i]);
+               }
+               for_each (vservers.begin(),vservers.end(),printer<string>("vservers"));
+               if (i == argc || strcmp(argv[i],"--")!=0){
+                       usage();
+               }else{
+                       i++;
+                       if (i < argc){
+                               list<PACKAGE_UNI> packages;
+                               vunify_loadallpkg (refserv,packages);
+                               if (i != argc-1 || strcmp(argv[i],"ALL")!=0){
+                                       // We keep only the packages supplied on the command line
+                                       packages.remove_if(deleteif (argv+i,argv+argc));
+                               }
+                               ret = 0;
+                               umask (0);
+                               for_each (vservers.begin(),vservers.end(),server_unifier(refserv,packages,ret));
+                       }else{
+                               usage();
+                       }
+               }
+       }
+       return ret;
+}
+
+
+
+
diff --git a/util-vserver/src/vutil.cc b/util-vserver/src/vutil.cc
new file mode 100644 (file)
index 0000000..94957a3
--- /dev/null
@@ -0,0 +1,265 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vutil.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#pragma implementation
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <utime.h>
+#include "vutil.h"
+#include <sys/ioctl.h>
+#include <linux/ext2_fs.h>
+
+bool testmode;
+int debug;
+
+int file_copy (const char *src, const char *dst, struct stat &st)
+{
+       int ret = -1;
+       FILE *fin = fopen (src,"r");
+       if (fin == NULL){
+               fprintf (stderr,"Can't open file %s (%s)\n",src,strerror(errno));
+       }else{
+               FILE *fout = fopen (dst,"w");
+               if (fout == NULL){
+                       fprintf (stderr,"Can't open file %s (%s)\n",dst,strerror(errno));
+               }else{
+                       char buf[8192];
+                       int len;
+                       while ((len=fread(buf,1,sizeof(buf),fin))>0){
+                               fwrite (buf,1,len,fout);
+                       }
+                       fflush (fout);
+                       ret = 0;
+                       if (fchown (fileno(fout),st.st_uid,st.st_gid)==-1){
+                               fprintf (stderr,"Can't chown file %s (%s)\n"
+                                       ,dst,strerror(errno));
+                               ret = -1;
+                       }else if (fchmod (fileno(fout),st.st_mode)==-1){
+                               fprintf (stderr,"Can't chmod file %s (%s)\n"
+                                       ,dst,strerror(errno));
+                               ret = -1;
+                       }
+                       fclose(fout);
+                       struct utimbuf timbuf;
+                       timbuf.modtime = st.st_mtime;
+                       timbuf.actime = st.st_atime;
+                       if (utime (dst,&timbuf)==-1){
+                               fprintf (stderr,"Can't set time stamp on file %s (%s)\n"
+                                       ,dst,strerror(errno));
+                       }
+               }
+               fclose (fin);
+       }
+       return ret;
+}
+
+/*
+       Set the immutable flag on a file
+*/
+int setext2flag (const char *fname, bool set, int ext2flags)
+{
+       int ret = -1;
+       if (testmode){
+               ret = 0;
+       }else{
+               int fd = open (fname,O_RDONLY);
+               if (fd == -1){
+                       fprintf (stderr,"Can't open file %s (%s)\n",fname 
+                               ,strerror(errno));
+               }else{
+                       int flags = set ? ext2flags : 0;
+                       ret = ioctl (fd,EXT2_IOC_SETFLAGS,&flags);
+                       close (fd);
+                       if (ret == -1){
+                               fprintf (stderr,"Can't %s immutable flag on file %s (^s)\n"
+                                       ,(set ? "set" : "unset")
+                                       ,fname
+                                       ,strerror(errno));
+                       }
+               }
+       }
+       return ret;
+}
+
+int vbuild_mkdir (const char *path, mode_t mode)
+{
+       int ret = -1;
+       if (testmode){
+               printf ("mkdir %s; chmod %o %s\n",path,mode,path);
+               ret = 0;
+       }else{
+               ret = mkdir (path,mode);
+               if (ret == -1 && errno == EEXIST){
+                       struct stat st;
+                       if (lstat(path,&st)!=-1 && S_ISDIR(st.st_mode)){
+                               ret = chmod (path,mode);
+                       }
+               }
+       }
+       return ret;
+}
+
+int vbuild_mknod(const char *path, mode_t mode, dev_t dev)
+{
+       int ret = -1;
+       if (testmode){
+               printf ("mknod %s %o %02x:%02x\n",path,mode,major(dev),minor(dev));
+               ret = 0;
+       }else{
+               ret = mknod (path,mode,dev);
+               if (ret == -1 && errno == EEXIST){
+                       struct stat st;
+                       lstat(path,&st);
+                       if (lstat(path,&st)!=-1
+                               && (st.st_mode & S_IFMT) == (mode & S_IFMT)
+                               && st.st_rdev == dev){
+                               ret = chmod (path,mode);
+                       }
+               }
+       }
+       return ret;
+}
+int vbuild_symlink(const char *src, const char *dst)
+{
+       int ret = -1;
+       if (testmode){
+               printf ("ln -s %s %s\n",src,dst);
+               ret = 0;
+       }else{
+               ret = symlink (src,dst);
+       }
+       return ret;
+}
+
+int vbuild_link(const char *src, const char *dst)
+{
+       int ret = -1;
+       if (testmode){
+               printf ("ln %s %s\n",src,dst);
+               ret = 0;
+       }else{
+               ret = link (src,dst);
+       }
+       return ret;
+}
+
+int vbuild_unlink(const char *path)
+{
+       int ret = -1;
+       if (testmode){
+               printf ("unlink %s\n",path);
+               ret = 0;
+       }else{
+               ret = unlink (path);
+       }
+       return ret;
+}
+
+int vbuild_chown(const char *path, uid_t uid, gid_t gid)
+{
+       int ret = -1;
+       if (testmode){
+               printf ("chown %d.%d %s\n",uid,gid,path);
+               ret = 0;
+       }else{
+               ret = chown (path,uid,gid);
+       }
+       return ret;
+}
+
+int vbuild_file_copy(
+       const char *src,
+       const char *dst,
+       struct stat &st)
+{
+       int ret = -1;
+       if (testmode){
+               printf ("cp -a %s %s\n",src,dst);
+               ret = 0;
+       }else{
+               ret = file_copy (src,dst,st);
+       }
+       return ret;
+}
+
+/*
+       Load the list of all packages in a vserver
+*/
+void vutil_loadallpkg (string &refserver, list<PACKAGE> &packages)
+{
+       FILE *fin = vutil_execdistcmd (K_PKGVERSION,refserver,NULL);
+       if (fin != NULL){
+               char line[1000];
+               while (fgets(line,sizeof(line)-1,fin)!=NULL){
+                       int last = strlen(line)-1;
+                       if (last >= 0 && line[last] == '\n') line[last] = '\0';
+                       packages.push_back (PACKAGE(line));
+               }
+               pclose (fin);
+       }
+}
+
+int vutil_lstat (string path, struct stat &st)
+{
+       int ret = 0;
+       if (lstat(path.c_str(),&st) == -1){
+               fprintf (stderr,"Can't lstat file %s (%s)\n"
+                       ,path.c_str(),strerror(errno));
+               ret = -1;
+       }
+       return ret;
+}
+
+const char K_PKGVERSION[]="pkgversion";
+const char K_DUMPFILES[]="dumpfiles";
+const char K_UNIFILES[]="unifiles";
+
+FILE *vutil_execdistcmd (const char *key, const string &vserver, const char *args)
+{
+       string cmd = PKGLIBDIR "/distrib-info ";
+       cmd += vserver;
+       cmd += " ";
+       cmd += key;
+       if (args != NULL){
+               cmd += " ";
+               cmd += args;
+       }
+       FILE *ret = popen (cmd.c_str(),"r");
+       if (ret == NULL){
+               fprintf (stderr,"Can't execute command %s\n",cmd.c_str());
+       }else{
+               #if 0
+               char buf[1000];
+               while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
+                       int last = strlen(buf)-1;
+                       if (last >= 0) buf[last] = '\0';
+                       ret = buf;
+                       break;
+               }
+               pclose (fin);
+               #endif
+       }
+       return ret;
+}
+
diff --git a/util-vserver/src/vutil.h b/util-vserver/src/vutil.h
new file mode 100644 (file)
index 0000000..d334df3
--- /dev/null
@@ -0,0 +1,134 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vutil.h by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#pragma interface
+#ifndef VUTIL_H
+#define VUTIL_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <string>
+#include <set>
+#include <algorithm>
+#include <iostream>
+#include <list>
+
+using namespace std;
+
+extern int debug;
+extern bool testmode;
+
+// Patch to help compile this utility on unpatched kernel source
+#ifndef EXT2_IMMUTABLE_FILE_FL
+       #define EXT2_IMMUTABLE_FILE_FL  0x00000010
+       #define EXT2_IMMUTABLE_LINK_FL  0x00008000
+#endif
+
+
+FILE *vutil_execdistcmd (const char *, const string &, const char *);
+extern const char K_DUMPFILES[];
+extern const char K_UNIFILES[];
+extern const char K_PKGVERSION[];
+
+class PACKAGE{
+public:
+       string name;
+       string version; // version + release
+       PACKAGE(string &_name, string &_version)
+               : name (_name), version(_version)
+       {
+       }
+       PACKAGE(const char *_name, const char *_version)
+               : name (_name), version(_version)
+       {
+       }
+       PACKAGE(const string &line)
+       {
+               *this = line;
+       }
+       PACKAGE & operator = (const string &_line)
+       {
+               string line (_line);
+               string::iterator pos = find (line.begin(),line.end(),'=');
+               if (pos != line.end()){
+                       name = string(line.begin(),pos);
+                       version = string(pos + 1,line.end());
+               }
+               return *this;
+       }
+       PACKAGE (const PACKAGE &pkg)
+       {
+               name = pkg.name;
+               version = pkg.version;
+       }
+       bool operator == (const PACKAGE &v) const
+       {
+               return name == v.name && version == v.version;
+       }
+       bool operator < (const PACKAGE &v) const
+       {
+               bool ret = false;
+               if (name < v.name){
+                       ret = true;
+               }else if (name == v.name && version < v.version){
+                       ret = true;
+               }
+               return ret;
+       }
+       // Load the file member of the package, but exclude configuration file
+       void loadfiles(const string &ref, set<string> &files)
+       {
+               if (debug > 2) cout << "Loading files for package " << name << endl;
+               string namever = name + '-' + version;
+               FILE *fin = vutil_execdistcmd (K_UNIFILES,ref,namever.c_str());
+               if (fin != NULL){
+                       char tmp[1000];
+                       while (fgets(tmp,sizeof(tmp)-1,fin)!=NULL){
+                               int last = strlen(tmp)-1;
+                               if (last >= 0 && tmp[last] == '\n') tmp[last] = '\0';
+                               files.insert (tmp);
+                       }
+               }
+               if (debug > 2) cout << "Done\n";
+       }
+       #if 0
+       bool locate(const string &path)
+       {
+               return find (files.begin(),files.end(),path) != files.end();
+       }
+       #endif
+};
+
+// Check if two package have the same name (but potentially different version)
+class same_name{
+       const PACKAGE &pkg;
+public:
+       same_name(const PACKAGE &_pkg) : pkg(_pkg) {}
+       bool operator()(const PACKAGE &p)
+       {
+               return pkg.name == p.name;
+       }
+};
+
+
+#include "vutil.p"
+
+#endif
+
diff --git a/util-vserver/src/vutil.p b/util-vserver/src/vutil.p
new file mode 100644 (file)
index 0000000..ada13e2
--- /dev/null
@@ -0,0 +1,49 @@
+// $Id$                --*- c++ -*--
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vutil.p by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+/* vutil.cc 11/04/2003 14.22.04 */
+int file_copy (const char *src, const char *dst, struct stat&st);
+int setext2flag (const char *fname, bool set, int ext2flags);
+int vbuild_mkdir (const char *path, mode_t mode);
+int vbuild_mknod (const char *path, mode_t mode, dev_t dev);
+int vbuild_symlink (const char *src, const char *dst);
+int vbuild_link (const char *src, const char *dst);
+int vbuild_unlink (const char *path);
+int vbuild_chown (const char *path, uid_t uid, gid_t gid);
+int vbuild_file_copy (const char *src,
+        const char *dst,
+        struct stat&st);
+void vutil_loadallpkg (string&refserver, list<PACKAGE>&packages);
+int vutil_lstat (string path, struct stat&st);
+FILE *vutil_execdistcmd (const char *key,
+        const string&vserver,
+        const char *args);
+/* syscall.cc 18/07/2003 09.50.10 */
+extern "C" int call_new_s_context (int nbctx,
+        int ctxs[],
+        int remove_cap,
+        int flags);
+extern "C" int call_set_ipv4root (unsigned long ip[],
+        int nb,
+        unsigned long bcast,
+        unsigned long mask[]);
+extern "C" int call_chrootsafe (const char *dir);
+extern "C" int has_chrootsafe (void);
+extern "C" int call_set_ctxlimit (int res, long limit);
diff --git a/util-vserver/sysv/Makefile-files b/util-vserver/sysv/Makefile-files
new file mode 100644 (file)
index 0000000..6601c4e
--- /dev/null
@@ -0,0 +1,57 @@
+## $Id$  -*- makefile -*-
+
+## Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+sysv_XTRAS             =  sysv/rebootmgr.subst \
+                          sysv/v_gated.subst \
+                          sysv/v_httpd.subst \
+                          sysv/v_named.subst \
+                          sysv/v_portmap.subst \
+                          sysv/v_sendmail.subst \
+                          sysv/v_smb.subst \
+                          sysv/v_sshd.subst \
+                          sysv/v_xinetd.subst \
+                          sysv/vservers.subst
+
+sysv_GENSCRPTS         =  sysv/rebootmgr \
+                          sysv/v_gated \
+                          sysv/v_httpd \
+                          sysv/v_named \
+                          sysv/v_portmap \
+                          sysv/v_sendmail \
+                          sysv/v_smb \
+                          sysv/v_sshd \
+                          sysv/v_xinetd \
+                          sysv/vservers
+
+sysv_SCRPTS            =  $(sysv_GENSCRPTS)
+
+sysv_CFG               =  sysv/vservers.conf
+
+
+sysv/%:                        sysv/%.subst
+                       @mkdir -p $$(dirname '$@')
+                       sed -s 's!/usr/lib/util-vserver!$(pkglibdir)!g; \
+                               s!^USR_SBIN=/usr/sbin$$!USR_SBIN=$(sbindir)!g' '$<' >'$@.tmp'
+                       if cmp -s '$<' '$@.tmp'; then \
+                               cp -p '$<' '$@'; \
+                       else \
+                               mv -f '$@.tmp' '$@'; \
+                       fi
+                       -rm -f '$@.tmp'
+                       @chmod a-w '$@'
diff --git a/util-vserver/sysv/rebootmgr.subst b/util-vserver/sysv/rebootmgr.subst
new file mode 100755 (executable)
index 0000000..a526dd8
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/sh
+# chkconfig: - 98 10
+# description: The rebootmgr service is monitoring all virtual servers \
+#              and restart them as need. Virtual servers are using \
+#              the /sbin/vreboot command to talk with the reboot manager
+# processname: rebootmgr
+# config: /etc/vservers
+
+
+USR_SBIN=/usr/sbin
+PIDFILE=/var/run/rebootmgr.pid
+# See how we were called.
+case "$1" in
+  start)
+       echo "Starting the reboot manager"
+       cd /etc/vservers
+       VSERVERS=
+       for serv in *.conf
+       do
+               serv=`basename $serv .conf`
+               if [ -d /vservers/$serv ] ; then
+                       VSERVERS="$VSERVERS $serv"
+               fi
+       done
+       $USR_SBIN/rebootmgr --pidfile $PIDFILE $VSERVERS &
+       touch /var/lock/subsys/rebootmgr
+       ;;
+  stop)
+       echo "Stopping the reboot manager"
+       kill `cat $PIDFILE`
+       rm -f /var/lock/subsys/rebootmgr
+       rm -f $PIDFILE
+       ;;
+  restart)
+       $0 stop
+       $0 start
+       ;;
+  reload)
+       echo Not implemented
+       ;;
+  status)
+       if [ -f $PIDFILE ] ; then
+               if kill -0 `cat $PIDFILE`
+               then
+                       echo rebootmgr is running
+               else
+                       echo rebootmgr is NOT running
+               fi
+       fi
+       ;;
+  *)
+       echo "Usage: rebootmgr {start|stop|restart|reload|status}"
+       exit 1
+esac
+
+exit 0
+
+
+
+
+
diff --git a/util-vserver/sysv/v_gated.subst b/util-vserver/sysv/v_gated.subst
new file mode 100755 (executable)
index 0000000..294857a
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+# chkconfig: - 32 75
+# description: Wrapper to start gated bound to a single IP
+
+# normally, you will need /etc/vservices/gated.conf
+# with the following line
+# IP=0.0.0.0
+# so gated is started without restriction even if you
+# restart it from an ssh session, itself "chbounded" to a single
+# IP.
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper gated $*
+
diff --git a/util-vserver/sysv/v_httpd.subst b/util-vserver/sysv/v_httpd.subst
new file mode 100755 (executable)
index 0000000..1c43a57
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+# chkconfig: - 85 15
+# description: Wrapper to start httpd bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper httpd $*
+
diff --git a/util-vserver/sysv/v_named.subst b/util-vserver/sysv/v_named.subst
new file mode 100755 (executable)
index 0000000..507847f
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+# chkconfig: - 55 45
+# description: Wrapper to start named bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper named $*
+
+
+
+
+
+
diff --git a/util-vserver/sysv/v_portmap.subst b/util-vserver/sysv/v_portmap.subst
new file mode 100755 (executable)
index 0000000..589f131
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+# chkconfig: - 91 35
+# description: Wrapper to start portmap bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper portmap $*
+
+
+
+
+
+
diff --git a/util-vserver/sysv/v_sendmail.subst b/util-vserver/sysv/v_sendmail.subst
new file mode 100755 (executable)
index 0000000..166597c
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+# chkconfig: - 80 30
+# description: Wrapper to start sendmail bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper sendmail $*
+
diff --git a/util-vserver/sysv/v_smb.subst b/util-vserver/sysv/v_smb.subst
new file mode 100755 (executable)
index 0000000..3058ba7
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+# chkconfig: - 91 35
+# description: Wrapper to start smb bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper smb $*
+
+
+
+
+
+
diff --git a/util-vserver/sysv/v_sshd.subst b/util-vserver/sysv/v_sshd.subst
new file mode 100755 (executable)
index 0000000..4459ce5
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+# chkconfig: - 55 25
+# description: Wrapper to start sshd bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper sshd $*
+
+
+
+
+
+
diff --git a/util-vserver/sysv/v_xinetd.subst b/util-vserver/sysv/v_xinetd.subst
new file mode 100755 (executable)
index 0000000..7933f12
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+# chkconfig: - 56 50
+# description: Wrapper to start xinetd bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper xinetd $*
+
diff --git a/util-vserver/sysv/vservers.conf b/util-vserver/sysv/vservers.conf
new file mode 100644 (file)
index 0000000..0f309e3
--- /dev/null
@@ -0,0 +1,7 @@
+# Configuration file for the vservers service
+# BACKGROUND=yes
+# start the vservers on tty9, in background so the rest of the
+# boot process end early
+BACKGROUND=no
+
+
diff --git a/util-vserver/sysv/vservers.subst b/util-vserver/sysv/vservers.subst
new file mode 100755 (executable)
index 0000000..d091d93
--- /dev/null
@@ -0,0 +1,89 @@
+#!/bin/sh
+# chkconfig: 345 98 10
+# description: The vservers service is used to start and stop all
+#              the virtual servers.
+
+USR_SBIN=/usr/sbin
+
+
+# Print the vserver name in priority/alpha order
+sortserver(){
+       (
+       cd /etc/vservers
+       for serv in *.conf
+       do
+               PRIORITY=100
+               . $serv
+               printf "%03d %s\n" $PRIORITY `basename $serv .conf`
+       done
+       ) | sort $* | (while read a b; do echo $b; done)
+}
+
+startservers(){
+       echo "Starting the virtual servers"
+       cd /etc/vservers
+       for name in `sortserver`
+       do
+               ONBOOT=
+               . $name.conf
+               if [ "$ONBOOT" = "yes" ] ; then
+                       $USR_SBIN/vserver $name start
+               else
+                       echo virtual server $name not configured for on boot start
+               fi
+       done
+}
+
+BACKGROUND=off
+if [ -f /etc/vservers.conf ] ; then
+       . /etc/vservers.conf
+fi
+
+
+# See how we were called.
+case "$1" in
+  start)
+       if [ "$BACKGROUND" = "yes" ] ; then
+               startservers >/dev/tty8 </dev/tty8 2>/dev/tty8 &
+       else
+               startservers
+       fi
+       touch /var/lock/subsys/vservers
+       ;;
+  stop)
+       echo "Stopping the virtual servers"
+       cd /etc/vservers
+       for name in `sortserver -r`
+       do
+               $USR_SBIN/vserver $name stop
+       done
+       rm -f /var/lock/subsys/vservers
+       ;;
+  restart)
+       $0 stop
+       $0 start
+       ;;
+  reload)
+       echo Not implemented
+       ;;
+  status)
+       cd /etc/vservers
+       for serv in *.conf
+       do
+               ONBOOT=no
+               name=`basename $serv .conf`
+               . $serv
+               echo -n ONBOOT=$ONBOOT " "
+               $USR_SBIN/vserver $name running
+       done
+       ;;
+  *)
+       echo "Usage: vservers {start|stop|restart|reload|status}"
+       exit 1
+esac
+
+exit 0
+
+
+
+
diff --git a/util-vserver/tests/Makefile-files b/util-vserver/tests/Makefile-files
new file mode 100644 (file)
index 0000000..f4b4331
--- /dev/null
@@ -0,0 +1,34 @@
+## $Id$  -*- makefile -*-
+
+## Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+##  
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##  
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##  
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##  
+
+test_PRGS              =  tests/chrootsafe \
+                          tests/escaperoot \
+                          tests/forkbomb \
+                          tests/testipc \
+                          tests/testlimit \
+                          tests/testopenf
+
+tests_chrootsafe_SOURCES       =  tests/chrootsafe.cc
+tests_chrootsafe_LDADD         =  lib/libvserver.a
+
+tests_escaperoot_SOURCES       =  tests/escaperoot.cc
+tests_forkbomb_SOURCES         =  tests/forkbomb.cc
+tests_testipc_SOURCES          =  tests/testipc.cc
+tests_testlimit_SOURCES                =  tests/testlimit.cc
+tests_testopenf_SOURCES                =  tests/testopenf.cc
diff --git a/util-vserver/tests/chrootsafe.cc b/util-vserver/tests/chrootsafe.cc
new file mode 100644 (file)
index 0000000..eac461d
--- /dev/null
@@ -0,0 +1,59 @@
+// $Id$    --*- c++ -*--
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/chrootsafe.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       Test the chrootsafe command.
+       Pass the path of a vserver as the only argument
+
+       chrootsafe /vservers/test
+*/
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "vserver.h"
+
+int main (int argc, char *argv[])
+{
+       // This test must fail
+       int fd = open ("/",O_RDONLY);
+       if (fd != -1){
+               if (call_chrootsafe(argv[1])==-1){
+                       fprintf (stderr,"Ok, chrootsafe failed with one open directory errno=%s\n",strerror(errno));
+               }else{
+                       fprintf (stderr,"Hum, chrootsafe succeed with one open directory\n");
+                       system ("/bin/sh");
+               }
+               close (fd);
+       }
+       // Now it should work
+       if (call_chrootsafe(argv[1])!=-1){
+               fprintf (stderr,"Ok, chrootsafe worked\n");
+               system ("/bin/sh");
+       }else{
+               fprintf (stderr,"chrootsafe failed errno=%s\n",strerror(errno));
+       }
+       return 0;
+}      
+
diff --git a/util-vserver/tests/escaperoot.cc b/util-vserver/tests/escaperoot.cc
new file mode 100644 (file)
index 0000000..1357229
--- /dev/null
@@ -0,0 +1,115 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/escaperoot.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       This program tries to escape out of a vserver using chroot flaws.
+       Once escaped, it exec a shell.
+
+       None of this works on 2.4.13.
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <wait.h>
+#include <limits.h>
+
+static void print_pwd()
+{
+       char path[PATH_MAX];
+       if (getcwd(path,sizeof(path)-1)!=NULL){
+               printf ("PWD: %s\n",path);
+       }
+}
+/*
+       Just set a chroot in a sub-directory and keep the
+       current directory behind
+*/
+static void test1()
+{
+       printf ("test1\n");
+       print_pwd();
+       mkdir ("dummy_dir",0755);
+       if (chroot ("dummy_dir")==-1){
+               fprintf (stderr,"Can't chroot into dummy_dir (%s)\n",strerror(errno));
+       }else{
+               // Try to chdir into the real root
+               for (int i=0; i<1000; i++) chdir("..");
+               print_pwd();
+               if (execl ("/bin/sh","/bin/sh",NULL)==-1){
+                       fprintf (stderr,"execl /bin/sh failed (%s)\n",strerror(errno));
+               }
+       }
+}
+
+/*
+       Same as test1, except we open the current directory and do
+       a fchdir() to it before trying to escape to the real root.
+*/
+static void test2()
+{
+       printf ("test2\n");
+       print_pwd();
+       mkdir ("dummy_dir",0755);
+       int fd = open (".",O_RDONLY);
+       if (fd == -1){
+               fprintf (stderr,"Can't open current directory (%s)\n",strerror(errno));
+       }else if (chroot ("dummy_dir")==-1){
+               fprintf (stderr,"Can't chroot into dummy_dir (%s)\n",strerror(errno));
+       }else if (fchdir(fd)==-1){
+               fprintf (stderr,"Can't fchdir to the current directory (%s)\n"
+                       ,strerror(errno));
+       }else{
+               // Try to chdir into the real root
+               for (int i=0; i<1000; i++) chdir("..");
+               print_pwd();
+               if (execl ("/bin/sh","/bin/sh",NULL)==-1){
+                       fprintf (stderr,"execl /bin/sh failed (%s)\n",strerror(errno));
+               }
+       }
+}
+
+/*
+       Perform the test in a sub-process so it won't affect the current one
+*/
+static void dotest (void (*f)())
+{
+       pid_t pid = fork();
+       if (pid == 0){
+               f();
+               _exit (0);
+       }else if (pid == -1){
+               fprintf (stderr,"Can't fork (%s)\n",strerror(errno));
+       }else{
+               int status;
+               wait (&status);
+       }
+}
+
+int main (int argc, char *argv[])
+{
+       dotest (test1);
+       dotest (test2);
+       printf ("All attempts failed\n");
+       return 0;
+}
+
+
diff --git a/util-vserver/tests/forkbomb.cc b/util-vserver/tests/forkbomb.cc
new file mode 100644 (file)
index 0000000..a877624
--- /dev/null
@@ -0,0 +1,107 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/forkbomb.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+
+enum MODE {MODE_SLEEP,MODE_LOOP,MODE_FORK, MODE_FORKSHELL};
+
+
+static void forkbomb_userfork (MODE mode)
+{
+       pid_t pid = fork();
+       if (pid==-1){
+               fprintf (stderr,"Fork failed (%s)\n",strerror(errno));
+       }else if (pid == 0){
+               if (mode == MODE_SLEEP){
+                       sleep(20);
+               }else if (mode == MODE_LOOP){
+                       int k=0;
+                       while (1) k++;
+               }else if (mode == MODE_FORKSHELL){
+                       system ("/bin/false");
+               }
+               _exit (0);
+       }
+}
+
+
+int main (int argc, char *argv[])
+{
+       if (argc != 4){
+               fprintf (stderr,"formboom N M mode\n"
+                       "where N is the number of process to start\n"
+                       "and M is the number of user to start\n"
+                       "Each user will try to start N process\n"
+                       "\n"
+                       "mode is:\n"
+                       "    sleep: Each process sleeps for 20 seconds and exits\n"
+                       "    loop:  Each process loops forever\n"
+                       "    fork:  Each process exits immediatly and is restarted\n"
+                       "           by the parent\n"
+                       "    forkshell: Each process runs /bin/false in a shell and\n"
+                       "           exits, then the parent start a new one\n"
+                       );
+       }else{
+               MODE mode;
+               if (strcmp(argv[3],"sleep")==0){
+                       mode = MODE_SLEEP;
+               }else if (strcmp(argv[3],"loop")==0){
+                       mode = MODE_LOOP;
+               }else if (strcmp(argv[3],"fork")==0){
+                       mode = MODE_FORK;
+               }else if (strcmp(argv[3],"forkshell")==0){
+                       mode = MODE_FORKSHELL;
+               }else{
+                       fprintf (stderr,"Invalid mode\n");
+                       exit (-1);
+               }
+               for (int i=0; i<atoi(argv[2]); i++){
+                       if (fork()==0){
+                               if (setuid (i+1)==-1){
+                                       fprintf (stderr,"Can't setuid to uid %d (%s)\n",i+1
+                                               ,strerror(errno));
+                               }else{
+                                       for (int j=0; j<atoi(argv[1]); j++){
+                                               forkbomb_userfork (mode);
+                                       }
+                                       if (mode == MODE_FORK || mode == MODE_FORKSHELL){
+                                               // Ok, all processes are started, in MODE_FORK
+                                               // we create a new one all the time
+                                               int status;
+                                               while (wait(&status)!=-1) forkbomb_userfork(mode);
+                                       }
+                               }
+                               _exit (0);
+                       }
+               }
+               system ("ps ax | wc -l");
+               printf ("All the process are running now\n");
+               printf ("Exit to end all processes\n");
+               system ("/bin/sh");
+               system ("killall forkbomb");
+       }
+       return 0;
+}
+
diff --git a/util-vserver/tests/testipc.cc b/util-vserver/tests/testipc.cc
new file mode 100644 (file)
index 0000000..86fd0d6
--- /dev/null
@@ -0,0 +1,127 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/testipc.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/*
+       Test to see isolation of the various IPC resources
+       between security context
+*/
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+
+int main (int argc, char *argv[])
+{
+       int ret = -1;
+       if (argc < 2){
+               fprintf (stderr,
+                       "testipc createshm\n"
+                       );
+       }else if(strcmp(argv[1],"createshm")==0){
+               int id = shmget (1,1024,IPC_CREAT|0666);
+               if (id == -1){
+                       fprintf (stderr,"shmget failed (%s)\n",strerror(errno));
+               }else{
+                       printf ("shmget id %d\n",id);
+                       void *pt = shmat (id,NULL,0);
+                       if (pt == NULL){
+                               fprintf (stderr,"can't shmat to id %d (%s)\n",id,strerror(errno));
+                       }else{
+                               strcpy ((char*)pt,"original string");
+
+                               printf ("Letting a sub-program attach to this memory\n");
+                               char tmp[100];
+                               sprintf (tmp,"./testipc accessshm %d",id);
+                               int ok = system (tmp);
+                               printf ("\tSub-program returned %d\n",ok);
+
+                               printf ("\tThe segment now hold :%s:\n",(char*)pt);
+                               shmdt (pt);
+
+                               printf ("A sub-program in another context can't attach\n");
+                               sprintf (tmp,"/usr/sbin/chcontext ./testipc accessshm %d",id);
+                               ok = system (tmp);
+                               printf ("\tSub-program returned %d\n",ok);
+
+                               printf ("Executing a sub-shell\n");
+                               system ("/bin/sh");
+                       }
+                       printf ("Delete the share memory segment\n");
+                       if (shmctl (id,IPC_RMID,NULL)==-1){
+                               fprintf (stderr,"shmctl failed (%s)\n",strerror(errno));
+                       }else{
+                               ret = 0;
+                       }
+               }
+       }else if(strcmp(argv[1],"accessshm")==0){
+               int id = atoi(argv[2]);
+               void *pt = shmat (id,NULL,0);
+               if (pt == (void*)-1){
+                       fprintf (stderr,"can't shmat to id %d (%s)\n",id,strerror(errno));
+               }else{
+                       printf ("\tWriting hello in share memory\n");
+                       strcpy ((char*)pt,"hello");
+                       ret = 0;
+               }
+       }else if(strcmp(argv[1],"createsem")==0){
+               int id = semget (1,1,IPC_CREAT|0666);
+               if (id == -1){
+                       fprintf (stderr,"semget failed (%s)\n",strerror(errno));
+               }else{
+                       printf ("semget id %d\n",id);
+
+                       printf ("Letting a sub-program play with this semaphore\n");
+                       char tmp[100];
+                       sprintf (tmp,"./testipc accesssem %d",id);
+                       int ok = system (tmp);
+                       printf ("\tSub-program returned %d\n",ok);
+
+                       printf ("A sub-program in another context can't use the semaphore\n");
+                       sprintf (tmp,"/usr/sbin/chcontext ./testipc accesssem %d",id);
+                       ok = system (tmp);
+                       printf ("\tSub-program returned %d\n",ok);
+
+                       printf ("Executing a sub-shell\n");
+                       system ("/bin/sh");
+
+                       printf ("Delete the semaphore\n");
+                       if (semctl (id,0,IPC_RMID,NULL)==-1){
+                               fprintf (stderr,"semctl failed (%s)\n",strerror(errno));
+                       }else{
+                               ret = 0;
+                       }
+               }
+       }else if(strcmp(argv[1],"accesssem")==0){
+               int id = atoi(argv[2]);
+               struct sembuf ops[]={
+                       {0,0,0}
+               };
+               if (semop (id,ops,1) == -1){
+                       fprintf (stderr,"can't semop with id %d (%s)\n",id,strerror(errno));
+               }else{
+                       ret = 0;
+               }
+       }
+       return ret;
+}
+               
+
diff --git a/util-vserver/tests/testlimit.cc b/util-vserver/tests/testlimit.cc
new file mode 100644 (file)
index 0000000..c5bfda1
--- /dev/null
@@ -0,0 +1,52 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/testlimit.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+int main (int argc, char *argv[])
+{
+       if (argc != 3){
+               fprintf (stderr,"testlimit nbprocess malloc_size\n");
+       }else{
+               int nbproc = atoi(argv[1]);
+               int size   = atoi(argv[2]);
+               for (int i=0; i<nbproc; i++){
+                       if (fork()==0){
+                               void *pt = malloc(size);
+                               if (pt == NULL){
+                                       fprintf (stderr,"Child %d: can't malloc (%s)\n"
+                                               ,i,strerror(errno));
+                               }else{
+                                       memset (pt,1,size);
+                               }
+                               sleep (100);
+                               _exit (0);
+                       }
+               }
+               int status;
+               while (wait(&status)!=-1);
+       }
+       return 0;
+}
+
diff --git a/util-vserver/tests/testopenf.cc b/util-vserver/tests/testopenf.cc
new file mode 100644 (file)
index 0000000..12c0078
--- /dev/null
@@ -0,0 +1,54 @@
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/testopenf.cc by Jacques Gelinas
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//  
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//  
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+int main (int argc, char *argv[])
+{
+       if (argc != 3){
+               fprintf (stderr,"testlimit nbprocess nbopen\n");
+       }else{
+               int nbproc = atoi(argv[1]);
+               int nbopen = atoi(argv[2]);
+               for (int i=0; i<nbproc; i++){
+                       if (fork()==0){
+                               int j;
+                               for (j=0; j<nbopen; j++){
+                                       FILE *fin = fopen ("/proc/self/status","r");
+                                       if (fin == NULL){
+                                               fprintf (stderr,"Can't open %d (%s)\n",errno,strerror(errno));
+                                               break;
+                                       }
+                               }
+                               printf ("%d open files, sleeping\n",j);
+                               sleep (100);
+                               _exit (0);
+                       }
+               }
+               int status;
+               while (wait(&status)!=-1);
+       }
+       return 0;
+}
+
diff --git a/util-vserver/vserver.spec.in b/util-vserver/vserver.spec.in
new file mode 100644 (file)
index 0000000..5334add
--- /dev/null
@@ -0,0 +1,85 @@
+Summary:       Linux virtual server utilities
+Name:          @PACKAGE@
+Version:       @VERSION@
+Release:       1
+Epoch:         0
+Copyright:     GPL
+Group:         System Environment/Base
+Source:                %name-%version.tar.bz2
+Provides:      %name-devel = %epoch:%version-%release
+BuildRoot:     %_tmppath/%name-%version-%release-root
+Provides:      vserver = %epoch:%version-%release
+Conflicts:     vserver < %epoch:%version
+
+
+%description
+This package provides the components and a framework to setup virtual
+servers.  A virtual server runs inside a linux server. It is nevertheless
+highly independent. As such, you can run various services with normal
+configuration. The various vservers can't interact with each other and
+can't interact with services in the main server.
+
+This requires a special kernel supporting the new new_s_context and
+set_ipv4root system call.
+
+
+%prep
+%setup -q
+
+
+%build
+%configure
+%__make %{?_smp_mflags}
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+%__make DESTDIR=$RPM_BUILD_ROOT install
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+
+%define v_services     httpd named portmap sendmail smb sshd xinetd
+%post
+/sbin/chkconfig --add vservers
+/sbin/chkconfig --add rebootmgr
+
+for i in %v_services; do
+       /sbin/chkconfig --add v_$i
+done
+
+
+%preun
+test "$1" != 0 || for i in %v_services; do
+       /sbin/chkconfig --del v_$i
+done
+
+test "$1" != 0 || %{_initrddir}/rebootmgr stop &>/dev/null || :
+test "$1" != 0 || /sbin/chkconfig --del rebootmgr
+test "$1" != 0 || /sbin/chkconfig --del vservers
+
+
+%postun
+test "$1" = 0  || %{_initrddir}/rebootmgr condrestart >/dev/null || :
+
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS COPYING ChangeLog NEWS README THANKS
+%doc doc/FAQ.txt
+%_sbindir/*
+%_libdir/%name
+%_includedir/vserver.h
+%_libdir/libvserver.a
+%_mandir/man8/*
+%config /etc/init.d/*
+%config(noreplace) /etc/vservers/newvserver.defaults
+%config(noreplace) /etc/vservers.conf
+
+
+%changelog
+
+* Fri Sep 26 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> - 0:0.23.4-1
+- initial build.