summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Thykier <niels@thykier.net>2022-10-30 10:44:33 +0000
committerNiels Thykier <niels@thykier.net>2022-10-30 10:44:33 +0000
commit62a8608ebc02fb6d2627cdcb0a1719cbf04be1b1 (patch)
tree454ad9f0499f0c8decb566f9579e7fccdedad0a5
parent5f76c46240e5b9b28af5b6b4e3185bbc5bb61114 (diff)
Dh_Lib.pm: `qx_cmd` support env/chdir changes like `doit`
Closes: #1016354 Signed-off-by: Niels Thykier <niels@thykier.net>
-rw-r--r--lib/Debian/Debhelper/Dh_Lib.pm59
1 files changed, 35 insertions, 24 deletions
diff --git a/lib/Debian/Debhelper/Dh_Lib.pm b/lib/Debian/Debhelper/Dh_Lib.pm
index cdce0026..0b35ab58 100644
--- a/lib/Debian/Debhelper/Dh_Lib.pm
+++ b/lib/Debian/Debhelper/Dh_Lib.pm
@@ -488,6 +488,35 @@ sub print_and_doit_noerror {
goto \&_doit;
}
+sub _post_fork_setup_and_exec {
+ my ($close_stdin, $options, @cmd) = @_;
+ if (defined($options)) {
+ if (defined(my $dir = $options->{chdir})) {
+ if ($dir ne '.') {
+ chdir($dir) or error("chdir(\"${dir}\") failed: $!");
+ }
+ }
+ if ($close_stdin) {
+ open(STDIN, '<', '/dev/null') or error("redirect STDIN failed: $!");
+ }
+ if (defined(my $output = $options->{stdout})) {
+ open(STDOUT, '>', $output) or error("redirect STDOUT failed: $!");
+ }
+ if (defined(my $update_env = $options->{update_env})) {
+ while (my ($k, $v) = each(%{$update_env})) {
+ if (defined($v)) {
+ $ENV{$k} = $v;
+ } else {
+ delete($ENV{$k});
+ }
+ }
+ }
+ }
+ # Force execvp call to avoid shell. Apparently, even exec can
+ # involve a shell if you don't do this.
+ exec { $cmd[0] } @cmd or error('exec (for cmd: ' . escape_shell(@cmd) . ") failed: $!");
+}
+
sub _doit {
my (@cmd) = @_;
my $options = ref($cmd[0]) ? shift(@cmd) : undef;
@@ -501,29 +530,7 @@ sub _doit {
return 1 if $dh{NO_ACT};
my $pid = fork() // error("fork(): $!");
if (not $pid) {
- if (defined($options)) {
- if (defined(my $dir = $options->{chdir})) {
- if ($dir ne '.') {
- chdir($dir) or error("chdir(\"${dir}\") failed: $!");
- }
- }
- open(STDIN, '<', '/dev/null') or error("redirect STDIN failed: $!");
- if (defined(my $output = $options->{stdout})) {
- open(STDOUT, '>', $output) or error("redirect STDOUT failed: $!");
- }
- if (defined(my $update_env = $options->{update_env})) {
- while (my ($k, $v) = each(%{$update_env})) {
- if (defined($v)) {
- $ENV{$k} = $v;
- } else {
- delete($ENV{$k});
- }
- }
- }
- }
- # Force execvp call to avoid shell. Apparently, even exec can
- # involve a shell if you don't do this.
- exec { $cmd[0] } @cmd;
+ _post_fork_setup_and_exec(1, $options, @cmd) // error("Assertion error: sub should not return!");
}
return waitpid($pid, 0) == $pid && $? == 0;
}
@@ -562,8 +569,12 @@ sub _format_cmdline {
sub qx_cmd {
my (@cmd) = @_;
+ my $options = ref($cmd[0]) ? shift(@cmd) : undef;
my ($output, @output);
- open(my $fd, '-|', @cmd) or error('fork+exec (' . escape_shell(@cmd) . "): $!");
+ my $pid = open(my $fd, '-|') // error('fork (for cmd: ' . escape_shell(@cmd) . ") failed: $!");
+ if ($pid == 0) {
+ _post_fork_setup_and_exec(0, $options, @cmd) // error("Assertion error: sub should not return!");
+ }
if (wantarray) {
@output = <$fd>;
} else {