gentoo: use /var/run for new /run compatibility
[util-vserver.git] / src / vspace.c
index 30f0dda..37ac2c3 100644 (file)
@@ -22,7 +22,7 @@
 #endif
 
 #include "util.h"
-#include <lib_internal/sys_unshare.h>
+#include <lib_internal/sys_clone.h>
 
 #include <vserver.h>
 
@@ -49,13 +49,25 @@ CMDLINE_OPTIONS[] = {
   { "new",        no_argument,       0, 'n' },
   { "enter",      required_argument, 0, 'e' },
   { "set",        no_argument,       0, 's' },
+  { "index",      required_argument, 0, 'i' },
   { "mask",       required_argument, 0, 'm' },
+  { "default",    no_argument,       0, 'd' },
+  { "~default",   no_argument,       0, 'd' | 0x10000 },
 
   { "mount",      no_argument,       0, 'M' },
+  { "~mount",     no_argument,       0, 'M' | 0x10000 },
   { "fs",         no_argument,       0, 'F' },
+  { "~fs",        no_argument,       0, 'F' | 0x10000 },
   { "ipc",        no_argument,       0, 'I' },
+  { "~ipc",       no_argument,       0, 'I' | 0x10000 },
   { "uts",        no_argument,       0, 'U' },
+  { "~uts",       no_argument,       0, 'U' | 0x10000 },
   { "user",       no_argument,       0, 'S' },
+  { "~user",      no_argument,       0, 'S' | 0x10000 },
+  { "pid",        no_argument,       0, 'P' },
+  { "~pid",       no_argument,       0, 'P' | 0x10000 },
+  { "net",        no_argument,       0, 'N' },
+  { "~net",       no_argument,       0, 'N' | 0x10000 },
   {0,0,0,0}
 };
 
@@ -74,15 +86,19 @@ showHelp(int fd, char const *cmd, int res)
            "                           <program> there; <program> is mandatory in this\n"
            "                           case\n"
            "    --set|-s          ...  assign the current spaces to the current context\n"
+           "    --index|-i <idx>  ...  work with the namespaces for <idx>\n"
            "\n"
            "<spaces>* specifies the spaces to manipulate.\n"
            "It can be any combination of:\n"
            "    --mask <mask>     ...  specify a mask of spaces\n"
+           "    --default         ...  the default spaces for this kernel\n"
            "    --mount           ...  the mount namespace\n"
            "    --fs              ...  the fs_struct\n"
            "    --ipc             ...  the IPC namespace\n"
            "    --uts             ...  the uts namespace\n"
            "    --user            ...  the user namespace\n"
+           "    --pid             ...  the pid namespace\n"
+           "    --net             ...  the network namespace\n"
            "\n"
            "Please report bugs to " PACKAGE_BUGREPORT "\n");
 
