This commit was manufactured by cvs2svn to create tag before-util-vserver-0_30_208-merge
authorPlanet-Lab Support <support@planet-lab.org>
Fri, 12 Aug 2005 21:13:03 +0000 (21:13 +0000)
committerPlanet-Lab Support <support@planet-lab.org>
Fri, 12 Aug 2005 21:13:03 +0000 (21:13 +0000)
'before-util-vserver-0_30_208-merge'.

47 files changed:
Makefile.am
Makefile.in
aclocal.m4
configure
distrib/Makefile-files
distrib/install-fc2 [new file with mode: 0644]
distrib/sample.conf
doc/FAQ.txt [deleted file]
doc/changelog.txt [deleted file]
lib/Makefile-files
lib/sched_cmd.h [new file with mode: 0644]
lib/virtual.h
lib/vserver-internal.h
lib/vserver.h
man/vsh.8 [new file with mode: 0644]
python/Makefile [new file with mode: 0644]
python/bwlimit.py [new file with mode: 0644]
python/cpulimit.py [new file with mode: 0755]
python/pybuild.mk [new file with mode: 0644]
python/setup.py [new file with mode: 0644]
python/vduimpl.c [new file with mode: 0644]
python/vserver.py [new file with mode: 0644]
python/vserverimpl.c [new file with mode: 0644]
scripts/Makefile-files
scripts/vcached [new file with mode: 0755]
scripts/vserver
scripts/vuseradd [new file with mode: 0755]
scripts/vuserdel [new file with mode: 0755]
src/Makefile-files
src/chcontext.c
src/dlimit.h [new file with mode: 0644]
src/showattr.c
src/vbuild.cc
src/vdu.c
src/vdu.h [new file with mode: 0644]
src/vlimit.c
src/vsh.c [new file with mode: 0644]
src/vunify.cc
src/vutil.h
sysv/Makefile-files
sysv/vcached.conf [new file with mode: 0644]
sysv/vcached.logrotate [new file with mode: 0644]
sysv/vcached.subst [new file with mode: 0755]
sysv/vservers.conf
sysv/vservers.subst
util-vserver.spec
util-vserver.spec.in

index 437c818..1ef9cc9 100644 (file)
@@ -83,6 +83,13 @@ else
                ln -sf '$(top_srcdir)/lib/virtual.h' '$@'
 endif
 
+install-exec-hook:
+       cd $(DESTDIR)$(sbindir) && $(LN_S) vuseradd vadduser
+       cd $(DESTDIR)$(sbindir) && $(LN_S) vuserdel vdeluser
+
+install-data-hook:
+       cd $(DESTDIR)$(sysvdir) && $(LN_S) vservers vserver-init
+
 include $(top_srcdir)/lib/Makefile-files
 include $(top_srcdir)/src/Makefile-files
 include $(top_srcdir)/distrib/Makefile-files
index 9500fae..92b8a06 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.8.4 from Makefile.am.
+# Makefile.in generated by automake 1.8.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -35,7 +35,7 @@
 
 
 
-SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) $(src_chbind_SOURCES) $(src_chcontext_SOURCES) $(src_fakerunlevel_SOURCES) $(src_filetime_SOURCES) $(src_ifspec_SOURCES) $(src_listdevip_SOURCES) $(src_parserpmdump_SOURCES) $(src_readlink_SOURCES) $(src_rebootmgr_SOURCES) $(src_reducecap_SOURCES) $(src_showattr_SOURCES) $(src_showperm_SOURCES) $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) $(src_vdu_SOURCES) $(src_vfiles_SOURCES) $(src_vkill_SOURCES) $(src_vlimit_SOURCES) $(src_vreboot_SOURCES) $(src_vserver_stat_SOURCES) $(src_vunify_SOURCES) $(tests_escaperoot_SOURCES) $(tests_forkbomb_SOURCES) $(tests_testipc_SOURCES) $(tests_testlimit_SOURCES) $(tests_testopenf_SOURCES)
+SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) $(src_chbind_SOURCES) $(src_chcontext_SOURCES) $(src_fakerunlevel_SOURCES) $(src_filetime_SOURCES) $(src_ifspec_SOURCES) $(src_listdevip_SOURCES) $(src_parserpmdump_SOURCES) $(src_readlink_SOURCES) $(src_rebootmgr_SOURCES) $(src_reducecap_SOURCES) $(src_showattr_SOURCES) $(src_showperm_SOURCES) $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) $(src_vdlimit_SOURCES) $(src_vdu_SOURCES) $(src_vfiles_SOURCES) $(src_vkill_SOURCES) $(src_vlimit_SOURCES) $(src_vreboot_SOURCES) $(src_vserver_stat_SOURCES) $(src_vsh_SOURCES) $(src_vunify_SOURCES) $(tests_escaperoot_SOURCES) $(tests_forkbomb_SOURCES) $(tests_testipc_SOURCES) $(tests_testlimit_SOURCES) $(tests_testopenf_SOURCES)
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
@@ -102,6 +102,7 @@ lib_libvserver_a_LIBADD =
 am__dirstamp = $(am__leading_dot)dirstamp
 am__objects_1 = lib/lib_libvserver_a-syscall.$(OBJEXT) \
        lib/lib_libvserver_a-syscall_rlimit.$(OBJEXT) \
+       lib/lib_libvserver_a-syscall_setsched.$(OBJEXT) \
        lib/lib_libvserver_a-syscall_kill.$(OBJEXT) \
        lib/lib_libvserver_a-checkversion.$(OBJEXT) \
        lib/lib_libvserver_a-getctx.$(OBJEXT) \
@@ -120,9 +121,10 @@ am__EXEEXT_2 = src/capchroot$(EXEEXT) src/fakerunlevel$(EXEEXT) \
        src/vreboot$(EXEEXT) src/vunify$(EXEEXT)
 pkglibPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 am__EXEEXT_3 = src/chbind$(EXEEXT) src/chcontext$(EXEEXT) \
-       src/rebootmgr$(EXEEXT) src/reducecap$(EXEEXT) \
-       src/vlimit$(EXEEXT) src/vdu$(EXEEXT) src/vfiles$(EXEEXT) \
-       src/vkill$(EXEEXT) src/vserver-stat$(EXEEXT)
+       src/rebootmgr$(EXEEXT) src/reducecap$(EXEEXT) src/vdu$(EXEEXT) \
+       src/vsh$(EXEEXT) src/vdlimit$(EXEEXT) src/vlimit$(EXEEXT) \
+       src/vfiles$(EXEEXT) src/vkill$(EXEEXT) \
+       src/vserver-stat$(EXEEXT)
 sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(noinst_PROGRAMS) $(pkglib_PROGRAMS) $(sbin_PROGRAMS)
 am_src_capchroot_OBJECTS = src/capchroot.$(OBJEXT)
@@ -170,6 +172,9 @@ src_vbuild_LDADD = $(LDADD)
 am_src_vcheck_OBJECTS = src/vcheck.$(OBJEXT) src/vutil.$(OBJEXT)
 src_vcheck_OBJECTS = $(am_src_vcheck_OBJECTS)
 src_vcheck_LDADD = $(LDADD)
+am_src_vdlimit_OBJECTS = src/vdlimit.$(OBJEXT)
+src_vdlimit_OBJECTS = $(am_src_vdlimit_OBJECTS)
+src_vdlimit_DEPENDENCIES = lib/libvserver.a
 am_src_vdu_OBJECTS = src/vdu.$(OBJEXT)
 src_vdu_OBJECTS = $(am_src_vdu_OBJECTS)
 src_vdu_LDADD = $(LDADD)
@@ -188,6 +193,9 @@ src_vreboot_LDADD = $(LDADD)
 am_src_vserver_stat_OBJECTS = src/vserver-stat.$(OBJEXT)
 src_vserver_stat_OBJECTS = $(am_src_vserver_stat_OBJECTS)
 src_vserver_stat_DEPENDENCIES = lib/libvserver.a
+am_src_vsh_OBJECTS = src/vsh.$(OBJEXT)
+src_vsh_OBJECTS = $(am_src_vsh_OBJECTS)
+src_vsh_DEPENDENCIES = lib/libvserver.a
 am_src_vunify_OBJECTS = src/src_vunify-vunify.$(OBJEXT) \
        src/src_vunify-vutil.$(OBJEXT)
 src_vunify_OBJECTS = $(am_src_vunify_OBJECTS)
@@ -223,6 +231,7 @@ am__depfiles_maybe = depfiles
 @AMDEP_TRUE@   lib/$(DEPDIR)/lib_libvserver_a-syscall.Po \
 @AMDEP_TRUE@   lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Po \
 @AMDEP_TRUE@   lib/$(DEPDIR)/lib_libvserver_a-syscall_rlimit.Po \
+@AMDEP_TRUE@   lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po \
 @AMDEP_TRUE@   lib/$(DEPDIR)/lib_libvserver_a-uint2str.Po \
 @AMDEP_TRUE@   src/$(DEPDIR)/capchroot.Po src/$(DEPDIR)/chbind.Po \
 @AMDEP_TRUE@   src/$(DEPDIR)/chcontext.Po \
@@ -239,9 +248,10 @@ am__depfiles_maybe = depfiles
 @AMDEP_TRUE@   src/$(DEPDIR)/src_vunify-vunify.Po \
 @AMDEP_TRUE@   src/$(DEPDIR)/src_vunify-vutil.Po \
 @AMDEP_TRUE@   src/$(DEPDIR)/vbuild.Po src/$(DEPDIR)/vcheck.Po \
-@AMDEP_TRUE@   src/$(DEPDIR)/vdu.Po src/$(DEPDIR)/vfiles.Po \
-@AMDEP_TRUE@   src/$(DEPDIR)/vlimit.Po src/$(DEPDIR)/vreboot.Po \
-@AMDEP_TRUE@   src/$(DEPDIR)/vserver-stat.Po \
+@AMDEP_TRUE@   src/$(DEPDIR)/vdlimit.Po src/$(DEPDIR)/vdu.Po \
+@AMDEP_TRUE@   src/$(DEPDIR)/vfiles.Po src/$(DEPDIR)/vlimit.Po \
+@AMDEP_TRUE@   src/$(DEPDIR)/vreboot.Po \
+@AMDEP_TRUE@   src/$(DEPDIR)/vserver-stat.Po src/$(DEPDIR)/vsh.Po \
 @AMDEP_TRUE@   src/$(DEPDIR)/vutil.Po \
 @AMDEP_TRUE@   tests/$(DEPDIR)/escaperoot.Po \
 @AMDEP_TRUE@   tests/$(DEPDIR)/forkbomb.Po \
@@ -264,13 +274,14 @@ SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) \
        $(src_parserpmdump_SOURCES) $(src_readlink_SOURCES) \
        $(src_rebootmgr_SOURCES) $(src_reducecap_SOURCES) \
        $(src_showattr_SOURCES) $(src_showperm_SOURCES) \
-       $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) $(src_vdu_SOURCES) \
+       $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) \
+       $(src_vdlimit_SOURCES) $(src_vdu_SOURCES) \
        $(src_vfiles_SOURCES) $(src_vkill_SOURCES) \
        $(src_vlimit_SOURCES) $(src_vreboot_SOURCES) \
-       $(src_vserver_stat_SOURCES) $(src_vunify_SOURCES) \
-       $(tests_escaperoot_SOURCES) $(tests_forkbomb_SOURCES) \
-       $(tests_testipc_SOURCES) $(tests_testlimit_SOURCES) \
-       $(tests_testopenf_SOURCES)
+       $(src_vserver_stat_SOURCES) $(src_vsh_SOURCES) \
+       $(src_vunify_SOURCES) $(tests_escaperoot_SOURCES) \
+       $(tests_forkbomb_SOURCES) $(tests_testipc_SOURCES) \
+       $(tests_testlimit_SOURCES) $(tests_testopenf_SOURCES)
 DIST_SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) \
        $(src_chbind_SOURCES) $(src_chcontext_SOURCES) \
        $(src_fakerunlevel_SOURCES) $(src_filetime_SOURCES) \
@@ -278,13 +289,14 @@ DIST_SOURCES = $(lib_libvserver_a_SOURCES) $(src_capchroot_SOURCES) \
        $(src_parserpmdump_SOURCES) $(src_readlink_SOURCES) \
        $(src_rebootmgr_SOURCES) $(src_reducecap_SOURCES) \
        $(src_showattr_SOURCES) $(src_showperm_SOURCES) \
-       $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) $(src_vdu_SOURCES) \
+       $(src_vbuild_SOURCES) $(src_vcheck_SOURCES) \
+       $(src_vdlimit_SOURCES) $(src_vdu_SOURCES) \
        $(src_vfiles_SOURCES) $(src_vkill_SOURCES) \
        $(src_vlimit_SOURCES) $(src_vreboot_SOURCES) \
-       $(src_vserver_stat_SOURCES) $(src_vunify_SOURCES) \
-       $(tests_escaperoot_SOURCES) $(tests_forkbomb_SOURCES) \
-       $(tests_testipc_SOURCES) $(tests_testlimit_SOURCES) \
-       $(tests_testopenf_SOURCES)
+       $(src_vserver_stat_SOURCES) $(src_vsh_SOURCES) \
+       $(src_vunify_SOURCES) $(tests_escaperoot_SOURCES) \
+       $(tests_forkbomb_SOURCES) $(tests_testipc_SOURCES) \
+       $(tests_testlimit_SOURCES) $(tests_testopenf_SOURCES)
 man8dir = $(mandir)/man8
 NROFF = nroff
 MANS = $(man_MANS)
@@ -440,6 +452,7 @@ CLEANFILES = $(sysv_GENSCRPTS) $(scripts_GENSCRPTS) \
 
 lib_SRCS = lib/syscall.c \
                                   lib/syscall_rlimit.c \
+                                  lib/syscall_setsched.c \
                                   lib/syscall_kill.c \
                                   lib/checkversion.c \
                                   lib/getctx.c \
@@ -450,6 +463,7 @@ lib_HDRS = lib/vserver.h
 lib_XHDRS = lib/syscall-compat.hc \
                                   lib/syscall-legacy.hc \
                                   lib/syscall_rlimit-v11.hc \
+                                  lib/syscall_setsched-v13.hc \
                                   lib/syscall_kill-v11.hc \
                                   lib/getctx-compat.hc \
                                   lib/getctx-legacy.hc \
@@ -483,8 +497,10 @@ src_sbin_PRGS = src/chbind \
                           src/chcontext \
                           src/rebootmgr \
                           src/reducecap \
-                          src/vlimit \
                           src/vdu \
+                          src/vsh \
+                          src/vdlimit \
+                          src/vlimit \
                           src/vfiles \
                           src/vkill \
                           src/vserver-stat
@@ -511,6 +527,10 @@ src_vlimit_LDADD = lib/libvserver.a
 src_vkill_SOURCES = src/vkill.c
 src_vkill_LDADD = lib/libvserver.a
 src_vkill_CPPFLAGS = $(AM_CPPFLAGS) -DLEGACYDIR=\"$(legacydir)\"
+src_vsh_SOURCES = src/vsh.c
+src_vsh_LDADD = lib/libvserver.a
+src_vdlimit_SOURCES = src/vdlimit.c
+src_vdlimit_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
@@ -530,6 +550,7 @@ distrib_SCRPTS = distrib/install-mdk8.2 \
                          distrib/install-rh8.0 \
                          distrib/install-rh9.0 \
                          distrib/install-fc1 \
+                         distrib/install-fc2 \
                          distrib/sample.sh
 
 distrib_DAT = distrib/mdk8.2-minimum \
@@ -569,6 +590,9 @@ scripts_src_PRGS = scripts/vpstree \
                           scripts/vrpm \
                           scripts/vserver \
                           scripts/vserver-copy \
+                          scripts/vcached \
+                          scripts/vuseradd \
+                          scripts/vuserdel \
                           scripts/vtop
 
 scripts_gen_PRGS = scripts/vps
@@ -606,6 +630,7 @@ sysv_XTRAS = sysv/rebootmgr.subst \
                           sysv/v_smb.subst \
                           sysv/v_sshd.subst \
                           sysv/v_xinetd.subst \
+                          sysv/vcached.subst \
                           sysv/vservers.subst
 
 sysv_GENSCRPTS = sysv/rebootmgr \
@@ -617,10 +642,11 @@ sysv_GENSCRPTS = sysv/rebootmgr \
                           sysv/v_smb \
                           sysv/v_sshd \
                           sysv/v_xinetd \
+                          sysv/vcached \
                           sysv/vservers
 
 sysv_SCRPTS = $(sysv_GENSCRPTS)
-sysv_CFG = sysv/vservers.conf
+sysv_CFG = sysv/vservers.conf sysv/vcached.conf
 linuxconf_gen_SCRPTS = linuxconf/newvserver
 linuxconf_src_DATMAN = linuxconf/newvserver.8
 linuxconf_cfg_src_DTA = linuxconf/newvserver.defaults
@@ -731,6 +757,8 @@ lib/lib_libvserver_a-syscall.$(OBJEXT): lib/$(am__dirstamp) \
        lib/$(DEPDIR)/$(am__dirstamp)
 lib/lib_libvserver_a-syscall_rlimit.$(OBJEXT): lib/$(am__dirstamp) \
        lib/$(DEPDIR)/$(am__dirstamp)
+lib/lib_libvserver_a-syscall_setsched.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
 lib/lib_libvserver_a-syscall_kill.$(OBJEXT): lib/$(am__dirstamp) \
        lib/$(DEPDIR)/$(am__dirstamp)
 lib/lib_libvserver_a-checkversion.$(OBJEXT): lib/$(am__dirstamp) \
@@ -876,6 +904,11 @@ src/vcheck.$(OBJEXT): src/$(am__dirstamp) \
 src/vcheck$(EXEEXT): $(src_vcheck_OBJECTS) $(src_vcheck_DEPENDENCIES) src/$(am__dirstamp)
        @rm -f src/vcheck$(EXEEXT)
        $(CXXLINK) $(src_vcheck_LDFLAGS) $(src_vcheck_OBJECTS) $(src_vcheck_LDADD) $(LIBS)
+src/vdlimit.$(OBJEXT): src/$(am__dirstamp) \
+       src/$(DEPDIR)/$(am__dirstamp)
+src/vdlimit$(EXEEXT): $(src_vdlimit_OBJECTS) $(src_vdlimit_DEPENDENCIES) src/$(am__dirstamp)
+       @rm -f src/vdlimit$(EXEEXT)
+       $(LINK) $(src_vdlimit_LDFLAGS) $(src_vdlimit_OBJECTS) $(src_vdlimit_LDADD) $(LIBS)
 src/vdu.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
 src/vdu$(EXEEXT): $(src_vdu_OBJECTS) $(src_vdu_DEPENDENCIES) src/$(am__dirstamp)
        @rm -f src/vdu$(EXEEXT)
@@ -905,6 +938,10 @@ src/vserver-stat.$(OBJEXT): src/$(am__dirstamp) \
 src/vserver-stat$(EXEEXT): $(src_vserver_stat_OBJECTS) $(src_vserver_stat_DEPENDENCIES) src/$(am__dirstamp)
        @rm -f src/vserver-stat$(EXEEXT)
        $(LINK) $(src_vserver_stat_LDFLAGS) $(src_vserver_stat_OBJECTS) $(src_vserver_stat_LDADD) $(LIBS)
+src/vsh.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/vsh$(EXEEXT): $(src_vsh_OBJECTS) $(src_vsh_DEPENDENCIES) src/$(am__dirstamp)
+       @rm -f src/vsh$(EXEEXT)
+       $(LINK) $(src_vsh_LDFLAGS) $(src_vsh_OBJECTS) $(src_vsh_LDADD) $(LIBS)
 src/src_vunify-vunify.$(OBJEXT): src/$(am__dirstamp) \
        src/$(DEPDIR)/$(am__dirstamp)
 src/src_vunify-vutil.$(OBJEXT): src/$(am__dirstamp) \
@@ -1028,6 +1065,7 @@ mostlyclean-compile:
        -rm -f lib/lib_libvserver_a-syscall.$(OBJEXT)
        -rm -f lib/lib_libvserver_a-syscall_kill.$(OBJEXT)
        -rm -f lib/lib_libvserver_a-syscall_rlimit.$(OBJEXT)
+       -rm -f lib/lib_libvserver_a-syscall_setsched.$(OBJEXT)
        -rm -f lib/lib_libvserver_a-uint2str.$(OBJEXT)
        -rm -f src/capchroot.$(OBJEXT)
        -rm -f src/chbind.$(OBJEXT)
@@ -1047,11 +1085,13 @@ mostlyclean-compile:
        -rm -f src/src_vunify-vutil.$(OBJEXT)
        -rm -f src/vbuild.$(OBJEXT)
        -rm -f src/vcheck.$(OBJEXT)
+       -rm -f src/vdlimit.$(OBJEXT)
        -rm -f src/vdu.$(OBJEXT)
        -rm -f src/vfiles.$(OBJEXT)
        -rm -f src/vlimit.$(OBJEXT)
        -rm -f src/vreboot.$(OBJEXT)
        -rm -f src/vserver-stat.$(OBJEXT)
+       -rm -f src/vsh.$(OBJEXT)
        -rm -f src/vutil.$(OBJEXT)
        -rm -f tests/escaperoot.$(OBJEXT)
        -rm -f tests/forkbomb.$(OBJEXT)
@@ -1068,6 +1108,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-syscall.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-syscall_rlimit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libvserver_a-uint2str.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/capchroot.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/chbind.Po@am__quote@
@@ -1087,11 +1128,13 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_vunify-vutil.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vbuild.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vcheck.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vdlimit.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vdu.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vfiles.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vlimit.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vreboot.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vserver-stat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vsh.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/vutil.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/escaperoot.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/forkbomb.Po@am__quote@
@@ -1147,6 +1190,22 @@ lib/lib_libvserver_a-syscall_rlimit.obj: lib/syscall_rlimit.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/lib_libvserver_a-syscall_rlimit.obj `if test -f 'lib/syscall_rlimit.c'; then $(CYGPATH_W) 'lib/syscall_rlimit.c'; else $(CYGPATH_W) '$(srcdir)/lib/syscall_rlimit.c'; fi`
 
