366b9676ec3c5286fca10b9f9ac155504ea07ebc
[util-vserver.git] / src / vnamespace.c
1 // $Id$    --*- c -*--
2
3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
8 //  
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //  
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include "util.h"
24 #include <lib_internal/sys_clone.h>
25
26 #include <vserver.h>
27
28 #include <getopt.h>
29 #include <libgen.h>
30 #include <errno.h>
31 #include <signal.h>
32 #include <sched.h>
33
34 #define ENSC_WRAPPERS_PREFIX    "vnamespace: "
35 #define ENSC_WRAPPERS_UNISTD    1
36 #define ENSC_WRAPPERS_VSERVER   1
37 #include <wrappers.h>
38
39 #ifndef CLONE_NEWUTS
40 #  define CLONE_NEWUTS          0x04000000
41 #endif
42 #ifndef CLONE_NEWIPC
43 #  define CLONE_NEWIPC          0x08000000
44 #endif
45
46 #define CMD_HELP                0x1000
47 #define CMD_VERSION             0x1001
48
49 int             wrapper_exit_code  =  255;
50
51 struct option const
52 CMDLINE_OPTIONS[] = {
53   { "help",       no_argument,       0, CMD_HELP },
54   { "version",    no_argument,       0, CMD_VERSION },
55   { "new",        no_argument,       0, 'n' },
56   { "enter",      required_argument, 0, 'e' },
57   { "set",        no_argument,       0, 's' },
58   { "cleanup",    no_argument,       0, 'c' },
59   {0,0,0,0}
60 };
61
62 static void
63 showHelp(int fd, char const *cmd, int res)
64 {
65   WRITE_MSG(fd, "Usage: ");
66   WRITE_STR(fd, cmd);
67   WRITE_MSG(fd,
68             " <operation> [--] [<program> <args>*]\n"
69             "\n"
70             "<operation> can be one of:\n"
71             "    --new|-n          ...  create new namespace and execute <program> there;\n"
72             "                           <program> is mandatory in this case\n"
73             "    --enter|-e <xid>  ...  enter the namespace of context <xid> and execute\n"
74             "                           <program> there; <program> is mandatory in this\n"
75             "                           case\n"
76             "    --set|-s          ...  make current namespace the namespace of the\n"
77             "                           current context\n"
78             "    --cleanup|-c      ...  remove all mounts from the namespace of the\n"
79             "                           current context\n"
80             "\n"
81             "Please report bugs to " PACKAGE_BUGREPORT "\n");
82
83   exit(res);
84 }
85
86 static void
87 showVersion()
88 {
89   WRITE_MSG(1,
90             "vnamespace " VERSION " -- manages filesystem-namespace\n"
91             "This program is part of " PACKAGE_STRING "\n\n"
92             "Copyright (C) 2004 Enrico Scholz\n"
93             VERSION_COPYRIGHT_DISCLAIMER);
94   exit(0);
95 }
96
97 static void
98 newNamespace(char const *cmd)
99 {
100   pid_t         pid;
101
102   signal(SIGCHLD, SIG_DFL);
103   
104 #ifdef NDEBUG    
105   pid = sys_clone(CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_VFORK|SIGCHLD, 0);
106 #else
107   pid = sys_clone(CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|SIGCHLD, 0);
108 #endif
109
110   switch (pid) {
111     case -1     :
112       perror("vnamespace: clone()");
113       exit(wrapper_exit_code);
114     case 0      :
115       break;
116     default     :
117       exitLikeProcess(pid, cmd, wrapper_exit_code);
118   }
119 }
120
121 static void
122 enterNamespace(xid_t xid)
123 {
124   if (vc_enter_namespace(xid)==-1) {
125     perror("vnamespace: vc_enter_namespace()");
126     exit(255);
127   }
128 }
129
130 static void
131 setNamespace()
132 {
133   if (vc_set_namespace()==-1) {
134     perror("vnamespace: vc_set_namespace()");
135     exit(255);
136   }
137 }
138
139 static void
140 cleanupNamespace()
141 {
142   if (vc_cleanup_namespace()==-1) {
143     perror("vnamespace: vc_cleanup_namespace()");
144     exit(255);
145   }
146 }
147
148 int main(int argc, char *argv[])
149 {
150   bool          do_new     = false;
151   bool          do_enter   = false;
152   bool          do_set     = false;
153   bool          do_cleanup = false;
154   xid_t         xid        = VC_NOCTX;
155   int           sum        = 0;
156   
157   while (1) {
158     int         c = getopt_long(argc, argv, "+nsce:", CMDLINE_OPTIONS, 0);
159     if (c==-1) break;
160
161     switch (c) {
162       case CMD_HELP     :  showHelp(1, argv[0], 0);
163       case CMD_VERSION  :  showVersion();
164       case 'n'          :  do_new     = true; break;
165       case 's'          :  do_set     = true; break;
166       case 'c'          :  do_cleanup = true; break;
167       case 'e'          :
168         do_enter = true;
169         xid      = Evc_xidopt2xid(optarg,true);
170         break;
171
172       default           :
173         WRITE_MSG(2, "Try '");
174         WRITE_STR(2, argv[0]);
175         WRITE_MSG(2, " --help' for more information.\n");
176         return 255;
177         break;
178     }
179   }
180
181   sum = ((do_new ? 1 : 0) + (do_enter ? 1 : 0) +
182          (do_set ? 1 : 0) + (do_cleanup ? 1 : 0));
183   
184   if (sum==0)
185     WRITE_MSG(2, "No operation was specified; try '--help' for more information\n");
186   else if (sum>1)
187     WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n");
188   else if (optind==argc && (do_new || do_enter))
189     WRITE_MSG(2, "No command specified; try '--help' for more information\n");
190   else {
191     if      (do_new)     newNamespace(argv[optind]);
192     else if (do_set)     setNamespace();
193     else if (do_cleanup) cleanupNamespace();
194     else if (do_enter)   enterNamespace(xid);
195
196     if (optind<argc)
197       EexecvpD(argv[optind], argv+optind);
198
199     return EXIT_SUCCESS;
200   }
201
202   return 255;
203 }