@@ -104,25 +120,42 @@ showVersion()
 static void
 newSpaces(uint_least64_t mask)
 {
-  if (sys_unshare((int) mask) == -1) {
-    perror(ENSC_WRAPPERS_PREFIX "unshare()");
-    exit(wrapper_exit_code);
+  pid_t pid;
+
+  mask &= ~CLONE_FS;
+
+  signal(SIGCHLD, SIG_DFL);
+
+#ifdef NDEBUG
+  pid = sys_clone((int) mask | CLONE_VFORK|SIGCHLD, 0);
+#else
+  pid = sys_clone((int) mask | SIGCHLD, 0);
+#endif
+
+  switch (pid) {
+    case -1    :
+      perror(ENSC_WRAPPERS_PREFIX "clone()");
+      exit(wrapper_exit_code);
+    case 0     :
+      break;
+    default    :
+      vc_exitLikeProcess(pid, wrapper_exit_code);
   }
 }
 
 static void
-enterSpaces(xid_t xid, uint_least64_t mask)
+enterSpaces(xid_t xid, uint_least64_t mask, uint32_t index)
 {
-  if (vc_enter_namespace(xid, mask)==-1) {
+  if (vc_enter_namespace(xid, mask, index)==-1) {
     perror(ENSC_WRAPPERS_PREFIX "vc_enter_namespace()");
     exit(wrapper_exit_code);
   }
 }
 
 static void
-setSpaces(xid_t xid, uint_least64_t mask)
+setSpaces(xid_t xid, uint_least64_t mask, uint32_t index)
 {
-  if (vc_set_namespace(xid, mask)==-1) {
+  if (vc_set_namespace(xid, mask, index)==-1) {
     perror(ENSC_WRAPPERS_PREFIX "vc_set_namespace()");
     exit(wrapper_exit_code);
   }
@@ -134,14 +167,16 @@ int main(int argc, char *argv[])
   bool                 do_enter   = false;
   bool                 do_set     = false;
   uint_least64_t       mask       = 0;
+  uint32_t             index      = 0;
   xid_t                        xid        = VC_NOCTX;
   int                  sum        = 0;
   
   while (1) {
-    int                c = getopt_long(argc, argv, "+nsce:m:" "MFIUS", CMDLINE_OPTIONS, 0);
+    int                        c = getopt_long(argc, argv, "+nsce:m:i:" "MFIUSPN", CMDLINE_OPTIONS, 0);
+    uint_least64_t     thisbit = 0;
     if (c==-1) break;
 
-    switch (c) {
+    switch (c & 0xFFFF) {
       case CMD_HELP    :  showHelp(1, argv[0], 0);
       case CMD_VERSION :  showVersion();
       case 'n'         :  do_new     = true; break;
@@ -150,19 +185,43 @@ int main(int argc, char *argv[])
        do_enter = true;
        xid      = Evc_xidopt2xid(optarg,true);
        break;
-      case 'm'         :
-       if (!isNumberUnsigned(optarg, &mask, true)) {
+      case 'i'         :  {
+       unsigned long   index_l;
+       if (!isNumberUnsigned(optarg, &index_l, true)) {
+         WRITE_MSG(2, "Invalid index '");
+         WRITE_STR(2, optarg);
+         WRITE_MSG(2, "'; try '--help' for more information\n");
+         return wrapper_exit_code;
+       }
+       index = (uint32_t)index_l;
+       break;
+      }
+      case 'm'         :  {
+       unsigned long   mask_l;
+       if (!isNumberUnsigned(optarg, &mask_l, true)) {
          WRITE_MSG(2, "Invalid mask '");
          WRITE_STR(2, optarg);
          WRITE_MSG(2, "'; try '--help' for more information\n");
          return wrapper_exit_code;
        }
+       mask = mask_l;
+       break;
+      }
+      case 'M'         :  thisbit = CLONE_NEWNS;       break;
+      case 'F'         :  thisbit = CLONE_FS;          break;
+      case 'I'         :  thisbit = CLONE_NEWIPC;      break;
+      case 'U'         :  thisbit = CLONE_NEWUTS;      break;
+      case 'S'         :  thisbit = CLONE_NEWUSER;     break;
+      case 'P'         :  thisbit = CLONE_NEWPID;      break;
+      case 'N'         :  thisbit = CLONE_NEWNET;      break;
+      case 'd'         :
+       thisbit = vc_get_space_default();
+       if (thisbit == (__typeof__(thisbit)) -1) {
+         thisbit = vc_get_space_mask();
+         if (thisbit == (__typeof__(thisbit)) -1)
+           thisbit = 0;
+       }
        break;
-      case 'M'         :  mask |= CLONE_NEWNS;         break;
-      case 'F'         :  mask |= CLONE_FS;            break;
-      case 'I'         :  mask |= CLONE_NEWIPC;        break;
-      case 'U'         :  mask |= CLONE_NEWUTS;        break;
-      case 'S'         :  mask |= CLONE_NEWUSER;       break;
 
       default          :
        WRITE_MSG(2, "Try '");
@@ -171,6 +230,11 @@ int main(int argc, char *argv[])
        return 255;
        break;
     }
+    /* ~ option used */
+    if (c & 0xFFFF0000)
+      mask &= ~thisbit;
+    else
+      mask |= thisbit;
   }
 
   sum = ((do_new ? 1 : 0) + (do_enter ? 1 : 0) +
@@ -180,14 +244,12 @@ int main(int argc, char *argv[])
     WRITE_MSG(2, "No operation was specified; try '--help' for more information\n");
   else if (sum>1)
     WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n");
-  else if (mask==0)
-    WRITE_MSG(2, "Must specify at least one space; try '--help' for more information\n");
   else if (optind==argc && (do_new || do_enter))
     WRITE_MSG(2, "No command specified; try '--help' for more information\n");
   else {
     if      (do_new)     newSpaces(mask);
-    else if (do_set)     setSpaces(VC_SAMECTX, mask);
-    else if (do_enter)   enterSpaces(xid, mask);
+    else if (do_set)     setSpaces(VC_SAMECTX, mask, index);
+    else if (do_enter)   enterSpaces(xid, mask, index);
 
     if (optind<argc)
       EexecvpD(argv[optind], argv+optind);