vshost-util-vserver

Build script and sources for util-vserver.
git clone https://ccx.te2000.cz/git/vshost-util-vserver
Log | Files | Refs

vspace.c (7844B)


      1 // $Id$    --*- c -*--
      2 
      3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
      4 // Copyright (C) 2007 Daniel Hokka Zakrisson
      5 //  
      6 // This program is free software; you can redistribute it and/or modify
      7 // it under the terms of the GNU General Public License as published by
      8 // the Free Software Foundation; version 2 of the License.
      9 //  
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU General Public License for more details.
     14 //  
     15 // You should have received a copy of the GNU General Public License
     16 // along with this program; if not, write to the Free Software
     17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     18 
     19 
     20 #ifdef HAVE_CONFIG_H
     21 #  include <config.h>
     22 #endif
     23 
     24 #include "util.h"
     25 #include <lib_internal/sys_clone.h>
     26 
     27 #include <vserver.h>
     28 
     29 #include <getopt.h>
     30 #include <libgen.h>
     31 #include <errno.h>
     32 #include <signal.h>
     33 #include <sched.h>
     34 
     35 #define ENSC_WRAPPERS_PREFIX	"vspace: "
     36 #define ENSC_WRAPPERS_UNISTD	1
     37 #define ENSC_WRAPPERS_VSERVER	1
     38 #include <wrappers.h>
     39 
     40 #define CMD_HELP		0x1000
     41 #define CMD_VERSION		0x1001
     42 
     43 int		wrapper_exit_code  =  255;
     44 
     45 struct option const
     46 CMDLINE_OPTIONS[] = {
     47   { "help",       no_argument,       0, CMD_HELP },
     48   { "version",    no_argument,       0, CMD_VERSION },
     49   { "new",        no_argument,       0, 'n' },
     50   { "enter",      required_argument, 0, 'e' },
     51   { "set",        no_argument,       0, 's' },
     52   { "index",      required_argument, 0, 'i' },
     53   { "mask",       required_argument, 0, 'm' },
     54   { "default",    no_argument,       0, 'd' },
     55   { "~default",   no_argument,       0, 'd' | 0x10000 },
     56 
     57   { "mount",      no_argument,       0, 'M' },
     58   { "~mount",     no_argument,       0, 'M' | 0x10000 },
     59   { "fs",         no_argument,       0, 'F' },
     60   { "~fs",        no_argument,       0, 'F' | 0x10000 },
     61   { "ipc",        no_argument,       0, 'I' },
     62   { "~ipc",       no_argument,       0, 'I' | 0x10000 },
     63   { "uts",        no_argument,       0, 'U' },
     64   { "~uts",       no_argument,       0, 'U' | 0x10000 },
     65   { "user",       no_argument,       0, 'S' },
     66   { "~user",      no_argument,       0, 'S' | 0x10000 },
     67   { "pid",        no_argument,       0, 'P' },
     68   { "~pid",       no_argument,       0, 'P' | 0x10000 },
     69   { "net",        no_argument,       0, 'N' },
     70   { "~net",       no_argument,       0, 'N' | 0x10000 },
     71   {0,0,0,0}
     72 };
     73 
     74 static void
     75 showHelp(int fd, char const *cmd, int res)
     76 {
     77   WRITE_MSG(fd, "Usage: ");
     78   WRITE_STR(fd, cmd);
     79   WRITE_MSG(fd,
     80 	    " <operation> <spaces>* [--] [<program> <args>*]\n"
     81 	    "\n"
     82 	    "<operation> can be one of:\n"
     83 	    "    --new|-n          ...  create new spaces and execute <program> there;\n"
     84 	    "                           <program> is mandatory in this case\n"
     85 	    "    --enter|-e <xid>  ...  enter the spaces of context <xid> and execute\n"
     86 	    "                           <program> there; <program> is mandatory in this\n"
     87 	    "                           case\n"
     88 	    "    --set|-s          ...  assign the current spaces to the current context\n"
     89 	    "    --index|-i <idx>  ...  work with the namespaces for <idx>\n"
     90 	    "\n"
     91 	    "<spaces>* specifies the spaces to manipulate.\n"
     92 	    "It can be any combination of:\n"
     93 	    "    --mask <mask>     ...  specify a mask of spaces\n"
     94 	    "    --default         ...  the default spaces for this kernel\n"
     95 	    "    --mount           ...  the mount namespace\n"
     96 	    "    --fs              ...  the fs_struct\n"
     97 	    "    --ipc             ...  the IPC namespace\n"
     98 	    "    --uts             ...  the uts namespace\n"
     99 	    "    --user            ...  the user namespace\n"
    100 	    "    --pid             ...  the pid namespace\n"
    101 	    "    --net             ...  the network namespace\n"
    102 	    "\n"
    103 	    "Please report bugs to " PACKAGE_BUGREPORT "\n");
    104 
    105   exit(res);
    106 }
    107 
    108 static void
    109 showVersion()
    110 {
    111   WRITE_MSG(1,
    112 	    "vspace " VERSION " -- manages spaces\n"
    113 	    "This program is part of " PACKAGE_STRING "\n\n"
    114 	    "Copyright (C) 2004 Enrico Scholz\n"
    115 	    "Copyright (C) 2007 Daniel Hokka Zakrisson\n"
    116 	    VERSION_COPYRIGHT_DISCLAIMER);
    117   exit(0);
    118 }
    119 
    120 static void
    121 newSpaces(uint_least64_t mask)
    122 {
    123   pid_t pid;
    124 
    125   mask &= ~CLONE_FS;
    126 
    127   signal(SIGCHLD, SIG_DFL);
    128 
    129 #ifdef NDEBUG
    130   pid = sys_clone((int) mask | CLONE_VFORK|SIGCHLD, 0);
    131 #else
    132   pid = sys_clone((int) mask | SIGCHLD, 0);
    133 #endif
    134 
    135   switch (pid) {
    136     case -1	:
    137       perror(ENSC_WRAPPERS_PREFIX "clone()");
    138       exit(wrapper_exit_code);
    139     case 0	:
    140       break;
    141     default	:
    142       vc_exitLikeProcess(pid, wrapper_exit_code);
    143   }
    144 }
    145 
    146 static void
    147 enterSpaces(xid_t xid, uint_least64_t mask, uint32_t index)
    148 {
    149   if (vc_enter_namespace(xid, mask, index)==-1) {
    150     perror(ENSC_WRAPPERS_PREFIX "vc_enter_namespace()");
    151     exit(wrapper_exit_code);
    152   }
    153 }
    154 
    155 static void
    156 setSpaces(xid_t xid, uint_least64_t mask, uint32_t index)
    157 {
    158   if (vc_set_namespace(xid, mask, index)==-1) {
    159     perror(ENSC_WRAPPERS_PREFIX "vc_set_namespace()");
    160     exit(wrapper_exit_code);
    161   }
    162 }
    163 
    164 int main(int argc, char *argv[])
    165 {
    166   bool			do_new     = false;
    167   bool			do_enter   = false;
    168   bool			do_set     = false;
    169   uint_least64_t	mask       = 0;
    170   uint32_t		index      = 0;
    171   xid_t			xid        = VC_NOCTX;
    172   int			sum        = 0;
    173   
    174   while (1) {
    175     int			c = getopt_long(argc, argv, "+nsce:m:i:" "MFIUSPN", CMDLINE_OPTIONS, 0);
    176     uint_least64_t	thisbit = 0;
    177     if (c==-1) break;
    178 
    179     switch (c & 0xFFFF) {
    180       case CMD_HELP	:  showHelp(1, argv[0], 0);
    181       case CMD_VERSION	:  showVersion();
    182       case 'n'		:  do_new     = true; break;
    183       case 's'		:  do_set     = true; break;
    184       case 'e'		:
    185 	do_enter = true;
    186 	xid      = Evc_xidopt2xid(optarg,true);
    187 	break;
    188       case 'i'		:  {
    189 	unsigned long	index_l;
    190 	if (!isNumberUnsigned(optarg, &index_l, true)) {
    191 	  WRITE_MSG(2, "Invalid index '");
    192 	  WRITE_STR(2, optarg);
    193 	  WRITE_MSG(2, "'; try '--help' for more information\n");
    194 	  return wrapper_exit_code;
    195 	}
    196 	index = (uint32_t)index_l;
    197 	break;
    198       }
    199       case 'm'		:  {
    200 	unsigned long	mask_l;
    201 	if (!isNumberUnsigned(optarg, &mask_l, true)) {
    202 	  WRITE_MSG(2, "Invalid mask '");
    203 	  WRITE_STR(2, optarg);
    204 	  WRITE_MSG(2, "'; try '--help' for more information\n");
    205 	  return wrapper_exit_code;
    206 	}
    207 	mask = mask_l;
    208 	break;
    209       }
    210       case 'M'		:  thisbit = CLONE_NEWNS;	break;
    211       case 'F'		:  thisbit = CLONE_FS;		break;
    212       case 'I'		:  thisbit = CLONE_NEWIPC;	break;
    213       case 'U'		:  thisbit = CLONE_NEWUTS;	break;
    214       case 'S'		:  thisbit = CLONE_NEWUSER;	break;
    215       case 'P'		:  thisbit = CLONE_NEWPID;	break;
    216       case 'N'		:  thisbit = CLONE_NEWNET;	break;
    217       case 'd'		:
    218 	thisbit = vc_get_space_default();
    219 	if (thisbit == (__typeof__(thisbit)) -1) {
    220 	  thisbit = vc_get_space_mask();
    221 	  if (thisbit == (__typeof__(thisbit)) -1)
    222 	    thisbit = 0;
    223 	}
    224 	break;
    225 
    226       default		:
    227 	WRITE_MSG(2, "Try '");
    228 	WRITE_STR(2, argv[0]);
    229 	WRITE_MSG(2, " --help' for more information.\n");
    230 	return 255;
    231 	break;
    232     }
    233     /* ~ option used */
    234     if (c & 0xFFFF0000)
    235       mask &= ~thisbit;
    236     else
    237       mask |= thisbit;
    238   }
    239 
    240   sum = ((do_new ? 1 : 0) + (do_enter ? 1 : 0) +
    241 	 (do_set ? 1 : 0));
    242   
    243   if (sum==0)
    244     WRITE_MSG(2, "No operation was specified; try '--help' for more information\n");
    245   else if (sum>1)
    246     WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n");
    247   else if (optind==argc && (do_new || do_enter))
    248     WRITE_MSG(2, "No command specified; try '--help' for more information\n");
    249   else {
    250     if      (do_new)     newSpaces(mask);
    251     else if (do_set)     setSpaces(VC_SAMECTX, mask, index);
    252     else if (do_enter)   enterSpaces(xid, mask, index);
    253 
    254     if (optind<argc)
    255       EexecvpD(argv[optind], argv+optind);
    256 
    257     return EXIT_SUCCESS;
    258   }
    259 
    260   return 255;
    261 }