App-LXC-Container
view release on metacpan or search on metacpan
lib/App/LXC/Container/Run.pm view on Meta::CPAN
push @todo, '', '# PipeWire / PulseAudio:',
'export PULSE_SERVER=' . $self->{gateway};
}
if ($self->{x11} eq 'X' and defined $ENV{DISPLAY})
{
my $display = $ENV{DISPLAY};
debug(3, 'DISPLAY is ', $display);
push @todo, '', '# X11:', 'export DISPLAY=' . $display;
# We must pass the X11-authority for the correct display here:
if (defined $ENV{XAUTHORITY})
{
my $container_path = $self->_write_xauthority($display);
push @todo, 'export XAUTHORITY=' . $container_path;
}
}
}
# next to last build command:
push @todo, '', '# run command:', 'cd "' . $self->{dir} . '"';
my @command = @{$self->{command}};
@command > 0 or @command = (SHELL);
my $cmd = shift @command;
$cmd =~ m/'/ and fatal 'can_t_run_with__1__2', $cmd, "'";
local $_;
foreach (@command)
{
if (! m/'/)
{ $_ = "'$_'"; }
elsif (! m/"/)
{ $_ = '"' . $_ . '"'; }
else
{ fatal 'can_t_run_with__1__2', $_, "'\""; }
}
if ($self->{user} ne 'root')
{
if ($cmd eq SHELL)
{ @command = ('su', $self->{user}, '-s', SHELL); }
elsif (0 == @command)
{ @command = ('su', $self->{user}, '-s', SHELL, '-c', "'$cmd'"); }
else
{
# su with command parameters is a bit tricky, but the following
# should do the job:
$cmd .= ' "$@"'; # a literal $@ in the command line itself
unshift @command,
'su', $self->{user}, '-s', SHELL, '-c', "'$cmd'",
'--', 'dummy_argv0';
}
}
else
{ unshift @command, "'$cmd'"; }
debug(4, 'command is "exec', join(' ', @command), '"');
push @todo, join(' ', 'exec', @command);
# finally write startup script:
open my $f, '>', $self->{init}
or fatal 'can_t_open__1__2', $self->{init}, $!;
say $f $_ foreach @todo;
close $f;
# A failing chmod can only happen in very unlikely race conditions:
# uncoverable branch true
unless (chmod(0755, $self->{init}) == 1)
{
# uncoverable statement
fatal 'call_failed__1__2', 'chmod', $self->{init};
}
# TODO: We could optimise everything if we only have /bin/sh as single
# command (no script needed)!
}
#########################################################################
=head2 B<_write_xauthority> - write X11 authority file for container/user
$container_path = $self->_write_xauthority($display);
=head3 description:
This method writes an X11 authority file for the container and the user it
is run (including attached) for. It is used when the container is started
or attached and an X11 display using the environment variable C<XAUTHORITY>
exists (within C<_write_init_sh> above). The method returns the path to the
created X11 authority file as it is used inside of the container.
Note that each user needs its own writable directory for the lock-file.
=cut
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
sub _write_xauthority($$)
{
my ($self, $display) = @_;
debug(4, __PACKAGE__, '::_write_xauthority($self)');
local $_ = '/.xauth-' . $self->{user};
my $container_path = $_ . '/.Xauthority';
my $xauth_dir = $self->{root} . $_;
-d $xauth_dir
or mkdir $xauth_dir, 0700
or fatal('can_t_create__1__2', $xauth_dir, $!);
my $xauth = $xauth_dir . '/.Xauthority';
unless (-f $xauth)
{
my @entries = `xauth list`;
my $name = $self->{name};
my $entry = undef;
foreach (@entries)
{
if (s|^[^/]+(?=/[^:]+$display)|$name|)
{ $entry = $_; }
}
defined $entry
or fatal('call_failed__1__2',
'xauth list', 'no ' . $display);
debug(4, 'Xauthority entry is: ', $entry);
my $xauth_add = 'xauth -b -f ' . $xauth . ' add ' . $entry;
system($xauth_add) == 0
or fatal('call_failed__1__2', $xauth_add, $?);
if ($self->{user} ne 'root')
{
my ($uid, $gid) = (getpwnam($self->{user}))[2..3];
chown $uid, $gid, $xauth_dir, $xauth;
}
}
return $container_path;
}
( run in 0.933 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )