]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/tools/lxc_execute.c
tools: use correct include for Android
[mirror_lxc.git] / src / lxc / tools / lxc_execute.c
CommitLineData
cc73685d 1/* SPDX-License-Identifier: LGPL-2.1+ */
791e7a73 2
1160ce89
CB
3#include "config.h"
4
7b40d70f 5#include <errno.h>
5e97c3fc 6#include <libgen.h>
ce4a1a11
CB
7#include <stdio.h>
8#include <stdlib.h>
5e97c3fc 9#include <string.h>
7b40d70f 10#include <sys/param.h>
ce4a1a11
CB
11#include <sys/stat.h>
12#include <sys/types.h>
0072887d 13#include <sys/wait.h>
d38dd64a 14#include <unistd.h>
5e97c3fc 15
12ae2a33 16#include "lxc.h"
ce4a1a11
CB
17
18#include "arguments.h"
d899f11b 19#include "caps.h"
20#include "confile.h"
21#include "log.h"
22#include "utils.h"
23
24lxc_log_define(lxc_execute, lxc);
5e97c3fc 25
e8c0bb81 26static int my_parser(struct lxc_arguments *args, int c, char *arg);
27static bool set_argv(struct lxc_container *c, struct lxc_arguments *args);
28
20117280
CLG
29static struct lxc_list defines;
30
e8c0bb81 31static const struct option my_longopts[] = {
32 {"daemon", no_argument, 0, 'd'},
33 {"rcfile", required_argument, 0, 'f'},
34 {"define", required_argument, 0, 's'},
35 {"uid", required_argument, 0, 'u'},
36 {"gid", required_argument, 0, 'g'},
37 {"share-net", required_argument, 0, OPT_SHARE_NET},
38 {"share-ipc", required_argument, 0, OPT_SHARE_IPC},
39 {"share-uts", required_argument, 0, OPT_SHARE_UTS},
40 {"share-pid", required_argument, 0, OPT_SHARE_PID},
41 LXC_COMMON_OPTIONS
42};
43
44static struct lxc_arguments my_args = {
45 .progname = "lxc-execute",
46 .help = "\
47--name=NAME -- COMMAND\n\
48\n\
49lxc-execute creates a container with the identifier NAME\n\
50and execs COMMAND into this container.\n\
51\n\
52Options :\n\
53 -n, --name=NAME NAME of the container\n\
54 -d, --daemon Daemonize the container\n\
55 -f, --rcfile=FILE Load configuration file FILE\n\
56 -s, --define KEY=VAL Assign VAL to configuration variable KEY\n\
57 -u, --uid=UID Execute COMMAND with UID inside the container\n\
58 -g, --gid=GID Execute COMMAND with GID inside the container\n",
59 .options = my_longopts,
60 .parser = my_parser,
61 .log_priority = "ERROR",
62 .log_file = "none",
63 .daemonize = 0,
cc94aaf3
CB
64 .uid = LXC_INVALID_UID,
65 .gid = LXC_INVALID_GID,
e8c0bb81 66};
67
d899f11b 68static int my_parser(struct lxc_arguments *args, int c, char *arg)
cda02a28 69{
791e7a73
CB
70 int ret;
71
cda02a28 72 switch (c) {
be442598
CB
73 case 'd':
74 args->daemonize = 1;
75 break;
fb111ba0
CB
76 case 'f':
77 args->rcfile = arg;
78 break;
79 case 's':
791e7a73
CB
80 ret = lxc_config_define_add(&defines, arg);
81 if (ret < 0)
82 lxc_config_define_free(&defines);
fb111ba0
CB
83 break;
84 case 'u':
85 if (lxc_safe_uint(arg, &args->uid) < 0)
86 return -1;
87 break;
88 case 'g':
89 if (lxc_safe_uint(arg, &args->gid) < 0)
90 return -1;
f4bdebfd
CB
91 break;
92 case OPT_SHARE_NET:
93 args->share_ns[LXC_NS_NET] = arg;
94 break;
95 case OPT_SHARE_IPC:
96 args->share_ns[LXC_NS_IPC] = arg;
97 break;
98 case OPT_SHARE_UTS:
99 args->share_ns[LXC_NS_UTS] = arg;
100 break;
101 case OPT_SHARE_PID:
102 args->share_ns[LXC_NS_PID] = arg;
103 break;
cda02a28
MN
104 }
105 return 0;
5e97c3fc 106}
107
791e7a73 108static bool set_argv(struct lxc_container *c, struct lxc_arguments *args)
5cda27c1 109{
791e7a73 110 int ret;
3a5996ff 111 char buf[PATH_MAX];
5cda27c1
SH
112 char **components, **p;
113
0044aab0 114 buf[0] = '\0';
3a5996ff 115 ret = c->get_config_item(c, "lxc.execute.cmd", buf, PATH_MAX);
791e7a73 116 if (ret < 0)
5cda27c1
SH
117 return false;
118
791e7a73 119 components = lxc_string_split_quoted(buf);
5cda27c1
SH
120 if (!components)
121 return false;
122
123 args->argv = components;
e8c0bb81 124
5cda27c1
SH
125 for (p = components; *p; p++)
126 args->argc++;
127
128 return true;
129}
130
5e97c3fc 131int main(int argc, char *argv[])
132{
aa460476 133 struct lxc_container *c;
73b910a3 134 struct lxc_log log;
020c90b7 135 int err = EXIT_FAILURE;
13bc2fd2 136 int ret;
aa460476 137 bool bret;
5e97c3fc 138
20117280
CLG
139 lxc_list_init(&defines);
140
0ed9cc8b 141 if (lxc_caps_init())
020c90b7 142 exit(err);
0ed9cc8b 143
cda02a28 144 if (lxc_arguments_parse(&my_args, argc, argv))
020c90b7 145 exit(err);
5e97c3fc 146
e8c0bb81 147 log.name = my_args.name;
148 log.file = my_args.log_file;
149 log.level = my_args.log_priority;
150 log.prefix = my_args.progname;
151 log.quiet = my_args.quiet;
152 log.lxcpath = my_args.lxcpath[0];
153
154 if (lxc_log_init(&log))
155 exit(err);
5e97c3fc 156
aa460476
CB
157 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
158 if (!c) {
d899f11b 159 ERROR("Failed to create lxc_container");
020c90b7 160 exit(err);
aa460476 161 }
fa9ab205 162
aa460476
CB
163 if (my_args.rcfile) {
164 c->clear_config(c);
d899f11b 165
aa460476 166 if (!c->load_config(c, my_args.rcfile)) {
d899f11b 167 ERROR("Failed to load rcfile");
020c90b7 168 goto out;
96c210bb 169 }
d899f11b 170
aa460476
CB
171 c->configfile = strdup(my_args.rcfile);
172 if (!c->configfile) {
d899f11b 173 ERROR("Out of memory setting new config filename");
020c90b7 174 goto out;
96c210bb
DL
175 }
176 }
177
19bfbf6e 178 if (!c->lxc_conf) {
d899f11b 179 ERROR("Executing a container with no configuration file may crash the host");
020c90b7 180 goto out;
19bfbf6e
CB
181 }
182
e8c0bb81 183 if (my_args.argc == 0)
791e7a73 184 if (!set_argv(c, &my_args)) {
d899f11b 185 ERROR("Missing command to execute!");
020c90b7 186 goto out;
5cda27c1 187 }
5cda27c1 188
e2eae703 189 bret = lxc_config_define_load(&defines, c);
020c90b7
FA
190 if (!bret)
191 goto out;
47d556f5 192
cc94aaf3 193 if (my_args.uid != LXC_INVALID_UID) {
791e7a73
CB
194 char buf[256];
195
196 ret = snprintf(buf, 256, "%d", my_args.uid);
020c90b7
FA
197 if (ret < 0 || (size_t)ret >= 256)
198 goto out;
791e7a73 199
e2eae703 200 bret = c->set_config_item(c, "lxc.init.uid", buf);
020c90b7
FA
201 if (!bret)
202 goto out;
791e7a73
CB
203 }
204
cc94aaf3 205 if (my_args.gid != LXC_INVALID_GID) {
791e7a73 206 char buf[256];
c5cd20ce 207
791e7a73 208 ret = snprintf(buf, 256, "%d", my_args.gid);
020c90b7
FA
209 if (ret < 0 || (size_t)ret >= 256)
210 goto out;
791e7a73 211
e2eae703 212 bret = c->set_config_item(c, "lxc.init.gid", buf);
020c90b7
FA
213 if (!bret)
214 goto out;
791e7a73 215 }
0d6b9aea 216
020c90b7
FA
217 if (!lxc_setup_shared_ns(&my_args, c))
218 goto out;
4be48327 219
be442598 220 c->daemonize = my_args.daemonize == 1;
d899f11b 221
aa460476 222 bret = c->start(c, 1, my_args.argv);
6de247e3 223 if (!bret) {
d899f11b 224 ERROR("Failed run an application inside container");
020c90b7 225 goto out;
6de247e3 226 }
d899f11b 227
020c90b7
FA
228 if (c->daemonize) {
229 err = EXIT_SUCCESS;
230 } else {
e8c0bb81 231 if (WIFEXITED(c->error_num))
020c90b7 232 err = WEXITSTATUS(c->error_num);
e8c0bb81 233 else
f9eff950
TA
234 /* Try to die with the same signal the task did. */
235 kill(0, WTERMSIG(c->error_num));
f9eff950 236 }
020c90b7 237
020c90b7
FA
238out:
239 lxc_container_put(c);
240 exit(err);
5e97c3fc 241}