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