]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/tools/lxc_start.c
Merge pull request #3235 from xinhua9569/master
[mirror_lxc.git] / src / lxc / tools / lxc_start.c
CommitLineData
cc73685d 1/* SPDX-License-Identifier: LGPL-2.1+ */
d06245b8 2
d38dd64a
CB
3#ifndef _GNU_SOURCE
4#define _GNU_SOURCE 1
5#endif
6#include <arpa/inet.h>
b0a33c1e 7#include <errno.h>
c36583c3 8#include <fcntl.h>
9810df07
CB
9#include <libgen.h>
10#include <net/if.h>
d38dd64a 11#include <netinet/in.h>
f8e09a0b 12#include <signal.h>
9810df07
CB
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
5e97c3fc 16#include <sys/param.h>
5e97c3fc 17#include <sys/socket.h>
c36583c3 18#include <sys/stat.h>
9810df07
CB
19#include <sys/types.h>
20#include <sys/utsname.h>
d38dd64a 21#include <unistd.h>
5e97c3fc 22
f2363e38
ÇO
23#include <lxc/lxccontainer.h>
24
fae349da 25#include "arguments.h"
eb0c9382 26#include "caps.h"
d38dd64a 27#include "config.h"
eb0c9382 28#include "confile.h"
29#include "log.h"
36eb9bde 30
eb0c9382 31lxc_log_define(lxc_start, lxc);
32
c7013c13 33static int my_parser(struct lxc_arguments *args, int c, char *arg);
720132e1 34static int ensure_path(char **confpath, const char *path);
596a818d 35
c7013c13 36static struct lxc_list defines;
a13daf8e 37
c7013c13 38static const struct option my_longopts[] = {
39 {"daemon", no_argument, 0, 'd'},
40 {"foreground", no_argument, 0, 'F'},
41 {"rcfile", required_argument, 0, 'f'},
42 {"define", required_argument, 0, 's'},
43 {"console", required_argument, 0, 'c'},
44 {"console-log", required_argument, 0, 'L'},
45 {"close-all-fds", no_argument, 0, 'C'},
46 {"pidfile", required_argument, 0, 'p'},
47 {"share-net", required_argument, 0, OPT_SHARE_NET},
48 {"share-ipc", required_argument, 0, OPT_SHARE_IPC},
49 {"share-uts", required_argument, 0, OPT_SHARE_UTS},
50 {"share-pid", required_argument, 0, OPT_SHARE_PID},
51 LXC_COMMON_OPTIONS
52};
596a818d 53
c7013c13 54static struct lxc_arguments my_args = {
55 .progname = "lxc-start",
56 .help = "\
57--name=NAME -- COMMAND\n\
58\n\
59lxc-start start COMMAND in specified container NAME\n\
60\n\
61Options :\n\
62 -n, --name=NAME NAME of the container\n\
63 -d, --daemon Daemonize the container (default)\n\
64 -F, --foreground Start with the current tty attached to /dev/console\n\
65 -p, --pidfile=FILE Create a file with the process id\n\
66 -f, --rcfile=FILE Load configuration file FILE\n\
67 -c, --console=FILE Use specified FILE for the container console\n\
68 -L, --console-log=FILE Log container console output to FILE\n\
69 -C, --close-all-fds If any fds are inherited, close them\n\
c7013c13 70 Note: --daemon implies --close-all-fds\n\
71 -s, --define KEY=VAL Assign VAL to configuration variable KEY\n\
72 --share-[net|ipc|uts|pid]=NAME Share a namespace with another container or pid\n\
73",
74 .options = my_longopts,
75 .parser = my_parser,
76 .checker = NULL,
77 .log_priority = "ERROR",
78 .log_file = "none",
79 .daemonize = 1,
80 .pidfile = NULL,
81};
596a818d 82
9810df07 83static int my_parser(struct lxc_arguments *args, int c, char *arg)
c36583c3
DL
84{
85 switch (c) {
9810df07
CB
86 case 'c':
87 args->console = arg;
88 break;
89 case 'L':
90 args->console_log = arg;
91 break;
92 case 'd':
93 args->daemonize = 1;
94 break;
95 case 'F':
96 args->daemonize = 0;
97 break;
98 case 'f':
99 args->rcfile = arg;
100 break;
101 case 'C':
b3187a81 102 args->close_all_fds = true;
9810df07
CB
103 break;
104 case 's':
105 return lxc_config_define_add(&defines, arg);
106 case 'p':
107 args->pidfile = arg;
108 break;
109 case OPT_SHARE_NET:
110 args->share_ns[LXC_NS_NET] = arg;
111 break;
112 case OPT_SHARE_IPC:
113 args->share_ns[LXC_NS_IPC] = arg;
114 break;
115 case OPT_SHARE_UTS:
116 args->share_ns[LXC_NS_UTS] = arg;
117 break;
118 case OPT_SHARE_PID:
119 args->share_ns[LXC_NS_PID] = arg;
120 break;
c36583c3
DL
121 }
122 return 0;
123}
124
720132e1 125static int ensure_path(char **confpath, const char *path)
c7013c13 126{
127 int fd;
128 char *fullpath = NULL;
9618063c 129
c7013c13 130 if (path) {
131 if (access(path, W_OK)) {
132 fd = creat(path, 0600);
133 if (fd < 0 && errno != EEXIST) {
134 ERROR("Failed to create '%s'", path);
135 return -1;
136 }
137
138 if (fd >= 0)
139 close(fd);
140 }
141
142 fullpath = realpath(path, NULL);
143 if (!fullpath) {
144 ERROR("Failed to get the real path of '%s'", path);
145 return -1;
146 }
147
148 *confpath = fullpath;
149 }
150
151 return 0;
152}
5e97c3fc 153
154int main(int argc, char *argv[])
155{
28d9e29e 156 const char *lxcpath;
91480a0f 157 char *const *args;
28d9e29e 158 struct lxc_container *c;
9810df07 159 struct lxc_log log;
28d9e29e 160 int err = EXIT_FAILURE;
91480a0f 161 char *rcfile = NULL;
9618063c 162 char *const default_args[] = {
b2b6c597 163 "/sbin/init",
13aad0ae 164 NULL,
b2b6c597 165 };
5e97c3fc 166
33ba4ad7
CLG
167 lxc_list_init(&defines);
168
0ed9cc8b 169 if (lxc_caps_init())
b52b0595 170 exit(err);
0ed9cc8b 171
e043236e 172 if (lxc_arguments_parse(&my_args, argc, argv))
b52b0595 173 exit(err);
5e97c3fc 174
9618063c 175 if (!my_args.argc)
f79d43bb 176 args = default_args;
9618063c
MN
177 else
178 args = my_args.argv;
5e97c3fc 179
c7013c13 180 log.name = my_args.name;
181 log.file = my_args.log_file;
182 log.level = my_args.log_priority;
183 log.prefix = my_args.progname;
184 log.quiet = my_args.quiet;
185 log.lxcpath = my_args.lxcpath[0];
f6d79ec1 186
c7013c13 187 if (lxc_log_init(&log))
188 exit(err);
51cab631 189
28d9e29e
CB
190 lxcpath = my_args.lxcpath[0];
191 if (access(lxcpath, O_RDONLY) < 0) {
eb0c9382 192 ERROR("You lack access to %s", lxcpath);
040f39c4
CB
193 exit(err);
194 }
195
79622932
SH
196 /*
197 * rcfile possibilities:
198 * 1. rcfile from random path specified in cli option
199 * 2. rcfile not specified, use $lxcpath/$lxcname/config
200 * 3. rcfile not specified and does not exist.
201 */
96c210bb 202 /* rcfile is specified in the cli option */
79622932 203 if (my_args.rcfile) {
96c210bb 204 rcfile = (char *)my_args.rcfile;
a13daf8e 205
69733b5d 206 c = lxc_container_new(my_args.name, lxcpath);
79622932 207 if (!c) {
eb0c9382 208 ERROR("Failed to create lxc_container");
b52b0595 209 exit(err);
79622932 210 }
a13daf8e 211
4df7f012 212 c->clear_config(c);
a13daf8e 213
79622932 214 if (!c->load_config(c, rcfile)) {
eb0c9382 215 ERROR("Failed to load rcfile");
79622932 216 lxc_container_put(c);
b52b0595 217 exit(err);
79622932 218 }
a13daf8e 219
b586db43
WB
220 c->configfile = strdup(my_args.rcfile);
221 if (!c->configfile) {
eb0c9382 222 ERROR("Out of memory setting new config filename");
b586db43
WB
223 goto out;
224 }
79622932 225 } else {
fa9ab205
NL
226 int rc;
227
79622932 228 rc = asprintf(&rcfile, "%s/%s/config", lxcpath, my_args.name);
fa9ab205 229 if (rc == -1) {
eb0c9382 230 ERROR("Failed to allocate memory");
b52b0595 231 exit(err);
96c210bb
DL
232 }
233
234 /* container configuration does not exist */
235 if (access(rcfile, F_OK)) {
236 free(rcfile);
237 rcfile = NULL;
79622932 238 }
a13daf8e 239
79622932
SH
240 c = lxc_container_new(my_args.name, lxcpath);
241 if (!c) {
eb0c9382 242 ERROR("Failed to create lxc_container");
b52b0595 243 exit(err);
96c210bb
DL
244 }
245 }
246
72c78e0e
CB
247 /* We do not check here whether the container is defined, because we
248 * support volatile containers. Which means the container does not need
249 * to be created for it to be started. You can just pass a configuration
250 * file as argument and start the container right away.
251 */
040f39c4 252 if (!c->may_control(c)) {
eb0c9382 253 ERROR("Insufficent privileges to control %s", c->name);
040f39c4
CB
254 goto out;
255 }
256
312f9c5d 257 if (c->is_running(c)) {
28b7b0f0 258 ERROR("Container is already running");
040f39c4 259 err = EXIT_SUCCESS;
312f9c5d
DY
260 goto out;
261 }
a13daf8e 262
79622932
SH
263 /*
264 * We should use set_config_item() over &defines, which would handle
265 * unset c->lxc_conf for us and let us not use lxc_config_define_load()
266 */
9810df07 267 if (!c->lxc_conf) {
eb0c9382 268 ERROR("No container config specified");
9810df07
CB
269 goto out;
270 }
fae349da 271
e2eae703 272 if (!lxc_config_define_load(&defines, c))
2d4bcb96 273 goto out;
33ba4ad7 274
f2ae79a0 275 if (!rcfile && !strcmp("/sbin/init", args[0])) {
eb0c9382 276 ERROR("Executing '/sbin/init' with no configuration file may crash the host");
2d4bcb96 277 goto out;
f2ae79a0
AN
278 }
279
c7013c13 280 if (my_args.pidfile)
720132e1 281 if (ensure_path(&c->pidfile, my_args.pidfile) < 0) {
eb0c9382 282 ERROR("Failed to ensure pidfile '%s'", my_args.pidfile);
72cf75fa
QH
283 goto out;
284 }
3114c982 285
766a3b2e
CB
286 if (my_args.console)
287 if (!c->set_config_item(c, "lxc.console.path", my_args.console))
288 goto out;
289
290 if (my_args.console_log)
291 if (!c->set_config_item(c, "lxc.console.logfile", my_args.console_log))
292 goto out;
293
4be48327
TA
294 if (!lxc_setup_shared_ns(&my_args, c))
295 goto out;
3c93577b 296
c7013c13 297 if (!my_args.daemonize)
c8ad5f46 298 c->want_daemonize(c, false);
c36583c3 299
b119f362 300 if (my_args.close_all_fds)
540f932a 301 c->want_close_all_fds(c, true);
b119f362 302
67c660d0 303 if (args == default_args)
b52b0595 304 err = c->start(c, 0, NULL) ? EXIT_SUCCESS : EXIT_FAILURE;
67c660d0 305 else
b52b0595 306 err = c->start(c, 0, args) ? EXIT_SUCCESS : EXIT_FAILURE;
307ab05d 307 if (err) {
28b7b0f0 308 ERROR("The container failed to start");
a13daf8e 309
307ab05d 310 if (my_args.daemonize)
28b7b0f0 311 ERROR("To get more details, run the container in foreground mode");
a13daf8e 312
eb0c9382 313 ERROR("Additional information can be obtained by setting the "
28b7b0f0 314 "--logfile and --logpriority options");
a13daf8e 315
d4ef230c
RV
316 err = c->error_num;
317 lxc_container_put(c);
b52b0595 318 exit(err);
307ab05d
SG
319 }
320
2d4bcb96 321out:
79622932 322 lxc_container_put(c);
b52b0595 323 exit(err);
5e97c3fc 324}