initial checkin
[util-vserver.git] / util-vserver / 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 "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 #include <wrappers.h>
37
38 #ifndef CLONE_NEWNS
39 #  define CLONE_NEWNS 0x00020000
40 #endif
41
42 #define CMD_HELP                0x1000
43 #define CMD_VERSION             0x1001
44
45 int             wrapper_exit_code  =  255;
46
47 struct option const
48 CMDLINE_OPTIONS[] = {
49   { "help",       no_argument,       0, CMD_HELP },
50   { "version",    no_argument,       0, CMD_VERSION },
51   { "new",        no_argument,       0, 'n' },
52   { "enter",      required_argument, 0, 'e' },
53   { "set",        no_argument,       0, 's' },
54   { "cleanup",    no_argument,       0, 'c' },
55   {0,0,0,0}
56 };
57
58 static void
59 showHelp(int fd, char const *cmd, int res)
60 {
61   WRITE_MSG(fd, "Usage: ");
62   WRITE_STR(fd, cmd);
63   WRITE_MSG(fd,
64             " <operation> [--] [<program> <args>*]\n"
65             "\n"
66             "<operation> can be one of:\n"
67             "    --new|-n          ...  create new namespace and execute <program> there;\n"
68             "                           <program> is mandatory in this case\n"
69             "    --enter|-e <xid>  ...  enter the namespace of context <xid> and execute\n"
70             "                           <program> there; <program> is mandatory in this\n"
71             "                           case\n"
72             "    --set|-s          ...  make current namespace the namespace of the\n"
73             "                           current context\n"
74             "    --cleanup|-c      ...  remove all mounts from the namespace of the\n"
75             "                           current context\n"
76             "\n"
77             "Please report bugs to " PACKAGE_BUGREPORT "\n");
78
79   exit(res);
80 }
81
82 static void
83 showVersion()
84 {
85   WRITE_MSG(1,
86             "vnamespace " VERSION " -- manages filesystem-namespace\n"
87             "This program is part of " PACKAGE_STRING "\n\n"
88             "Copyright (C) 2004 Enrico Scholz\n"
89             VERSION_COPYRIGHT_DISCLAIMER);
90   exit(0);
91 }
92
93 static void
94 newNamespace()
95 {
96   pid_t         pid;
97 #ifdef NDEBUG    
98   pid = sys_clone(CLONE_NEWNS|CLONE_VFORK|SIGCHLD, 0);
99 #else
100   pid = sys_clone(CLONE_NEWNS|SIGCHLD, 0);
101 #endif
102
103   switch (pid) {
104     case -1     :
105       perror("vnamespace: clone()");
106       exit(wrapper_exit_code);
107     case 0      :
108       break;
109     default     :
110       exitLikeProcess(pid);
111   }
112 }
113
114 static void
115 enterNamespace(xid_t xid)
116 {
117   if (vc_enter_namespace(xid)==-1) {
118     perror("vnamespace: vc_enter_namespace()");
119     exit(255);
120   }
121 }
122
123 static void
124 setNamespace()
125 {
126   if (vc_set_namespace()==-1) {
127     perror("vnamespace: vc_set_namespace()");
128     exit(255);
129   }
130 }
131
132 static void
133 cleanupNamespace()
134 {
135   if (vc_cleanup_namespace()==-1) {
136     perror("vnamespace: vc_cleanup_namespace()");
137     exit(255);
138   }
139 }
140
141 int main(int argc, char *argv[])
142 {
143   bool          do_new     = false;
144   bool          do_enter   = false;
145   bool          do_set     = false;
146   bool          do_cleanup = false;
147   xid_t         xid        = VC_NOCTX;
148   int           sum        = 0;
149   
150   while (1) {
151     int         c = getopt_long(argc, argv, "+nsce:", CMDLINE_OPTIONS, 0);
152     if (c==-1) break;
153
154     switch (c) {
155       case CMD_HELP     :  showHelp(1, argv[0], 0);
156       case CMD_VERSION  :  showVersion();
157       case 'n'          :  do_new     = true; break;
158       case 's'          :  do_set     = true; break;
159       case 'c'          :  do_cleanup = true; break;
160       case 'e'          :  do_enter   = true; xid = atol(optarg); break;
161
162       default           :
163         WRITE_MSG(2, "Try '");
164         WRITE_STR(2, argv[0]);
165         WRITE_MSG(2, " --help\" for more information.\n");
166         return 255;
167         break;
168     }
169   }
170
171   sum = ((do_new ? 1 : 0) + (do_enter ? 1 : 0) +
172          (do_set ? 1 : 0) + (do_cleanup ? 1 : 0));
173   
174   if (sum==0)
175     WRITE_MSG(2, "No operation was specified; try '--help' for more information\n");
176   else if (sum>1)
177     WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n");
178   else if (optind==argc && (do_new || do_enter))
179     WRITE_MSG(2, "No command specified; try '--help' for more information\n");
180   else {
181     if      (do_new)     newNamespace();
182     else if (do_set)     setNamespace();
183     else if (do_cleanup) cleanupNamespace();
184     else if (do_enter)   enterNamespace(xid);
185
186     if (optind<argc)
187       EexecvpD(argv[optind], argv+optind);
188
189     return EXIT_SUCCESS;
190   }
191
192   return 255;
193 }