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