+lib/lib_libvserver_a-syscall_setsched.o: lib/syscall_setsched.c
+@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/lib_libvserver_a-syscall_setsched.o -MD -MP -MF "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo" -c -o lib/lib_libvserver_a-syscall_setsched.o `test -f 'lib/syscall_setsched.c' || echo '$(srcdir)/'`lib/syscall_setsched.c; \
+@am__fastdepCC_TRUE@   then mv -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo" "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po"; else rm -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='lib/syscall_setsched.c' object='lib/lib_libvserver_a-syscall_setsched.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      depfile='lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po' tmpdepfile='lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/lib_libvserver_a-syscall_setsched.o `test -f 'lib/syscall_setsched.c' || echo '$(srcdir)/'`lib/syscall_setsched.c
+
+lib/lib_libvserver_a-syscall_setsched.obj: lib/syscall_setsched.c
+@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/lib_libvserver_a-syscall_setsched.obj -MD -MP -MF "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo" -c -o lib/lib_libvserver_a-syscall_setsched.obj `if test -f 'lib/syscall_setsched.c'; then $(CYGPATH_W) 'lib/syscall_setsched.c'; else $(CYGPATH_W) '$(srcdir)/lib/syscall_setsched.c'; fi`; \
+@am__fastdepCC_TRUE@   then mv -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo" "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po"; else rm -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='lib/syscall_setsched.c' object='lib/lib_libvserver_a-syscall_setsched.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      depfile='lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.Po' tmpdepfile='lib/$(DEPDIR)/lib_libvserver_a-syscall_setsched.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib/lib_libvserver_a-syscall_setsched.obj `if test -f 'lib/syscall_setsched.c'; then $(CYGPATH_W) 'lib/syscall_setsched.c'; else $(CYGPATH_W) '$(srcdir)/lib/syscall_setsched.c'; fi`
+
 lib/lib_libvserver_a-syscall_kill.o: lib/syscall_kill.c
 @am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libvserver_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/lib_libvserver_a-syscall_kill.o -MD -MP -MF "lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Tpo" -c -o lib/lib_libvserver_a-syscall_kill.o `test -f 'lib/syscall_kill.c' || echo '$(srcdir)/'`lib/syscall_kill.c; \
 @am__fastdepCC_TRUE@   then mv -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Tpo" "lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Po"; else rm -f "lib/$(DEPDIR)/lib_libvserver_a-syscall_kill.Tpo"; exit 1; fi
@@ -1435,6 +1494,22 @@ src/showperm.obj: src/showperm.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/showperm.obj `if test -f 'src/showperm.c'; then $(CYGPATH_W) 'src/showperm.c'; else $(CYGPATH_W) '$(srcdir)/src/showperm.c'; fi`
 
+src/vdlimit.o: src/vdlimit.c
+@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vdlimit.o -MD -MP -MF "src/$(DEPDIR)/vdlimit.Tpo" -c -o src/vdlimit.o `test -f 'src/vdlimit.c' || echo '$(srcdir)/'`src/vdlimit.c; \
+@am__fastdepCC_TRUE@   then mv -f "src/$(DEPDIR)/vdlimit.Tpo" "src/$(DEPDIR)/vdlimit.Po"; else rm -f "src/$(DEPDIR)/vdlimit.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='src/vdlimit.c' object='src/vdlimit.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      depfile='src/$(DEPDIR)/vdlimit.Po' tmpdepfile='src/$(DEPDIR)/vdlimit.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vdlimit.o `test -f 'src/vdlimit.c' || echo '$(srcdir)/'`src/vdlimit.c
+
+src/vdlimit.obj: src/vdlimit.c
+@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vdlimit.obj -MD -MP -MF "src/$(DEPDIR)/vdlimit.Tpo" -c -o src/vdlimit.obj `if test -f 'src/vdlimit.c'; then $(CYGPATH_W) 'src/vdlimit.c'; else $(CYGPATH_W) '$(srcdir)/src/vdlimit.c'; fi`; \
+@am__fastdepCC_TRUE@   then mv -f "src/$(DEPDIR)/vdlimit.Tpo" "src/$(DEPDIR)/vdlimit.Po"; else rm -f "src/$(DEPDIR)/vdlimit.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='src/vdlimit.c' object='src/vdlimit.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      depfile='src/$(DEPDIR)/vdlimit.Po' tmpdepfile='src/$(DEPDIR)/vdlimit.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vdlimit.obj `if test -f 'src/vdlimit.c'; then $(CYGPATH_W) 'src/vdlimit.c'; else $(CYGPATH_W) '$(srcdir)/src/vdlimit.c'; fi`
+
 src/vdu.o: src/vdu.c
 @am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vdu.o -MD -MP -MF "src/$(DEPDIR)/vdu.Tpo" -c -o src/vdu.o `test -f 'src/vdu.c' || echo '$(srcdir)/'`src/vdu.c; \
 @am__fastdepCC_TRUE@   then mv -f "src/$(DEPDIR)/vdu.Tpo" "src/$(DEPDIR)/vdu.Po"; else rm -f "src/$(DEPDIR)/vdu.Tpo"; exit 1; fi
@@ -1515,6 +1590,22 @@ src/vserver-stat.obj: src/vserver-stat.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vserver-stat.obj `if test -f 'src/vserver-stat.c'; then $(CYGPATH_W) 'src/vserver-stat.c'; else $(CYGPATH_W) '$(srcdir)/src/vserver-stat.c'; fi`
 
