+sub cd_cmd {
+ my $directory=$_[1];
+ if (-e $directory) {
+ chdir("$directory");
+ print "[Tesh/INFO] change directory to $directory\n";
+ } else {
+ die "[Tesh/CRITICAL] Directory not found : \"$directory\"\n";
+ }
+}
+
+sub setenv_cmd {
+ if ($_[1] =~ /^(.*)=(.*)$/) {
+ my($var,$ctn)=($1,$2);
+ $ENV{$var} = $ctn;
+ print "[Tesh/INFO] setenv $var=$ctn\n";
+ } else {
+ die "[Tesh/CRITICAL] Malformed argument to setenv: expected 'name=value' but got '$_[1]'\n";
+ }
+}
+
+my $tesh_file;
+sub get_options {
+ # remove the tesh file from the ARGV used
+ my @ARGV = @_;
+ $tesh_file = pop @ARGV;
+
+ # temporary arrays for GetOption
+ my @verbose = ();
+ my @cfg;
+
+ my %opt = (
+ "help" => 0,
+ "debug" => 0,
+ "verbose" => 0
+ );
+
+ Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev');
+
+ GetOptions(
+ 'help|h' => \$opt{'help'},
+
+ 'verbose|v' => \@verbose,
+ 'debug|d' => \$opt{"debug"},
+
+ 'cd=s' => \&cd_cmd,
+ 'setenv=s' => \&setenv_cmd,
+ 'cfg=s' => \@cfg,
+ );
+
+ $opt{'verbose'} = scalar @verbose;
+ foreach (@cfg) {
+ $opt{'cfg'} .= " --cfg=$_";
+ }
+ return %opt;
+}
+
+my %opts = get_options(@ARGV);
+
+# parse tesh file
+open SH_LIGNE, $tesh_file or die "[Tesh/CRITICAL] Unable to open $tesh_file: $!\n";
+
+while(defined($line1=<SH_LIGNE>))
+{
+ if($line1 =~ /^\< \$ /){ # arg command line
+ $line1 =~ s/\${EXEEXT:=}//g;
+ $line1 =~ s/^\< \$\ *//g;
+ $line1 =~ s/^.\/lua/lua/g;
+ $line1 =~ s/^.\/ruby/ruby/g;
+ $line1 =~ s/^.\///g;
+ $line1 =~ s/^tesh/.\/tesh/g;
+ $line1 =~ s/\(%i:%P@%h\)/\\\(%i:%P@%h\\\)/g;
+ chomp $line1;
+ $command_tesh = $line1;
+ print "[Tesh/INFO] arg_exec_line : $command_tesh\n";
+ }
+ elsif($line1 =~ /^\< \< /){ # arg buffer line
+ $line1 =~ s/^\< \<\ *//g;
+ chomp $line1;
+ print "[Tesh/INFO] arg_buffer_line : $line1\n";
+ push @buffer_tesh, "$line1\n";
+ }
+ elsif($line1 =~ /^\< \> /){ # arg output line
+ $line1 =~ s/^\< \>\ *//g;
+ $line1 =~ s/\r//g;
+ chomp $line1;
+ push @list2, $line1;
+ print "[Tesh/INFO] arg_output_line : $line1\n";
+ $expected_result_line = 1;
+ }
+ elsif($line1 =~ /^\$ mkfile/){ # "mkfile" command line
+ $line1 =~ s/\$ //g;
+ $line1 =~ s/mkfile//g;
+ chomp $line1;
+ $fich_name = $line1;
+ $line1 =();
+ print "[Tesh/INFO] exec_line : mkfile $fich_name\n";
+ `rm -f $fich_name`;
+ open(FILE,">$fich_name") or die "[Tesh/CRITICAL] Unable to make file : $fich_name. $!\n";
+ print FILE @buffer;
+ close(FILE);
+ @buffer = ();
+ }
+ elsif($line1 =~ /^\$ cd/){ # "cd" command line
+ $line1 =~ s/\$ //g;
+ chomp $line1;
+ print "[Tesh/INFO] exec_line : $line1\n";
+ $line1 =~ s/cd //g;
+ chdir("$line1") or die "[Tesh/CRITICAL] Unable to open $line1. $!\n";
+ }
+ elsif($line1 =~ /^\$ /){ #command line
+ if($line1 =~ /^\$ .\/tesh/){ # tesh command line
+ $tesh_command = 1;
+ @buffer = @buffer_tesh;
+ @buffer_tesh=();
+ }
+ $line1 =~ s/\${EXEEXT:=}//g;
+ $line1 =~ s/^\$\ *//g;
+ $line1 =~ s/^.\/lua/lua/g;
+ $line1 =~ s/^.\/ruby/ruby/g;
+ $line1 =~ s/^.\///g;
+ $line1 =~ s/^tesh/.\/tesh/g;
+ $line1 =~ s/\(%i:%P@%h\)/\\\(%i:%P@%h\\\)/g;
+ chomp $line1;
+ $line1 = "$line1 $config";
+
+ if(@list1){
+ print color("red");
+ print "[Tesh/CRITICAL] -\n";
+ print "[Tesh/CRITICAL] + @list1";
+ print color("reset"), "\n";
+ die;}
+ if(@list_of_commands){ # need parallel execution
+ push @list_of_commands, $line1;
+ print "[Tesh/INFO] exec_line : $line1\n";
+ }
+ else{
+ print "[Tesh/INFO] exec_line : $line1\n";
+ if($tesh_command)
+ { $execline = $command_tesh;
+ $tesh_command=0;}
+ else
+ { $execline = $line1;}
+ $pid = open3(\*IN, \*OUT, \*OUT, $execline );
+ if( $timeout){
+ $forked = fork();die "fork() failed: $!" unless defined $forked;
+ if ( $forked == 0 )
+ {
+ sleep $timeout;
+ kill(9, $pid);
+ exit;
+ }
+ }
+
+ while(@buffer)
+ {
+ $line1 = shift (@buffer);
+ print IN $line1;
+ }
+ close IN ;
+
+ waitpid( $pid, 0 );
+ if($timeout){kill(9, $forked);$timeout=0;}
+ $timeout = 0;
+
+ while(defined($linebis=<OUT>))
+ {
+ $linebis =~ s/\r//g;
+ $linebis =~ s/^( )*//g;
+ chomp $linebis;
+ push @list1,"$linebis";
+ }
+ close OUT;
+ $command_executed = 1;
+ }
+ }
+ elsif($line1 =~ /^\& /){ # parallel command line
+ $command_executed = 0;
+ $expected_result_line = 0;
+ $line1 =~ s/\${EXEEXT:=}//g;
+ $line1 =~ s/^\& //g;
+ $line1 =~ s/^.\/lua/lua/g;
+ $line1 =~ s/^.\/ruby/ruby/g;
+ $line1 =~ s/^.\///g;
+ $line1 =~ s/\(%i:%P@%h\)/\\\(%i:%P@%h\\\)/g;
+ chomp $line1;
+ $line1 = "$line1 $config";
+
+ $execline = "$line1";
+ print "[Tesh/INFO] exec_line : $execline\n";
+ push @list_of_commands, $execline;
+ }
+ elsif($line1 =~ /^\>/){ #expected result line
+ $line1 =~ s/^\>( )*//g;
+ $line1 =~ s/\r//g;
+ chomp $line1;
+ push @list2, $line1;
+ $expected_result_line = 1;
+ }
+ elsif($line1 =~ /^\</ or $encore==1){ #need to buffer
+ $line1 =~ s/^\<( )*//g; #delete < with space or tab after
+ $line1 =~ s/\r//g;
+ chomp $line1;
+ if($line1 =~ /\\$/) # need to store this line into old_buff