1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/types.h>
26 #include <sys/syscall.h>
27 #include <sys/mount.h>
33 #include <sys/prctl.h>
34 #include <sys/capability.h>
36 #include <sys/epoll.h>
38 #include <sys/signalfd.h>
42 #include <sys/socket.h>
44 #include <systemd/sd-daemon.h>
51 #include "cgroup-util.h"
53 #include "loopback-setup.h"
55 static char *arg_directory = NULL;
56 static char *arg_user = NULL;
57 static char **arg_controllers = NULL;
58 static char *arg_uuid = NULL;
59 static bool arg_private_network = false;
60 static bool arg_read_only = false;
61 static bool arg_boot = false;
63 static int help(void) {
65 printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
66 "Spawn a minimal namespace container for debugging, testing and building.\n\n"
67 " -h --help Show this help\n"
68 " -D --directory=NAME Root directory for the container\n"
69 " -b --boot Boot up full system (i.e. invoke init)\n"
70 " -u --user=USER Run the command under specified user or uid\n"
71 " -C --controllers=LIST Put the container in specified comma-separated cgroup hierarchies\n"
72 " --uuid=UUID Set a specific machine UUID for the container\n"
73 " --private-network Disable network in container\n"
74 " --read-only Mount the root directory read-only\n",
75 program_invocation_short_name);
80 static int parse_argv(int argc, char *argv[]) {
83 ARG_PRIVATE_NETWORK = 0x100,
88 static const struct option options[] = {
89 { "help", no_argument, NULL, 'h' },
90 { "directory", required_argument, NULL, 'D' },
91 { "user", required_argument, NULL, 'u' },
92 { "controllers", required_argument, NULL, 'C' },
93 { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
94 { "boot", no_argument, NULL, 'b' },
95 { "uuid", required_argument, NULL, ARG_UUID },
96 { "read-only", no_argument, NULL, ARG_READ_ONLY },
105 while ((c = getopt_long(argc, argv, "+hD:u:C:b", options, NULL)) >= 0) {
115 arg_directory = canonicalize_file_name(optarg);
116 if (!arg_directory) {
117 log_error("Failed to canonicalize root directory.");
125 if (!(arg_user = strdup(optarg))) {
126 log_error("Failed to duplicate user name.");
133 strv_free(arg_controllers);
134 arg_controllers = strv_split(optarg, ",");
135 if (!arg_controllers) {
136 log_error("Failed to split controllers list.");
139 strv_uniq(arg_controllers);
143 case ARG_PRIVATE_NETWORK:
144 arg_private_network = true;
156 arg_read_only = true;
163 log_error("Unknown option code %c", c);
171 static int mount_all(const char *dest) {
173 typedef struct MountPoint {
182 static const MountPoint mount_table[] = {
183 { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
184 { "/proc/sys", "/proc/sys", "bind", NULL, MS_BIND, true }, /* Bind mount first */
185 { "/proc/sys", "/proc/sys", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
186 { "/sys", "/sys", "bind", NULL, MS_BIND, true }, /* Bind mount first */
187 { "/sys", "/sys", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true }, /* Then, make it r/o */
188 { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true },
189 { "/dev/pts", "/dev/pts", "bind", NULL, MS_BIND, true },
190 { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true },
192 { "/sys/fs/selinux", "/sys/fs/selinux", "bind", NULL, MS_BIND, false }, /* Bind mount first */
193 { "/sys/fs/selinux", "/sys/fs/selinux", "bind", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false }, /* Then, make it r/o */
201 for (k = 0; k < ELEMENTSOF(mount_table); k++) {
204 if (asprintf(&where, "%s/%s", dest, mount_table[k].where) < 0) {
205 log_error("Out of memory");
213 t = path_is_mount_point(where, false);
215 log_error("Failed to detect whether %s is a mount point: %s", where, strerror(-t));
224 mkdir_p(where, 0755);
226 if (mount(mount_table[k].what,
229 mount_table[k].flags,
230 mount_table[k].options) < 0 &&
231 mount_table[k].fatal) {
233 log_error("mount(%s) failed: %m", where);
245 static int setup_timezone(const char *dest) {
250 /* Fix the timezone, if possible */
251 if (asprintf(&where, "%s/etc/localtime", dest) < 0) {
252 log_error("Out of memory");
256 if (mount("/etc/localtime", where, "bind", MS_BIND, NULL) >= 0)
257 mount("/etc/localtime", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
261 if (asprintf(&where, "%s/etc/timezone", dest) < 0) {
262 log_error("Out of memory");
266 if (mount("/etc/timezone", where, "bind", MS_BIND, NULL) >= 0)
267 mount("/etc/timezone", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
274 static int setup_resolv_conf(const char *dest) {
279 if (arg_private_network)
282 /* Fix resolv.conf, if possible */
283 if (asprintf(&where, "%s/etc/resolv.conf", dest) < 0) {
284 log_error("Out of memory");
288 if (mount("/etc/resolv.conf", where, "bind", MS_BIND, NULL) >= 0)
289 mount("/etc/resolv.conf", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
296 static int copy_devnodes(const char *dest) {
298 static const char devnodes[] =
316 NULSTR_FOREACH(d, devnodes) {
318 char *from = NULL, *to = NULL;
320 asprintf(&from, "/dev/%s", d);
321 asprintf(&to, "%s/dev/%s", dest, d);
324 log_error("Failed to allocate devnode path");
337 if (stat(from, &st) < 0) {
339 if (errno != ENOENT) {
340 log_error("Failed to stat %s: %m", from);
345 } else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
347 log_error("%s is not a char or block device, cannot copy.", from);
351 } else if (mknod(to, st.st_mode, st.st_rdev) < 0) {
353 log_error("mknod(%s) failed: %m", dest);
367 static int setup_dev_console(const char *dest, const char *console) {
378 if (stat(console, &st) < 0) {
379 log_error("Failed to stat %s: %m", console);
383 } else if (!S_ISCHR(st.st_mode)) {
384 log_error("/dev/console is not a char device.");
389 r = chmod_and_chown(console, 0600, 0, 0);
391 log_error("Failed to correct access mode for TTY: %s", strerror(-r));
395 if (asprintf(&to, "%s/dev/console", dest) < 0) {
396 log_error("Out of memory");
401 /* We need to bind mount the right tty to /dev/console since
402 * ptys can only exist on pts file systems. To have something
403 * to bind mount things on we create a device node first, that
404 * has the right major/minor (note that the major minor
405 * doesn't actually matter here, since we mount it over
408 if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) {
409 log_error("mknod() for /dev/console failed: %m");
414 if (mount(console, to, "bind", MS_BIND, NULL) < 0) {
415 log_error("Bind mount for /dev/console failed: %m");
427 static int setup_kmsg(const char *dest, int kmsg_socket) {
428 char *from = NULL, *to = NULL;
432 struct cmsghdr cmsghdr;
433 uint8_t buf[CMSG_SPACE(sizeof(int))];
436 struct cmsghdr *cmsg;
439 assert(kmsg_socket >= 0);
443 /* We create the kmsg FIFO as /dev/kmsg, but immediately
444 * delete it after bind mounting it to /proc/kmsg. While FIFOs
445 * on the reading side behave very similar to /proc/kmsg,
446 * their writing side behaves differently from /dev/kmsg in
447 * that writing blocks when nothing is reading. In order to
448 * avoid any problems with containers deadlocking due to this
449 * we simply make /dev/kmsg unavailable to the container. */
450 if (asprintf(&from, "%s/dev/kmsg", dest) < 0) {
451 log_error("Out of memory");
456 if (asprintf(&to, "%s/proc/kmsg", dest) < 0) {
457 log_error("Out of memory");
462 if (mkfifo(from, 0600) < 0) {
463 log_error("mkfifo() for /dev/kmsg failed: %m");
468 r = chmod_and_chown(from, 0600, 0, 0);
470 log_error("Failed to correct access mode for /dev/kmsg: %s", strerror(-r));
474 if (mount(from, to, "bind", MS_BIND, NULL) < 0) {
475 log_error("Bind mount for /proc/kmsg failed: %m");
480 fd = open(from, O_RDWR|O_NDELAY|O_CLOEXEC);
482 log_error("Failed to open fifo: %m");
490 mh.msg_control = &control;
491 mh.msg_controllen = sizeof(control);
493 cmsg = CMSG_FIRSTHDR(&mh);
494 cmsg->cmsg_level = SOL_SOCKET;
495 cmsg->cmsg_type = SCM_RIGHTS;
496 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
497 memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
499 mh.msg_controllen = cmsg->cmsg_len;
501 /* Store away the fd in the socket, so that it stays open as
502 * long as we run the child */
503 k = sendmsg(kmsg_socket, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
504 close_nointr_nofail(fd);
507 log_error("Failed to send FIFO fd: %m");
512 /* And now make the FIFO unavailable as /dev/kmsg... */
523 static int setup_hostname(void) {
527 hn = file_name_from_path(arg_directory);
533 hostname_cleanup(hn);
536 if (sethostname(hn, strlen(hn)) < 0)
545 static int drop_capabilities(void) {
546 static const unsigned long retain[] = {
556 CAP_NET_BIND_SERVICE,
572 for (l = 0; l <= cap_last_cap(); l++) {
575 for (i = 0; i < ELEMENTSOF(retain); i++)
579 if (i < ELEMENTSOF(retain))
582 if (prctl(PR_CAPBSET_DROP, l) < 0) {
583 log_error("PR_CAPBSET_DROP failed: %m");
591 static int is_os_tree(const char *path) {
594 /* We use /bin/sh as flag file if something is an OS */
596 if (asprintf(&p, "%s/bin/sh", path) < 0)
602 return r < 0 ? 0 : 1;
605 static int process_pty(int master, sigset_t *mask) {
607 char in_buffer[LINE_MAX], out_buffer[LINE_MAX];
608 size_t in_buffer_full = 0, out_buffer_full = 0;
609 struct epoll_event stdin_ev, stdout_ev, master_ev, signal_ev;
610 bool stdin_readable = false, stdout_writable = false, master_readable = false, master_writable = false;
611 int ep = -1, signal_fd = -1, r;
613 fd_nonblock(STDIN_FILENO, 1);
614 fd_nonblock(STDOUT_FILENO, 1);
615 fd_nonblock(master, 1);
617 if ((signal_fd = signalfd(-1, mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0) {
618 log_error("signalfd(): %m");
623 if ((ep = epoll_create1(EPOLL_CLOEXEC)) < 0) {
624 log_error("Failed to create epoll: %m");
630 stdin_ev.events = EPOLLIN|EPOLLET;
631 stdin_ev.data.fd = STDIN_FILENO;
634 stdout_ev.events = EPOLLOUT|EPOLLET;
635 stdout_ev.data.fd = STDOUT_FILENO;
638 master_ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
639 master_ev.data.fd = master;
642 signal_ev.events = EPOLLIN;
643 signal_ev.data.fd = signal_fd;
645 if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev) < 0 ||
646 epoll_ctl(ep, EPOLL_CTL_ADD, STDOUT_FILENO, &stdout_ev) < 0 ||
647 epoll_ctl(ep, EPOLL_CTL_ADD, master, &master_ev) < 0 ||
648 epoll_ctl(ep, EPOLL_CTL_ADD, signal_fd, &signal_ev) < 0) {
649 log_error("Failed to regiser fds in epoll: %m");
655 struct epoll_event ev[16];
659 if ((nfds = epoll_wait(ep, ev, ELEMENTSOF(ev), -1)) < 0) {
661 if (errno == EINTR || errno == EAGAIN)
664 log_error("epoll_wait(): %m");
671 for (i = 0; i < nfds; i++) {
672 if (ev[i].data.fd == STDIN_FILENO) {
674 if (ev[i].events & (EPOLLIN|EPOLLHUP))
675 stdin_readable = true;
677 } else if (ev[i].data.fd == STDOUT_FILENO) {
679 if (ev[i].events & (EPOLLOUT|EPOLLHUP))
680 stdout_writable = true;
682 } else if (ev[i].data.fd == master) {
684 if (ev[i].events & (EPOLLIN|EPOLLHUP))
685 master_readable = true;
687 if (ev[i].events & (EPOLLOUT|EPOLLHUP))
688 master_writable = true;
690 } else if (ev[i].data.fd == signal_fd) {
691 struct signalfd_siginfo sfsi;
694 if ((n = read(signal_fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
697 log_error("Failed to read from signalfd: invalid block size");
702 if (errno != EINTR && errno != EAGAIN) {
703 log_error("Failed to read from signalfd: %m");
709 if (sfsi.ssi_signo == SIGWINCH) {
712 /* The window size changed, let's forward that. */
713 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
714 ioctl(master, TIOCSWINSZ, &ws);
723 while ((stdin_readable && in_buffer_full <= 0) ||
724 (master_writable && in_buffer_full > 0) ||
725 (master_readable && out_buffer_full <= 0) ||
726 (stdout_writable && out_buffer_full > 0)) {
728 if (stdin_readable && in_buffer_full < LINE_MAX) {
730 if ((k = read(STDIN_FILENO, in_buffer + in_buffer_full, LINE_MAX - in_buffer_full)) < 0) {
732 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
733 stdin_readable = false;
735 log_error("read(): %m");
740 in_buffer_full += (size_t) k;
743 if (master_writable && in_buffer_full > 0) {
745 if ((k = write(master, in_buffer, in_buffer_full)) < 0) {
747 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
748 master_writable = false;
750 log_error("write(): %m");
756 assert(in_buffer_full >= (size_t) k);
757 memmove(in_buffer, in_buffer + k, in_buffer_full - k);
762 if (master_readable && out_buffer_full < LINE_MAX) {
764 if ((k = read(master, out_buffer + out_buffer_full, LINE_MAX - out_buffer_full)) < 0) {
766 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
767 master_readable = false;
769 log_error("read(): %m");
774 out_buffer_full += (size_t) k;
777 if (stdout_writable && out_buffer_full > 0) {
779 if ((k = write(STDOUT_FILENO, out_buffer, out_buffer_full)) < 0) {
781 if (errno == EAGAIN || errno == EPIPE || errno == ECONNRESET || errno == EIO)
782 stdout_writable = false;
784 log_error("write(): %m");
790 assert(out_buffer_full >= (size_t) k);
791 memmove(out_buffer, out_buffer + k, out_buffer_full - k);
792 out_buffer_full -= k;
800 close_nointr_nofail(ep);
803 close_nointr_nofail(signal_fd);
808 int main(int argc, char *argv[]) {
810 int r = EXIT_FAILURE, k;
811 char *oldcg = NULL, *newcg = NULL;
812 char **controller = NULL;
814 const char *console = NULL;
815 struct termios saved_attr, raw_attr;
817 bool saved_attr_valid = false;
819 int kmsg_socket_pair[2] = { -1, -1 };
821 log_parse_environment();
824 if ((r = parse_argv(argc, argv)) <= 0)
830 p = path_make_absolute_cwd(arg_directory);
834 arg_directory = get_current_dir_name();
836 if (!arg_directory) {
837 log_error("Failed to determine path");
841 path_kill_slashes(arg_directory);
843 if (geteuid() != 0) {
844 log_error("Need to be root.");
848 if (sd_booted() <= 0) {
849 log_error("Not running on a systemd system.");
853 if (path_equal(arg_directory, "/")) {
854 log_error("Spawning container on root directory not supported.");
858 if (is_os_tree(arg_directory) <= 0) {
859 log_error("Directory %s doesn't look like an OS root directory. Refusing.", arg_directory);
863 if ((k = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &oldcg)) < 0) {
864 log_error("Failed to determine current cgroup: %s", strerror(-k));
868 if (asprintf(&newcg, "%s/nspawn-%lu", oldcg, (unsigned long) getpid()) < 0) {
869 log_error("Failed to allocate cgroup path.");
873 k = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, newcg, 0);
875 log_error("Failed to create cgroup: %s", strerror(-k));
879 STRV_FOREACH(controller,arg_controllers) {
880 k = cg_create_and_attach(*controller, newcg, 0);
882 log_warning("Failed to create cgroup in controller %s: %s", *controller, strerror(-k));
885 if ((master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY)) < 0) {
886 log_error("Failed to acquire pseudo tty: %m");
890 if (!(console = ptsname(master))) {
891 log_error("Failed to determine tty name: %m");
895 log_info("Spawning namespace container on %s (console is %s).", arg_directory, console);
897 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
898 ioctl(master, TIOCSWINSZ, &ws);
900 if (unlockpt(master) < 0) {
901 log_error("Failed to unlock tty: %m");
905 if (tcgetattr(STDIN_FILENO, &saved_attr) < 0) {
906 log_error("Failed to get terminal attributes: %m");
910 saved_attr_valid = true;
912 raw_attr = saved_attr;
913 cfmakeraw(&raw_attr);
914 raw_attr.c_lflag &= ~ECHO;
916 if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr) < 0) {
917 log_error("Failed to set terminal attributes: %m");
921 if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
922 log_error("Failed to create kmsg socket pair");
926 assert_se(sigemptyset(&mask) == 0);
927 sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
928 assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
930 pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWIPC|CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWUTS|(arg_private_network ? CLONE_NEWNET : 0), NULL);
933 log_error("clone() failed, do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in): %m");
935 log_error("clone() failed: %m");
943 const char *home = NULL;
944 uid_t uid = (uid_t) -1;
945 gid_t gid = (gid_t) -1;
946 const char *envp[] = {
947 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
948 "container=systemd-nspawn", /* LXC sets container=lxc, so follow the scheme here */
953 NULL, /* container_uuid */
957 envp[2] = strv_find_prefix(environ, "TERM=");
959 close_nointr_nofail(master);
961 close_nointr(STDIN_FILENO);
962 close_nointr(STDOUT_FILENO);
963 close_nointr(STDERR_FILENO);
965 close_all_fds(&kmsg_socket_pair[1], 1);
967 reset_all_signal_handlers();
969 assert_se(sigemptyset(&mask) == 0);
970 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
975 if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
978 /* Mark / as private, in case somebody marked it shared */
979 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0)
982 /* Turn directory into bind mount */
983 if (mount(arg_directory, arg_directory, "bind", MS_BIND, NULL) < 0) {
984 log_error("Failed to make bind mount.");
989 if (mount(arg_directory, arg_directory, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
990 log_error("Failed to make read-only.");
994 if (mount_all(arg_directory) < 0)
997 if (copy_devnodes(arg_directory) < 0)
1000 if (setup_dev_console(arg_directory, console) < 0)
1003 if (setup_kmsg(arg_directory, kmsg_socket_pair[1]) < 0)
1006 close_nointr_nofail(kmsg_socket_pair[1]);
1008 if (setup_timezone(arg_directory) < 0)
1011 if (setup_resolv_conf(arg_directory) < 0)
1014 if (chdir(arg_directory) < 0) {
1015 log_error("chdir(%s) failed: %m", arg_directory);
1019 if (open_terminal("dev/console", O_RDWR) != STDIN_FILENO ||
1020 dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
1021 dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
1024 if (mount(arg_directory, "/", "bind", MS_MOVE, NULL) < 0) {
1025 log_error("mount(MS_BIND) failed: %m");
1029 if (chroot(".") < 0) {
1030 log_error("chroot() failed: %m");
1034 if (chdir("/") < 0) {
1035 log_error("chdir() failed: %m");
1043 if (drop_capabilities() < 0)
1048 if (get_user_creds((const char**)&arg_user, &uid, &gid, &home) < 0) {
1049 log_error("get_user_creds() failed: %m");
1053 if (mkdir_parents(home, 0775) < 0) {
1054 log_error("mkdir_parents() failed: %m");
1058 if (safe_mkdir(home, 0775, uid, gid) < 0) {
1059 log_error("safe_mkdir() failed: %m");
1063 if (initgroups((const char*)arg_user, gid) < 0) {
1064 log_error("initgroups() failed: %m");
1068 if (setresgid(gid, gid, gid) < 0) {
1069 log_error("setregid() failed: %m");
1073 if (setresuid(uid, uid, uid) < 0) {
1074 log_error("setreuid() failed: %m");
1079 if ((asprintf((char**)(envp + 3), "HOME=%s", home ? home: "/root") < 0) ||
1080 (asprintf((char**)(envp + 4), "USER=%s", arg_user ? arg_user : "root") < 0) ||
1081 (asprintf((char**)(envp + 5), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)) {
1082 log_error("Out of memory");
1087 if (asprintf((char**)(envp + 6), "container_uuid=%s", arg_uuid) < 0) {
1088 log_error("Out of memory");
1099 /* Automatically search for the init system */
1101 l = 1 + argc - optind;
1102 a = newa(char*, l + 1);
1103 memcpy(a + 1, argv + optind, l * sizeof(char*));
1105 a[0] = (char*) "/usr/lib/systemd/systemd";
1106 execve(a[0], a, (char**) envp);
1108 a[0] = (char*) "/lib/systemd/systemd";
1109 execve(a[0], a, (char**) envp);
1111 a[0] = (char*) "/sbin/init";
1112 execve(a[0], a, (char**) envp);
1113 } else if (argc > optind)
1114 execvpe(argv[optind], argv + optind, (char**) envp);
1116 chdir(home ? home : "/root");
1117 execle("/bin/bash", "-bash", NULL, (char**) envp);
1120 log_error("execv() failed: %m");
1123 _exit(EXIT_FAILURE);
1126 if (process_pty(master, &mask) < 0)
1129 if (saved_attr_valid) {
1130 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
1131 saved_attr_valid = false;
1134 r = wait_for_terminate_and_warn(argc > optind ? argv[optind] : "bash", pid);
1140 if (saved_attr_valid)
1141 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
1144 close_nointr_nofail(master);
1146 close_pipe(kmsg_socket_pair);
1149 cg_attach(SYSTEMD_CGROUP_CONTROLLER, oldcg, 0);
1152 cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, newcg, true);
1154 free(arg_directory);
1155 strv_free(arg_controllers);