Add chroot(8) -I option.
This commit is contained in:
parent
bd3d7df078
commit
d1632a9706
3 changed files with 35 additions and 4 deletions
|
@ -1751,7 +1751,7 @@ int main(void)
|
||||||
unmount_all_but_root();
|
unmount_all_but_root();
|
||||||
unsetenv("SYSINSTALL_TARGET");
|
unsetenv("SYSINSTALL_TARGET");
|
||||||
unsetenv("SHLVL");
|
unsetenv("SHLVL");
|
||||||
exit(execute((const char*[]) { "chroot", "-d", fs,
|
exit(execute((const char*[]) { "chroot", "-dI", fs,
|
||||||
"/sbin/init", NULL }, "f"));
|
"/sbin/init", NULL }, "f"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
.Nd run command with changed root directory
|
.Nd run command with changed root directory
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl d
|
.Op Fl dI
|
||||||
.Ar newroot
|
.Ar newroot
|
||||||
.Oo
|
.Oo
|
||||||
.Ar command
|
.Ar command
|
||||||
|
@ -43,6 +43,12 @@ The mountpoint is removed when
|
||||||
.Ar command
|
.Ar command
|
||||||
completes.
|
completes.
|
||||||
This option is useful for running installations.
|
This option is useful for running installations.
|
||||||
|
.It Fl I , Fl \-init
|
||||||
|
Become an init process using
|
||||||
|
.Xr setinit 2
|
||||||
|
and transfer the controlling terminal temporarily to the new session using the
|
||||||
|
.Sy TIOCSCTTY
|
||||||
|
.Xr ioctl 2 .
|
||||||
.El
|
.El
|
||||||
.Sh ENVIRONMENT
|
.Sh ENVIRONMENT
|
||||||
The environment is preserved.
|
The environment is preserved.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* Runs a process with another root directory.
|
* Runs a process with another root directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
@ -47,6 +48,7 @@ static void compact_arguments(int* argc, char*** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* mount_point_dev;
|
static char* mount_point_dev;
|
||||||
|
static int tty_fd = -1;
|
||||||
|
|
||||||
static void unmount_handler(int signum)
|
static void unmount_handler(int signum)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +64,7 @@ static void unmount_handler(int signum)
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
bool devices = false;
|
bool devices = false;
|
||||||
|
bool init = false;
|
||||||
for ( int i = 1; i < argc; i++ )
|
for ( int i = 1; i < argc; i++ )
|
||||||
{
|
{
|
||||||
const char* arg = argv[i];
|
const char* arg = argv[i];
|
||||||
|
@ -76,12 +79,15 @@ int main(int argc, char* argv[])
|
||||||
while ( (c = *++arg) ) switch ( c )
|
while ( (c = *++arg) ) switch ( c )
|
||||||
{
|
{
|
||||||
case 'd': devices = true; break;
|
case 'd': devices = true; break;
|
||||||
|
case 'I': init = true; break;
|
||||||
default:
|
default:
|
||||||
errx(1, "unknown option -- '%c'", c);
|
errx(1, "unknown option -- '%c'", c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( !strcmp(arg, "--devices") )
|
else if ( !strcmp(arg, "--devices") )
|
||||||
devices = true;
|
devices = true;
|
||||||
|
else if ( !strcmp(arg, "--init") )
|
||||||
|
init = true;
|
||||||
else
|
else
|
||||||
errx(1, "unknown option: %s", arg);
|
errx(1, "unknown option: %s", arg);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +97,7 @@ int main(int argc, char* argv[])
|
||||||
if ( argc < 2 )
|
if ( argc < 2 )
|
||||||
error(1, 0, "missing operand, expected new root directory");
|
error(1, 0, "missing operand, expected new root directory");
|
||||||
|
|
||||||
bool need_cleanup = devices;
|
bool need_cleanup = devices || init;
|
||||||
|
|
||||||
// TODO: Why do we even have signal handling instead of just blocking the
|
// TODO: Why do we even have signal handling instead of just blocking the
|
||||||
// signals and waiting for the subprocess to react?
|
// signals and waiting for the subprocess to react?
|
||||||
|
@ -124,6 +130,9 @@ int main(int argc, char* argv[])
|
||||||
close(old_dev_fd);
|
close(old_dev_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( init && (tty_fd = open("/dev/tty", O_RDWR | O_CLOEXEC)) < 0 )
|
||||||
|
error(1, errno, "/dev/tty");
|
||||||
|
|
||||||
sigset_t oldset, sigs;
|
sigset_t oldset, sigs;
|
||||||
if ( need_cleanup )
|
if ( need_cleanup )
|
||||||
{
|
{
|
||||||
|
@ -156,6 +165,14 @@ int main(int argc, char* argv[])
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( init )
|
||||||
|
{
|
||||||
|
if ( setinit() < 0 )
|
||||||
|
error(1, errno, "setinit");
|
||||||
|
if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 )
|
||||||
|
error(1, errno, "TIOCSCTTY");
|
||||||
|
}
|
||||||
|
|
||||||
if ( chroot(argv[1]) != 0 )
|
if ( chroot(argv[1]) != 0 )
|
||||||
error(1, errno, "`%s'", argv[1]);
|
error(1, errno, "`%s'", argv[1]);
|
||||||
|
|
||||||
|
@ -175,8 +192,16 @@ int main(int argc, char* argv[])
|
||||||
int code;
|
int code;
|
||||||
waitpid(child_pid, &code, 0);
|
waitpid(child_pid, &code, 0);
|
||||||
sigprocmask(SIG_BLOCK, &sigs, &oldset);
|
sigprocmask(SIG_BLOCK, &sigs, &oldset);
|
||||||
|
if ( init )
|
||||||
|
{
|
||||||
|
if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 )
|
||||||
|
error(0, errno, "TIOCSCTTY");
|
||||||
|
}
|
||||||
if ( devices )
|
if ( devices )
|
||||||
unmount(mount_point_dev, 0);
|
{
|
||||||
|
if ( unmount(mount_point_dev, 0) < 0 )
|
||||||
|
error(0, errno, "unmount: %s", mount_point_dev);
|
||||||
|
}
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
mount_point_dev = NULL;
|
mount_point_dev = NULL;
|
||||||
if ( WIFEXITED(code) )
|
if ( WIFEXITED(code) )
|
||||||
|
|
Loading…
Reference in a new issue