1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
#! /usr/bin/perl
use strict;
use warnings;
use sigtrap qw(die normal-signals error-signals);
use Config;
use Errno;
use Fcntl qw(:DEFAULT);
use File::Temp 'mktemp';
use Test::More tests => 8;
use POSIX::2008;
my $perlpath = $Config{perlpath};
if ($^O ne 'VMS' && $perlpath !~ m/$Config{_exe}$/i) {
$perlpath .= $Config{_exe};
}
my $rv;
my $tmpf = mktemp('X'x20);
my $envp = {_ec_ => 73};
my $argv = ['perl', '-e', 'exit($ENV{_ec_})'];
SKIP: {
if (! defined &POSIX::2008::execveat) {
skip 'execveat() UNAVAILABLE', 4;
}
$rv = eval {
POSIX::2008::execveat(POSIX::2008::AT_FDCWD, $tmpf, 'foo', {});
};
# Note: The /i is needed because some Perls say "ARRAY", others say "array".
ok(!$rv && $@ =~ /not an ARRAY/i, 'execveat fails due to non-arrayref');
$rv = eval {
POSIX::2008::execveat(POSIX::2008::AT_FDCWD, $tmpf, [$tmpf], 'foo');
};
ok(!$rv && $@ =~ /not a HASH/, 'execveat fails due to non-hashref');
$rv = POSIX::2008::execveat(POSIX::2008::AT_FDCWD, $tmpf, [$tmpf], {});
ok(!$rv && $!{ENOENT}, "execveat fails with ENOENT for $tmpf");
my $pid = fork();
if ($pid) {
wait();
cmp_ok($?>>8, '==', 73, 'execveat() returned 73');
}
elsif (defined $pid) {
POSIX::2008::execveat(POSIX::2008::AT_FDCWD, $perlpath, $argv, $envp);
diag("execveat() failed for $perlpath: $!");
exit(1);
}
else {
die "Could not fork: $!";
}
}
SKIP: {
my $omode =
defined &POSIX::2008::O_EXEC ? &POSIX::2008::O_EXEC :
defined &POSIX::2008::O_PATH ? &POSIX::2008::O_PATH :
O_RDONLY;
if (! defined &POSIX::2008::fexecve) {
skip 'fexecve() UNAVAILABLE', 4;
}
if (! sysopen my $fh, $perlpath, $omode) {
diag("sysopen($perlpath, $omode) failed: $! (skipping fexecve() test)");
skip 'fexecve() not testable', 4;
}
$rv = eval {
POSIX::2008::fexecve(1337, 'foo', {});
};
ok(!$rv && $@ =~ /not an ARRAY/i, 'fexecve fails due to non-arrayref');
$rv = eval {
POSIX::2008::fexecve(1337, [], 'foo');
};
ok(!$rv && $@ =~ /not a HASH/, 'fexecve fails due to non-hashref');
$rv = POSIX::2008::fexecve(1337, [], {});
# ENOENT occurs when fexecve() uses execveat() with a /proc filesystem path.
ok(!$rv && ($!{ENOENT} || $!{EBADF} || $!{EINVAL}), 'fexecve fails with invalid fd');
my $pid = fork();
if ($pid) {
wait();
cmp_ok($?>>8, '==', 73, 'fexecve() returned 73');
}
elsif (defined $pid) {
my $omode =
defined &POSIX::2008::O_EXEC ? &POSIX::2008::O_EXEC :
defined &POSIX::2008::O_PATH ? &POSIX::2008::O_PATH :
O_RDONLY;
if (! sysopen my $fh, $perlpath, $omode) {
diag("sysopen($perlpath, $omode) failed: $!");
}
else {
POSIX::2008::fexecve($fh, $argv, $envp);
diag("fexecve() failed: $!");
}
exit(1);
}
else {
die "Could not fork: $!";
}
}
END {
unlink $tmpf if defined $tmpf;
}
|