]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/tools/lxc_execute.c
tree-wide: fix includes to fix bionic builds
[mirror_lxc.git] / src / lxc / tools / lxc_execute.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #ifndef _GNU_SOURCE
25 #define _GNU_SOURCE 1
26 #endif
27 #include <errno.h>
28 #include <libgen.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/param.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <unistd.h>
37
38 #include <lxc/lxccontainer.h>
39
40 #include "arguments.h"
41 #include "caps.h"
42 #include "config.h"
43 #include "confile.h"
44 #include "log.h"
45 #include "utils.h"
46
47 lxc_log_define(lxc_execute, lxc);
48
49 static int my_parser(struct lxc_arguments *args, int c, char *arg);
50 static bool set_argv(struct lxc_container *c, struct lxc_arguments *args);
51
52 static struct lxc_list defines;
53
54 static const struct option my_longopts[] = {
55 {"daemon", no_argument, 0, 'd'},
56 {"rcfile", required_argument, 0, 'f'},
57 {"define", required_argument, 0, 's'},
58 {"uid", required_argument, 0, 'u'},
59 {"gid", required_argument, 0, 'g'},
60 {"share-net", required_argument, 0, OPT_SHARE_NET},
61 {"share-ipc", required_argument, 0, OPT_SHARE_IPC},
62 {"share-uts", required_argument, 0, OPT_SHARE_UTS},
63 {"share-pid", required_argument, 0, OPT_SHARE_PID},
64 LXC_COMMON_OPTIONS
65 };
66
67 static struct lxc_arguments my_args = {
68 .progname = "lxc-execute",
69 .help = "\
70 --name=NAME -- COMMAND\n\
71 \n\
72 lxc-execute creates a container with the identifier NAME\n\
73 and execs COMMAND into this container.\n\
74 \n\
75 Options :\n\
76 -n, --name=NAME NAME of the container\n\
77 -d, --daemon Daemonize the container\n\
78 -f, --rcfile=FILE Load configuration file FILE\n\
79 -s, --define KEY=VAL Assign VAL to configuration variable KEY\n\
80 -u, --uid=UID Execute COMMAND with UID inside the container\n\
81 -g, --gid=GID Execute COMMAND with GID inside the container\n",
82 .options = my_longopts,
83 .parser = my_parser,
84 .log_priority = "ERROR",
85 .log_file = "none",
86 .daemonize = 0,
87 };
88
89 static int my_parser(struct lxc_arguments *args, int c, char *arg)
90 {
91 int ret;
92
93 switch (c) {
94 case 'd':
95 args->daemonize = 1;
96 break;
97 case 'f':
98 args->rcfile = arg;
99 break;
100 case 's':
101 ret = lxc_config_define_add(&defines, arg);
102 if (ret < 0)
103 lxc_config_define_free(&defines);
104 break;
105 case 'u':
106 if (lxc_safe_uint(arg, &args->uid) < 0)
107 return -1;
108 break;
109 case 'g':
110 if (lxc_safe_uint(arg, &args->gid) < 0)
111 return -1;
112 break;
113 case OPT_SHARE_NET:
114 args->share_ns[LXC_NS_NET] = arg;
115 break;
116 case OPT_SHARE_IPC:
117 args->share_ns[LXC_NS_IPC] = arg;
118 break;
119 case OPT_SHARE_UTS:
120 args->share_ns[LXC_NS_UTS] = arg;
121 break;
122 case OPT_SHARE_PID:
123 args->share_ns[LXC_NS_PID] = arg;
124 break;
125 }
126 return 0;
127 }
128
129 static bool set_argv(struct lxc_container *c, struct lxc_arguments *args)
130 {
131 int ret;
132 char buf[MAXPATHLEN];
133 char **components, **p;
134
135 buf[0] = '\0';
136 ret = c->get_config_item(c, "lxc.execute.cmd", buf, MAXPATHLEN);
137 if (ret < 0)
138 return false;
139
140 components = lxc_string_split_quoted(buf);
141 if (!components)
142 return false;
143
144 args->argv = components;
145
146 for (p = components; *p; p++)
147 args->argc++;
148
149 return true;
150 }
151
152 int main(int argc, char *argv[])
153 {
154 struct lxc_container *c;
155 struct lxc_log log;
156 int err = EXIT_FAILURE;
157 int ret;
158 bool bret;
159
160 lxc_list_init(&defines);
161
162 if (lxc_caps_init())
163 exit(err);
164
165 if (lxc_arguments_parse(&my_args, argc, argv))
166 exit(err);
167
168 log.name = my_args.name;
169 log.file = my_args.log_file;
170 log.level = my_args.log_priority;
171 log.prefix = my_args.progname;
172 log.quiet = my_args.quiet;
173 log.lxcpath = my_args.lxcpath[0];
174
175 if (lxc_log_init(&log))
176 exit(err);
177
178 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
179 if (!c) {
180 ERROR("Failed to create lxc_container");
181 exit(err);
182 }
183
184 if (my_args.rcfile) {
185 c->clear_config(c);
186
187 if (!c->load_config(c, my_args.rcfile)) {
188 ERROR("Failed to load rcfile");
189 goto out;
190 }
191
192 c->configfile = strdup(my_args.rcfile);
193 if (!c->configfile) {
194 ERROR("Out of memory setting new config filename");
195 goto out;
196 }
197 }
198
199 if (!c->lxc_conf) {
200 ERROR("Executing a container with no configuration file may crash the host");
201 goto out;
202 }
203
204 if (my_args.argc == 0)
205 if (!set_argv(c, &my_args)) {
206 ERROR("Missing command to execute!");
207 goto out;
208 }
209
210 bret = lxc_config_define_load(&defines, c);
211 if (!bret)
212 goto out;
213
214 if (my_args.uid) {
215 char buf[256];
216
217 ret = snprintf(buf, 256, "%d", my_args.uid);
218 if (ret < 0 || (size_t)ret >= 256)
219 goto out;
220
221 bret = c->set_config_item(c, "lxc.init.uid", buf);
222 if (!bret)
223 goto out;
224 }
225
226 if (my_args.gid) {
227 char buf[256];
228
229 ret = snprintf(buf, 256, "%d", my_args.gid);
230 if (ret < 0 || (size_t)ret >= 256)
231 goto out;
232
233 bret = c->set_config_item(c, "lxc.init.gid", buf);
234 if (!bret)
235 goto out;
236 }
237
238 if (!lxc_setup_shared_ns(&my_args, c))
239 goto out;
240
241 c->daemonize = my_args.daemonize == 1;
242
243 bret = c->start(c, 1, my_args.argv);
244 if (!bret) {
245 ERROR("Failed run an application inside container");
246 goto out;
247 }
248
249 if (c->daemonize) {
250 err = EXIT_SUCCESS;
251 } else {
252 if (WIFEXITED(c->error_num))
253 err = WEXITSTATUS(c->error_num);
254 else
255 /* Try to die with the same signal the task did. */
256 kill(0, WTERMSIG(c->error_num));
257 }
258
259 out:
260 lxc_container_put(c);
261 exit(err);
262 }