]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/cmd/lxc_init.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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.
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.
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
34 #include <sys/types.h>
38 #include <lxc/lxccontainer.h>
39 #include <lxc/version.h>
42 #include "initutils.h"
44 #include "namespace.h"
47 /* option keys for long only options */
48 #define OPT_USAGE 0x1000
49 #define OPT_VERSION OPT_USAGE - 1
51 #define QUOTE(macro) #macro
52 #define QUOTEVAL(macro) QUOTE(macro)
54 lxc_log_define(lxc_init
, lxc
);
56 static sig_atomic_t was_interrupted
= 0;
58 static void interrupt_handler(int sig
)
61 was_interrupted
= sig
;
64 static struct option long_options
[] = {
65 { "name", required_argument
, 0, 'n' },
66 { "help", no_argument
, 0, 'h' },
67 { "usage", no_argument
, 0, OPT_USAGE
},
68 { "version", no_argument
, 0, OPT_VERSION
},
69 { "quiet", no_argument
, 0, 'q' },
70 { "logfile", required_argument
, 0, 'o' },
71 { "logpriority", required_argument
, 0, 'l' },
72 { "lxcpath", required_argument
, 0, 'P' },
75 static char short_options
[] = "n:hqo:l:P:";
78 const struct option
*options
;
79 const char *shortopts
;
87 /* remaining arguments */
92 static int arguments_parse(struct arguments
*my_args
, int argc
,
95 static struct arguments my_args
= {
96 .options
= long_options
,
97 .shortopts
= short_options
100 static void prevent_forking(void)
106 char path
[MAXPATHLEN
];
108 f
= fopen("/proc/self/cgroup", "r");
112 while (getline(&line
, &len
, f
) != -1) {
116 p
= strchr(line
, ':');
125 /* This is a cgroup v2 entry. Skip it. */
129 if (strcmp(p
, "pids") != 0)
133 p2
+= lxc_char_left_gc(p2
, strlen(p2
));
134 p2
[lxc_char_right_gc(p2
, strlen(p2
))] = '\0';
136 ret
= snprintf(path
, sizeof(path
),
137 "/sys/fs/cgroup/pids/%s/pids.max", p2
);
138 if (ret
< 0 || (size_t)ret
>= sizeof(path
)) {
139 ERROR("Failed to create string");
143 fd
= open(path
, O_WRONLY
);
145 SYSERROR("Failed to open \"%s\"", path
);
149 if (write(fd
, "1", 1) != 1)
150 SYSERROR("Failed to write to \"%s\"", path
);
162 static void kill_children(pid_t pid
)
168 ret
= snprintf(path
, sizeof(path
), "/proc/%d/task/%d/children", pid
, pid
);
169 if (ret
< 0 || (size_t)ret
>= sizeof(path
)) {
170 ERROR("Failed to create string");
174 f
= fopen(path
, "r");
176 SYSERROR("Failed to open %s", path
);
183 if (fscanf(f
, "%d ", &pid
) != 1) {
184 ERROR("Failed to retrieve pid");
196 static void remove_self(void)
200 char path
[MAXPATHLEN
] = {0};
202 n
= readlink("/proc/self/exe", path
, sizeof(path
));
203 if (n
< 0 || n
>= MAXPATHLEN
) {
204 SYSERROR("Failed to readlink \"/proc/self/exe\"");
209 ret
= umount2(path
, MNT_DETACH
);
211 SYSERROR("Failed to unmount \"%s\"", path
);
217 SYSERROR("Failed to unlink \"%s\"", path
);
222 int main(int argc
, char *argv
[])
226 struct sigaction act
;
228 sigset_t mask
, omask
;
229 int have_status
= 0, exit_with
= 1, shutdown
= 0;
231 if (arguments_parse(&my_args
, argc
, argv
))
234 log
.prefix
= "lxc-init";
235 log
.name
= my_args
.name
;
236 log
.file
= my_args
.log_file
;
237 log
.level
= my_args
.log_priority
;
238 log
.quiet
= my_args
.quiet
;
239 log
.lxcpath
= my_args
.lxcpath
;
241 ret
= lxc_log_init(&log
);
244 lxc_log_options_no_override();
247 ERROR("Please specify a command to execute");
251 /* Mask all the signals so we are safe to install a signal handler and
254 ret
= sigfillset(&mask
);
258 ret
= sigdelset(&mask
, SIGILL
);
262 ret
= sigdelset(&mask
, SIGSEGV
);
266 ret
= sigdelset(&mask
, SIGBUS
);
270 ret
= sigprocmask(SIG_SETMASK
, &mask
, &omask
);
274 ret
= sigfillset(&act
.sa_mask
);
278 ret
= sigdelset(&act
.sa_mask
, SIGILL
);
282 ret
= sigdelset(&act
.sa_mask
, SIGSEGV
);
286 ret
= sigdelset(&act
.sa_mask
, SIGBUS
);
290 ret
= sigdelset(&act
.sa_mask
, SIGSTOP
);
294 ret
= sigdelset(&act
.sa_mask
, SIGKILL
);
299 act
.sa_handler
= interrupt_handler
;
301 for (i
= 1; i
< NSIG
; i
++) {
302 /* Exclude some signals: ILL, SEGV and BUS are likely to reveal
303 * a bug and we want a core. STOP and KILL cannot be handled
304 * anyway: they're here for documentation. 32 and 33 are not
307 if (i
== SIGILL
|| i
== SIGSEGV
|| i
== SIGBUS
||
308 i
== SIGSTOP
|| i
== SIGKILL
|| i
== 32 || i
== 33)
311 ret
= sigaction(i
, &act
, NULL
);
316 SYSERROR("Failed to change signal action");
328 /* restore default signal handlers */
329 for (i
= 1; i
< NSIG
; i
++) {
331 sigerr
= signal(i
, SIG_DFL
);
332 if (sigerr
== SIG_ERR
) {
333 DEBUG("%s - Failed to reset to default action "
334 "for signal \"%d\": %d", strerror(errno
),
339 ret
= sigprocmask(SIG_SETMASK
, &omask
, NULL
);
341 SYSERROR("Failed to set signal mask");
347 DEBUG("Failed to make child session leader");
349 if (ioctl(STDIN_FILENO
, TIOCSCTTY
, 0) < 0)
350 DEBUG("Failed to set controlling terminal");
352 NOTICE("Exec'ing \"%s\"", my_args
.argv
[0]);
354 ret
= execvp(my_args
.argv
[0], my_args
.argv
);
355 ERROR("%s - Failed to exec \"%s\"", strerror(errno
), my_args
.argv
[0]);
359 INFO("Attempting to set proc title to \"init\"");
360 setproctitle("init");
362 /* Let's process the signals now. */
363 ret
= sigdelset(&omask
, SIGALRM
);
367 ret
= sigprocmask(SIG_SETMASK
, &omask
, NULL
);
369 SYSERROR("Failed to set signal mask");
373 /* No need of other inherited fds but stderr. */
375 close(STDOUT_FILENO
);
381 switch (was_interrupted
) {
383 /* Some applications send SIGHUP in order to get init to reload
384 * its configuration. We don't want to forward this onto the
385 * application itself, because it probably isn't expecting this
386 * signal since it was expecting init to do something with it.
388 * Instead, let's explicitly ignore it here. The actual
389 * terminal case is handled in the monitor's handler, which
390 * sends this task a SIGTERM in the case of a SIGHUP, which is
398 pid_t mypid
= lxc_raw_getpid();
403 kill_children(mypid
);
405 ret
= kill(-1, SIGTERM
);
407 DEBUG("%s - Failed to send SIGTERM to "
408 "all children", strerror(errno
));
414 pid_t mypid
= lxc_raw_getpid();
418 kill_children(mypid
);
420 ret
= kill(-1, SIGKILL
);
422 DEBUG("%s - Failed to send SIGTERM to "
423 "all children", strerror(errno
));
428 ret
= kill(pid
, was_interrupted
);
430 DEBUG("%s - Failed to send signal \"%d\" to "
431 "%d", strerror(errno
), was_interrupted
, pid
);
437 waited_pid
= wait(&status
);
438 if (waited_pid
< 0) {
445 ERROR("%s - Failed to wait on child %d",
446 strerror(errno
), pid
);
450 /* Reset timer each time a process exited. */
454 /* Keep the exit code of the started application (not wrapped
455 * pid) and continue to wait for the end of the orphan group.
457 if (waited_pid
== pid
&& !have_status
) {
458 exit_with
= lxc_error_set_and_log(waited_pid
, status
);
468 static void print_usage(const struct option longopts
[])
471 fprintf(stderr
, "Usage: lxc-init [-n|--name=NAME] [-h|--help] [--usage] [--version] \n\
472 [-q|--quiet] [-o|--logfile=LOGFILE] [-l|--logpriority=LOGPRIORITY] [-P|--lxcpath=LXCPATH]\n");
476 static void print_version()
478 printf("%s\n", LXC_VERSION
);
482 static void print_help()
485 Usage: lxc-init --name=NAME -- COMMAND\n\
487 lxc-init start a COMMAND as PID 2 inside a container\n\
490 -n, --name=NAME NAME of the container\n\
491 -o, --logfile=FILE Output log to FILE instead of stderr\n\
492 -l, --logpriority=LEVEL Set log priority to LEVEL\n\
493 -q, --quiet Don't produce any output\n\
494 -P, --lxcpath=PATH Use specified container path\n\
495 -?, --help Give this help list\n\
496 --usage Give a short usage message\n\
497 --version Print the version number\n\
499 Mandatory or optional arguments to long options are also mandatory or optional\n\
500 for any corresponding short options.\n\
502 See the lxc-init man page for further information.\n\n");
506 static int arguments_parse(struct arguments
*args
, int argc
,
513 c
= getopt_long(argc
, argv
, args
->shortopts
, args
->options
, &index
);
521 args
->log_file
= optarg
;
524 args
->log_priority
= optarg
;
530 remove_trailing_slashes(optarg
);
531 args
->lxcpath
= optarg
;
534 print_usage(args
->options
);
547 * Reclaim the remaining command arguments
549 args
->argv
= &argv
[optind
];
550 args
->argc
= argc
- optind
;
552 /* If no lxcpath was given, use default */
553 if (!args
->lxcpath
) {
554 args
->lxcpath
= lxc_global_config_value("lxc.lxcpath");
557 /* Check the command options */
560 fprintf(stderr
, "lxc-init: missing container name, use --name option\n");