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 }