+src/vsh.o: src/vsh.c
+@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vsh.o -MD -MP -MF "src/$(DEPDIR)/vsh.Tpo" -c -o src/vsh.o `test -f 'src/vsh.c' || echo '$(srcdir)/'`src/vsh.c; \
+@am__fastdepCC_TRUE@   then mv -f "src/$(DEPDIR)/vsh.Tpo" "src/$(DEPDIR)/vsh.Po"; else rm -f "src/$(DEPDIR)/vsh.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='src/vsh.c' object='src/vsh.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      depfile='src/$(DEPDIR)/vsh.Po' tmpdepfile='src/$(DEPDIR)/vsh.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vsh.o `test -f 'src/vsh.c' || echo '$(srcdir)/'`src/vsh.c
+
+src/vsh.obj: src/vsh.c
+@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/vsh.obj -MD -MP -MF "src/$(DEPDIR)/vsh.Tpo" -c -o src/vsh.obj `if test -f 'src/vsh.c'; then $(CYGPATH_W) 'src/vsh.c'; else $(CYGPATH_W) '$(srcdir)/src/vsh.c'; fi`; \
+@am__fastdepCC_TRUE@   then mv -f "src/$(DEPDIR)/vsh.Tpo" "src/$(DEPDIR)/vsh.Po"; else rm -f "src/$(DEPDIR)/vsh.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='src/vsh.c' object='src/vsh.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      depfile='src/$(DEPDIR)/vsh.Po' tmpdepfile='src/$(DEPDIR)/vsh.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/vsh.obj `if test -f 'src/vsh.c'; then $(CYGPATH_W) 'src/vsh.c'; else $(CYGPATH_W) '$(srcdir)/src/vsh.c'; fi`
+
 .cc.o:
 @am__fastdepCXX_TRUE@  if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@@ -1858,11 +1949,9 @@ TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
          done | \
          $(AWK) '    { files[$$0] = 1; } \
               END { for (i in files) print i; }'`; \
-       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
-         test -z "$$unique" && unique=$$empty_fix; \
-         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-           $$tags $$unique; \
-       fi
+       test -z "$(ETAGS_ARGS)$$tags$$unique" \
+         || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+            $$tags $$unique
 ctags: CTAGS
 CTAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
                $(TAGS_FILES) $(LISP)
@@ -1958,7 +2047,7 @@ distcheck: dist
        *.tar.Z*) \
          uncompress -c $(distdir).tar.Z | $(AMTAR) xf - ;;\
        *.shar.gz*) \
-         GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | unshar ;;\
        *.zip*) \
          unzip $(distdir).zip ;;\
        esac
@@ -2080,10 +2169,14 @@ info-am:
 install-data-am: install-includeHEADERS install-legacySCRIPTS \
        install-man install-scriptscfgDATA install-sysvSCRIPTS \
        install-vservercfgDATA
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-data-hook
 
 install-exec-am: install-libLIBRARIES install-pkglibDATA \
        install-pkglibPROGRAMS install-pkglibSCRIPTS \
        install-sbinPROGRAMS install-sbinSCRIPTS install-sysconfDATA
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
 
 install-info: install-info-am
 
@@ -2160,6 +2253,13 @@ linuxvirtual.h:
 @ENSC_ENABLE_INTERNAL_HEADERS_FALSE@           ln -sf '$(kernelincludedir)/linux/virtual.h' '$@' && test -e '$@' || \
 @ENSC_ENABLE_INTERNAL_HEADERS_FALSE@           ln -sf '$(top_srcdir)/lib/virtual.h' '$@'
 
+install-exec-hook:
+       cd $(DESTDIR)$(sbindir) && $(LN_S) vuseradd vadduser
+       cd $(DESTDIR)$(sbindir) && $(LN_S) vuserdel vdeluser
+
+install-data-hook:
+       cd $(DESTDIR)$(sysvdir) && $(LN_S) vservers vserver-init
+
 #install-data-hook:            $(DESTDIR)$(pkglibdir)/setattr
 
 #$(DESTDIR)$(pkglibdir)/setattr:
index c34e705..928b11c 100644 (file)
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.8.4 -*- Autoconf -*-
+# generated automatically by aclocal 1.8.3 -*- Autoconf -*-
 
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 # Free Software Foundation, Inc.
@@ -5965,7 +5965,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"])
 # Call AM_AUTOMAKE_VERSION so it can be traced.
 # This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-        [AM_AUTOMAKE_VERSION([1.8.4])])
+        [AM_AUTOMAKE_VERSION([1.8.3])])
 
 # AM_AUX_DIR_EXPAND
 
@@ -6191,14 +6191,9 @@ AC_CACHE_CHECK([dependency style of $depcc],
        grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
        ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
       # icc doesn't choke on unknown options, it will just issue warnings
-      # or remarks (even with -Werror).  So we grep stderr for any message
-      # that says an option was ignored or not supported.
-      # When given -MP, icc 7.0 and 7.1 complain thusly:
-      #   icc: Command line warning: ignoring option '-M'; no argument required
-      # The diagnosis changed in icc 8.0:
-      #   icc: Command line remark: option '-MP' not supported
-      if (grep 'ignoring option' conftest.err ||
-          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+      # (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored.
+      if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else
         am_cv_$1_dependencies_compiler_type=$depmode
         break
       fi
index eb2a46c..1177303 100755 (executable)
--- a/configure
+++ b/configure
@@ -2491,14 +2491,9 @@ else
        grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
        ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
       # icc doesn't choke on unknown options, it will just issue warnings
-      # or remarks (even with -Werror).  So we grep stderr for any message
-      # that says an option was ignored or not supported.
-      # When given -MP, icc 7.0 and 7.1 complain thusly:
-      #   icc: Command line warning: ignoring option '-M'; no argument required
-      # The diagnosis changed in icc 8.0:
-      #   icc: Command line remark: option '-MP' not supported
-      if (grep 'ignoring option' conftest.err ||
-          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+      # (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored.
+      if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else
         am_cv_CXX_dependencies_compiler_type=$depmode
         break
       fi
@@ -3329,14 +3324,9 @@ else
        grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
        ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
       # icc doesn't choke on unknown options, it will just issue warnings
-      # or remarks (even with -Werror).  So we grep stderr for any message
-      # that says an option was ignored or not supported.
-      # When given -MP, icc 7.0 and 7.1 complain thusly:
-      #   icc: Command line warning: ignoring option '-M'; no argument required
-      # The diagnosis changed in icc 8.0:
-      #   icc: Command line remark: option '-MP' not supported
-      if (grep 'ignoring option' conftest.err ||
-          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+      # (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored.
+      if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else
         am_cv_CC_dependencies_compiler_type=$depmode
         break
       fi
index a0e22cc..b870522 100644 (file)
@@ -24,6 +24,7 @@ distrib_SCRPTS                = distrib/install-mdk8.2 \
                          distrib/install-rh8.0 \
                          distrib/install-rh9.0 \
                          distrib/install-fc1 \
+                         distrib/install-fc2 \
                          distrib/sample.sh
 
 distrib_DAT            = distrib/mdk8.2-minimum \
diff --git a/distrib/install-fc2 b/distrib/install-fc2
new file mode 100644 (file)
index 0000000..bf8f76b
--- /dev/null
@@ -0,0 +1,50 @@
+#!/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
+
+: ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+    echo "Can not find util-vserver installation; aborting..."
+    exit 1
+}
+. "$UTIL_VSERVER_VARS"
+
+USR_LIB_VSERVER=$PKGLIBDIR
+
+if [ $# -lt 1 ] ; then
+       echo $0 vserver-id [ group ]
+elif [ -d $VROOTDIR/$1/var/lib/rpm ] ; then
+       echo $VROOTDIR/$1 already exist
+else
+       VROOT=$VROOTDIR/$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
+       yum --installroot="$VROOT" -y groupinstall "$2"
+       umount $VROOT/proc
+       umount $VROOT/dev/pts
+       $USR_LIB_VSERVER/install-post.sh $1
+fi
index b56d9a3..9eb0dbc 100644 (file)
@@ -2,23 +2,12 @@
 # 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
+S_HOSTNAME=
 # 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
diff --git a/doc/FAQ.txt b/doc/FAQ.txt
deleted file mode 100644 (file)
index fe4bd67..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-                               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/doc/changelog.txt b/doc/changelog.txt
deleted file mode 100644 (file)
index fe4bd67..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-                               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/
index c193cd6..5404f72 100644 (file)
@@ -19,6 +19,7 @@
 
 lib_SRCS                       =  lib/syscall.c \
                                   lib/syscall_rlimit.c \
+                                  lib/syscall_setsched.c \
                                   lib/syscall_kill.c \
                                   lib/checkversion.c \
                                   lib/getctx.c \
@@ -30,6 +31,7 @@ lib_HDRS                      =  lib/vserver.h
 lib_XHDRS                       =  lib/syscall-compat.hc \
                                   lib/syscall-legacy.hc \
                                   lib/syscall_rlimit-v11.hc \
+                                  lib/syscall_setsched-v13.hc \
                                   lib/syscall_kill-v11.hc \
                                   lib/getctx-compat.hc \
                                   lib/getctx-legacy.hc \
diff --git a/lib/sched_cmd.h b/lib/sched_cmd.h
new file mode 100644 (file)
index 0000000..2a6f55b
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _VX_SCHED_CMD_H
+#define _VX_SCHED_CMD_H
+
+/*  sched vserver commands */
+
+#define VCMD_set_sched_v2      VC_CMD(SCHED, 1, 2)
+#define VCMD_set_sched         VC_CMD(SCHED, 1, 3)
+
+struct vcmd_set_sched_v2 {
+       int32_t fill_rate;
+       int32_t interval;
+       int32_t tokens;
+       int32_t tokens_min;
+       int32_t tokens_max;
+       uint64_t cpu_mask;
+};
+
+struct vcmd_set_sched_v3 {
+       uint32_t set_mask;
+       int32_t fill_rate;
+       int32_t interval;
+       int32_t tokens;
+       int32_t tokens_min;
+       int32_t tokens_max;
+       int32_t priority_bias;
+};
+
+
+#define VXSM_FILL_RATE         0x0001
+#define VXSM_INTERVAL          0x0002
+#define VXSM_TOKENS            0x0010
+#define VXSM_TOKENS_MIN                0x0020
+#define VXSM_TOKENS_MAX                0x0040
+#define VXSM_PRIO_BIAS         0x0100
+
+#define SCHED_KEEP             (-2)
+
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+
+extern int vc_set_sched_v1(uint32_t, void __user *);
+extern int vc_set_sched_v2(uint32_t, void __user *);
+extern int vc_set_sched(uint32_t, void __user *);
+
+#endif /* __KERNEL__ */
+#endif /* _VX_SCHED_CMD_H */
index f55e6dd..f12b3d7 100644 (file)
@@ -47,6 +47,8 @@
 
 #define VC_CAT_PROCTRL         12
 
+#define VC_CAT_DLIMIT          36
+
 #define VC_CAT_RLIMIT          60
 
 #define VC_CAT_SYSTEST         61
index bb9b7db..972f301 100644 (file)
 extern "C" {
 #endif
 
+#define ENSC_STRUCT_IDX(STRUCT,ATTR)                   \
+  ((char*)(&(STRUCT).ATTR) - (char*)(&(STRUCT)))
+#define ENSC_SAME_STRUCT_IDX(LHS,RHS,ATTR)                     \
+  (ENSC_STRUCT_IDX(LHS,ATTR) == ENSC_STRUCT_IDX(RHS,ATTR))
+#define ENSC_SAME_STRUCT_ITEM(LHS,RHS,ATTR)    \
+  (ENSC_SAME_STRUCT_IDX(LHS,RHS,ATTR) &&       \
+   sizeof((LHS).ATTR)==sizeof((RHS).ATTR) &&   \
+   sizeof(LHS)==sizeof(RHS))
+
 #ifndef HAVE_VSERVER
 #ifdef ENSC_SYSCALL_TRADITIONAL
 inline static UNUSED ALWAYSINLINE
index 284f4a4..4f9205a 100644 (file)
 #define VC_LIM_INFINITY                (~0ULL)
 #define VC_LIM_KEEP            (~1ULL)
 
+#define VC_VXSM_FILL_RATE              0x0001
+#define VC_VXSM_INTERVAL               0x0002
+#define VC_VXSM_TOKENS                 0x0010
+#define VC_VXSM_TOKENS_MIN             0x0020
+#define VC_VXSM_TOKENS_MAX             0x0040
+#define VC_VXSM_PRIO_BIAS              0x0100
+
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -81,6 +90,19 @@ extern "C" {
   int  vc_get_rlimit_mask(xid_t ctx, struct vc_rlimit_mask *lim);
 
 
+#define VC_CAT_SCHED           14
+  struct vc_set_sched {
+      uint_least32_t   set_mask;
+      int_least32_t    fill_rate;
+      int_least32_t    interval;
+      int_least32_t    tokens;
+      int_least32_t    tokens_min;
+      int_least32_t    tokens_max;
+      int_least32_t    priority_bias;
+  };
+
+  int          vc_set_sched(xid_t xid, struct vc_set_sched const *);
+
   /** sends a signal to a context/pid
       Special values for pid are:
       * -1   which means every process in ctx except the init-process
diff --git a/man/vsh.8 b/man/vsh.8
new file mode 100644 (file)
index 0000000..85f914c
--- /dev/null
+++ b/man/vsh.8
@@ -0,0 +1,48 @@
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "VSH" 8 "2004-07-29" "PlanetLab specific Vserver shell" "vsh"
+
+.SH NAME
+vsh \- Safely trampoline's a slice user from global vserver context to
+the correspondingly named local vserver context\&.
+
+.SH "SYNOPSIS"
+.PP
+\fBvsh\fR [COMMAND] \fR
+.TP
+[COMMAND]
+when specified, the command to run, otherwise vsh will just run the
+user's shell as a login shell
+
+.SH "SUMMARY"
+.PP
+vsh is used as the login shell for slice users in the global vserver's
+/etc/passwd\&. It is invoked either by sshd when a slice user logs on
+to a PlanetLab node or as root using the su command\&. When this
+occurs, vsh switches vserver context and sets the uid/gid of the slice
+user, as specified in the slice's vserver /etc/passwd\&.
+
+.PP
+vsh assumes that the same account (by name) used to ssh/su into the
+vserver also exists in the vserver specific /etc/passwd file\&.  This
+is the only reason that for now it is deemed to be PlanetLab
+specific\&.
diff --git a/python/Makefile b/python/Makefile
new file mode 100644 (file)
index 0000000..35b5f43
--- /dev/null
@@ -0,0 +1,15 @@
+INCLUDES := -I.. -I../lib
+LIBS = -L../lib -lvserver
+
+PY_MODS := vserver.py cpulimit.py bwlimit.py
+PY_EXT_MODS := vduimpl.so vserverimpl.so
+
+all: py-build
+
+install: py-install
+       ln -s /usr/lib/util-vserver/util-vserver-vars \
+       $(INSTALL_ROOT)/usr/lib/python2.3/site-packages/util_vserver_vars.py
+
+-include pybuild.mk
+
+.PHONY: all install
diff --git a/python/bwlimit.py b/python/bwlimit.py
new file mode 100644 (file)
index 0000000..b408caa
--- /dev/null
@@ -0,0 +1,158 @@
+#!/bin/env python2 -u
+
+# Based on code written by: Andy Bavier, acb@cs.princeton.edu
+# 
+# Bandwidth limit script to run on PlanetLab nodes.  The intent is to use
+# the Hierarchical Token Bucket queueing discipline of 'tc' to (1) cap 
+# the output bandwidth of the node at a specified rate (e.g., 5Mbps) and 
+# (2) to allow all vservers to fairly share this rate.  For instance,
+# if there are N vservers, then each should get at least 5/N Mbps of 
+# bandwidth.
+#
+# Some relevant URLs:
+#   http://lartc.org/howto               for how to use tc
+#   http://luxik.cdi.cz/~devik/qos/htb/  for info on htb
+
+import sys, os, re, string
+
+# Global variables
+TC="/sbin/tc"                 # Where the modified tc program lives
+OPS = ["change","add"]  # Sequence of TC ops we'll try
+
+# Support to run system commands
+import runcmd
+def run(cmd):
+    try:
+        runcmd.run(cmd)
+        ret = True
+    except runcmd.Error, ex:
+        ret = False
+
+    return ret
+
+def get_defaults(cap_file="/etc/planetlab/bwcap", default_cap="10mbit"):
+    # The maximum output bandwidth, read in from cap_file (if it
+    # exists). If cap_file does not exist, use default_cap for
+    # bandwidth cap.  See also the 'cburst' parameter below.
+    cap=default_cap
+    try:
+        os.stat(cap_file)
+        fp = open(cap_file)
+        lines = fp.readlines()
+        fp.close()
+        try:
+            cap=string.strip(lines[0])
+        except ValueError, ex:
+            pass
+    except OSError, ex:
+        pass
+
+    # How many bytes a single token bucket is allowed to send at once.
+    # Small values (i.e., 3080 = two maximum-sized Ethernet packets)
+    # provide better fine-grained fairness.  At high rates (e.g.,
+    # cap=100mbit) this needs to be raised to allow full throughput.
+    cburst=30800
+
+    # The 'share' and 'quantum' parameters both influence the actual throughput
+    # seen by a particular vserver:
+
+    # 'share' is the rate at which tokens fill the bucket, and so is
+    # the minimum bandwidth given to the task.  I think this just
+    # needs to be set to some small value that is the same for all
+    # vservers.  With the current value and a 5mbit cap, we can
+    # support 5000 vservers (5mbit/1kbit = 5000).  With values lower
+    # than 10kbit, the HTB output (from tc -s -d class dev eth0) looks
+    # strange... this needs to be looked into further.
+    share="1kbit"
+
+    # 'quantum' influences how excess bandwidth (i.e., above the
+    # 'share') is distributed to vservers.  Apparently, vservers can
+    # send additional packets in proportion to their quantums (and not
+    # their shares, as one might expect).  See:
+    #   http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm#sharing
+    #   The above link states that 'quantum' is automatically
+    #   calculated for shares above 120kbit.  Otherwise it should be
+    #   set to a small value but at least one MTU, so I set it to one
+    #   MTU.  All vservers are assigned the same quantum and so they
+    #   should share equally.
+    quantum=1540
+
+    return cap, cburst, share, quantum
+
+
+def init(eth):
+    global TC, OPS
+
+    cap, cburst, share, quantum = get_defaults()
+    if cap == "-1": return
+
+    # Install HTB on $ETH.  Specifies that all packets not matching a
+    # filter rule go to class with handle 9999.  If we don't supply a
+    # default class, it sounds like non-matching packets can be sent
+    # at an unlimited rate.
+    for op in OPS:
+        cmd = "%s qdisc %s dev %s root handle 1: htb default 9999" % (TC,op,eth)
+        if run(cmd): break
+
+    # Add a root class with bwcap capped rate
+    for op in OPS:
+        cmd = "%s class %s dev %s parent 1: classid 1:1 htb rate %s quantum %d" % \
+              (TC, op, eth, cap, quantum)
+        if run(cmd): break
+
+    # Set up the default class.  Packets will fail to match a filter rule
+    # and end up here if they are sent by a process with UID < 500.
+    for op in OPS:
+        cmd = "%s class %s dev %s parent 1:1 classid 1:9999 htb rate %s ceil %s quantum %d cburst %d" % \
+              (TC, op, eth, share, cap, quantum, cburst)
+        if run(cmd): break
+
+    # The next command appears to throttle back processes that are
+    # sending faster than the token bucket can support, rather than
+    # just dropping their packets.
+    for op in OPS:
+        cmd = "%s qdisc %s dev %s parent 1:9999 handle 9999 pfifo" % \
+              (TC, op, eth)
+        if run(cmd): break
+
+def on(xid, eth, bwlimit, cap, minrate, maxrate):
+    global TC, OPS
+
+    default_cap, default_cburst, default_share, default_quantum = get_defaults()
+    quantum = bwlimit * default_quantum
+
+    # Set up the per-vserver token bucket
+    for op in OPS:
+        cmd = "%s class %s dev %s parent 1:1 classid 1:%d htb rate %s ceil %s quantum %d cburst %d" % \
+              (TC, op, eth, xid, minrate, cap, quantum, default_cburst)
+        if run(cmd): break
+
+    # The next command appears to throttle back processes that are
+    # sending faster than the token bucket can support, rather than
+    # just dropping their packets.
+    for op in OPS:
+        cmd = "%s qdisc %s dev %s parent 1:%d handle %d pfifo" % \
+              (TC, op, eth, xid, xid)
+        if run(cmd): break
+
+    # Matches packets sent by a vserver to the appropriate token bucket.
+    # The raw socket module marks each packet with its vserver id.
+    # See: http://lartc.org/howto/lartc.qdisc.filters.html for more
+    # info on the filter command.
+    cmd = "%s filter del dev %s protocol ip prio %d" % (TC, eth, xid)
+    run(cmd)
+    cmd = "%s filter add dev %s prio %d parent 1:0 protocol ip handle %d fw flowid 1:%d" % \
+          (TC, eth, xid, xid, xid)
+    run(cmd)
+
+def off(xid, eth):
+    cmd = "%s filter del dev %s protocol ip prio %d" % (TC, eth, xid)
+    run(cmd)
+
+    cmd = "%s qdisc del dev %s parent 1:%d" % (TC, eth, xid)
+    run(cmd)
+
+    cmd = "%s class del dev %s classid 1:%d" % (TC, eth, xid)
+    run(cmd)
+
+    
diff --git a/python/cpulimit.py b/python/cpulimit.py
new file mode 100755 (executable)
index 0000000..708f092
--- /dev/null
@@ -0,0 +1,117 @@
+#!/usr/bin/python2 -u
+
+import sys, os, re, string
+
+
+TCBASE="/rcfs/taskclass/"
+RULES="/rcfs/ce/rules/"
+
+SYSCLASS=TCBASE + "system"
+SYSRULE=RULES + "system"
+SYSCPUSHARE=100
+DEFAULTMAXCPUSHARE=8192
+
+def checkckrm():
+    checks = [ "/rcfs", TCBASE, RULES ]
+
+    for check in checks:
+        try:
+            answer = os.stat(check)
+        except:
+            print "%s does not exist" % check
+            return False
+    
+    return True
+
+def checkclass(tc):
+    try:
+        answer = os.stat(TCBASE + tc)
+        return True
+
+    except:
+        print "%s class does not exist" % tc
+        return False
+
+def getxid(name):
+    xid = -1
+    fp = open('/etc/passwd')
+    for line in fp.readlines():
+        rec = string.splitfields(line,':')
+        if rec[0] == name:
+            xid = int(rec[2])
+            break
+
+    fp.close()
+    
+    if xid == -1:
+        # raise an exception
+        pass
+
+    return xid
+
+def write(filename,s):
+    fp = os.open(filename,os.O_WRONLY|os.O_CREAT)
+    os.write(fp,s)
+    os.close(fp)
+
+def vs2ckrm_on(tc):
+    xid = getxid(tc)
+
+    try:
+        os.mkdir(TCBASE + tc)
+    except OSError:
+        pass # ignore oserror for file exists
+    
+    s = "xid=%d,class=%s" % (xid,TCBASE+tc)
+    fname = RULES + tc
+    write(fname, s)
+
+def vs2ckrm_off(tc):
+    fname = TCBASE + tc + "/members"
+    for i in range(1,15):
+        fp = open(fname)
+        lines = fp.readlines()
+        try:
+            lines.remove("No data to display\n")
+        except ValueError:
+            pass
+        if len(lines) == 0:
+            try:
+                answer = os.stat(RULES + tc)
+                os.unlink(RULES + tc)
+                answer = os.stat(TCBASE + tc)                
+                os.rmdir(TCBASE + tc)
+            except:
+                pass
+            break
+
+        else:
+            print "enter context 1 and kill processes", lines
+        
+
+def cpulimit(tc,limit):
+    global TCBASE
+
+    fname = TCBASE + tc + "/shares"
+    s = "res=cpu,guarantee=%d\n" % limit
+    write(fname,s)
+
+def cpuinit():
+    global TCBASE
+
+    fname = TCBASE + "shares"
+    s = "res=cpu,total_guarantee=%d\n" % DEFAULTMAXCPUSHARE
+    write(fname,s)
+
+if __name__ == "__main__":
+    try:
+        name = sys.argv[1]
+        limit = int(sys.argv[2])
+    except:
+        print "caught exception"
+
+    if checkckrm() is True:
+        cpuinit()
+        vs2ckrm_on(name)
+        cpulimit(name,limit)
+        vs2ckrm_off(name)
diff --git a/python/pybuild.mk b/python/pybuild.mk
new file mode 100644 (file)
index 0000000..140cc14
--- /dev/null
@@ -0,0 +1,32 @@
+# Copyright 2005 Princeton University
+#
+# PY_MODS variable should be list of Python source modules
+# PY_EXT_MODS should be list of Python extension modules (.so) that need
+# to be built
+#
+
+_PY_TMPDIR := .pybuild
+
+# use strip to remove extra whitespace
+_PY_SETUP = $(strip python setup.py \
+       $(foreach i,DEFS INCLUDES LIBS PY_MODS PY_EXT_MODS,\
+       $(if $(subst undefined,,$(origin $i)),$i="$($i)")))
+
+_PY_BUILD_ARGS := -t $(_PY_TMPDIR) -b $(_PY_TMPDIR)/build
+
+py-build: .pybuild/.prep-done $(PY_MODS) $(PY_EXT_MODS)
+
+.pybuild/.prep-done:
+       mkdir build .pybuild
+       ln -s ../build .pybuild
+       touch $@
+
+$(PY_EXT_MODS): PY_EXT_MODS = $@
+
+$(PY_EXT_MODS): %.so: %.c
+       $(_PY_SETUP) build_ext -f $(_PY_BUILD_ARGS)
+
+py-install:
+       $(_PY_SETUP) install --root=$(INSTALL_ROOT)
+
+.PHONY: py-build py-install py-clean
diff --git a/python/setup.py b/python/setup.py
new file mode 100644 (file)
index 0000000..507a5c2
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+
+import re
+import sys
+
+from distutils.core import setup, Extension
+
+MODULE_NAME_RE = "[A-Za-z_]+"
+
+if __name__ == "__main__":
+
+    build_arg_re = re.compile(r"^([A-Z_]+)= *(.*)")
+    def split_args((build_args, argv), arg):
+        m = build_arg_re.match(arg)
+        if m:
+            (k, v) = m.groups()
+            build_args[k] = v
+        else:
+            argv += [arg]
+        return (build_args, argv)
+
+    (build_args, argv) = reduce(split_args, sys.argv[1:], ({}, []))
+    sys.argv[1:] = argv
+    extension_args = { "extra_compile_args": ["-Wall"] }
+    if "INCLUDES" in build_args:
+        extension_args["include_dirs"] = re.findall(r"-I([^ ]+)",
+                                                    build_args["INCLUDES"])
+    lib_args = build_args.get("LIBS", "")
+    if lib_args:
+        extension_args["library_dirs"] = re.findall(r"-L([^ ]+)", lib_args)
+        extension_args["libraries"] = re.findall(r"-l([^ ]+)", lib_args)
+    modules = re.findall("(%s).py" % MODULE_NAME_RE,
+                         build_args.get("PY_MODS", ""))
+    extensions = map(lambda modname: Extension(modname,
+                                               [modname + ".c"],
+                                               **extension_args),
+                     re.findall("(%s).so" % MODULE_NAME_RE,
+                                build_args.get("PY_EXT_MODS", "")))
+
+    setup(py_modules = modules, ext_modules = extensions)
diff --git a/python/vduimpl.c b/python/vduimpl.c
new file mode 100644 (file)
index 0000000..01fc63c
--- /dev/null
@@ -0,0 +1,574 @@
+/* Copyright 2005 Princeton University */
+
+#include <Python.h>
+
+#define _LARGEFILE64_SOURCE 1
+
+#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>
+#include <sys/ioctl.h>
+#include <assert.h>
+
+
+/*
+ * hash table implementation
+ */
+
+typedef ino64_t KEY;
+typedef KEY *PKEY;
+typedef struct stat64 VAL;
+typedef VAL *PVAL;
+
+static inline
+unsigned int
+HASH(PKEY key){
+       return (int) *key;
+}
+
+static inline
+unsigned int // boolean
+EQUAL(PKEY key1, PKEY key2){
+       return *key1 == *key2;
+}
+
+#ifndef MIN
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#endif // MIN
+
+#ifndef MAX
+#define MAX(x,y) (((x)>(y))?(x):(y))
+#endif // MAX
+
+
+/*
+ * hash table support for efficient lookup of duplicate inodes
+ */
+
+#define Multiplier  (0x9e3779b9)
+#define MaxLogBuckets  (((sizeof (unsigned long))*8) - 2)
+#define MaxBuckets     (1<<MaxLogBuckets)
+#define MinLogBuckets  (4)
+#define MinBuckets     (1<<MinLogBuckets)
+
+/* Thresholds for rehashing the table: *)
+ * to avoid crazy oscillations, we must have MaxDensity > 2*MinDensity; *)
+ * to avoid excessive probes, we must try to keep MaxDensity low. *)
+ * Divide by 100 before using
+ */
+#define MaxDensity 75 /* max numEntries/NUMBER(buckets) */
+#define MinDensity 20 /* min numEntries/NUMBER(buckets) */
+#define IdealDensity 50
+#define BITSIZE(x) (sizeof(x)*8)
+
+#define NEW(type,num) ((type*)malloc(sizeof(type)*num))
+#define DISPOSE(ptr) (free((void*)ptr))
+
+/*
+ * Generic Hash Entry Type
+ */
+
+typedef struct VoidList {
+       struct VoidList *tail;
+} VoidList, *PVoidList;
+
+typedef struct HashTable {
+       PVoidList *buckets;
+       unsigned int numBuckets;    // number of buckets
+       unsigned int minLogBuckets; // minimum value for Log_2(initial size) 
+       unsigned int logBuckets;    // CEILING(Log2(NUMBER(buckets^))) 
+       unsigned int maxEntries;    // maximum number of entries 
+       unsigned int minEntries;    // minimum number of entries 
+       unsigned int numEntries;    // current num of entries in table 
+       PVoidList cache;            // cache of removed elements 
+       int cacheSize;              // current size of the cache 
+       int maxCacheSize;           // maximum size, -1 means unbounded, 0 no cache 
+} HashTable, *PHashTable;
+
+/*
+ * Hash Prototypes
+ */
+
+PHashTable
+Init(PHashTable tbl, unsigned int n, int maxCacheSize);
+
+void
+Dispose(PHashTable tbl);
+
+unsigned int
+Log_2(unsigned int x);
+
+void
+NewBuckets(PHashTable tbl, unsigned int logBuckets);
+
+/*
+ * Generic Hash Table support
+ */
+
+PHashTable
+Init(PHashTable tbl, unsigned int n, int maxCacheSize){
+       int idealBuckets;
+       int minBuckets;
+  
+       idealBuckets = MIN(((n*100)/IdealDensity),MaxBuckets);
+       minBuckets = MAX(MinBuckets, idealBuckets);
+       tbl->minLogBuckets = Log_2(minBuckets);
+
+       NewBuckets(tbl, tbl->minLogBuckets);
+       tbl->numEntries = 0;
+       tbl->maxCacheSize = maxCacheSize;
+       tbl->cacheSize = 0;
+       tbl->cache = 0;
+       return tbl;
+} // Init()
+
+
+/*
+ * Internal procedures
+ */
+
+unsigned int
+Log_2(unsigned int x){
+       /* return CEILING(LOG_2(x)) */
+       unsigned int log = 0;
+       unsigned int n= 1;
+
+       assert(x != 0);
+       while ((log < MaxLogBuckets) && (x > n)){
+               log++; 
+               n += n;
+       }
+       return log;
+}
+
+void
+NewBuckets(PHashTable tbl, unsigned int logBuckets){
+       /* Allocate "2^logBuckets" buckets. */
+       unsigned int numBuckets = 1 << logBuckets;
+       PVoidList *b;
+       unsigned int i;
+
+       tbl->buckets = NEW(PVoidList, numBuckets);
+       tbl->numBuckets = numBuckets;
+       b = tbl->buckets;
+
+       for (i=0; i<tbl->numBuckets; i++){
+               b[i] = NULL;
+       }
+       tbl->logBuckets = logBuckets;
+       tbl->maxEntries = MaxDensity * numBuckets / 100;
+       tbl->minEntries = MinDensity * numBuckets / 100;
+}
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/*
+ * Type specific hash entry
+ */
+typedef struct EntryList {
+       struct EntryList *tail;
+       KEY key;
+       VAL val;
+}EntryList, *PEntryList;
+
+/*
+ * Type specific Hash implementation functions
+ */
+
+static
+void
+Rehash(PHashTable tbl, unsigned int logBuckets) {
+       /* Reallocate "2^logBuckets" buckets, and rehash the entries into
+        * the new table.
+        */
+
+       PVoidList *oldBucketPointer;
+       PEntryList *ob, obi;
+       PEntryList *nb, *nbh;
+       PEntryList that, tail;
+       unsigned int index; 
+       unsigned int i;
+       unsigned int oldNumBuckets;
+
+       return;
+       assert(logBuckets <= MaxLogBuckets);
+       assert(logBuckets >= tbl->minLogBuckets);
+       oldBucketPointer = tbl->buckets;
+       ob = (PEntryList*)tbl->buckets;
+       oldNumBuckets = tbl->numBuckets;
+
+       NewBuckets(tbl, logBuckets);
+       nb = (PEntryList*)tbl->buckets;
+
+       for(i=0;i<oldNumBuckets;i++){
+               obi = ob[i];
+               that = obi;
+               while (that != NULL) {
+                       index = (HASH(&(that->key))*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets);
+                       nbh = &(nb[index]);
+                       tail = that->tail;
+                       that->tail = *nbh;
+                       *nbh = that;
+                       that = tail;
+               }
+       }
+       DISPOSE (oldBucketPointer);
+}
+
+static inline
+unsigned int /* boolean */
+Get(PHashTable tbl, PKEY key, PVAL *val){
+       PEntryList that;
+       unsigned int index;
+
+       index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets);
+       that = (PEntryList)tbl->buckets[index];
+       while ((that != NULL) && !EQUAL(key,&(that->key))) {
+               that = that->tail;
+       }
+       if (that != NULL){
+               *val = &that->val;
+               return TRUE;
+       }
+       else {
+               return FALSE;
+       }
+}
+
+static inline 
+unsigned int /* boolean */
+Put(PHashTable tbl, PKEY key, PVAL *val){
+       PEntryList that;
+       PEntryList *first;
+       unsigned int index;
+       unsigned int res;
+
+       index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets);
+       first = (PEntryList*)&(tbl->buckets[index]);
+       that = *first;
+       while ((that != NULL) && !EQUAL(key, &(that->key))){
+               that = that->tail;
+       }
+  
+       /* found an entry in the hash table given above key */
+       if (that != NULL){
+               res = TRUE;
+       }
+       else {
+               /* check if we can reuse something from the cache */
+               if (tbl->cache != NULL) {
+                       that = (PEntryList)tbl->cache;
+                       tbl->cache = (PVoidList)tbl->cache->tail;
+                       that->key = *key;
+                       that->tail = *first;
+                       *first = that;
+               }
+               else {
+                       that = NEW(EntryList,1);
+                       that->key = *key;
+                       that->tail = *first;
+                       *first = that;
+               }
+               that->val = **val;
+
+               tbl->numEntries++;
+               if ((tbl->logBuckets < MaxLogBuckets)
+                   && (tbl->numEntries > tbl->maxEntries)){
+                       Rehash(tbl, tbl->logBuckets + 1); /* too crowded */
+               }
+               res = FALSE;
+       }
+       *val = &that->val;
+       return res;
+
+}
+
+static inline
+int
+Delete(PHashTable tbl,PKEY key){
+       PEntryList that, prev;
+       PEntryList *first;
+       unsigned int index;
+
+       index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets);
+       first = (PEntryList*)&(tbl->buckets[index]);
+       that = *first;
+       prev = NULL;
+
+       while ((that != NULL) && !EQUAL(key, &(that->key))){
+               prev = that;
+               that = that->tail;
+       }
+       if (that != NULL) {
+               if (prev == NULL) {
+                       *first = that->tail;
+               }
+               else {
+                       prev->tail = that->tail;
+               }
+               if ((tbl->maxCacheSize == -1)||(tbl->cacheSize < tbl->maxCacheSize)) {
+                       that->tail = (PEntryList)tbl->cache;
+                       tbl->cache = (PVoidList)that;
+                       tbl->cacheSize++;
+               }
+               else {
+                       DISPOSE (that);
+               }
+               tbl->numEntries--;
+               if (tbl->maxCacheSize == 0) {
+                       if ((tbl->logBuckets > tbl->minLogBuckets)
+                           && (tbl->numEntries < tbl->minEntries)) {
+                               Rehash(tbl, tbl->logBuckets - 1); /* too sparse */
+                       }
+               }
+               return TRUE;
+       }
+       else {
+               return FALSE;
+       }
+}
+
+typedef void (*callback)(PKEY key, PVAL val);
+
+void
+Iterate(PHashTable tbl, callback fn)
+{
+       PVoidList that;
+       unsigned int i;
+  
+       for(i=0;i<tbl->numBuckets;i++) {
+               that = tbl->buckets[i];
+               while ( that != (PVoidList)0 ) {
+                       PEntryList entry = (PEntryList)that;
+                       fn(&entry->key,&entry->val);
+                       that = that->tail;
+               }
+       }
+}
+
+void
+Dispose(PHashTable tbl)
+{
+       PVoidList that, next;
+       unsigned int i;
+
+       for(i=0;i<tbl->numBuckets;i++) {
+               that = tbl->buckets[i];
+               while( that != NULL) {
+                       next = that->tail;
+                       DISPOSE (that);
+                       tbl->numEntries--;
+                       that = next;
+               }
+       }
+       DISPOSE(tbl->buckets);
+       assert(tbl->numEntries = 0);
+}
+
+static int /* boolean */
+INOPut(PHashTable tbl, ino64_t* key, struct stat64 **val){
+       return Put(tbl, key, val);
+}
+
+__extension__ typedef long long                longlong;
+
+struct stats {
+       longlong inodes;
+       longlong blocks;
+       longlong size;
+};
+
+static short verbose = 0;
+
+static int vdu_onedir (PHashTable tbl, struct stats *__s, char const *path)
+{
+       char const *foo = path;
+       struct stat64 dirst, st;
+       struct dirent *ent;
+       char *name;
+       DIR *dir;
+       int dirfd;
+       int res = 0;
+       longlong dirsize, dirinodes, dirblocks;
+
+       dirsize = dirinodes = dirblocks = 0;
+
+       // A handle to speed up chdir
+       if ((dirfd = open (path,O_RDONLY)) == -1) {
+               return -1;
+       }
+
+       if (fchdir (dirfd) == -1) {
+               return -1;
+       }
+
+       if (fstat64 (dirfd,&dirst) != 0) {
+               return -1;
+       }
+
+       if ((dir = opendir (".")) == NULL) {
+               return -1;
+       }
+
+       /* Walk the directory entries and compute the sum of inodes,
+        * blocks, and disk space used. This code will recursively descend
+        * down the directory structure. 
+        */
+
+       while ((ent=readdir(dir))!=NULL){
+               if (lstat64(ent->d_name,&st)==-1){
+                       continue;
+               }
+       
+               dirinodes ++;
+
+               if (S_ISREG(st.st_mode)){
+                       if (st.st_nlink > 1){
+                               struct stat64 *val;
+                               int nlink;
+
+                               /* Check hash table if we've seen this inode
+                                * before. Note that the hash maintains a
+                                * (inode,struct stat) key value pair.
+                                */
+
+                               val = &st;
+
+                               (void) INOPut(tbl,&st.st_ino,&val);
+
+                               /* Note that after the INOPut call "val" refers to the
+                                * value entry in the hash table --- not &st.  This
+                                * means that if the inode has been put into the hash
+                                * table before, val will refer to the first st that
+                                * was put into the hashtable.  Otherwise, if it is
+                                * the first time it is put into the hash table, then
+                                * val will be equal to this &st.
+                                */
+                               nlink = val->st_nlink;
+                               nlink --;
+
+                               /* val refers to value in hash tbale */
+                               if (nlink == 0) {
+
+                                       /* We saw all hard links to this particular inode
+                                        * as part of this sweep of vdu. So account for
+                                        * the size and blocks required by the file.
+                                        */
+
+                                       dirsize += val->st_size;
+                                       dirblocks += val->st_blocks;
+
+                                       /* Do not delete the (ino,val) tuple from the tbl,
+                                        * as we need to handle the case when we are
+                                        * double counting a file due to a bind mount.
+                                        */
+                                       val->st_nlink = 0;
+
+                               } else if (nlink > 0) {
+                                       val->st_nlink = nlink;
+                               } else /* if(nlink < 0) */ {
+                                       /* We get here when we are double counting nlinks
+                                          due a bind mount. */
+
+                                       /* DO NOTHING */
+                               }
+                       } else {
+                               dirsize += st.st_size;
+                               dirblocks += st.st_blocks;
+                       }
+
+               } else if (S_ISDIR(st.st_mode)) {
+                       if ((st.st_dev == dirst.st_dev) &&
+                           (strcmp(ent->d_name,".")!=0) &&
+                           (strcmp(ent->d_name,"..")!=0)) {
+
+                               dirsize += st.st_size;
+                               dirblocks += st.st_blocks;
+
+                               name = strdup(ent->d_name);
+                               if (name==0) {
+                                       return -1;
+                               }
+                               res |= vdu_onedir(tbl,__s,name);
+                               free(name);
+                               fchdir(dirfd);
+                       }
+               } else {
+                       /* dirsize += st.st_size; */
+                       /* dirblocks += st.st_blocks; */
+               }
+       }
+       closedir (dir);
+       close (dirfd);
+       __s->inodes += dirinodes;
+       __s->blocks += dirblocks;
+       __s->size   += dirsize;
+       if (verbose) {
+               printf("%16lld %16lld %16lld %s\n",dirinodes, dirblocks, dirsize,foo);
+               printf("%16lld %16lld %16lld %s\n",__s->inodes, __s->blocks, __s->size,foo);
+       }
+
+       return res;
+}
+
+
+static PyObject *
+do_vdu(PyObject *self, PyObject *args)
+{
+       PyObject *tuple;
+
+       const char *path;
+       int res;
+       struct stats s;
+       HashTable tbl;
+
+       if (!PyArg_ParseTuple(args, "s", &path))
+               return Py_None;
+
+       /* init of tbl and stats */
+       s.inodes = s.blocks = s.size = 0;
+       (void) Init(&tbl,0,0);
+
+       res = vdu_onedir(&tbl, &s, path);
+
+       /* deallocate whatever has been added to tbl */
+       Dispose(&tbl);
+
+       /* create a python (inode, block, size) tuple */
+       tuple = Py_BuildValue("(L,L,L)",
+                             s.inodes,
+                             s.blocks>>1, /* NOTE: div by 2 to adjust
+                                           * 512b block count to 1K
+                                           * block count 
+                                           */
+                             s.size);
+       return (res == -1) ? PyErr_SetFromErrno(PyExc_OSError) : tuple;
+}
+
+static PyMethodDef  methods[] = {
+       { "vdu", do_vdu, METH_VARARGS,
+         "perform vdu operation on directory tree" },
+       { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC
+initvduimpl(void)
+{
+       Py_InitModule("vduimpl", methods);
+}
diff --git a/python/vserver.py b/python/vserver.py
new file mode 100644 (file)
index 0000000..1ec678a
--- /dev/null
@@ -0,0 +1,360 @@
+# Copyright 2005 Princeton University
+
+import errno
+import fcntl
+import os
+import re
+import sys
+import time
+import traceback
+
+import mountimpl
+import linuxcaps
+import passfdimpl
+import utmp
+import vserverimpl, vduimpl
+import cpulimit, bwlimit
+
+from util_vserver_vars import *
+
+CAP_SAFE = (linuxcaps.CAP_CHOWN |
+            linuxcaps.CAP_DAC_OVERRIDE |
+            linuxcaps.CAP_DAC_READ_SEARCH |
+            linuxcaps.CAP_FOWNER |
+            linuxcaps.CAP_FSETID |
+            linuxcaps.CAP_KILL |
+            linuxcaps.CAP_SETGID |
+            linuxcaps.CAP_SETUID |
+            linuxcaps.CAP_SETPCAP |
+            linuxcaps.CAP_SYS_TTY_CONFIG |
+            linuxcaps.CAP_LEASE |
+            linuxcaps.CAP_SYS_CHROOT |
+            linuxcaps.CAP_SYS_PTRACE)
+
+#
+# these are the flags taken from the kernel linux/vserver/legacy.h
+#
+FLAGS_LOCK = 1
+FLAGS_SCHED = 2  # XXX - defined in util-vserver/src/chcontext.c
+FLAGS_NPROC = 4
+FLAGS_PRIVATE = 8
+FLAGS_INIT = 16
+FLAGS_HIDEINFO = 32
+FLAGS_ULIMIT = 64
+FLAGS_NAMESPACE = 128
+
+# default values for new vserver scheduler
+SCHED_TOKENS_MIN = 50
+SCHED_TOKENS_MAX = 100
+
+              
+class VServer:
+
+    INITSCRIPTS = [('/etc/rc.vinit', 'start'),
+                   ('/etc/rc.d/rc', '%(runlevel)d')]
+
+    def __init__(self, name):
+
+        self.name = name
+        self.config = self.__read_config_file("/etc/vservers.conf")
+        self.config.update(self.__read_config_file("/etc/vservers/%s.conf" %
+                                                   self.name))
+        self.flags = 0
+        flags = self.config["S_FLAGS"].split(" ")
+        if "lock" in flags:
+            self.flags |= FLAGS_LOCK
+        if "nproc" in flags:
+            self.flags |= FLAGS_NPROC
+        self.remove_caps = ~CAP_SAFE
+        self.ctx = int(self.config["S_CONTEXT"])
+
+    config_var_re = re.compile(r"^ *([A-Z_]+)=(.*)\n?$", re.MULTILINE)
+
+    def __read_config_file(self, filename):
+
+        f = open(filename, "r")
+        data = f.read()
+        f.close()
+        config = {}
+        for m in self.config_var_re.finditer(data):
+            (key, val) = m.groups()
+            config[key] = val.strip('"')
+        return config
+
+    def __do_chroot(self):
+
+        return os.chroot("%s/%s" % (VROOTDIR, self.name))
+
+    def set_disklimit(self, blocktotal):
+        path = "%s/%s" % (VROOTDIR, self.name)
+        inodes, blockcount, size = vduimpl.vdu(path)
+        blockcount = blockcount >> 1
+
+        if blocktotal > blockcount:
+            vserverimpl.setdlimit(path, self.ctx, blockcount>>1, \
+                                  blocktotal, inodes, -1, 2)
+        else:
+            # should raise some error value
+            print "block limit (%d) ignored for vserver %s" %(blocktotal,self.name)
+
+    def get_disklimit(self):
+        path = "%s/%s" % (VROOTDIR, self.name)
+        try:
+            blocksused, blocktotal, inodesused, inodestotal, reserved = \
+                        vserverimpl.getdlimit(path,self.ctx)
+        except OSError, ex:
+            if ex.errno == 3:
+                # get here if no vserver disk limit has been set for xid
+                # set blockused to -1 to indicate no limit
+                blocktotal = -1
+
+        return blocktotal
+
+    def set_sched(self, shares, besteffort = True):
+        # for the old CKRM scheduler
+        if cpulimit.checkckrm() is True:
+            cpulimit.cpuinit()
+            cpulimit.vs2ckrm_on(self.name)
+            try:
+                cpulimit.cpulimit(self.name,shares)
+            except OSError, ex:
+                if ex.errno == 22:
+                    print "invalid shares argument"
+                    # should re-raise exception?!
+
+        # for the new vserver scheduler
+        else:
+            global SCHED_TOKENS_MIN, SCHED_TOKENS_MAX
+            tokensmin = SCHED_TOKENS_MIN
+            tokensmax = SCHED_TOKENS_MAX
+
+            if besteffort is True:
+                # magic "interval" value for Andy's scheduler to denote besteffort
+                interval = 1000
+                fillrate = shares
+            else:
+                interval = 1001
+                fillrate = shares
+
+            try:
+                vserverimpl.setsched(self.ctx,fillrate,interval,tokensmin,tokensmax)
+            except OSError, ex:
+                if ex.errno == 22:
+                    print "kernel does not support vserver scheduler"
+                else:
+                    raise ex
+
+    def get_sched(self):
+        # have no way of querying scheduler right now on a per vserver basis
+        return (-1, False)
+
+    def set_memlimit(self, limit):
+        ret = vserverimpl.setrlimit(self.ctx,5,limit)
+        return ret
+
+    def get_memlimit(self):
+        ret = vserverimpl.getrlimit(self.ctx,5)
+        return ret
+    
+    def set_tasklimit(self, limit):
+        ret = vserverimpl.setrlimit(self.ctx,6,limit)
+        return ret
+
+    def get_tasklimit(self):
+        ret = vserverimpl.getrlimit(self.ctx,6)
+        return ret
+
+    def set_bwlimit(self, eth, limit, cap, minrate, maxrate):
+        if cap == "-1":
+            bwlimit.off(self.ctx,eth)
+        else:
+            bwlimit.on(self.ctx, eth, limit, cap, minrate, maxrate)
+
+    def get_bwlimit(self, eth):
+        # not implemented yet
+        bwlimit = -1
+        cap = "unknown"
+        minrate = "unknown"
+        maxrate = "unknown"
+        return (bwlimit, cap, minrate, maxrate)
+        
+    def open(self, filename, mode = "r", bufsize = -1):
+
+        (sendsock, recvsock) = passfdimpl.socketpair()
+        child_pid = os.fork()
+        if child_pid == 0:
+            try:
+                # child process
+                self.__do_chroot()
+                f = open(filename, mode)
+                passfdimpl.sendmsg(f.fileno(), sendsock)
+                os._exit(0)
+            except EnvironmentError, ex:
+                (result, errmsg) = (ex.errno, ex.strerror)
+            except Exception, ex:
+                (result, errmsg) = (255, str(ex))
+            os.write(sendsock, errmsg)
+            os._exit(result)
+
+        # parent process
+
+        # XXX - need this since a lambda can't raise an exception
+        def __throw(ex):
+            raise ex
+
+        os.close(sendsock)
+        throw = lambda : __throw(Exception(errmsg))
+        while True:
+            try:
+                (pid, status) = os.waitpid(child_pid, 0)
+                if os.WIFEXITED(status):
+                    result = os.WEXITSTATUS(status)
+                    if result != 255:
+                        errmsg = os.strerror(result)
+                        throw = lambda : __throw(IOError(result, errmsg))
+                    else:
+                        errmsg = "unexpected exception in child"
+                else:
+                    result = -1
+                    errmsg = "child killed"
+                break
+            except OSError, ex:
+                if ex.errno != errno.EINTR:
+                    os.close(recvsock)
+                    raise ex
+        fcntl.fcntl(recvsock, fcntl.F_SETFL, os.O_NONBLOCK)
+        try:
+            (fd, errmsg) = passfdimpl.recvmsg(recvsock)
+        except OSError, ex:
+            if ex.errno != errno.EAGAIN:
+                throw = lambda : __throw(ex)
+            fd = 0
+        os.close(recvsock)
+        if not fd:
+            throw()
+
+        return os.fdopen(fd, mode, bufsize)
+
+    def __do_chcontext(self, state_file = None):
+
+        vserverimpl.chcontext(self.ctx, self.remove_caps)
+        if not state_file:
+            return
+        print >>state_file, "S_CONTEXT=%d" % self.ctx
+        print >>state_file, "S_PROFILE=%s" % self.config.get("S_PROFILE", "")
+        state_file.close()
+
+    def __prep(self, runlevel, log):
+
+        """ Perform all the crap that the vserver script does before
+        actually executing the startup scripts. """
+
+        # remove /var/run and /var/lock/subsys files
+        # but don't remove utmp from the top-level /var/run
+        RUNDIR = "/var/run"
+        LOCKDIR = "/var/lock/subsys"
+        filter_fn = lambda fs: filter(lambda f: f != 'utmp', fs)
+        garbage = reduce((lambda (out, ff), (dir, subdirs, files):
+                          (out + map((dir + "/").__add__, ff(files)),
+                           lambda fs: fs)),
+                         list(os.walk(RUNDIR)),
+                         ([], filter_fn))[0]
+        garbage += filter(os.path.isfile, map((LOCKDIR + "/").__add__,
+                                              os.listdir(LOCKDIR)))
+        for f in garbage:
+            os.unlink(f)
+
+        # set the initial runlevel
+        f = open(RUNDIR + "/utmp", "w")
+        utmp.set_runlevel(f, runlevel)
+        f.close()
+
+        # mount /proc and /dev/pts
+        self.__do_mount("none", "/proc", "proc")
+        # XXX - magic mount options
+        self.__do_mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=0620")
+
+    def __do_mount(self, *mount_args):
+
+        try:
+            mountimpl.mount(*mount_args)
+        except OSError, ex:
+            if ex.errno == errno.EBUSY:
+                # assume already mounted
+                return
+            raise ex
+
+    def enter(self):
+
+        state_file = open("/var/run/vservers/%s.ctx" % self.name, "w")
+        self.__do_chroot()
+        self.__do_chcontext(state_file)
+
+    def start(self, wait, runlevel = 3):
+
+        child_pid = os.fork()
+        if child_pid == 0:
+            # child process
+            try:
+                # get a new session
+                os.setsid()
+
+                # open state file to record vserver info
+                state_file = open("/var/run/vservers/%s.ctx" % self.name, "w")
+
+                # use /dev/null for stdin, /var/log/boot.log for stdout/err
+                os.close(0)
+                os.close(1)
+                os.open("/dev/null", os.O_RDONLY)
+                self.__do_chroot()
+                log = open("/var/log/boot.log", "w", 0)
+                os.dup2(1, 2)
+
+                print >>log, ("%s: starting the virtual server %s" %
+                              (time.asctime(time.gmtime()), self.name))
+
+                # perform pre-init cleanup
+                self.__prep(runlevel, log)
+
+                # execute each init script in turn
+                # XXX - we don't support all scripts that vserver script does
+                cmd_pid = 0
+                for cmd in self.INITSCRIPTS + [None]:
+                    # wait for previous command to terminate, unless it
+                    # is the last one and the caller has specified to wait
+                    if cmd_pid and (cmd != None or wait):
+                        try:
+                            os.waitpid(cmd_pid, 0)
+                        except:
+                            print >>log, "error waiting for %s:" % cmd_pid
+                            traceback.print_exc()
+
+                    # end of list
+                    if cmd == None:
+                        os._exit(0)
+
+                    # fork and exec next command
+                    cmd_pid = os.fork()
+                    if cmd_pid == 0:
+                        try:
+                            # enter vserver context
+                            self.__do_chcontext(state_file)
+                            arg_subst = { 'runlevel': runlevel }
+                            cmd_args = [cmd[0]] + map(lambda x: x % arg_subst,
+                                                      cmd[1:])
+                            print >>log, "executing '%s'" % " ".join(cmd_args)
+                            os.execl(cmd[0], *cmd_args)
+                        except:
+                            traceback.print_exc()
+                            os._exit(1)
+                    else:
+                        # don't want to write state_file multiple times
+                        state_file = None
+
+            # we get here due to an exception in the top-level child process
+            except Exception, ex:
+                traceback.print_exc()
+            os._exit(0)
+
+        # parent process
+        return child_pid
diff --git a/python/vserverimpl.c b/python/vserverimpl.c
new file mode 100644 (file)
index 0000000..5b2cdb8
--- /dev/null
@@ -0,0 +1,261 @@
+/* Copyright 2005 Princeton University
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met: 
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+      
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+      
+    * Neither the name of the copyright holder nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+      
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PRINCETON
+UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. 
+
+*/
+
+#include <Python.h>
+
+#include "config.h"
+#include "compat.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include "vserver.h"
+#include "vserver-internal.h"
+#include "sched_cmd.h"
+#include "virtual.h"
+
+/*
+ * chcontext
+ */
+static PyObject *
+vserver_chcontext(PyObject *self, PyObject *args)
+{
+  unsigned  xid;
+  unsigned  caps_remove = 0;
+
+  if (!PyArg_ParseTuple(args, "I|I", &xid, &caps_remove))
+    return NULL;
+
+  if (vc_new_s_context(xid, caps_remove, 0) < 0)
+    return PyErr_SetFromErrno(PyExc_OSError);
+
+  return Py_None;
+}
+
+static PyObject *
+vserver_set_rlimit(PyObject *self, PyObject *args) {
+       struct vc_rlimit limits;
+       int xid, resource;
+       PyObject *ret;
+
+       limits.min = VC_LIM_KEEP;
+       limits.soft = VC_LIM_KEEP;
+       limits.hard = VC_LIM_KEEP;
+
+       if (!PyArg_ParseTuple(args, "iiL", &xid, &resource, &limits.hard))
+               return NULL;
+
+       ret = Py_None;
+       if (vc_set_rlimit(xid, resource, &limits)) 
+               ret = PyErr_SetFromErrno(PyExc_OSError);
+       else if (vc_get_rlimit(xid, resource, &limits)==-1)
+               ret = PyErr_SetFromErrno(PyExc_OSError);
+       else
+               ret = Py_BuildValue("L",limits.hard);
+
+       return ret;
+}
+
+static PyObject *
+vserver_get_rlimit(PyObject *self, PyObject *args) {
+       struct vc_rlimit limits;
+       int xid, resource;
+       PyObject *ret;
+
+       limits.min = VC_LIM_KEEP;
+       limits.soft = VC_LIM_KEEP;
+       limits.hard = VC_LIM_KEEP;
+
+       if (!PyArg_ParseTuple(args, "ii", &xid, &resource))
+               return NULL;
+
+       ret = Py_None;
+       if (vc_get_rlimit(xid, resource, &limits)==-1)
+               ret = PyErr_SetFromErrno(PyExc_OSError);
+       else
+               ret = Py_BuildValue("L",limits.hard);
+
+       return ret;
+}
+
+/*
+ * setsched
+ */
+static PyObject *
+vserver_setsched(PyObject *self, PyObject *args)
+{
+  unsigned  xid;
+  struct vc_set_sched sched;
+
+  sched.set_mask = (VC_VXSM_FILL_RATE | 
+                   VC_VXSM_INTERVAL | 
+                   VC_VXSM_TOKENS_MIN | 
+                   VC_VXSM_TOKENS_MAX);
+
+  if (!PyArg_ParseTuple(args, "I|I|I|I|I", &xid, 
+                       &sched.fill_rate,
+                       &sched.interval,
+                       &sched.tokens_min,
+                       &sched.tokens_max))
+    return NULL;
+
+  if (vc_set_sched(xid, &sched) == -1)
+    return PyErr_SetFromErrno(PyExc_OSError);
+
+  return Py_None;
+}
+
+/*
+ * setsched
+ */
+
+/*  inode vserver commands */
+#define VCMD_add_dlimit                VC_CMD(DLIMIT, 1, 0)
+#define VCMD_rem_dlimit                VC_CMD(DLIMIT, 2, 0)
+#define VCMD_set_dlimit                VC_CMD(DLIMIT, 5, 0)
+#define VCMD_get_dlimit                VC_CMD(DLIMIT, 6, 0)
+
+struct  vcmd_ctx_dlimit_base_v0 {
+       char *name;
+       uint32_t flags;
+};
+
+struct  vcmd_ctx_dlimit_v0 {
+       char *name;
+       uint32_t space_used;                    /* used space in kbytes */
+       uint32_t space_total;                   /* maximum space in kbytes */
+       uint32_t inodes_used;                   /* used inodes */
+       uint32_t inodes_total;                  /* maximum inodes */
+       uint32_t reserved;                      /* reserved for root in % */
+       uint32_t flags;
+};
+
+#define CDLIM_UNSET             (0ULL)
+#define CDLIM_INFINITY          (~0ULL)
+#define CDLIM_KEEP              (~1ULL)
+
+static PyObject *
+vserver_get_dlimit(PyObject *self, PyObject *args)
+{
+       PyObject *res;
+       char* path;
+       unsigned xid;
+       struct vcmd_ctx_dlimit_v0 data;
+       int r;
+
+       if (!PyArg_ParseTuple(args, "si", &path,&xid))
+               return NULL;
+
+       memset(&data, 0, sizeof(data));
+       data.name = path;
+       data.flags = 0;
+       r = vserver(VCMD_get_dlimit, xid, &data);
+       if (r>=0) {
+               res = Py_BuildValue("(i,i,i,i,i)",
+                                   data.space_used,
+                                   data.space_total,
+                                   data.inodes_used,
+                                   data.inodes_total,
+                                   data.reserved);
+       } else {
+               res = PyErr_SetFromErrno(PyExc_OSError);
+       }
+
+       return res;
+}
+
+
+static PyObject *
+vserver_set_dlimit(PyObject *self, PyObject *args)
+{
+       char* path;
+       unsigned xid;
+       struct vcmd_ctx_dlimit_base_v0 init;
+       struct vcmd_ctx_dlimit_v0 data;
+       int r;
+
+       memset(&data,0,sizeof(data));
+       if (!PyArg_ParseTuple(args, "siiiiii", &path,
+                             &xid,
+                             &data.space_used,
+                             &data.space_total,
+                             &data.inodes_used,
+                             &data.inodes_total,
+                             &data.reserved))
+               return NULL;
+
+       data.name = path;
+       data.flags = 0;
+
+       memset(&init, 0, sizeof(init));
+       init.name = path;
+       init.flags = 0;
+
+       r = vserver(VCMD_rem_dlimit, xid, &init);
+       if (r<0){}
+       r = vserver(VCMD_add_dlimit, xid, &init);
+       if (r<0){}
+       r = vserver(VCMD_set_dlimit, xid, &data);
+       if (r<0){}
+       return Py_None; 
+}
+
+static PyMethodDef  methods[] = {
+  { "chcontext", vserver_chcontext, METH_VARARGS,
+    "Change to the given vserver context" },
+  { "setsched", vserver_setsched, METH_VARARGS,
+    "Change vserver scheduling attributes for given vserver context" },
+  { "setdlimit", vserver_set_dlimit, METH_VARARGS,
+    "Set disk limits for given vserver context" },
+  { "getdlimit", vserver_get_dlimit, METH_VARARGS,
+    "Get disk limits for given vserver context" },
+  { "setrlimit", vserver_set_rlimit, METH_VARARGS,
+    "Set resource limits for given resource of a vserver context" },
+  { "getrlimit", vserver_get_rlimit, METH_VARARGS,
+    "Get resource limits for given resource of a vserver context" },
+  { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC
+initvserverimpl(void)
+{
+  Py_InitModule("vserverimpl", methods);
+}
index cec9518..fccc81b 100644 (file)
@@ -36,6 +36,9 @@ scripts_src_PRGS      =  scripts/vpstree \
                           scripts/vrpm \
                           scripts/vserver \
                           scripts/vserver-copy \
+                          scripts/vcached \
+                          scripts/vuseradd \
+                          scripts/vuserdel \
                           scripts/vtop
 scripts_gen_PRGS       =  scripts/vps
 
diff --git a/scripts/vcached b/scripts/vcached
new file mode 100755 (executable)
index 0000000..19e0dff
--- /dev/null
@@ -0,0 +1,102 @@
+#!/bin/bash
+#
+# vcached: VServer cache daemon
+#
+# Description: A daemon that periodically preallocates vservers and stores
+# them in a cache.  Preallocated vservers from the cache may be then used to 
+# instantiate real vservers. Requires that /var/run/vcached.pid does not
+# exist on startup. Should start/stop/restart from /etc/init.d. Can also be
+# run periodically with -s from /etc/cron.d.
+#
+# Based on work by:
+# 
+# Brent Chun - bnc@intel-research.net
+# Tristan Koo - tristan.koo@intel-research.net
+# William Wung - wungism@uclink.berkeley.edu
+#
+# Mark Huang <mlhuang@cs.princeton.edu>
+# Copyright (c) 2004  The Trustees of Princeton University (Trustees).
+#
+# $Id: vcached,v 1.9 2004/11/23 14:47:35 mlhuang Exp $
+#
+
+# get configuration
+. /etc/vcached.conf
+
+# parse options
+while getopts 'fdsl:' OPT ; do
+    case "$OPT" in
+        f) foreground=1 ;;
+        d) debug=1 ;;
+       s) single=1 ;;
+       l) exec 1>>$OPTARG ; exec 2>>$OPTARG ;;
+    esac
+done
+
+# check if we are already running
+if [ -f $pidfile ] ; then
+    echo "vcached(`cat $pidfile`) already running"
+    exit 1
+fi
+
+# daemonize
+if [ $foreground -eq 0 ] ; then
+    nohup setsid nice -n $nice -- $0 $* -f -l $logfile >/dev/null 2>&1 </dev/null &
+    exit 0
+fi
+
+# record PID
+trap "rm -f $pidfile ; exit 255" EXIT
+trap "exec 1>>$logfile ; exec 2>>$logfile" HUP
+echo $$ > $pidfile
+
+: ${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"
+
+# make sure barrier bit is set on /vservers to prevent chroot() escapes
+$PKGLIBDIR/setattr --barrier $VROOTDIR
+
+# take out the trash
+rm -rf "$VROOTDIR/.vtmp"
+
+mkdir -p "$VROOTDIR/.vcache"
+mkdir -p "$VROOTDIR/.vtmp"
+
+# loop forever
+while : ; do
+    [ $debug -ne 0 ] && echo "$(date) Checking the cache"
+    for i in $(seq 0 $(($slots - 1))) ; do
+       if [ ! -d "$VROOTDIR/.vcache/v$i" ] ; then
+           echo "$(date) Caching v$i"
+           # build image in .vtmp
+           TMP=$(mktemp -d "$VROOTDIR/.vtmp/v$i.XXXXXX")
+           "$PKGLIBDIR/vbuild" "$VROOTDIR/vserver-reference" "$TMP"
+           RETVAL=$?
+           # move it to .vcache when complete
+           if [ $RETVAL -eq 0 ] ; then
+                # sanity check
+               vnewsize=$(du -s "$TMP" | awk "{ print \$1 }")
+               vrefsize=$(du -s "$VROOTDIR/vserver-reference" | awk "{ print \$1 }")
+               if [ $vnewsize -lt $vrefsize ] ; then
+                   echo "WARNING: Unexpected for 'du -s $VROOTDIR/$NAME'=$vnewsize to be less than 'du -s $VROOTDIR/vserver-reference'=$vrefsize"
+               fi
+
+               mv "$TMP" "$VROOTDIR/.vcache/v$i"
+               echo "$(date) v$i ready"
+           else
+               echo "$(date) Error $RETVAL building v$i"
+               rm -rf "$TMP"
+           fi
+       fi
+    done
+    # just run once
+    if [ $single -ne 0 ] ; then
+       break
+    fi
+    [ $debug -ne 0 ] && echo "$(date) Sleeping for $period seconds"
+    sleep $period
+done
index 79e553f..7aae608 100755 (executable)
@@ -30,7 +30,8 @@ USR_SBIN=$SBINDIR
 USR_LIB_VSERVER=$PKGLIBDIR
 
 VSERVER_CMD=$USR_SBIN/vserver
-CHBIND_CMD=$USR_SBIN/chbind
+WAITFOR_CMD="waitfor 60"
+VINIT_CMD=/etc/rc.vinit
 CHCONTEXT_CMD=$USR_SBIN/chcontext
 SAVE_S_CONTEXT_CMD=$USR_LIB_VSERVER/save_s_context
 CAPCHROOT_CMD=$USR_LIB_VSERVER/capchroot
@@ -74,114 +75,6 @@ testperm()
                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()
@@ -202,6 +95,28 @@ readlastconf()
        export PROFILE
        . /etc/vservers/$1.conf
 }
+
+# Wait for a process to finish for $1 seconds.
+waitfor()
+{
+       timeout=$1
+       shift
+       # Background the process.
+       $@ &
+       # Wait for it to finish.
+       while [ $timeout -gt 0 ] ; do
+               sleep 1
+               kill -0 $! 2>/dev/null || break
+               timeout=$(($timeout - 1))
+       done
+       # Try nicely terminating it, then just kill it.
+       if [ $timeout -eq 0 ] ; then
+               kill -TERM $! && kill -0 $! 2>/dev/null && kill -KILL $!
+       fi
+       # Cleanup.
+       wait
+}
+
 usage()
 {
        echo vserver [ options ] server-name command ...
@@ -224,10 +139,6 @@ usage()
        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"
 }
@@ -248,15 +159,11 @@ calculateCaps()
 }
 
 SILENT=
-NODEV=
 while true
 do
        if [ "$1" = "--silent" ] ; then
                SILENT=--silent
                shift
-       elif [ "$1" = "--nodev" ] ; then
-               NODEV=--nodev
-               shift
        else
                break
        fi
@@ -395,7 +302,8 @@ S_FLAGS="lock nproc"
 # ULIMIT="-HS -u 200"
 # The example above, combined with the nproc S_FLAGS will limit the
 # vserver to a maximum of 200 processes
-ULIMIT="-HS -u 1000"
+#ULIMIT="-HS -u 1000"
+ULIMIT=""
 # 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
@@ -443,15 +351,10 @@ elif [ "$2" = "start" ] ; then
        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 $VROOTDIR/$1 || exit 1
 
                if [ "$PROFILE" != "" ] ; then
@@ -539,12 +442,14 @@ elif [ "$2" = "start" ] ; then
                # We switch to $VROOTDIR/$1 now, because after the
                # security context switch $VROOTDIR directory becomes a dead zone.
                cd $VROOTDIR/$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
+               # XXX execute /etc/rc.vinit first for backward compatibility
+               for CMD in "$VINIT_CMD $2" "$STARTCMD" ; do
+                       $NICECMD \
+                               $CHCONTEXT_CMD $SILENT $DISCONNECT $CAPS $FLAGS $CTXOPT $HOSTOPT $DOMAINOPT --secure \
+                               $SAVE_S_CONTEXT_CMD /var/run/vservers/$1.ctx \
+                               $CAPCHROOT_CMD $CHROOTOPT . $CMD
+               done
                sleep 2
                test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-start $1
        fi
@@ -575,17 +480,12 @@ elif [ "$2" = "status" ] ; then
        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 $VROOTDIR/$1
                mountproc $VROOTDIR/$1
                # The fakeinit flag tell us how to turn off the server
@@ -625,11 +525,12 @@ elif [ "$2" = "stop" ] ; then
                calculateCaps $S_CAPS
 
                cd $VROOTDIR/$1
-               IPOPT=`setipopt $IPROOT`
                export PATH=$DEFAULTPATH
-               $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
-                       $CHCONTEXT_CMD $SILENT $CAPS --secure --ctx $S_CONTEXT \
-                       $CAPCHROOT_CMD . $STOPCMD
+               # XXX execute /etc/rc.vinit first for backward compatibility
+               for CMD in "$VINIT_CMD $2" "$STOPCMD" ; do
+                       $WAITFOR_CMD $CHCONTEXT_CMD $SILENT $CAPS --secure --ctx $S_CONTEXT \
+                               $CAPCHROOT_CMD . $CMD
+               done
 
                if test "$IS_MINIT"; then
                    echo "Waiting for minit finish-signal"
@@ -641,8 +542,7 @@ elif [ "$2" = "stop" ] ; then
                fi
 
                echo Killing all processes
-               $CHBIND_CMD --silent $IPOPT --bcast $IPROOTBCAST \
-                       $CHCONTEXT_CMD $CAPS --secure --silent --ctx $S_CONTEXT \
+               $CHCONTEXT_CMD $CAPS --secure --silent --ctx $S_CONTEXT \
                        $VSERVERKILLALL_CMD
        fi
        # We umount anyway, because "enter" establish the mount
@@ -650,7 +550,6 @@ elif [ "$2" = "stop" ] ; then
        umountproc $VROOTDIR/$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
@@ -667,14 +566,9 @@ elif [ "$2" = "suexec" ] ; then
                echo "vserver vserver-name suexec user command [ args ... ]" >&2
                exit 1
        else
-               IPROOT=
-               IPROOTMASK=
-               IPROOTBCAST=
-               IPROOTDEV=
                readlastconf $1
                . /etc/vservers/$1.conf
                cd $VROOTDIR/$1
-               ifconfig_iproot $1
                mountproc $VROOTDIR/$1
                PS1="[\u@vserver:$1 \W]"
                export PS1
@@ -718,10 +612,8 @@ elif [ "$2" = "suexec" ] ; then
                then
                        . /var/run/vservers/$VSERVER.ctx
                        cd $VROOTDIR/$VSERVER
-                       IPOPT=`setipopt $IPROOT`
                        export PATH=$DEFAULTPATH
-                       exec $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
-                               $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure --ctx $S_CONTEXT \
+                       exec $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
@@ -740,10 +632,8 @@ elif [ "$2" = "suexec" ] ; then
                        fi
                        mkdir -p /var/run/vservers
                        cd $VROOTDIR/$VSERVER
-                       IPOPT=`setipopt $IPROOT`
                        export PATH=$DEFAULTPATH
-                       exec $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
-                               $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \
+                       exec $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \
                                $SAVE_S_CONTEXT_CMD /var/run/vservers/$VSERVER.ctx \
                                $CAPCHROOT_CMD --suid $USERID $CHROOTOPT . "$@"
                fi
@@ -751,15 +641,15 @@ elif [ "$2" = "suexec" ] ; then
 elif [ "$2" = "exec" ] ; then
        VSERV=$1
        shift; shift
-       exec $0 $NODEV $SILENT $VSERV suexec root "$@"
+       exec $0 $SILENT $VSERV suexec root "$@"
 elif [ "$2" = "enter" ] ; then
        testperm $1
-       exec $0 $NODEV $SILENT $1 exec /bin/bash -login
+       exec $0 $SILENT $1 exec /bin/bash -login
 elif [ "$2" = "service" ] ; then
        VSERVER=$1
        shift
        shift
-       exec $0 $NODEV $SILENT $VSERVER exec /sbin/service "$@"
+       exec $0 $SILENT $VSERVER exec /sbin/service "$@"
 elif [ "$2" = "chkconfig" ] ; then
        VSERVER=$1
        LEVELS=()
diff --git a/scripts/vuseradd b/scripts/vuseradd
new file mode 100755 (executable)
index 0000000..2be0ac9
--- /dev/null
@@ -0,0 +1,98 @@
+#!/bin/bash
+#
+# useradd(8) wrapper for vservers
+#
+# Copyright (c) 2004  The Trustees of Princeton University (Trustees).
+#
+# $Id: vuseradd,v 1.21 2005/04/26 21:23:28 mlhuang Exp $
+#
+
+: ${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 "usage: $0 name"
+    exit 1
+}
+
+[ -z "$1" ] && usage
+[ "$1" == "--static" ] && { STATIC=yes; shift; }
+NAME=$1
+
+# add slices group if not already present
+groupadd slices 2>/dev/null || :
+
+# add user
+[ -z "$STATIC" ] && useradd -g slices -s /bin/vsh $NAME
+
+# openssh-server 3.8 and above refuse login for "locked" accounts
+sed -i -e "s/$NAME:\!\!:\(.*\)/$NAME:*:\1/" /etc/shadow
+
+USERID=`id -u $NAME`
+GROUPID=`id -g $NAME`
+GROUPNAME=`id -gn $NAME`
+
+# create vserver configuration file
+if [ ! -f /etc/vservers/$NAME.conf ] ; then
+    sed \
+       -e "s/.*S_CONTEXT=.*/S_CONTEXT=$USERID/" \
+       -e "s/.*ONBOOT=.*/ONBOOT=yes/" \
+       < $PKGLIBDIR/sample.conf \
+       > /etc/vservers/$NAME.conf
+fi
+
+if [ ! -d "$VROOTDIR/$NAME" ] ; then
+    # check the cache
+    shopt -s nullglob
+    for i in "$VROOTDIR/.vcache/"* ; do
+       [ -d "$i" ] && mv "$i" "$VROOTDIR/$NAME" && break
+    done
+    # build vserver
+    if [ ! -d "$VROOTDIR/$NAME" ] ; then
+       # build image in .vtmp
+       TMP=$(mktemp -d "$VROOTDIR/.vtmp/$NAME.XXXXXX")
+       "$PKGLIBDIR/vbuild" "$VROOTDIR/vserver-reference" "$TMP"
+       RETVAL=$?
+       # move it to .vcache when complete
+       if [ $RETVAL -ne 0 ] ; then 
+           echo "Error $RETVAL building $VROOTDIR/$NAME"
+           rm -rf "$TMP" /etc/vservers/$NAME.conf /var/run/vservers/$NAME.ctx
+           userdel -r $NAME
+           exit $RETVAL
+       else
+           # sanity check
+           vnewsize=$(du -s "$TMP" | awk "{ print \$1 }")
+           vrefsize=$(du -s "$VROOTDIR/vserver-reference" | awk "{ print \$1 }")
+           if [ $vnewsize -lt $vrefsize ] ; then
+               echo "WARNING: Unexpected for 'du -s $VROOTDIR/$NAME'=$vnewsize to be less than 'du -s $VROOTDIR/vserver-reference'=$vrefsize"
+           fi
+
+           mv "$TMP" "$VROOTDIR/$NAME"
+       fi
+    fi
+fi
+
+if [ -d "$VROOTDIR/$NAME" ] ; then
+    # fix permissions
+    chmod 755 "$VROOTDIR/$NAME"
+
+    # add user in vserver
+    vserver $NAME suexec root groupadd -g $GROUPID $GROUPNAME
+    vserver $NAME suexec root useradd -u $USERID -g $GROUPID -p '' $NAME
+
+    # add an unrestricted entry to /etc/sudoers file
+    if [ -f "$VROOTDIR/$NAME/etc/sudoers" ] && \
+       ! grep -q "^$NAME" "$VROOTDIR/$NAME/etc/sudoers" ; then
+       echo "$NAME     ALL=(ALL)       ALL" >> "$VROOTDIR/$NAME/etc/sudoers"
+    fi
+fi
+
+# turn resource management on for vserver $NAME
+service resman start $NAME
+# XXX - resman doesn't print a trailing newline
+echo
diff --git a/scripts/vuserdel b/scripts/vuserdel
new file mode 100755 (executable)
index 0000000..24d4bd6
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/bash
+#
+# userdel(8) wrapper for vservers
+#
+# Copyright (c) 2004  The Trustees of Princeton University (Trustees).
+#
+# $Id: vuserdel,v 1.7 2005/04/07 19:37:25 smuir Exp $
+#
+
+: ${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 "usage: $0 name"
+    exit 1
+}
+
+[ -z "$1" ] && usage
+[ "$1" == "--static" ] && { STATIC=yes; shift; }
+NAME=$1
+
+# read config file to get context ID
+. /etc/vservers/$NAME.conf
+CTX=$S_CONTEXT
+
+# don't bother stopping gracefully, just kill all the processes
+$SBINDIR/chcontext --silent --secure --ctx $CTX $PKGLIBDIR/vserverkillall
+
+# unmount any directories in vserver that are mount points
+for d in `sed -ne "s%^[^ ]* \($VROOTDIR/$NAME/[^ ]*\) .*%\1%p" /proc/mounts`
+do
+        # use echo -e to turn escaped whitespace back into regular chars
+        # be careful about embedded backquotes here (i think we're safe)
+        dir=`echo -e "$d"`
+        echo "unmounting $dir"
+        umount -l "$dir"
+done
+
+# turn resource management off for vserver $NAME
+service resman stop $NAME
+# XXX - resman doesn't print a trailing newline
+echo
+
+# delete user
+[ -z "$STATIC" ] && userdel -r $NAME
+
+# remove vserver configuration file
+rm -f /etc/vservers/$NAME.conf
+
+# remove vserver profile
+rm -f /var/run/vservers/$NAME.ctx
+
+# destroy vserver
+if [ -d $VROOTDIR/$NAME ] ; then
+    TMP=$(mktemp -d "$VROOTDIR/.vtmp/$NAME.XXXXXX")
+    mv "$VROOTDIR/$NAME" "$TMP"
+    rm -rf "$TMP"
+fi
index 2d2586e..695aea8 100644 (file)
@@ -39,8 +39,10 @@ src_sbin_PRGS                =  src/chbind \
                           src/chcontext \
                           src/rebootmgr \
                           src/reducecap \
-                          src/vlimit \
                           src/vdu \
+                          src/vsh \
+                          src/vdlimit \
+                          src/vlimit \
                           src/vfiles \
                           src/vkill \
                           src/vserver-stat
@@ -76,6 +78,12 @@ src_vkill_SOURCES            =  src/vkill.c
 src_vkill_LDADD                        =  lib/libvserver.a
 src_vkill_CPPFLAGS             =  $(AM_CPPFLAGS) -DLEGACYDIR=\"$(legacydir)\"
 
+src_vsh_SOURCES                        =  src/vsh.c
+src_vsh_LDADD                  =  lib/libvserver.a
+
+src_vdlimit_SOURCES            =  src/vdlimit.c
+src_vdlimit_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
index 236e0cc..1b5275a 100644 (file)
@@ -122,6 +122,7 @@ int main (int argc, char *argv[])
        unsigned remove_cap = 0;
        unsigned add_cap = 0;
        unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
+               |(1<<CAP_NET_BIND_SERVICE)
                |(1<<CAP_NET_BROADCAST)
                |(1<<CAP_NET_ADMIN)
                |(1<<CAP_NET_RAW)
diff --git a/src/dlimit.h b/src/dlimit.h
new file mode 100644 (file)
index 0000000..5cbb1a1
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef _VX_DLIMIT_H
+#define _VX_DLIMIT_H
+
+#include "virtual.h"
+// #include "switch.h"
+
+/*  inode vserver commands */
+
+#define VCMD_add_dlimit                VC_CMD(DLIMIT, 1, 0)
+#define VCMD_rem_dlimit                VC_CMD(DLIMIT, 2, 0)
+
+#define VCMD_set_dlimit                VC_CMD(DLIMIT, 5, 0)
+#define VCMD_get_dlimit                VC_CMD(DLIMIT, 6, 0)
+
+
+struct  vcmd_ctx_dlimit_base_v0 {
+       char *name;
+       uint32_t flags;
+};
+
+struct  vcmd_ctx_dlimit_v0 {
+       char *name;
+       uint32_t space_used;                    /* used space in kbytes */
+       uint32_t space_total;                   /* maximum space in kbytes */
+       uint32_t inodes_used;                   /* used inodes */
+       uint32_t inodes_total;                  /* maximum inodes */
+       uint32_t reserved;                      /* reserved for root in % */
+       uint32_t flags;
+};
+
+#define CDLIM_UNSET             (0ULL)
+#define CDLIM_INFINITY          (~0ULL)
+#define CDLIM_KEEP              (~1ULL)
+
+
+#ifdef __KERNEL__
+
+struct super_block;
+
+struct dl_info {
+       struct hlist_node dl_hlist;             /* linked list of contexts */
+       struct rcu_head dl_rcu;                 /* the rcu head */
+       xid_t dl_xid;                           /* context id */
+       atomic_t dl_usecnt;                     /* usage count */
+       atomic_t dl_refcnt;                     /* reference count */
+
+       struct super_block *dl_sb;              /* associated superblock */
+
+       struct rw_semaphore dl_sem;             /* protect the values */
+
+       uint64_t dl_space_used;                 /* used space in bytes */
+       uint64_t dl_space_total;                /* maximum space in bytes */
+       uint32_t dl_inodes_used;                /* used inodes */
+       uint32_t dl_inodes_total;               /* maximum inodes */
+
+       unsigned int dl_nrlmult;                /* non root limit mult */
+};
+
+extern void rcu_free_dl_info(void *);
+extern void unhash_dl_info(struct dl_info *);
+
+struct kstatfs;
+
+extern void vx_vsi_statfs(struct super_block *, struct kstatfs *);
+
+
+extern int vc_add_dlimit(uint32_t, void __user *);
+extern int vc_rem_dlimit(uint32_t, void __user *);
+
+extern int vc_set_dlimit(uint32_t, void __user *);
+extern int vc_get_dlimit(uint32_t, void __user *);
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _VX_DLIMIT_H */
index c9d1055..1d7783e 100644 (file)
 
 
 // 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
+#ifndef EXT2_IUNLINK_FL
+/* Set both bits for backward compatibility */
+#define EXT2_IUNLINK_FL 0x08008000
+#endif
+
+#ifndef EXT2_BARRIER_FL
+#define EXT2_BARRIER_FL 0x04000000
 #endif
 
 /*
@@ -108,22 +112,36 @@ int main (int argc, char *argv[])
                        }
                }
        }else if (strstr(argv[0],"setattr")!=NULL){
-               long flags = 0;
+               long flags, add_flags = 0, remove_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;
+                                       add_flags |= EXT2_IMMUTABLE_FL;
+                               }else if (strcmp(arg,"--!immutable")==0 || strcmp(arg,"--~immutable")==0){
+                                       remove_flags |= EXT2_IMMUTABLE_FL;
                                }else if (strcmp(arg,"--immulink")==0){
-                                       flags |= EXT2_IMMUTABLE_LINK_FL;
+                                       add_flags |= EXT2_IUNLINK_FL;
+                               }else if (strcmp(arg,"--!immulink")==0 || strcmp(arg,"--~immulink")==0){
+                                       remove_flags |= EXT2_IUNLINK_FL;
+                               }else if (strcmp(arg,"--barrier")==0){
+                                       add_flags |= EXT2_BARRIER_FL;
+                               }else if (strcmp(arg,"--!barrier")==0 || strcmp(arg,"--~barrier")==0){
+                                       remove_flags |= EXT2_BARRIER_FL;
                                }else{
                                        fprintf (stderr,"Invalid option %s\n",arg);
                                        ret = -1;
                                        break;
                                }
                        }else{
+                               ret = getext2flags (arg,&flags);
+                               if (ret == -1){
+                                       break;
+                               }
+                               flags |= add_flags;
+                               flags &= ~remove_flags;
                                ret = setext2flags (arg,flags);
                                if (ret == -1){
                                        break;
index ed27809..dcaaa9f 100644 (file)
@@ -51,7 +51,7 @@ struct EXCLDIR{
 static vector<EXCLDIR> excldirs;
 
 
-static int  ext2flags = EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL;
+static int  ext2flags = EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL;
 static struct {
        int nblink;
        int nbcopy;
@@ -228,9 +228,9 @@ int main (int argc, char *argv[])
                }else if (strcmp(arg,"--noflags")==0){
                        ext2flags = 0;
                }else if (strcmp(arg,"--immutable")==0){
-                       ext2flags |= EXT2_IMMUTABLE_FILE_FL;
+                       ext2flags |= EXT2_IMMUTABLE_FL;
                }else if (strcmp(arg,"--immutable-mayunlink")==0){
-                       ext2flags |= EXT2_IMMUTABLE_LINK_FL;
+                       ext2flags |= EXT2_IUNLINK_FL;
                }else if (strcmp(arg,"--excldir")==0){
                        i++;
                        excldirs.push_back (EXCLDIR(argv[i]));
index 55f6082..b6cfc59 100644 (file)
--- a/src/vdu.c
+++ b/src/vdu.c
@@ -1,4 +1,4 @@
-// $Id: vdu.c,v 1.1 2003/09/29 22:01:57 ensc Exp $
+// $Id: vdu-new.c,v 1.2 2004/08/17 14:44:14 mef-pl_kernel Exp $
 
 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
 // based on vdu.cc by Jacques Gelinas
@@ -17,6 +17,8 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
+#define _LARGEFILE64_SOURCE
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <dirent.h>
 #include <errno.h>
 #include <string.h>
+#include <sys/ioctl.h>
+
+#include <assert.h>
+
+#include "vdu.h"
+
+HashTable tbl;
+
+static int // boolean
+INOPut(PHashTable tbl, ino64_t* key, struct stat64 **val){
+    return Put(tbl, key, val);
+}
 
 __extension__ typedef long long                longlong;
+//__extension__ typedef long           longlong;
+
+static longlong inodes;
+static longlong blocks;
+static longlong size;
+
+static short verbose = 0;
+
+static inline void warning(char *s) {
+    fprintf(stderr,"%s (%s)\n",s,strerror(errno));    
+}
+
+void panic(char *s) {
+    warning(s);
+    exit(2);
+}
 
-static int vdu_onedir (char const *path, longlong *size)
+static void vdu_onedir (char const *path)
 {
-       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;
+    char const *foo = path;
+    struct stat64 dirst, st;
+    struct dirent *ent;
+    char *name;
+    DIR *dir;
+    int dirfd;
+    longlong dirsize, dirinodes, dirblocks;
+
+    dirsize = dirinodes = dirblocks = 0;
+
+    // A handle to speed up chdir
+    if ((dirfd = open (path,O_RDONLY)) == -1) {
+       fprintf (stderr,"Can't open directory %s\n",path);
+       panic("open failed");
+    }
+
+    if (fchdir (dirfd) == -1) {
+       fprintf (stderr,"Can't fchdir directory %s\n",path);
+       panic("fchdir failed");
+    }
+
+    if (fstat64 (dirfd,&dirst) != 0) {
+       fprintf (stderr,"Can't lstat directory %s\n",path);
+       panic("lstat failed");
+    }
+
+    if ((dir = opendir (".")) == NULL) {
+       fprintf (stderr,"Can't open (opendir) directory %s\n",path);
+       panic("opendir failed");
+    }
+
+
+    /* Walk the directory entries and compute the sum of inodes,
+     * blocks, and disk space used. This code will recursively descend
+     * down the directory structure. 
+     */
+
+    while ((ent=readdir(dir))!=NULL){
+       if (lstat64(ent->d_name,&st)==-1){
+           fprintf (stderr,"Can't stat %s/%s\n",path,ent->d_name);
+           warning("lstat failed");
+           continue;
+       }
+       
+       dirinodes ++;
+
+       if (S_ISREG(st.st_mode)){
+           if (st.st_nlink > 1){
+               struct stat64 *val;
+               int nlink;
+
+               /* Check hash table if we've seen this inode
+                * before. Note that the hash maintains a
+                * (inode,struct stat) key value pair.
+                */
+
+               val = &st;
+
+               (void) INOPut(&tbl,&st.st_ino,&val);
+
+               /* Note that after the INOPut call "val" refers to the
+                * value entry in the hash table --- not &st.  This
+                * means that if the inode has been put into the hash
+                * table before, val will refer to the first st that
+                * was put into the hashtable.  Otherwise, if it is
+                * the first time it is put into the hash table, then
+                * val will be equal to this &st.
+                */
+               nlink = val->st_nlink;
+               nlink --;
+
+               /* val refers to value in hash tbale */
+               if (nlink == 0) {
+
+                   /* We saw all hard links to this particular inode
+                    * as part of this sweep of vdu. So account for
+                    * the size and blocks required by the file.
+                    */
+
+                   dirsize += val->st_size;
+                   dirblocks += val->st_blocks;
+
+                   /* Do not delete the (ino,val) tuple from the tbl,
+                    * as we need to handle the case when we are
+                    * double counting a file due to a bind mount.
+                    */
+                   val->st_nlink = 0;
+
+               } else if (nlink > 0) {
+                   val->st_nlink = nlink;
+               } else /* if(nlink < 0) */ {
+                   /* We get here when we are double counting nlinks
+                      due a bind mount. */
+
+                   /* DO NOTHING */
+               }
+           } else {
+               dirsize += st.st_size;
+               dirblocks += st.st_blocks;
+           }
+
+       } else if (S_ISDIR(st.st_mode)) {
+           if ((st.st_dev == dirst.st_dev) &&
+               (strcmp(ent->d_name,".")!=0) &&
+               (strcmp(ent->d_name,"..")!=0)) {
+
+               dirsize += st.st_size;
+               dirblocks += st.st_blocks;
+
+               name = strdup(ent->d_name);
+               if (name==0) {
+                   panic("Out of memory\n");
                }
-               close (dirfd);
+               vdu_onedir(name);
+               free(name);
+               fchdir(dirfd);
+           }
+       } else {
+           // dirsize += st.st_size;
+           // dirblocks += st.st_blocks;
        }
-       return ret;
+    }
+    closedir (dir);
+    close (dirfd);
+    if (verbose)
+       printf("%16lld %16lld %16lld %s\n",dirinodes, dirblocks, dirsize,foo);
+    inodes += dirinodes;
+    blocks += dirblocks;
+    size   += dirsize;
 }
 
-int main (int argc, char *argv[])
+static void
+Count(ino64_t* key, struct stat64* val) {
+    if(val->st_nlink) {
+       blocks += val->st_blocks;
+       size += val->st_size;
+       printf("ino=%16lld nlink=%d\n",val->st_ino, val->st_nlink);
+    }
+}
+
+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);
-               }
+    int startdir, i;
+
+    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.\n");
+    }else{
+       if ((startdir = open (".",O_RDONLY)) == -1) {
+           fprintf (stderr,"Can't open current working directory\n");
+           panic("open failed");
        }
-       return ret;
+
+       /* hash table support for hard link count */
+       (void) Init(&tbl,0,0);
+
+       for (i=1; i<argc; i++){
+           inodes = blocks = size = 0;
+           vdu_onedir (argv[i]);
+
+           printf("%16lld %16lld %16lld %s\n",
+                  inodes, 
+                  blocks>>1, 
+                  size,
+                  argv[i]);
+           if (fchdir (startdir) == -1) {
+               panic("fchdir failed");
+           }
+       }
+
+       if(0) {
+           /* show size & blocks for files with nlinks from outside of dir */
+           inodes = blocks = size = 0;
+           Iterate(&tbl,Count);
+           printf("%16lld %16lld %16lld NOT COUNTED\n",
+                  inodes, 
+                  blocks, 
+                  size);
+       }
+
+       // Dispose(&tbl); this fails to delete all entries 
+       close(startdir);
+    }
+    return 0;
 }
 
+/*
+ * Local variables:
+ *  c-basic-offset: 4
+ * End:
+ */
diff --git a/src/vdu.h b/src/vdu.h
new file mode 100644 (file)
index 0000000..5405a59
--- /dev/null
+++ b/src/vdu.h
@@ -0,0 +1,374 @@
+#ifndef __VDU_H
+#define __VDU_H
+
+typedef ino64_t KEY;
+typedef KEY *PKEY;
+typedef struct stat64 VAL;
+typedef VAL *PVAL;
+
+static inline
+unsigned int
+HASH(PKEY key){
+    return (int) *key;
+}
+
+static inline
+unsigned int // boolean
+EQUAL(PKEY key1, PKEY key2){
+    return *key1 == *key2;
+}
+
+#ifndef MIN
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#endif // MIN
+
+#ifndef MAX
+#define MAX(x,y) (((x)>(y))?(x):(y))
+#endif // MAX
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+// hash table support for efficient lookup of duplicate inodes */
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+#define Multiplier  (0x9e3779b9)
+#define MaxLogBuckets  (((sizeof (unsigned long))*8) - 2)
+#define MaxBuckets     (1<<MaxLogBuckets)
+#define MinLogBuckets  (4)
+#define MinBuckets     (1<<MinLogBuckets)
+
+// Thresholds for rehashing the table: *)
+// to avoid crazy oscillations, we must have MaxDensity > 2*MinDensity; *)
+// to avoid excessive probes, we must try to keep MaxDensity low. *)
+// Divide by 100 before using
+#define MaxDensity 75 /* max numEntries/NUMBER(buckets) */
+#define MinDensity 20 /* min numEntries/NUMBER(buckets) */
+#define IdealDensity 50
+#define BITSIZE(x) (sizeof(x)*8)
+
+#define NEW(type,num) ((type*)malloc(sizeof(type)*num))
+#define DISPOSE(ptr) (free((void*)ptr))
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+// Generic Hash Entry Type
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+typedef struct VoidList {
+  struct VoidList *tail;
+} VoidList, *PVoidList;
+
+typedef struct HashTable {
+  PVoidList *buckets;
+  unsigned int numBuckets;    // number of buckets
+  unsigned int minLogBuckets; // minimum value for Log_2(initial size) 
+  unsigned int logBuckets;    // CEILING(Log2(NUMBER(buckets^))) 
+  unsigned int maxEntries;    // maximum number of entries 
+  unsigned int minEntries;    // minimum number of entries 
+  unsigned int numEntries;    // current num of entries in table 
+  PVoidList cache;            // cache of removed elements 
+  int cacheSize;              // current size of the cache 
+  int maxCacheSize;           // maximum size, -1 means unbounded, 0 no cache 
+} HashTable, *PHashTable;
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+// Hash Prototypes
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+PHashTable
+Init(PHashTable tbl, unsigned int n, int maxCacheSize);
+
+void
+Dispose(PHashTable tbl);
+
+unsigned int
+Log_2(unsigned int x);
+
+void
+NewBuckets(PHashTable tbl, unsigned int logBuckets);
+
+//
+// Generic Hash Table support
+//
+
+PHashTable
+Init(PHashTable tbl, unsigned int n, int maxCacheSize){
+  int idealBuckets;
+  int minBuckets;
+  
+  idealBuckets = MIN(((n*100)/IdealDensity),MaxBuckets);
+  minBuckets = MAX(MinBuckets, idealBuckets);
+  tbl->minLogBuckets = Log_2(minBuckets);
+
+  NewBuckets(tbl, tbl->minLogBuckets);
+  tbl->numEntries = 0;
+  tbl->maxCacheSize = maxCacheSize;
+  tbl->cacheSize = 0;
+  tbl->cache = 0;
+  return tbl;
+} // Init()
+
+
+//
+// Internal procedures
+//
+
+unsigned int
+Log_2(unsigned int x){
+  // return CEILING(LOG_2(x))
+  unsigned int log = 0;
+  unsigned int n= 1;
+
+  assert(x != 0);
+  while ((log < MaxLogBuckets) && (x > n)){
+    log++; 
+    n += n;
+  }
+  return log;
+} // Log_2()
+
+void
+NewBuckets(PHashTable tbl, unsigned int logBuckets){
+  // Allocate "2^logBuckets" buckets.
+  unsigned int numBuckets = 1 << logBuckets;
+  PVoidList *b;
+  unsigned int i;
+
+  tbl->buckets = NEW(PVoidList, numBuckets);
+  tbl->numBuckets = numBuckets;
+  b = tbl->buckets;
+
+  for (i=0; i<tbl->numBuckets; i++){
+    b[i] = NULL;
+  }
+  tbl->logBuckets = logBuckets;
+  tbl->maxEntries = MaxDensity * numBuckets / 100;
+  tbl->minEntries = MinDensity * numBuckets / 100;
+} // NewBuckets()
+
+#ifndef NULL
+#define NULL (void*)0
+#endif // !NULL
+
+#ifndef TRUE
+#define TRUE 1
+#endif // !TRUE
+
+#ifndef FALSE
+#define FALSE 0
+#endif // !FALSE
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+// Type specific hash entry
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+typedef struct EntryList {
+  struct EntryList *tail;
+  KEY key;
+  VAL val;
+}EntryList, *PEntryList;
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+// Type specific Hash implementation functions
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+static
+void
+Rehash(PHashTable tbl, unsigned int logBuckets) {
+  // Reallocate "2^logBuckets" buckets, and rehash the entries into
+  // the new table.
+
+  PVoidList *oldBucketPointer;
+  PEntryList *ob, obi;
+  PEntryList *nb, *nbh;
+  PEntryList that, tail;
+  unsigned int index; 
+  unsigned int i;
+  unsigned int oldNumBuckets;
+
+  return;
+  assert(logBuckets <= MaxLogBuckets);
+  assert(logBuckets >= tbl->minLogBuckets);
+  oldBucketPointer = tbl->buckets;
+  ob = (PEntryList*)tbl->buckets;
+  oldNumBuckets = tbl->numBuckets;
+
+  NewBuckets(tbl, logBuckets);
+  nb = (PEntryList*)tbl->buckets;
+
+  for(i=0;i<oldNumBuckets;i++){
+    obi = ob[i];
+    that = obi;
+    while (that != NULL) {
+      index = (HASH(&(that->key))*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets);
+      nbh = &(nb[index]);
+      tail = that->tail;
+      that->tail = *nbh;
+      *nbh = that;
+      that = tail;
+    }
+  }
+  DISPOSE (oldBucketPointer);
+}
+
+static inline
+unsigned int // boolean
+Get(PHashTable tbl, PKEY key, PVAL *val){
+  PEntryList that;
+  unsigned int index;
+
+  index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets);
+  that = (PEntryList)tbl->buckets[index];
+  while ((that != NULL) && !EQUAL(key,&(that->key))) {
+    that = that->tail;
+  }
+  if (that != NULL){
+    *val = &that->val;
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+} // Get()
+
+static inline 
+unsigned int // boolean
+Put(PHashTable tbl, PKEY key, PVAL *val){
+  PEntryList that;
+  PEntryList *first;
+  unsigned int index;
+  unsigned int res;
+
+  index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets);
+  first = (PEntryList*)&(tbl->buckets[index]);
+  that = *first;
+  while ((that != NULL) && !EQUAL(key, &(that->key))){
+    that = that->tail;
+  }
+  
+  // found an entry in the hash table given above key
+  if (that != NULL){
+    res = TRUE;
+  }
+  else {
+    // check if we can reuse something from the cache
+    if (tbl->cache != NULL) {
+          that = (PEntryList)tbl->cache;
+          tbl->cache = (PVoidList)tbl->cache->tail;
+          that->key = *key;
+          that->tail = *first;
+          *first = that;
+    }
+    else {
+          that = NEW(EntryList,1);
+         that->key = *key;
+         that->tail = *first;
+         *first = that;
+    }
+    that->val = **val;
+
+    tbl->numEntries++;
+    if ((tbl->logBuckets < MaxLogBuckets)
+       && (tbl->numEntries > tbl->maxEntries)){
+      Rehash(tbl, tbl->logBuckets + 1); // too crowded
+    }
+    res = FALSE;
+  }
+  *val = &that->val;
+  return res;
+
+} // Put()
+
+static inline
+int
+Delete(PHashTable tbl,PKEY key){
+  PEntryList that, prev;
+  PEntryList *first;
+  unsigned int index;
+
+  index = (HASH(key)*Multiplier)>>(BITSIZE(unsigned long)-tbl->logBuckets);
+  first = (PEntryList*)&(tbl->buckets[index]);
+  that = *first;
+  prev = NULL;
+
+  while ((that != NULL) && !EQUAL(key, &(that->key))){
+    prev = that;
+    that = that->tail;
+  }
+  if (that != NULL) {
+    if (prev == NULL) {
+      *first = that->tail;
+    }
+    else {
+      prev->tail = that->tail;
+    }
+    if ((tbl->maxCacheSize == -1)||(tbl->cacheSize < tbl->maxCacheSize)) {
+      that->tail = (PEntryList)tbl->cache;
+      tbl->cache = (PVoidList)that;
+      tbl->cacheSize++;
+    }
+    else {
+      DISPOSE (that);
+    }
+    tbl->numEntries--;
+    if (tbl->maxCacheSize == 0) {
+      if ((tbl->logBuckets > tbl->minLogBuckets)
+         && (tbl->numEntries < tbl->minEntries)) {
+       Rehash(tbl, tbl->logBuckets - 1); // too sparse
+      }
+    }
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+} // Delete()
+
+typedef void (*callback)(PKEY key, PVAL val);
+
+void
+Iterate(PHashTable tbl, callback fn)
+{
+  PVoidList that;
+  unsigned int i;
+  
+  for(i=0;i<tbl->numBuckets;i++) {
+    that = tbl->buckets[i];
+    while ( that != (PVoidList)0 ) {
+      PEntryList entry = (PEntryList)that;
+      fn(&entry->key,&entry->val);
+      that = that->tail;
+    }
+  }
+}
+
+void
+Dispose(PHashTable tbl)
+{
+  PVoidList that, next;
+  unsigned int i;
+
+  for(i=0;i<tbl->numBuckets;i++) {
+    that = tbl->buckets[i];
+    while( that != NULL) {
+        next = that->tail;
+        DISPOSE (that);
+        tbl->numEntries--;
+        that = next;
+    }
+  }
+  DISPOSE(tbl->buckets);
+  assert(tbl->numEntries = 0);
+} // Dispose;
+
+
+
+#endif // __VDU_H
index 44fe511..6fd955b 100644 (file)
@@ -195,7 +195,7 @@ int main (int argc, char *argv[])
 
       if (set_mask & 1) limits[id].min  = val;
       if (set_mask & 2) limits[id].soft = val;
-      if (set_mask & 4) limits[id].soft = val;
+      if (set_mask & 4) limits[id].hard = val;
 
       lim_mask |= (1<<id);
       set_mask  = 0;
diff --git a/src/vsh.c b/src/vsh.c
new file mode 100644 (file)
index 0000000..084e1cc
--- /dev/null
+++ b/src/vsh.c
@@ -0,0 +1,645 @@
+/*
+ * Marc E. Fiuczynski <mef@cs.princeton.edu>
+ *
+ * Copyright (c) 2004 The Trustees of Princeton University (Trustees).
+ *
+ * vsh 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.
+ *
+ * vsh 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 Poptop; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+#include "compat.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <syscall.h>
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+//--------------------------------------------------------------------
+#include "linuxcaps.h"
+#include "vserver.h"
+
+/* Null byte made explicit */
+#define NULLBYTE_SIZE                    1
+
+/* Base for all vserver roots for chroot */
+#define VSERVER_ROOT_BASE       "/vservers"
+
+/* Change to root:root (before entering new context) */
+static int setuidgid_root()
+{
+       if (setgid(0) < 0) {
+               fprintf(stderr, "setgid error\n");
+               return -1;
+       }
+       if (setuid(0) < 0) {
+               fprintf(stderr, "setuid error\n");
+               return -1;
+       }
+       return 0;
+}
+
+static void compute_new_root(char *base, char **root, uid_t uid)
+{
+       int             root_len;
+       struct passwd   *pwd;
+
+       if ((pwd = getpwuid(uid)) == NULL) {
+               perror("vserver: getpwuid error ");
+               exit(1);
+       }
+
+       root_len = 
+               strlen(base) + strlen("/") +
+               strlen(pwd->pw_name)      + NULLBYTE_SIZE;
+       (*root) = (char *)malloc(root_len);
+       if ((*root) == NULL) {
+               perror("vserver: malloc error ");
+               exit(1);
+       }
+    
+       sprintf((*root), "%s/%s", base, pwd->pw_name);
+       (*root)[root_len - 1] = '\0';
+}
+
+/* Example: sandbox_root = /vservers/bnc, relpath = /proc/1 */
+static int sandbox_file_exists(char *sandbox_root, char *relpath)
+{
+       struct stat stat_buf;
+       char   *file;
+       int    len, exists = 0;
+
+       len = strlen(sandbox_root) + strlen(relpath) + NULLBYTE_SIZE;
+       if ((file = (char *)malloc(len)) == NULL) {
+               perror("vserver: malloc error ");
+               exit(1);
+       }
+       sprintf(file, "%s%s", sandbox_root, relpath);
+       file[len - 1] = '\0';
+       if (stat(file, &stat_buf) == 0) {
+               exists = 1;
+       }
+
+
+       free(file);
+       return exists;
+}
+
+static int proc_mounted(char *sandbox_root)
+{
+       return sandbox_file_exists(sandbox_root, "/proc/1");
+}
+
+static int devpts_mounted(char *sandbox_root)
+{
+       return sandbox_file_exists(sandbox_root, "/dev/pts/0");
+}
+
+static void mount_proc(char *sandbox_root,uid_t uid)
+{
+       char        *source = "/proc";
+       char        *target;
+       int         len;
+
+       len = strlen(sandbox_root) + strlen("/") + strlen("proc") + NULLBYTE_SIZE;
+       if ((target = (char *)malloc(len)) == NULL) {
+               perror("vserver: malloc error ");
+               exit(1);
+       }
+
+       sprintf(target, "%s/proc", sandbox_root);
+       target[len - 1] = '\0';
+       if (!proc_mounted(sandbox_root))
+               mount(source, target, "proc", MS_BIND | MS_RDONLY, NULL);
+
+       free(target);
+}
+
+static void mount_devpts(char *sandbox_root)
+{
+       char        *source = "/dev/pts";
+       char        *target;
+       int         len;
+    
+       len = strlen(sandbox_root) + strlen("/") + strlen("dev/pts") + NULLBYTE_SIZE;
+       if ((target = (char *)malloc(len)) == NULL) {
+               perror("vserver: malloc error ");
+               exit(1);
+       }
+
+       sprintf(target, "%s/dev/pts", sandbox_root);
+       target[len - 1] = '\0';
+       if (!devpts_mounted(sandbox_root))
+               mount(source, target, "devpts", 0, NULL);
+
+       free(target);
+}
+
+static int sandbox_chroot(uid_t uid)
+{
+       char *sandbox_root = NULL;
+
+       compute_new_root(VSERVER_ROOT_BASE,&sandbox_root, uid);
+       mount_proc(sandbox_root,uid);
+       mount_devpts(sandbox_root);
+       if (chroot(sandbox_root) < 0) {
+               fprintf(stderr,"vserver: chroot error (%s): ",sandbox_root);
+               perror("");
+               exit(1);
+       }
+       if (chdir("/") < 0) {
+               perror("vserver: chdir error ");
+               exit(1);
+       }
+       return 0;
+}
+
+#ifndef CAP_CONTEXT
+#  define CAP_CONTEXT  29
+#endif
+
+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},
+       {"CAP_CONTEXT",         CAP_CONTEXT},
+       {NULL,0}
+};
+
+#define VSERVERCONF "/etc/vservers/"
+static unsigned get_remove_cap(char *name) {
+       FILE     *fb;
+       unsigned remove_cap;
+
+       char *vserverconf;
+       int vserverconflen;
+
+       remove_cap = /* NOTE: keep in sync with chcontext.c */
+               (1<<CAP_LINUX_IMMUTABLE)|
+               (1<<CAP_NET_BIND_SERVICE)|
+               (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)|
+               (1<<CAP_CONTEXT)|
+               0
+               ;
+
+       /*
+        * find out which capabilities to put back in by reading the conf file 
+        */
+
+       /* construct the pathname to the conf file */
+       vserverconflen = strlen(VSERVERCONF) + strlen(name) + strlen(".conf") + NULLBYTE_SIZE;
+       vserverconf    = (char *)malloc(vserverconflen);        
+       sprintf(vserverconf, "%s%s.conf", VSERVERCONF, name);
+       
+       /* open the conf file for reading */
+       fb = fopen(vserverconf,"r");
+       if (fb != NULL) {
+               unsigned cap;
+               size_t index;
+               size_t len;
+               char buffer[1000], *p;
+
+               /* the conf file file exist */ 
+               while((p=fgets(buffer,sizeof(buffer)-1,fb))!=NULL) {
+
+                       /* walk past leading spaces */
+                       index = 0;
+                       len = strnlen(buffer,sizeof(buffer)-1);
+                       while(isspace((int)buffer[index])) {
+                               if (index < len) {
+                                       index++;
+                               } else {
+                                       goto out;
+                               }
+                       }
+
+                       if (buffer[index] == '#') continue;
+                               
+                       /* check if it is the S_CAPS */
+                       if ((p=strstr(&buffer[index],"S_CAPS"))!=NULL) {
+                               int j;
+                               cap = 0;
+
+                               /* what follows is a bunch of error
+                                  checking to parse the S_CAPS="..."
+                                  string */
+
+                               /* adjust index into buffer */
+                               index+= (p-&buffer[index])+strlen("S_CAPS");
+
+                               /* skip over whitespace */
+                               while(isspace((int)buffer[index])) {
+                                       if (index < len) {
+                                               index++;
+                                       } else {
+                                       /* parse error */
+                                               goto out;
+                                       }
+                               }
+
+                               /* expecting to see = sign */
+                               if (buffer[index++]!='=') {
+                                       /* parse error */
+                                       goto out;
+                               }
+
+                               /* skip over whitespace */
+                               while(isspace((int)buffer[index])) {
+                                       if (index < len) {
+                                               index++;
+                                       } else {
+                                               /* parse error */
+                                               goto out;
+                                       }
+                               }
+
+                               /* expecting to see the opening " */
+                               if (buffer[index]!='"') {
+                                       /* parse error */
+                                       goto out;
+                               }
+
+                               /* check to see that we are still within bounds */
+                               if (index < len) {
+                                       index++;
+                               } else {
+                                       /* parse error */
+                                       goto out;
+                               }
+
+                               /* search for the closing " */
+                               if((p=strstr(&buffer[index],"\""))==NULL) {
+                                       /* parse error */
+                                       goto out;
+                               }
+
+                               /* ok... we should now have a bunch of
+                                  CAP keys words within the quotes */
+
+                               for (j=0; tbcap[j].option != NULL; j++){
+                                       if ((p=strstr(buffer,tbcap[j].option))!=NULL){
+                                               len = strlen(tbcap[j].option);
+                                               if (((isspace(*(p-1))) || (*(p-1)=='"')) &&
+                                                   ((isspace(*(p+len))) || (*(p+len)=='"'))) {
+                                                       cap |= (1<<tbcap[j].bit);
+                                               } else {
+                                                       /* parse error */
+                                                       goto out;
+                                               }
+                                       }
+                               }
+                               remove_cap &= ~cap;
+                               break;
+                       }
+               }
+ out:
+               /* close the conf file */
+               fclose(fb);
+       }
+       return remove_cap;
+}
+
+static int sandbox_processes(uid_t uid, unsigned remove_cap)
+{
+       int      context;
+       int      flags;
+
+       /* Unique context */
+       context = uid;
+
+       flags = 0;
+       flags |= 1; /* VX_INFO_LOCK -- cannot request a new vx_id */
+       /* flags |= 4; VX_INFO_NPROC -- limit number of procs in a context */
+
+       if (vc_new_s_context(context,remove_cap,flags) < 0) {
+               perror("vserver: new_s_context error ");
+               exit(1);
+       }
+       return 0;
+}
+
+
+void runas_slice_user(char *username)
+{
+       struct passwd pwdd, *pwd = &pwdd, *result;
+       char          *pwdBuffer;
+       char          *home_env, *logname_env, *mail_env, *shell_env, *user_env;
+       int           home_len, logname_len, mail_len, shell_len, user_len;
+       long          pwdBuffer_len;
+       static char   *envp[10];
+
+
+       pwdBuffer_len = sysconf(_SC_GETPW_R_SIZE_MAX);
+       if (pwdBuffer_len == -1) {
+               perror("vserver: _SC_GETPW_R_SIZE_MAX not defined ");
+               exit(1);
+       }
+
+       pwdBuffer = (char*)malloc(pwdBuffer_len);
+       if (pwdBuffer == NULL) {
+               perror("vserver: malloc error ");
+               exit(1);
+       }
+
+       errno = 0;
+       if ((getpwnam_r(username,pwd,pwdBuffer,pwdBuffer_len, &result) != 0) || (errno != 0)) {
+               perror("vserver: getpwnam error ");
+               exit(1);
+       }
+
+       if (setgid(pwd->pw_gid) < 0) {
+               perror("vserver: setgid error ");
+               exit(1);
+       }
+
+       if (setuid(pwd->pw_uid) < 0) {
+               perror("vserver: setuid error ");
+               exit(1);
+       }
+
+       if (chdir(pwd->pw_dir) < 0) {
+               perror("vserver: chdir error ");
+               exit(1);
+       }
+
+       home_len    = strlen("HOME=") + strlen(pwd->pw_dir) + NULLBYTE_SIZE;
+       logname_len = strlen("LOGNAME=") + strlen(username) + NULLBYTE_SIZE;
+       mail_len    = strlen("MAIL=/var/spool/mail/") + strlen(username) 
+               + NULLBYTE_SIZE;
+       shell_len   = strlen("SHELL=") + strlen(pwd->pw_shell) + NULLBYTE_SIZE;
+       user_len    = strlen("USER=") + strlen(username) + NULLBYTE_SIZE;
+
+       home_env    = (char *)malloc(home_len);
+       logname_env = (char *)malloc(logname_len);
+       mail_env    = (char *)malloc(mail_len);
+       shell_env   = (char *)malloc(shell_len);
+       user_env    = (char *)malloc(user_len);
+
+       if ((home_env    == NULL)  || 
+           (logname_env == NULL)  ||
+           (mail_env    == NULL)  ||
+           (shell_env   == NULL)  ||
+           (user_env    == NULL)) {
+               perror("vserver: malloc error ");
+               exit(1);
+       }
+
+       sprintf(home_env, "HOME=%s", pwd->pw_dir);
+       sprintf(logname_env, "LOGNAME=%s", username);
+       sprintf(mail_env, "MAIL=/var/spool/mail/%s", username);
+       sprintf(shell_env, "SHELL=%s", pwd->pw_shell);
+       sprintf(user_env, "USER=%s", username);
+    
+       home_env[home_len - 1]       = '\0';
+       logname_env[logname_len - 1] = '\0';
+       mail_env[mail_len - 1]       = '\0';
+       shell_env[shell_len - 1]     = '\0';
+       user_env[user_len - 1]       = '\0';
+
+       envp[0] = home_env;
+       envp[1] = logname_env;
+       envp[2] = mail_env;
+       envp[3] = shell_env;
+       envp[4] = user_env;
+       envp[5] = 0;
+
+       if ((putenv(home_env)    < 0) ||
+           (putenv(logname_env) < 0) ||
+           (putenv(mail_env)    < 0) ||
+           (putenv(shell_env)   < 0) ||
+           (putenv(user_env)    < 0)) {
+               perror("vserver: putenv error ");
+               exit(1);
+       }
+}
+
+void slice_enter(char *context)
+{
+       struct passwd pwdd, *pwd = &pwdd, *result;
+       char          *pwdBuffer;
+       long          pwdBuffer_len;
+       unsigned remove_cap;
+       uid_t uid;
+
+       pwdBuffer_len = sysconf(_SC_GETPW_R_SIZE_MAX);
+       if (pwdBuffer_len == -1) {
+               perror("vserver: _SC_GETPW_R_SIZE_MAX not defined ");
+               exit(1);
+       }
+
+       pwdBuffer = (char*)malloc(pwdBuffer_len);
+       if (pwdBuffer == NULL) {
+               perror("vserver: malloc error ");
+               exit(1);
+       }
+
+       errno = 0;
+       if ((getpwnam_r(context,pwd,pwdBuffer,pwdBuffer_len, &result) != 0) || (errno != 0)) {
+               fprintf(stderr,"vserver: getpwname(%s) failed",context);
+               perror("");
+               exit(2);
+       }
+
+       context = (char*)malloc(strlen(pwd->pw_name)+NULLBYTE_SIZE);
+       if (!context) {
+               perror("vserver: malloc failed");
+               exit(2);
+       }
+       strcpy(context,pwd->pw_name);
+
+       if (setuidgid_root() < 0) { /* For chroot, new_s_context */
+               fprintf(stderr,"vserver: Could not setuid/setguid to root:root\n");
+               exit(2);
+       }
+
+       remove_cap = get_remove_cap(context);
+
+       uid = pwd->pw_uid;
+       if (sandbox_chroot(uid) < 0) {
+               fprintf(stderr, "vserver: Could not chroot to vserver root\n");
+               exit(2);
+       }
+
+       if (sandbox_processes(uid, remove_cap) < 0) {
+               fprintf(stderr, "vserver: Could not sandbox processes in vserver\n");
+               exit(2);
+       }
+}
+
+//--------------------------------------------------------------------
+
+#define DEFAULT_SHELL "/bin/sh"
+
+/* Exit statuses for programs like 'env' that exec other programs.
+   EXIT_FAILURE might not be 1, so use EXIT_FAIL in such programs.  */
+enum
+{
+  EXIT_CANNOT_INVOKE = 126,
+  EXIT_ENOENT = 127
+};
+
+int main(int argc, char **argv)
+{
+    struct passwd   pwdd, *pwd = &pwdd, *result;
+    char            *context, *username, *shell, *pwdBuffer;
+    long            pwdBuffer_len;
+    uid_t           uid;
+    int             index, i;
+
+    if (argv[0][0]=='-') 
+      index = 1;
+    else
+      index = 0;
+
+    uid = getuid();
+    if ((pwd = getpwuid(uid)) == NULL) {
+      fprintf(stderr,"vsh: getpwnam error failed for %d\n",uid); 
+      exit(1);
+    }
+
+    context = (char*)strdup(pwd->pw_name);
+    if (!context) {
+      perror("vsh: strdup failed");
+      exit(2);
+    }
+
+    /* enter vserver "context" */
+    slice_enter(context);
+
+    /* Now run as username in this context. Note that for PlanetLab's
+       vserver configuration the context name also happens to be the
+       "default" username within the vserver context.
+    */
+    username = context;
+    runas_slice_user(username);
+
+    /* With the uid/gid appropriately set. Let's figure out what the
+     * shell in the vserver's /etc/passwd is for the given username.
+     */
+
+    pwdBuffer_len = sysconf(_SC_GETPW_R_SIZE_MAX);
+    if (pwdBuffer_len == -1) {
+           perror("vserver: _SC_GETPW_R_SIZE_MAX not defined ");
+           exit(1);
+    }
+    pwdBuffer = (char*)malloc(pwdBuffer_len);
+    if (pwdBuffer == NULL) {
+           perror("vserver: malloc error ");
+           exit(1);
+    }
+
+    errno = 0;
+    if ((getpwnam_r(username,pwd,pwdBuffer,pwdBuffer_len, &result) != 0) || (errno != 0)) {
+        fprintf(stderr,"vsh: getpwnam error failed for %s\n",username); 
+        exit(1);
+    }
+
+    /* Make sure pw->pw_shell is non-NULL.*/
+    if (pwd->pw_shell == NULL || pwd->pw_shell[0] == '\0') {
+      pwd->pw_shell = (char *) DEFAULT_SHELL;
+    }
+
+    shell = (char *)strdup(pwd->pw_shell);
+    if (!shell) {
+      perror("vsh: strdup failed");
+      exit(2);
+    }
+
+    /* Check whether 'su' or 'sshd' invoked us as a login shell or
+       not; did this above when testing argv[0]=='-'.
+    */
+    argv[0] = shell;
+    if (index == 1) {
+      char **args;
+      args = (char**)malloc(sizeof(char*)*(argc+2));
+      if (!args) {
+       perror("vsh: malloc failed");
+      }
+      args[0] = argv[0];
+      args[1] = "-l";
+      for(i=1;i<argc+1;i++) {
+       args[i+1] = argv[i];
+      }
+      argv = args;
+    }
+    (void) execvp(shell,argv);
+    {
+      int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+      exit (exit_status);
+    }
+
+    return 0; /* shutup compiler */
+}
index 2b0cac9..8065f5e 100644 (file)
@@ -43,7 +43,7 @@ using namespace std;
 
 static bool undo = false;
 
-static int  ext2flags = EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL;
+static int  ext2flags = EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL;
 struct EXCLDIR{
        string prefix;
        int len;
@@ -338,9 +338,9 @@ int main (int argc, char *argv[])
                }else if (strcmp(arg,"--noflags")==0){
                        ext2flags = 0;
                }else if (strcmp(arg,"--immutable")==0){
-                       ext2flags |= EXT2_IMMUTABLE_FILE_FL;
+                       ext2flags |= EXT2_IMMUTABLE_FL;
                }else if (strcmp(arg,"--immutable-mayunlink")==0){
-                       ext2flags |= EXT2_IMMUTABLE_LINK_FL;
+                       ext2flags |= EXT2_IUNLINK_FL;
                }else if (strcmp(arg,"--excldir")==0){
                        i++;
                        //excldirs[excldirs.size()] = EXCLDIR(argv[i]);
index c567267..153076d 100644 (file)
@@ -36,9 +36,17 @@ 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
+#ifndef EXT2_IMMUTABLE_FL
+#define EXT2_IMMUTABLE_FL 0x00000010
+#endif
+
+#ifndef EXT2_IUNLINK_FL
+/* Set both bits for backward compatibility */
+#define EXT2_IUNLINK_FL 0x08008000
+#endif
+
+#ifndef EXT2_BARRIER_FL
+#define EXT2_BARRIER_FL 0x04000000
 #endif
 
 
index 338a782..5d0864c 100644 (file)
@@ -26,6 +26,7 @@ sysv_XTRAS            =  sysv/rebootmgr.subst \
                           sysv/v_smb.subst \
                           sysv/v_sshd.subst \
                           sysv/v_xinetd.subst \
+                          sysv/vcached.subst \
                           sysv/vservers.subst
 
 sysv_GENSCRPTS         =  sysv/rebootmgr \
@@ -37,11 +38,12 @@ sysv_GENSCRPTS              =  sysv/rebootmgr \
                           sysv/v_smb \
                           sysv/v_sshd \
                           sysv/v_xinetd \
+                          sysv/vcached \
                           sysv/vservers
 
 sysv_SCRPTS            =  $(sysv_GENSCRPTS)
 
-sysv_CFG               =  sysv/vservers.conf
+sysv_CFG               =  sysv/vservers.conf sysv/vcached.conf
 
 
 sysv/%:                        sysv/%.subst
diff --git a/sysv/vcached.conf b/sysv/vcached.conf
new file mode 100644 (file)
index 0000000..498811f
--- /dev/null
@@ -0,0 +1,23 @@
+# number of images to keep cached
+slots=32
+
+# fill the cache periodically (seconds)
+period=$((60 * 15))
+
+# nice adjustment
+nice=10
+
+# PID file
+pidfile=/var/run/vcached.pid
+
+# log file
+logfile=/var/log/vcached.log
+
+# run in foreground
+foreground=0
+
+# debug
+debug=0
+
+# run once
+single=0
diff --git a/sysv/vcached.logrotate b/sysv/vcached.logrotate
new file mode 100644 (file)
index 0000000..203baba
--- /dev/null
@@ -0,0 +1,10 @@
+/var/log/vcached.log {
+    compress
+    daily
+    notifempty
+    rotate 5
+    missingok
+    postrotate
+        kill -HUP `cat /var/run/vcached.pid 2>/dev/null` 2>/dev/null || true
+    endscript
+}
diff --git a/sysv/vcached.subst b/sysv/vcached.subst
new file mode 100755 (executable)
index 0000000..7714371
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# chkconfig: 2345 65 80
+# description: vcached startup script
+# pidfile: /var/run/vcached.pid
+#
+. /etc/init.d/functions
+RETVAL=0
+USR_SBIN=/usr/sbin
+
+start() {
+    echo -n "Starting vcached: "
+    initlog -c $USR_SBIN/vcached
+    RETVAL=$?
+    [ "$RETVAL" -eq 0 ] && success $"vcached start" || failure $"vcached start"
+    echo
+    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/vcached
+    return $RETVAL
+}
+
+stop() {
+    echo -n "Stopping vcached: "
+    if [[ -e /var/run/vcached.pid ]]; then
+        /bin/kill `cat /var/run/vcached.pid`
+        RETVAL=$?
+    else
+        RETVAL=1
+    fi
+    [ "$RETVAL" -eq 0 ] && success $"vcached shutdown" || failure $"vcached shutdown
+"
+    echo
+    rm -f /var/lock/subsys/vcached
+    rm -f /var/run/vcached.pid
+    return $RETVAL
+}    
+
+restart() {
+    stop
+    start
+}    
+
+case "$1" in
+    start)
+        start
+        ;;
+    stop)
+        stop
+        ;;
+    restart)
+        restart
+        ;;
+    *)
+        echo $"Usage: $0 {start|stop|restart}"
+        exit 1
+esac
+exit $?
index 0f309e3..7f13fc1 100644 (file)
@@ -2,6 +2,6 @@
 # BACKGROUND=yes
 # start the vservers on tty9, in background so the rest of the
 # boot process end early
-BACKGROUND=no
+BACKGROUND=yes
 
 
index 7be797d..acaced0 100755 (executable)
@@ -1,91 +1,92 @@
 #!/bin/sh
-# chkconfig: 345 98 10
+# chkconfig: 345 99 01
 # description: The vservers service is used to start and stop all
 #              the virtual servers.
 
 USR_SBIN=/usr/sbin
-
+VROOTDIR=/vservers
 
 # Print the vserver name in priority/alpha order
 sortserver(){
-       (
-       cd /etc/vservers
-       for serv in *.conf
-       do
-               test -f "$serv" || continue
-
-               PRIORITY=100
-               . $serv
-               printf "%03d %s\n" $PRIORITY `basename $serv .conf`
-       done
-       ) | sort $* | (while read a b; do echo $b; done)
+    (
+    cd /etc/vservers
+    for serv in *.conf ; do
+       # XXX - why is this check necessary?
+       test -f "$serv" || continue
+       PRIORITY=100
+       . $serv
+       echo $PRIORITY `basename $serv .conf`
+    done
+    ) | sort -n $* | cut -d ' ' -f 2
 }
 
 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
+    echo "Starting the virtual servers"
+    cd /etc/vservers
+    for name in $*; do
+       if ! test -f "$name.conf" ; then
+           echo No configuration for this vserver: /etc/vservers/$name.conf
+           continue
+       fi
+       ONBOOT=
+       BACKGROUND=no
+       if [ -f /etc/vservers.conf ] ; then
+           . /etc/vservers.conf
+       fi
+       . $name.conf
+       if [ "$ONBOOT" = "yes" ] ; then
+           mkdir -p $VROOTDIR/$name/var/log
+           if [ "$BACKGROUND" = "yes" ] ; then
+               nohup setsid $USR_SBIN/vserver $name start >$VROOTDIR/$name/var/log/boot.log 2>&1 </dev/null &
+               sleep 1
+           else
+               $USR_SBIN/vserver $name start 2>&1 </dev/null | tee $VROOTDIR/$name/var/log/boot.log
+           fi
+       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 &
+       # do nothing unless passed a vserver name - 'start all' functionality
+       # subsumed by Node Manager
+       if [ -z "$2" ]; then
+           touch /var/lock/subsys/vservers
        else
-               startservers
+           startservers $2
        fi
-       touch /var/lock/subsys/vservers
        ;;
   stop)
+       shift
        echo "Stopping the virtual servers"
        cd /etc/vservers
-       for name in `sortserver -r`
-       do
-               $USR_SBIN/vserver $name stop
+       for name in ${*:-`sortserver -r`} ; do
+           chcontext --ctx `id -u $name` /usr/lib/util-vserver/vserverkillall
+           umount $VROOTDIR/$name/proc
+           umount $VROOTDIR/$name/dev/pts
        done
        rm -f /var/lock/subsys/vservers
        ;;
   restart|force-reload)
-       $0 stop
-       $0 start
+       shift
+       $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
+       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
-
-
-
-
index dfb7941..2e337a3 100644 (file)
@@ -1,13 +1,19 @@
-%define __chattr       /usr/bin/chattr
+%define name util-vserver
+%define version 0.30
+%define release 15.planetlab%{?date:.%{date}}
+
+Vendor: PlanetLab
+Packager: PlanetLab Central <support@planet-lab.org>
+Distribution: PlanetLab 3.0
+URL: http://cvs.planet-lab.org/cvs/util-vserver
 
 Summary:       Linux virtual server utilities
-Name:          util-vserver
-Version:       0.30
-Release:       0
+Name:          %{name}
+Version:       %{version}
+Release:       %{release}
 Epoch:         0
 Copyright:     GPL
 Group:         System Environment/Base
-URL:           http://savannah.nongnu.org/projects/util-vserver/
 Source0:       http://savannah.nongnu.org/download/util-vserver/stable.pkg/%version/%name-%version.tar.bz2
 Provides:      %name-devel = %epoch:%version-%release
 BuildRoot:     %_tmppath/%name-%version-%release-root
@@ -15,7 +21,6 @@ Provides:     vserver = %epoch:%version-%release
 Conflicts:     vserver < %epoch:%version-%release
 Conflicts:     vserver > %epoch:%version-%release
 BuildRequires: e2fsprogs-devel
-Requires(post):        %__chattr
 
 %package linuxconf
 Summary:       Linuxconf administration modules for vservers
@@ -43,12 +48,17 @@ linuxconf.
 
 %prep
 %setup -q
+aclocal -I m4
+autoconf
+automake --add-missing
+# bootstrap to avoid BuildRequires of kernel-source
+for linux in $RPM_BUILD_DIR/linux-* /lib/modules/`uname -r`/build ; do
+   [[ -d $linux/include ]] && %configure --with-kerneldir=$linux --enable-linuxconf && break
+done
 
 
 %build
-%configure --enable-linuxconf
-%__make %{?_smp_mflags}
-
+make
 
 %install
 rm -rf $RPM_BUILD_ROOT
@@ -60,36 +70,44 @@ test "%_initrddir" = %_sysconfdir/init.d || {
        mv ${RPM_BUILD_ROOT}%_sysconfdir/init.d/* ${RPM_BUILD_ROOT}%_initrddir/
 }
 
+mkdir -p ${RPM_BUILD_ROOT}/bin
+ln -f ${RPM_BUILD_ROOT}%_sbindir/vsh ${RPM_BUILD_ROOT}/bin/vsh
 
-%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
+install -D -m 644 sysv/vcached.logrotate ${RPM_BUILD_ROOT}/etc/logrotate.d/vcached
 
-for i in %v_services; do
-       /sbin/chkconfig --add v_$i
-done
+mkdir -p $RPM_BUILD_ROOT/etc/cron.d
+. sysv/vcached.conf
+echo "*/$(($period / 60)) * * * * root %_sbindir/vcached -s -f -l $logfile" > $RPM_BUILD_ROOT/etc/cron.d/vcached
 
-%__chattr +t /vservers || :
+%__make -C python INSTALL_ROOT=$RPM_BUILD_ROOT install
 
+%clean
+rm -rf $RPM_BUILD_ROOT
 
-%preun
-test "$1" != 0 || for i in %v_services; do
-       /sbin/chkconfig --del v_$i
-done
+%post
+chkconfig --add vservers
+chkconfig vservers on
 
-test "$1" != 0 || %{_initrddir}/rebootmgr stop &>/dev/null || :
-test "$1" != 0 || /sbin/chkconfig --del rebootmgr
-test "$1" != 0 || /sbin/chkconfig --del vservers
+if [ ! -f /etc/shells ] || ! grep -q '^/bin/vsh$' /etc/shells ; then
+    echo /bin/vsh >> /etc/shells
+fi
 
+# make sure barrier bit is set on /vservers to prevent chroot() escapes
+%_libdir/%name/setattr --barrier /vservers
 
 %postun
-test "$1" = 0  || %{_initrddir}/rebootmgr condrestart >/dev/null || :
+# 0 = erase, 1 = upgrade
+if [ "$1" = 0 ] ; then
+    perl -i -n -e 'next if /^\/bin\/vsh$/; print' /etc/shells
+fi
 
+%preun
+# 0 = erase, 1 = upgrade
+if [ $1 -eq 0 ] ; then
+    [ "$PL_BOOTCD" = "1" ] || service vservers stop
+    chkconfig vservers off
+    chkconfig --del vservers
+fi
 
 %files
 %defattr(-,root,root)
@@ -101,12 +119,17 @@ test "$1" = 0  || %{_initrddir}/rebootmgr condrestart >/dev/null || :
 %_mandir/man8/*
 %config %_initrddir/*
 %config(noreplace) /etc/vservers.conf
+%config(noreplace) /etc/vcached.conf
+/etc/logrotate.d/vcached
+/etc/cron.d/vcached
+%dir /etc/vservers
 %attr(0,root,root) %dir /vservers
+%attr(4755,root,root) /usr/sbin/vsh
+%attr(4755,root,root) /bin/vsh
 
 %exclude %_sbindir/newvserver
 %exclude %_mandir/man8/newvserver*
 
-
 %files linuxconf
 %defattr(-,root,root)
 %config(noreplace) /etc/vservers/newvserver.defaults
@@ -114,9 +137,90 @@ test "$1" = 0  || %{_initrddir}/rebootmgr condrestart >/dev/null || :
 %_mandir/man8/newvserver*
 
 
+
+%package py23
+Summary: Python modules for manipulating vservers
+Group: Applications/System
+Requires: python /usr/lib/util-vserver/util-vserver-vars util-python
+
+%description py23
+Python modules for manipulating vservers.  Provides a superset of the
+functionality of the vserver script (at least will do in the future),
+but more readily accessible from Python code.
+
+%files py23
+%defattr(0644,root,root)
+/usr/lib/python2.3/site-packages/bwlimit.py
+/usr/lib/python2.3/site-packages/bwlimit.pyc
+/usr/lib/python2.3/site-packages/cpulimit.py
+/usr/lib/python2.3/site-packages/cpulimit.pyc
+/usr/lib/python2.3/site-packages/util_vserver_vars.py
+/usr/lib/python2.3/site-packages/vduimpl.so
+/usr/lib/python2.3/site-packages/vserver.py
+/usr/lib/python2.3/site-packages/vserver.pyc
+/usr/lib/python2.3/site-packages/vserverimpl.so
+
+
+
 %changelog
+* Thu Jul 28 2005 Steve Muir <smuir@cs.princeton.edu>
+- add support for static vserver IDs to vuseradd and vuserdel
+
+* Thu Jul 21 2005 Steve Muir <smuir@cs.princeton.edu>
+- add bwlimit and cpulimit modules
+
+* Mon Jun 20 2005 Steve Muir <smuir@cs.princeton.edu>
+- import Marc's vdu implementation
+
+* Wed Jun 15 2005 Steve Muir <smuir@cs.princeton.edu>
+- 'vserver-init start' functionality subsumed by Node Manager
+
+* Thu Jun 02 2005 Marc E. Fiuczynski <mef@cs.princeton.edu>
+- Fixed vlimit command
+
+* Wed May 25 2005 Steve Muir <smuir@cs.princeton.edu>
+- add Python modules for manipulating vservers
+
+* Thu Apr  7 2005 Steve Muir <smuir@cs.princeton.edu>
+- vuserdel changes: don't shutdown vserver, just kill all processes;
+  unmount all mountpoints in vserver before deleting
+
+* Fri Nov 19 2004 Mark Huang <mlhuang@cs.princeton.edu>
+- vcached no longer runs as a daemon
+- do not restart vservers when package is upgraded
+
+* Wed Nov 17 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.30-6.planetlab
++ planetlab-3_0-rc4
+- PL2445
+- Both vcached and vuseradd now print a warning message when vbuild
+  succeeds but the resulting new vserver image is smaller in size than
+  the vserver-reference image.
+- vuseradd: clean up some more junk on failure
+
+* Tue Nov 16 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.30-5.planetlab
++ planetlab-3_0-rc3
+- PL3026: This is the upgraded version of vdu that maintains an
+  internal hash table of files with a nlink count > 1.  Only if vdu
+  sees all hard links to a particular inode does it add its size and
+  block count to the total.
+
+* Fri Nov 12 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.30-4.planetlab
+- PL2445 Use -b option to du to avoid rounding errors.
+
+* Sat Nov  6 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.30-3.planetlab
++ planetlab-3_0-rc2
+- don't create the symbolic link /home/slice/.ssh, this is not how
+  pl_sshd works
+
+* Mon Oct 11 2004 Marc E. Fiuczynski <mef@cs.princeton.edu>
+- added vsh
+
+* Wed Aug 11 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.29-1.planetlab
+- initial PlanetLab 3.0 build.
+
 * Thu Mar 18 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> - 0:0.29.3-0
 - removed '%%doc doc/FAQ.txt' since file does not exist anymore
 
 * Fri Sep 26 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> - 0:0.23.4-1
 - initial build.
+
index 2c9b396..0d625bc 100644 (file)
@@ -1,13 +1,19 @@
-%define __chattr       /usr/bin/chattr
+%define name @PACKAGE@
+%define version @VERSION@
+%define release 15.planetlab%{?date:.%{date}}
+
+Vendor: PlanetLab
+Packager: PlanetLab Central <support@planet-lab.org>
+Distribution: PlanetLab 3.0
+URL: http://cvs.planet-lab.org/cvs/util-vserver
 
 Summary:       Linux virtual server utilities
-Name:          @PACKAGE@
-Version:       @VERSION@
-Release:       0
+Name:          %{name}
+Version:       %{version}
+Release:       %{release}
 Epoch:         0
 Copyright:     GPL
 Group:         System Environment/Base
-URL:           http://savannah.nongnu.org/projects/util-vserver/
 Source0:       http://savannah.nongnu.org/download/util-vserver/stable.pkg/%version/%name-%version.tar.bz2
 Provides:      %name-devel = %epoch:%version-%release
 BuildRoot:     %_tmppath/%name-%version-%release-root
@@ -15,7 +21,6 @@ Provides:     vserver = %epoch:%version-%release
 Conflicts:     vserver < %epoch:%version-%release
 Conflicts:     vserver > %epoch:%version-%release
 BuildRequires: e2fsprogs-devel
-Requires(post):        %__chattr
 
 %package linuxconf
 Summary:       Linuxconf administration modules for vservers
@@ -43,12 +48,17 @@ linuxconf.
 
 %prep
 %setup -q
+aclocal -I m4
+autoconf
+automake --add-missing
+# bootstrap to avoid BuildRequires of kernel-source
+for linux in $RPM_BUILD_DIR/linux-* /lib/modules/`uname -r`/build ; do
+   [[ -d $linux/include ]] && %configure --with-kerneldir=$linux --enable-linuxconf && break
+done
 
 
 %build
-%configure --enable-linuxconf
-%__make %{?_smp_mflags}
-
+make
 
 %install
 rm -rf $RPM_BUILD_ROOT
@@ -60,36 +70,44 @@ test "%_initrddir" = %_sysconfdir/init.d || {
        mv ${RPM_BUILD_ROOT}%_sysconfdir/init.d/* ${RPM_BUILD_ROOT}%_initrddir/
 }
 
+mkdir -p ${RPM_BUILD_ROOT}/bin
+ln -f ${RPM_BUILD_ROOT}%_sbindir/vsh ${RPM_BUILD_ROOT}/bin/vsh
 
-%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
+install -D -m 644 sysv/vcached.logrotate ${RPM_BUILD_ROOT}/etc/logrotate.d/vcached
 
-for i in %v_services; do
-       /sbin/chkconfig --add v_$i
-done
+mkdir -p $RPM_BUILD_ROOT/etc/cron.d
+. sysv/vcached.conf
+echo "*/$(($period / 60)) * * * * root %_sbindir/vcached -s -f -l $logfile" > $RPM_BUILD_ROOT/etc/cron.d/vcached
 
-%__chattr +t /vservers || :
+%__make -C python INSTALL_ROOT=$RPM_BUILD_ROOT install
 
+%clean
+rm -rf $RPM_BUILD_ROOT
 
-%preun
-test "$1" != 0 || for i in %v_services; do
-       /sbin/chkconfig --del v_$i
-done
+%post
+chkconfig --add vservers
+chkconfig vservers on
 
-test "$1" != 0 || %{_initrddir}/rebootmgr stop &>/dev/null || :
-test "$1" != 0 || /sbin/chkconfig --del rebootmgr
-test "$1" != 0 || /sbin/chkconfig --del vservers
+if [ ! -f /etc/shells ] || ! grep -q '^/bin/vsh$' /etc/shells ; then
+    echo /bin/vsh >> /etc/shells
+fi
 
+# make sure barrier bit is set on /vservers to prevent chroot() escapes
+%_libdir/%name/setattr --barrier /vservers
 
 %postun
-test "$1" = 0  || %{_initrddir}/rebootmgr condrestart >/dev/null || :
+# 0 = erase, 1 = upgrade
+if [ "$1" = 0 ] ; then
+    perl -i -n -e 'next if /^\/bin\/vsh$/; print' /etc/shells
+fi
 
+%preun
+# 0 = erase, 1 = upgrade
+if [ $1 -eq 0 ] ; then
+    [ "$PL_BOOTCD" = "1" ] || service vservers stop
+    chkconfig vservers off
+    chkconfig --del vservers
+fi
 
 %files
 %defattr(-,root,root)
@@ -101,12 +119,17 @@ test "$1" = 0  || %{_initrddir}/rebootmgr condrestart >/dev/null || :
 %_mandir/man8/*
 %config %_initrddir/*
 %config(noreplace) /etc/vservers.conf
+%config(noreplace) /etc/vcached.conf
+/etc/logrotate.d/vcached
+/etc/cron.d/vcached
+%dir /etc/vservers
 %attr(0,root,root) %dir /vservers
+%attr(4755,root,root) /usr/sbin/vsh
+%attr(4755,root,root) /bin/vsh
 
 %exclude %_sbindir/newvserver
 %exclude %_mandir/man8/newvserver*
 
-
 %files linuxconf
 %defattr(-,root,root)
 %config(noreplace) /etc/vservers/newvserver.defaults
@@ -114,9 +137,90 @@ test "$1" = 0  || %{_initrddir}/rebootmgr condrestart >/dev/null || :
 %_mandir/man8/newvserver*
 
 
+
+%package py23
+Summary: Python modules for manipulating vservers
+Group: Applications/System
+Requires: python /usr/lib/util-vserver/util-vserver-vars util-python
+
+%description py23
+Python modules for manipulating vservers.  Provides a superset of the
+functionality of the vserver script (at least will do in the future),
+but more readily accessible from Python code.
+
+%files py23
+%defattr(0644,root,root)
+/usr/lib/python2.3/site-packages/bwlimit.py
+/usr/lib/python2.3/site-packages/bwlimit.pyc
+/usr/lib/python2.3/site-packages/cpulimit.py
+/usr/lib/python2.3/site-packages/cpulimit.pyc
+/usr/lib/python2.3/site-packages/util_vserver_vars.py
+/usr/lib/python2.3/site-packages/vduimpl.so
+/usr/lib/python2.3/site-packages/vserver.py
+/usr/lib/python2.3/site-packages/vserver.pyc
+/usr/lib/python2.3/site-packages/vserverimpl.so
+
+
+
 %changelog
+* Thu Jul 28 2005 Steve Muir <smuir@cs.princeton.edu>
+- add support for static vserver IDs to vuseradd and vuserdel
+
+* Thu Jul 21 2005 Steve Muir <smuir@cs.princeton.edu>
+- add bwlimit and cpulimit modules
+
+* Mon Jun 20 2005 Steve Muir <smuir@cs.princeton.edu>
+- import Marc's vdu implementation
+
+* Wed Jun 15 2005 Steve Muir <smuir@cs.princeton.edu>
+- 'vserver-init start' functionality subsumed by Node Manager
+
+* Thu Jun 02 2005 Marc E. Fiuczynski <mef@cs.princeton.edu>
+- Fixed vlimit command
+
+* Wed May 25 2005 Steve Muir <smuir@cs.princeton.edu>
+- add Python modules for manipulating vservers
+
+* Thu Apr  7 2005 Steve Muir <smuir@cs.princeton.edu>
+- vuserdel changes: don't shutdown vserver, just kill all processes;
+  unmount all mountpoints in vserver before deleting
+
+* Fri Nov 19 2004 Mark Huang <mlhuang@cs.princeton.edu>
+- vcached no longer runs as a daemon
+- do not restart vservers when package is upgraded
+
+* Wed Nov 17 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.30-6.planetlab
++ planetlab-3_0-rc4
+- PL2445
+- Both vcached and vuseradd now print a warning message when vbuild
+  succeeds but the resulting new vserver image is smaller in size than
+  the vserver-reference image.
+- vuseradd: clean up some more junk on failure
+
+* Tue Nov 16 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.30-5.planetlab
++ planetlab-3_0-rc3
+- PL3026: This is the upgraded version of vdu that maintains an
+  internal hash table of files with a nlink count > 1.  Only if vdu
+  sees all hard links to a particular inode does it add its size and
+  block count to the total.
+
+* Fri Nov 12 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.30-4.planetlab
+- PL2445 Use -b option to du to avoid rounding errors.
+
+* Sat Nov  6 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.30-3.planetlab
++ planetlab-3_0-rc2
+- don't create the symbolic link /home/slice/.ssh, this is not how
+  pl_sshd works
+
+* Mon Oct 11 2004 Marc E. Fiuczynski <mef@cs.princeton.edu>
+- added vsh
+
+* Wed Aug 11 2004 Mark Huang <mlhuang@cs.princeton.edu> 0.29-1.planetlab
+- initial PlanetLab 3.0 build.
+
 * Thu Mar 18 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> - 0:0.29.3-0
 - removed '%%doc doc/FAQ.txt' since file does not exist anymore
 
 * Fri Sep 26 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> - 0:0.23.4-1
 - initial build.
+