BATsh
view release on metacpan or search on metacpan
child-process helpers used a single quoted shell string for
system(), which cmd.exe re-wraps in an extra pair of double
quotes and mis-parses ("filename, directory name, or volume
label syntax is incorrect"). Rewritten to use LIST-form
system() (bypasses the shell entirely) with STDIN/STDOUT
redirected at the Perl level via dup/reopen instead of a
shell "<"/">" string. lib/BATsh.pm itself was unaffected; this
was a test-harness-only bug. Re-verified on Linux (16/16).
Desk review of the Win32-specific code paths (no Windows host
available in this environment): BATsh::SH::_bg_launch_decoded()
uses system(1, $cmdline) (P_NOWAIT) to background a job on
Win32; the success/failure check (defined $pid && $pid > 0)
matches the documented Win32 system(1, ...) contract (PID on
success, 0 on failure). t/0016's _run_child() LIST-form
system($^X, "-I$lib", $pm, $prog, @args) calls CreateProcess
directly and does not re-enter cmd.exe, so the original
quote-re-wrapping failure mode cannot recur. _bg_tempfile()'s
temp-directory selection already accounts for %TEMP%/%TMP% and
backslash path separators. No logic defects found in review;
confirmation on an actual Windows host (locale, path-length,
lib/BATsh/MB.pm view on Meta::CPAN
my $n = scalar @{$chars};
$off = $n + $off if $off < 0;
$off = 0 if $off < 0;
return '' if $off >= $n;
my $end = defined $len ? $off + $len : $n;
$end = $n if $end > $n;
return '' if $end <= $off;
return enc(join('', @{$chars}[$off .. $end - 1]));
}
# Split RAW (decoded) DBCS bytes into characters, forward-scanning:
# a lead byte followed by a valid trail byte forms one two-byte
# character; anything else is a single byte.
sub _mb_chars {
my ($s) = @_;
my @c = ();
my $i = 0;
my $n = length($s);
while ($i < $n) {
my $b = substr($s, $i, 1);
if ($b =~ /[$LEAD]/ && $i + 1 < $n
lib/BATsh/SH.pm view on Meta::CPAN
# and returns the PID directly.
# Unix-like : delegate to /bin/sh so the job is backgrounded without a
# Perl fork; the shell's $! (the job PID) is written to a
# temp file and read back into BATsh's own $!.
# On a successful launch $? (LAST_STATUS) is 0; the exit code of the
# background job itself is not awaited (sh semantics).
# _bg_launch: un-guard the command line, then hand it to the platform-
# specific spawner below (system(1,...) on Win32, "&" on POSIX).
sub _bg_launch {
my ($class, $cmdline) = @_;
return _bg_launch_decoded($class, BATsh::MB::dec($cmdline));
}
sub _bg_launch_decoded {
my ($class, $cmdline) = @_;
$cmdline = '' unless defined $cmdline;
return 0 if $cmdline =~ /\A\s*\z/;
BATsh::Env->sync_to_env();
if ($^O =~ /MSWin32/i) {
my $pid = system(1, $cmdline);
if (defined $pid && $pid > 0) {
$_LAST_BG_PID = $pid;
$LAST_STATUS = 0;
( run in 0.754 second using v1.01-cache-2.11-cpan-9169edd2b0e )