+#eval {
+ use POSIX;
+
+ 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";
+ }
+ return "Unparsable status. Is the process stopped?";
+ }
+#};
+#if ($@) { # no POSIX available?
+# warn "POSIX not usable to parse the return value of forked child: $@\n";
+# sub exit_status {
+# return "returned code -1 $@ ";
+# }
+#}
+
+sub exec_cmd {
+ my %cmd = %{$_[0]};
+ if ($opts{'debug'}) {
+ print "IN BEGIN\n";
+ map {print " $_"} @{$cmd{'in'}};
+ print "IN END\n";
+ print "OUT BEGIN\n";
+ map {print " $_"} @{$cmd{'out'}};
+ print "OUT END\n";
+ print "CMD: $cmd{'cmd'}\n";
+ }
+
+ # cleanup the command line
+ if($OS eq "WIN"){
+ $cmd{'cmd'} =~ s/\${EXEEXT:=}/.exe/g;
+ $cmd{'cmd'} =~ s/\${EXEEXT}/.exe/g;
+ $cmd{'cmd'} =~ s/\$EXEEXT/.exe/g;
+ }
+ else{
+ $cmd{'cmd'} =~ s/\${EXEEXT:=}//g;
+ }
+ $cmd{'cmd'} =~ s/\${bindir:=}/$bindir/g;
+ $cmd{'cmd'} =~ s/\${srcdir:=}/$srcdir/g;
+ $cmd{'cmd'} =~ s/\${bindir:=.}/$bindir/g;
+ $cmd{'cmd'} =~ s/\${srcdir:=.}/$srcdir/g;
+ $cmd{'cmd'} =~ s/\${bindir}/$bindir/g;
+ $cmd{'cmd'} =~ s/\${srcdir}/$srcdir/g;
+# $cmd{'cmd'} =~ s|^\./||g;
+# $cmd{'cmd'} =~ s|tesh|tesh.pl|g;
+ $cmd{'cmd'} =~ s/\(%i:%P@%h\)/\\\(%i:%P@%h\\\)/g;
+ $cmd{'cmd'} .= " $opts{'cfg'}" if (defined($opts{'cfg'}) && length($opts{'cfg'}));
+
+ print "[$tesh_name:$cmd{'line'}] $cmd{'cmd'}\n" ;
+
+ ###
+ # exec the command line
+ ### $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'}};
+ close CHILD_IN;
+
+ # if timeout specified, fork and kill executing child at the end of timeout
+ if (defined($cmd{'timeout'}) or defined($opts{'timeout'})){
+ $time_to_wait= defined($cmd{'timeout'}) ? $cmd{'timeout'} : $opts{'timeout'};
+ $forked = fork();
+ $timeout=-1;
+ die "fork() failed: $!" unless defined $forked;
+ if ( $forked == 0 ) { # child
+ sleep $time_to_wait;
+ kill(SIGKILL, $cmd{'pid'});
+ exit $time_to_wait;