my $tesh_name;
my $error=0;
my $exitcode=0;
+my @bg_cmds;
$path =~ s|[^/]*$||;
push @INC,$path;
}
else{
$OS = "WIN";
+ $ENV{"PRINTF_EXPONENT_DIGITS"} = "2";
}
sub exit_status {
my $status = shift;
if (POSIX::WIFEXITED($status)) {
+ $exitcode=POSIX::WEXITSTATUS($status)+40;
return "returned code ".POSIX::WEXITSTATUS($status);
} elsif (POSIX::WIFSIGNALED($status)) {
- my $code;
- if (POSIX::WTERMSIG($status) == SIGINT){$code="SIGINT"; }
- elsif (POSIX::WTERMSIG($status) == SIGTERM) {$code="SIGTERM"; }
- elsif (POSIX::WTERMSIG($status) == SIGKILL) {$code= "SIGKILL"; }
- elsif (POSIX::WTERMSIG($status) == SIGABRT) {$code="SIGABRT"; }
- elsif (POSIX::WTERMSIG($status) == SIGSEGV) {$code="SIGSEGV" ;}
- $exitcode=POSIX::WTERMSIG($status)+4;
- return "got signal $code";
+ my $code;
+ if (POSIX::WTERMSIG($status) == SIGINT){$code="SIGINT"; }
+ elsif (POSIX::WTERMSIG($status) == SIGTERM) {$code="SIGTERM"; }
+ elsif (POSIX::WTERMSIG($status) == SIGKILL) {$code= "SIGKILL"; }
+ elsif (POSIX::WTERMSIG($status) == SIGABRT) {$code="SIGABRT"; }
+ elsif (POSIX::WTERMSIG($status) == SIGSEGV) {$code="SIGSEGV" ;}
+ $exitcode=POSIX::WTERMSIG($status)+4;
+ return "got signal $code";
}
return "Unparsable status. Is the process stopped?";
}
###
# exec the command line
- ###
- $pid = open3(\*CHILD_IN, \*OUT, \*OUT, $cmd{'cmd'} );
+ ### $line =~ s/\r//g;
+
+ $cmd{'got'} = IO::File->new_tmpfile;
+ $cmd{'got'}->autoflush(1);
+ local *E = $cmd{'got'};
+ $cmd{'pid'} = open3(\*CHILD_IN, ">&E", ">&E", $cmd{'cmd'} );
# push all provided input to executing child
- map { print CHILD_IN "$_\n" } @{$cmd{'in'}};
+ map { print CHILD_IN "$_\n"; } @{$cmd{'in'}};
close CHILD_IN;
# if timeout specified, fork and kill executing child at the end of timeout
die "fork() failed: $!" unless defined $forked;
if ( $forked == 0 ) { # child
sleep $time_to_wait;
- kill(9, $pid);
+ kill(SIGKILL, $cmd{'pid'});
exit $time_to_wait;
}
}
+
+ # Cleanup the executing child, and kill the timeouter brother on need
+ $cmd{'return'} = 0 unless defined($cmd{'return'});
+ if($cmd{'background'} != 1){
+ waitpid ($cmd{'pid'}, 0);
+ $cmd{'gotret'} = exit_status($?);
+ parse_out(\%cmd);
+ }else{
+ # & commands, which will be handled at the end
+ push @bg_cmds, \%cmd;
+ # no timeout for background commands
+ if($forked){
+ kill(SIGKILL, $forked);
+ $timeout=0;
+ $forked=0;
+ }
+ }
+}
+
+sub parse_out {
+ my %cmd = %{$_[0]};
+ my $gotret=$cmd{'gotret'};
+
+ my $wantret;
+
+ if(defined($cmd{'expect'}) and ($cmd{'expect'} ne "")){
+ $wantret = "got signal $cmd{'expect'}";
+ }else{
+ $wantret = "returned code ".(defined($cmd{'return'})? $cmd{'return'} : 0);
+ }
+
+ local *got = $cmd{'got'};
+ seek(got,0,0);
# pop all output from executing child
my @got;
- while(defined(my $got=<OUT>)) {
+ while(defined(my $got=<got>)) {
$got =~ s/\r//g;
$got =~ s/^( )*//g;
chomp $got;
}
}
}
- close OUT;
-
+
if ($cmd{'sort'}){
sub mysort{
$a cmp $b
@{$cmd{'out'}}=sort mysort @{$cmd{'out'}};
}
}
-
- # Cleanup the executing child, and kill the timeouter brother on need
- $cmd{'return'} = 0 unless defined($cmd{'return'});
- my $wantret;
- if(defined($cmd{'expect'}) and ($cmd{'expect'} ne "")){
- $wantret = "got signal $cmd{'expect'}";
- }else{
- $wantret = "returned code ".(defined($cmd{'return'})? $cmd{'return'} : 0);
- $exitcode= 41;
- }
- my $gotret;
- waitpid ($pid, 0);
- $gotret = exit_status($?);
+
#Did we timeout ? If yes, handle it. If not, kill the forked process.
if($timeout==-1 and $gotret eq "got signal SIGKILL"){
my $file = $cmd{'arg'};
print "[Tesh/INFO] mkfile $file\n";
- die "[TESH/CRITICAL] no input provided to mkfile\n" unless defined($cmd{'in'}) && scalar @{$cmd{'in'}};
unlink($file);
open(FILE,">$file") or die "[Tesh/CRITICAL] Unable to create file $file: $!\n";
print FILE join("\n", @{$cmd{'in'}});
$line_num++;
chomp $line;
- if($line!=~/\s/){
- next LINE;
- }
+ $line =~ s/\r//g;
print "[TESH/debug] $line_num: $line\n" if $opts{'debug'};
my $next;
# deal with line continuations
}
# Push delayed commands on empty lines
- unless ($line =~ m/^(.)\s*(.*)$/) {
- if (defined($cmd{'cmd'})) {
+ unless ($line =~ m/^(.).(.*)$/) {
+ if (defined($cmd{'cmd'})) {
exec_cmd(\%cmd);
%cmd = ();
}
}
$cmd{'output ignore'} = 1;
}
- elsif($line =~ /^!\s*expect signal (\w*)$/) {#expect signal SIGABRT
+ elsif($line =~ /^!\s*expect signal (\w*)/) {#expect signal SIGABRT
if (defined($cmd{'cmd'})) {
exec_cmd(\%cmd);
%cmd = ();
}
+print "hey\n";
$cmd{'expect'} = "$1";
}
elsif($line =~ /^!\s*expect return/){ #expect return
} else {
die "[TESH/CRITICAL] parse error: $line\n";
}
+ if($forked){
+ kill(SIGKILL, $forked);
+ $timeout=0;
+ }
+
}
if($forked){
- kill(9, $forked);
+ kill(SIGKILL, $forked);
$timeout=0;
}
+foreach(@bg_cmds){
+ my %test=%{$_};
+ waitpid ($test{'pid'}, 0);
+ $test{'gotret'} = exit_status($?);
+ parse_out(\%test);
+}
+
+@bg_cmds=();
+
+
if($error !=0){
exit $exitcode;
}elsif($tesh_file eq "(stdin)"){