use URI::Escape;
use Encode;
use Digest::SHA1;
+use Text::ParseWords;
+use String::ShellQuote;
our @EXPORT_OK = qw(
lock_file
$cmd = [ $cmd ] if !ref($cmd);
- my $cmdstr = join (' ', @$cmd);
+ my $cmdstr = cmd2string($cmd);
my $errmsg;
my $laststderr;
my $oldtimeout;
my $pid;
+ my $outfunc;
+ my $errfunc;
+ my $logfunc;
+ my $input;
+ my $output;
+
eval {
- my $input;
- my $output;
- my $outfunc;
- my $errfunc;
- my $logfunc;
foreach my $p (keys %param) {
if ($p eq 'timeout') {
umask($param{$p});
} elsif ($p eq 'errmsg') {
$errmsg = $param{$p};
- $errfunc = sub {
- print STDERR "$laststderr\n" if $laststderr;
- $laststderr = shift;
- };
} elsif ($p eq 'input') {
$input = $param{$p};
} elsif ($p eq 'output') {
}
}
+ if ($errmsg) {
+ my $origerrfunc = $errfunc;
+ $errfunc = sub {
+ if ($laststderr) {
+ if ($origerrfunc) {
+ &$origerrfunc("$laststderr\n");
+ } else {
+ print STDERR "$laststderr\n" if $laststderr;
+ }
+ }
+ $laststderr = shift;
+ };
+ }
+
my $reader = $output && $output =~ m/^>&/ ? $output : IO::File->new();
my $writer = $input && $input =~ m/^<&/ ? $input : IO::File->new();
my $error = IO::File->new();
alarm(0);
- print STDERR "$laststderr\n" if $laststderr;
+ if ($errmsg && $laststderr) {
+ &$errfunc(undef); # flush laststderr
+ }
umask ($old_umask) if defined($old_umask);
my $outfh = IO::File->new ($filename, O_WRONLY|O_CREAT|O_EXCL, $perm) ||
die "unable to create output file '$filename' - $!\n";
- chown $wwwid, $outfh;
+ chown $wwwid, -1, $outfh;
return $outfh;
};
sub shellquote {
my $str = shift;
- return "''" if !defined ($str) || ($str eq '');
-
- die "unable to quote string containing null (\\000) bytes"
- if $str =~ m/\x00/;
+ return String::ShellQuote::shell_quote($str);
+}
- # from String::ShellQuote
- if ($str =~ m|[^\w!%+,\-./:@^]|) {
+sub cmd2string {
+ my ($cmd) = @_;
- # ' -> '\''
- $str =~ s/'/'\\''/g;
+ die "no arguments" if !$cmd;
- $str = "'$str'";
- $str =~ s/^''//;
- $str =~ s/''$//;
- }
+ return $cmd if !ref($cmd);
- return $str;
+ my @qa = ();
+ foreach my $arg (@$cmd) { push @qa, shellquote($arg); }
+
+ return join (' ', @qa);
}
-# a clumsy way to split an shell argument string into an array,
-# we simply pass it to the cli (exec call)
-# fixme: use Text::ParseWords::shellwords() ?
+# split an shell argument string into an array,
sub split_args {
my ($str) = @_;
- my $args = [];
+ return $str ? [ Text::ParseWords::shellwords($str) ] : [];
+}
- return $args if !$str;
+sub dump_logfile {
+ my ($filename, $start, $limit) = @_;
- my $cmd = 'perl -e \'foreach my $a (@ARGV) { print "$a\n"; } \' -- ' . $str;
+ my $lines = [];
+ my $count = 0;
- eval {
- run_command($cmd, outfunc => sub {
- my $data = shift;
- push @$args, $data;
- });
- };
+ my $fh = IO::File->new($filename, "r");
+ if (!$fh) {
+ $count++;
+ push @$lines, { n => $count, t => "unable to open file - $!"};
+ return ($count, $lines);
+ }
- my $err = $@;
+ $start = 0 if !$start;
+ $limit = 50 if !$limit;
+
+ my $line;
+ while (defined($line = <$fh>)) {
+ next if $count++ < $start;
+ next if $limit <= 0;
+ chomp $line;
+ push @$lines, { n => $count, t => $line};
+ $limit--;
+ }
- die "unable to parse args: $str\n" if $err;
+ close($fh);
+
+ # HACK: ExtJS store.guaranteeRange() does not like empty array
+ # so we add a line
+ if (!$count) {
+ $count++;
+ push @$lines, { n => $count, t => "no content"};
+ }
- return $args;
+ return ($count, $lines);
}
1;