459cd0f14cc56a7636173f1ba5717fb1400fe557
[util-vserver.git] / src / vnamespace.c
1 // $Id: vnamespace.c,v 1.5 2004/08/19 14:31:24 ensc Exp $    --*- 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 #define CMD_HELP                0x1000
40 #define CMD_VERSION             0x1001
41
42 int             wrapper_exit_code  =  255;
43
44 struct option const
45 CMDLINE_OPTIONS[] = {
46   { "help",       no_argument,       0, CMD_HELP },
47   { "version",    no_argument,       0, CMD_VERSION },
48   { "new",        no_argument,       0, 'n' },
49   { "enter",      required_argument, 0, 'e' },
50   { "set",        no_argument,       0, 's' },
51   { "cleanup",    no_argument,       0, 'c' },
52   {0,0,0,0}
53 };
54
55 static void
56 showHelp(int fd, char const *cmd, int res)
57 {
58   WRITE_MSG(fd, "Usage: ");
59   WRITE_STR(fd, cmd);
60   WRITE_MSG(fd,
61             " <operation> [--] [<program> <args>*]\n"
62             "\n"
63             "<operation> can be one of:\n"
64             "    --new|-n          ...  create new namespace and execute <program> there;\n"
65             "                           <program> is mandatory in this case\n"
66             "    --enter|-e <xid>  ...  enter the namespace of context <xid> and execute\n"
67             "                           <program> there; <program> is mandatory in this\n"
68             "                           case\n"
69             "    --set|-s          ...  make current namespace the namespace of the\n"
70             "                           current context\n"
71             "    --cleanup|-c      ...  remove all mounts from the namespace of the\n"
72             "                           current context\n"
73             "\n"
74             "Please report bugs to " PACKAGE_BUGREPORT "\n");
75
76   exit(res);
77 }
78
79 static void
80 showVersion()
81 {
82   WRITE_MSG(1,
83             "vnamespace " VERSION " -- manages filesystem-namespace\n"
84             "This program is part of " PACKAGE_STRING "\n\n"
85             "Copyright (C) 2004 Enrico Scholz\n"
86             VERSION_COPYRIGHT_DISCLAIMER);
87   exit(0);
88 }
89
90 static void
91 newNamespace(char const *cmd)
92 {
93   pid_t         pid;
94
95   signal(SIGCHLD, SIG_DFL);
96   
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, cmd, wrapper_exit_code);
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'          :
161         do_enter = true;
162         xid      = Evc_xidopt2xid(optarg,true);
163         break;
164
165       default           :
166         WRITE_MSG(2, "Try '");
167         WRITE_STR(2, argv[0]);
168         WRITE_MSG(2, " --help\" for more information.\n");
169         return 255;
170         break;
171     }
172   }
173
174   sum = ((do_new ? 1 : 0) + (do_enter ? 1 : 0) +
175          (do_set ? 1 : 0) + (do_cleanup ? 1 : 0));
176   
177   if (sum==0)
178     WRITE_MSG(2, "No operation was specified; try '--help' for more information\n");
179   else if (sum>1)
180     WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n");
181   else if (optind==argc && (do_new || do_enter))
182     WRITE_MSG(2, "No command specified; try '--help' for more information\n");
183   else {
184     if      (do_new)     newNamespace(argv[optind]);
185     else if (do_set)     setNamespace();
186     else if (do_cleanup) cleanupNamespace();
187     else if (do_enter)   enterNamespace(xid);
188
189     if (optind<argc)
190       EexecvpD(argv[optind], argv+optind);
191
192     return EXIT_SUCCESS;
193   }
194
195   return 255;
196 }