Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
last version of tesh
[simgrid.git] / tools / tesh2 / src / command.c
1
2 #include <command.h>
3 #include <context.h>
4 #include <writer.h>
5 #include <reader.h>
6 #include <timer.h>
7
8 #ifndef WIN32
9 #include <sys/types.h>
10 #include <sys/wait.h>
11 #endif
12
13 #include "../include/_signal.h"
14
15
16
17 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
18
19 static void sig_io_handler(int status)
20 {
21         INFO0("*************************Got a SIGIO**************************************");    
22 }
23
24 static void*
25 command_start(void* p);
26
27 command_t
28 command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
29 {
30         command_t command = xbt_new0(s_command_t, 1);
31         
32         /* get the context of the execution of the command */
33         command->context = context_dup(context);
34         
35         /* the exit code of the command is indefinite */
36         command->exit_code = INDEFINITE;
37         
38         /* the signal of the command is indefinite */
39         command->signal = INDEFINITE_SIGNAL;
40         
41         command->failed = 0;
42         command->interrupted = 0;
43         
44         /* the mutex used to safetly access to the command unit properties */
45         command->mutex = mutex;
46         
47         if(context->output->used)
48                 /* instantiate the buffer filled with the content of the command stdout */
49                 command->output = xbt_strbuff_new();
50         else
51                 command->output = NULL;
52
53         command->pid = INDEFINITE_PID;
54         
55         command->stat_val = -1;
56         
57         /* set the unit of the command */
58         command->unit = unit->root ? unit->root : unit; 
59         
60         /* all the commands are runned in a thread */
61         command->thread = NULL;
62         
63         command->successeded = 0;
64         
65         if(context->output->used)
66                 command->reader = reader_new(command);
67         else
68                 command->reader = NULL;
69
70         if(context->input->used)
71                 command->writer = writer_new(command);
72         else
73                 command->writer = NULL;
74
75         if(context->timeout != INDEFINITE)
76                 command->timer = timer_new(command);
77         else
78                 command->timer = NULL;
79
80         command->status = cs_initialized;
81         command->reason = csr_unknown;
82         
83         command->stdin_fd = INDEFINITE_FD;
84         command->stdout_fd = INDEFINITE_FD;
85         
86         
87         /* register the command */
88         xbt_os_mutex_acquire(mutex);
89         
90         vector_push_back(unit->commands, command);
91         
92         (command->unit->number_of_commands)++;
93         
94         xbt_os_mutex_release(mutex);
95         
96         command->fn_sig_io_handler = sig_io_handler;
97         
98         #ifndef WIN32
99         command->killed = 0;
100         #endif
101         
102         
103
104         return command;
105 }
106
107 void
108 command_run(command_t command)
109 {
110         if(!want_silent)
111                 INFO1("tesh %s",command->context->command_line);
112         
113         if(!want_just_display)
114         {       
115                 if(!interrupted)
116                 {
117                         /* start the command */
118                         
119                         if(command->context->async)
120                         {
121                                 command->thread = xbt_os_thread_create("", command_start, command);
122                         
123                                 if(!command->thread)
124                                         ERROR0("xbt_os_thread_create() failed\n");
125                         }
126                         else
127                                 command_start(command);
128                 }
129                 else
130                 {
131                         command_interrupt(command);             
132                 }
133         }
134
135 }
136
137 static void*
138 command_start(void* p)
139 {
140         command_t command = (command_t)p;
141         unit_t unit = command->unit;
142         
143         /* the command is started */
144         command->status = cs_started;
145         
146         /* increment the number of started commands of the unit */
147         xbt_os_mutex_acquire(command->mutex);
148         (command->unit->number_of_started_commands)++;
149         xbt_os_mutex_release(command->mutex);
150         
151         /* execute the command of the test */
152         command_exec(command, command->context->command_line);
153         
154         if(cs_in_progress == command->status)
155         {
156                 /*printf("the command %p is in progress\n",command);*/
157                 
158                 /* on attend la fin de la commande.
159                  * la command peut soit se terminée normalement,
160                  * soit se terminée à la suite d'un timeout, d'une erreur de lecture des son reader ou d'une erreur d'écriture de son writer
161                  * soit à la suit d'une demande d'interruption
162                  */
163                 
164                 command_wait(command);
165         
166                 if(cs_failed != command->status && cs_interrupted != command->status)
167                 {
168                         /*printf("checking the command %p\n",command);*/
169                         command_check(command);
170                 }
171         }
172         
173         
174         xbt_os_mutex_acquire(command->mutex);
175         
176         /* if it's the last command release its unit */
177         if(!unit->interrupted && unit->parsed && (unit->number_of_started_commands == (unit->number_of_failed_commands + unit->number_of_interrupted_commands + unit->number_of_successeded_commands)))
178         {
179                 /* first release the mutex */
180                 unit->released = 1;
181                 xbt_os_mutex_release(command->mutex);
182                 /* the last command release the unit */
183                 xbt_os_sem_release(command->unit->sem);
184         }
185         else
186                 xbt_os_mutex_release(command->mutex);
187                 
188         
189         /* wait the end of the timer, the reader and the writer */
190         if(command->timer && command->timer->thread)
191                 timer_wait(command->timer);
192
193         if(command->writer && command->writer->thread)
194                 writer_wait(command->writer);
195
196         if(command->reader && command->reader->thread)
197                 reader_wait(command->reader);
198         
199         return NULL;
200 }
201
202 #ifdef WIN32
203 void
204 command_exec(command_t command, const char* command_line)
205 {
206         
207         STARTUPINFO si = {0};                                   /* contains the informations about the child process windows*/
208         PROCESS_INFORMATION pi = {0};                   /* contains child process informations                                          */
209         SECURITY_ATTRIBUTES sa = {0};                   /* contains the security descriptor for the pipe handles        */
210         HANDLE child_stdin_handle[2] = {NULL};  /* child_stdin_handle[1]        <-> stdout of the child process */
211         HANDLE child_stdout_handle[2] = {NULL}; /* child_stdout_handle[0]       <-> stdin of the child process  */
212         HANDLE child_stderr = NULL;
213         
214         sa.nLength = sizeof(SECURITY_ATTRIBUTES);
215     sa.lpSecurityDescriptor = NULL;                     /* use default security for the pipe handles                            */
216         
217         sa.bInheritHandle = TRUE;                               /* the pipe handles can be inherited                                            */
218         
219         if(!CreatePipe(&(child_stdin_handle[0]),&(child_stdin_handle[1]),&sa,0))
220     {
221                 ERROR1("CreatePipe1() failed (%lu)",GetLastError());
222                 command->failed = 1;
223                 command->status = cs_failed;    
224
225                 return;
226     }
227         
228         
229         if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[1]),GetCurrentProcess(),&(child_stderr),0,TRUE,DUPLICATE_SAME_ACCESS))
230     {
231                 ERROR1("DuplicateHandle1() failed (%lu)",GetLastError());
232                 
233                 CloseHandle(child_stdin_handle[0]);
234                 CloseHandle(child_stdin_handle[1]);
235
236                 command->failed = 1;
237                 command->status = cs_failed;    
238
239                 return;
240     }
241         
242         if(!CreatePipe(&(child_stdout_handle[0]),&(child_stdout_handle[1]),&sa,0))
243     {
244                 ERROR1("CreatePipe2() failed (%lu)",GetLastError()); 
245                 
246                 CloseHandle(child_stdout_handle[0]);
247                 CloseHandle(child_stdout_handle[1]);
248                 CloseHandle(child_stdin_handle[0]);
249                 CloseHandle(child_stdin_handle[1]);
250
251                 command->failed = 1;
252                 command->status = cs_failed;    
253
254                 return;
255     }
256                 
257         /* Read handle for read operations on the child std output. */
258         if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[0]),GetCurrentProcess(),&(command->stdout_fd),0,FALSE, DUPLICATE_SAME_ACCESS))
259     {
260                 CloseHandle(child_stdout_handle[0]);
261                 CloseHandle(child_stdout_handle[1]);
262                 CloseHandle(child_stdin_handle[0]);
263                 CloseHandle(child_stdin_handle[1]);
264
265                 command->failed = 1;
266                 command->status = cs_failed;    
267
268                 ERROR1("DuplicateHandle2() failed (%lu)",GetLastError()); 
269     }
270         
271         
272         /* Write handle for write operations on the child std input. */
273         if(!DuplicateHandle(GetCurrentProcess(),(child_stdout_handle[1]),GetCurrentProcess(),&(command->stdin_fd), 0,FALSE,DUPLICATE_SAME_ACCESS))
274     {
275                 CloseHandle(child_stdout_handle[0]);
276                 CloseHandle(child_stdout_handle[1]);
277                 CloseHandle(child_stdin_handle[0]);
278                 CloseHandle(child_stdin_handle[1]);
279
280                 command->failed = 1;
281                 command->status = cs_failed;    
282
283                 ERROR1("DuplicateHandle3() failed (%lu)",GetLastError());
284     }
285
286         
287         CloseHandle(child_stdin_handle[0]);
288         CloseHandle(child_stdout_handle[1]);
289         
290         if(command->timer)
291         {
292                 /* launch the timer */
293                 timer_time(command->timer);
294         }
295         
296         if(command->reader)
297         {
298                 /* launch the reader */
299                 reader_read(command->reader);
300         }
301     
302
303         if(command->writer)
304         {
305                 /* launch the writer */
306                 writer_write(command->writer);
307         }
308
309     si.cb = sizeof(STARTUPINFO);
310         
311         si.dwFlags |= STARTF_USESTDHANDLES;
312         si.hStdOutput = child_stdin_handle[1];
313         si.hStdInput  = child_stdout_handle[0];
314         si.hStdError  = child_stderr;
315
316         /* launch the process */
317         if(!CreateProcess(
318                                                 NULL,
319                                                 (char*)command_line,
320                                                 NULL,
321                                                 NULL,
322                                                 TRUE,
323                                                 CREATE_NO_WINDOW,
324                                                 NULL,
325                                                 NULL,
326                                                 &si,
327                                                 &pi)
328         )
329         {
330                 
331                 if(ERROR_FILE_NOT_FOUND == GetLastError())
332                 {
333                         exit_code = ECMDNOTFOUND;
334                         command_handle_failure(command,csr_command_not_found);
335                 }
336                 else
337                 {
338                         exit_code = EEXEC;
339                         command_handle_failure(command,csr_exec_failure);
340                 }
341     }
342         else
343         {
344                 /* the command is running */
345                 command->status = cs_in_progress;
346
347                 /* save the pid of the command */
348                 command->pid = pi.hProcess;
349
350                 /* close non used thread handle */
351                 CloseHandle(pi.hThread);
352                 
353         }
354
355         
356         /* close non used handles */
357         CloseHandle(child_stdin_handle[1]);
358     CloseHandle(child_stdout_handle[0]);
359         CloseHandle(child_stderr);
360
361
362 }
363 #else
364 void
365 command_exec(command_t command, const char* command_line)
366 {
367         int child_stdin_fd[2] ;
368         int child_stdout_fd[2];
369         
370         if(pipe(child_stdin_fd) || pipe(child_stdout_fd)) 
371         {
372                 ERROR1("pipe() failed (%d)",errno);
373                 command_handle_failure(command, csr_pipe_function_failed);      
374
375                 return;
376         }
377         
378         command->pid= fork();
379                                 
380         if(command->pid < 0) 
381         {
382                 close(child_stdin_fd[0]);
383                 close(child_stdin_fd[1]);
384                 close(child_stdout_fd[0]);
385                 close(child_stdout_fd[1]);
386                 
387                 exit_code = EEXEC;
388                 ERROR1("fork() failed (%d)",errno);
389                 command_handle_failure(command,csr_exec_failure);
390         }
391         else
392         {
393                 if(command->pid) 
394                 {/* father */
395                         
396                         
397                         close(child_stdin_fd[0]);
398                         close(child_stdout_fd[1]);
399                         
400                         command->stdin_fd = child_stdin_fd[1];
401                         
402                         command->stdout_fd = child_stdout_fd[0];
403                         
404                         /* on indique que c'est le processus parent qui doit recevoir le signal */
405                         /*fcntl(command->stdin_fd,F_SETOWN, pid);*/
406                         
407                         if(command->reader)
408                         {
409                                 /* launch the reader */
410                                 reader_read(command->reader);
411                         }
412                     
413                         if(command->writer)
414                         {
415                                 /* launch the writer */
416                                 writer_write(command->writer);
417                         }
418                         
419                         if(command->timer)
420                         {
421                                 /* launch the timer */
422                                 timer_time(command->timer);
423                         }
424                         
425                         /* the command is running */
426                         command->status = cs_in_progress;
427                 
428                 } 
429                 else 
430                 {/* child */
431                         
432                         
433                         close(child_stdin_fd[1]);
434                         close(child_stdout_fd[0]);
435                         
436                         if(dup2(child_stdin_fd[0],STDIN_FILENO/*0*/) < 0)
437                         {
438                                 exit_code = EEXEC;
439                                 ERROR1("dup2() failed (%d)",errno);
440                                 command_handle_failure(command,csr_exec_failure);
441                         }
442                         
443                         /*close(child_stdin_fd[0]);
444                         */
445                         
446                         if(dup2(child_stdout_fd[1],STDOUT_FILENO/*1*/) < 0)
447                         {
448                                 exit_code = EEXEC;
449                                 ERROR1("dup2() failed (%d)",errno);
450                                 command_handle_failure(command,csr_exec_failure);
451                         }
452                         
453                         if(dup2(child_stdout_fd[1], STDERR_FILENO/*2*/) < 0)
454                         {
455                                 exit_code = EEXEC;
456                                 ERROR1("dup2() failed (%d)",errno);
457                                 command_handle_failure(command,csr_exec_failure);
458                         }
459                         
460                         fcntl(command->stdin_fd, F_SETFL, fcntl(command->stdin_fd, F_GETFL) | O_NONBLOCK);
461                         
462                         
463                         if(command->writer)
464                                 xbt_os_sem_release(command->writer->can_write);
465                         
466                         /*close(child_stdout_fd[1]);*/
467                         
468                         if(command->reader)
469                                 xbt_os_sem_acquire(command->reader->started);
470                         
471                         if(command->writer)
472                                 xbt_os_sem_acquire(command->writer->written);
473                                 
474                         if(command->timer)
475                                 xbt_os_sem_acquire(command->timer->started);
476                         
477                         if(execlp("/bin/sh", "sh", "-c", command->context->command_line, NULL) < 0)
478                         {
479                                 exit_code = EEXEC;
480                                 ERROR1("execlp() failed (%d)",errno);
481                                 command_handle_failure(command,csr_exec_failure);
482                         }
483                 }
484         }
485 }
486 #endif
487
488 #ifdef WIN32
489 void
490 command_wait(command_t command)
491 {
492         /* wait for the command terminaison */
493         DWORD rv;
494
495         if(WAIT_FAILED == WaitForSingleObject(command->pid, INFINITE))
496         {
497                 ERROR0("WaitForSingleObject() failed");
498                 /* TODO : see for the interruption      */      
499         }
500         else
501         {
502                 /* don't take care of the timer or the writer or the reader failue */
503                 if(cs_failed != command->status && cs_interrupted != command->status)
504                 {
505                         if(!GetExitCodeProcess(command->pid,&rv))
506                         {
507                                 ERROR1("GetExitCodeProcess() failed for the child %s",command->context->command_line);
508                                 /* TODO : see for the interruption      */      
509                         }
510                         else
511                                 command->stat_val = command->exit_code = rv;
512                 }
513         }
514 }
515 #else
516 void
517 command_wait(command_t command)
518 {
519         
520         int pid;
521         
522         /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
523         
524         
525         xbt_os_mutex_acquire(command->unit->mutex);
526         command->unit->number_of_waiting_commands++;
527         xbt_os_mutex_release(command->unit->mutex);
528         
529         pid = waitpid(command->pid, &(command->stat_val), 0);
530         
531         
532         xbt_os_mutex_acquire(command->unit->mutex);
533         command->unit->number_of_waiting_commands--;
534         xbt_os_mutex_release(command->unit->mutex);
535         
536         /*printf("The %p command ended\n",command);*/
537         if(pid != command->pid) 
538         {
539                 ERROR1("waitpid() failed for the child %s",command->context->command_line);
540                 exit_code = EWAIT;
541                 command_handle_failure(command, csr_wait_failure);
542         }
543         else
544         {
545                 if(WIFEXITED(command->stat_val))
546                         command->exit_code = WEXITSTATUS(command->stat_val);    
547         }
548         
549         
550 }
551 #endif
552
553 void
554 command_check(command_t command)
555 {
556         int success = 1;
557         cs_reason_t reason;
558         
559         /* we have a signal, store it */
560         if(WIFSIGNALED(command->stat_val))
561         {
562                 command->signal = strdup(signal_name(WTERMSIG(command->stat_val),command->context->signal));
563                 /*INFO3("the command -PID %d %s receive the signal : %s",command->pid, command->context->command_line, command->signal);*/
564         }
565         
566         /* we have a signal and not signal is expected */
567         if(WIFSIGNALED(command->stat_val) && !command->context->signal) 
568         {
569                 success = 0;
570                 exit_code = EUNEXPECTEDSIG;
571                 reason = csr_unexpected_signal_caught;
572         }
573         
574         /* we have a signal that differ form the expected signal */
575         if(success && WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal)) 
576         {
577                 success = 0;
578                 exit_code = ESIGNOTMATCH;
579                 reason = csr_signals_dont_match;
580         }
581         
582         /* we don't receipt the expected signal */
583         if(success && !WIFSIGNALED(command->stat_val) && command->context->signal) 
584         {
585                 success = 0;
586                 exit_code = ESIGNOTRECEIPT;
587                 reason = csr_expected_signal_not_receipt;
588         }
589         
590         /* if the command exit normaly and we expect a exit code : test it */
591         if(success && WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)
592         {
593                 /* the exit codes don't match */
594                 if(WEXITSTATUS(command->stat_val) != command->context->exit_code)
595                 {
596                         success = 0;
597                         exit_code = EEXITCODENOTMATCH;
598                         reason = csr_exit_codes_dont_match;
599                 }
600         }
601         
602         /* if ouput handling flag is specified check the output */
603         if(success && oh_check == command->context->output_handling && command->reader)
604         {
605                 /* make sure the reader done */
606                 while(!command->reader->done)
607                         xbt_os_thread_yield();
608                         
609                 close(command->stdout_fd);
610                 command->stdout_fd = INDEFINITE_FD;
611
612                 xbt_strbuff_chomp(command->output);
613                 xbt_strbuff_chomp(command->context->output);
614                 xbt_strbuff_trim(command->output);
615                 xbt_strbuff_trim(command->context->output);
616
617                 if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))
618                 {
619                         success = 0;
620                         exit_code = EOUTPUTNOTMATCH;
621                         reason = csr_outputs_dont_match;
622                 }
623         }
624         
625         if(success)
626         {
627                 xbt_os_mutex_acquire(command->mutex);
628                 
629                 if(command->status != cs_interrupted)
630                 {
631                 
632                         /* signal the success of the command */
633                         command->status = cs_successeded;
634                         command->successeded = 1;
635
636                         /* increment the number of successeded command of the unit */
637                         /*xbt_os_mutex_acquire(command->mutex);*/
638                         (command->unit->number_of_successeded_commands)++;
639                 }
640                 
641                 xbt_os_mutex_release(command->mutex);
642                         
643         }
644         else
645         {
646                 command_handle_failure(command,reason);
647         }
648 }
649
650 #ifdef WIN32
651 void
652 command_kill(command_t command)
653 {
654         if(INDEFINITE_PID != command->pid)
655                 TerminateProcess(command->pid, INDEFINITE);
656 }
657 #else
658 void
659 command_kill(command_t command)
660 {
661         if(INDEFINITE_PID != command->pid)
662         {
663                 /*INFO1("Kill the command - PID %d",command->pid);*/
664                 
665                 kill(command->pid,SIGTERM);
666                 
667                 if(!command->context->signal)
668                         command->context->signal = strdup("SIGTERM");
669                         
670                 command->exit_code = INDEFINITE;
671                 command->killed = 1;
672                 
673                 usleep(100);
674                 kill(command->pid,SIGKILL); 
675
676                 
677         }
678 }
679 #endif
680
681 void
682 command_interrupt(command_t command)
683 {
684         xbt_os_mutex_acquire(command->mutex);
685         
686         if((command->status != cs_interrupted) && (command->status != cs_failed) && (command->status != cs_successeded))
687         {
688                 /*INFO1("Begin interrupt the command - PID %d",command->pid);*/
689                 
690                 command->status = cs_interrupted;       
691                 command->reason = csr_interruption_request;
692                 command->interrupted = 1;
693                 xbt_os_mutex_acquire(command->unit->mutex);
694                 (command->unit->number_of_interrupted_commands)++;
695                 xbt_os_mutex_release(command->unit->mutex);
696                 
697                 if(command->pid != INDEFINITE_PID)
698                         command_kill(command);
699                 
700                 
701                 /*INFO1("End interrupt the command - PID %d",command->pid);*/
702         }
703         
704         xbt_os_mutex_release(command->mutex);
705         
706         
707 }
708
709 void
710 command_display_status(command_t command)
711 {
712         
713         /*printf("\033[1m");*/
714         
715         if(cs_successeded != command->status)
716         {
717                         
718                 #ifndef WIN32
719                 if(command->killed)
720                         printf("          <killed command>\n");
721                 #endif
722                 
723                 /* display the reason of the status of the command */
724                 switch(command->reason)
725                 {
726                         /* the function pipe or CreatePipe() fails */
727                         case csr_pipe_function_failed :
728                         printf("          reason                      : pipe() or CreatePipe() function failed (system error)\n");
729                         break;
730                         
731                         /* reader failure reasons*/
732                         case csr_read_pipe_broken :
733                         printf("          reason                      : command read pipe broken\n");
734                         break;
735
736                         case csr_read_failure :
737                         printf("          reason                      : command stdout read failed\n");
738                         break;
739         
740                         /* writer failure reasons */
741                         case csr_write_failure :
742                         printf("          reason                      : command stdin write failed\n");
743                         break;
744
745                         case csr_write_pipe_broken :
746                         printf("          reason                      : command write pipe broken\n");
747                         break;
748                         
749                         /* timer reason */
750                         case csr_timeout :
751                         printf("          reason                      : command timeouted\n");
752                         break;
753                         
754                         /* command failure reason */
755                         case csr_command_not_found :
756                         printf("          reason                      : command not found\n");
757                         break;
758                         
759                         /* context failure reasons */
760                         case csr_exit_codes_dont_match :
761                         printf("          reason                      : exit codes don't match\n");
762                         
763                         break;
764
765                         case csr_outputs_dont_match :
766                         {
767                                 char *diff;
768                                 printf("          reason                      : ouputs don't match\n");
769                                 diff = xbt_str_diff(command->context->output->data,command->output->data);              
770                                 printf("          output diff :\n%s\n",diff);
771                                 free(diff);
772                         }     
773
774                         break;
775
776                         case csr_signals_dont_match :
777                         printf("          reason                      : signals don't match\n"); 
778                         break;
779                         
780                         case csr_unexpected_signal_caught:
781                         printf("                reason                      : unexpected signal caught\n");
782                         break;
783                         
784                         case csr_expected_signal_not_receipt :
785                         printf("          reason                      : expected signal not receipt\n");
786                         break;
787
788                         /* system failure reasons */
789                         case csr_exec_failure :
790                         printf("          reason                      : can't excute the command\n");
791                         break;
792                         
793                         case csr_wait_failure :
794                         printf("          reason                      : wait command failure\n");
795                         break;
796                         
797                         /* global/local interruption */
798                         case csr_interruption_request :
799                         printf("          reason                      : the command receive a interruption request\n");
800                         break;
801                         
802                         /* unknown ? */
803                         case csr_unknown :
804                         printf("          reason                      : unknown \n");
805                 }
806         }
807
808         if(csr_command_not_found != command->reason && csr_exec_failure != command->reason)
809         {
810                 if(INDEFINITE != command->exit_code)
811                         /* the command exit code */
812                         printf("          exit code                   : %d\n",command->exit_code);
813                 
814                 /* if an expected exit code was specified display it */
815                 if(INDEFINITE != command->context->exit_code)
816                         printf("          expected exit code          : %d\n",command->context->exit_code);
817                 else
818                         printf("          no expected exit code specified\n");
819                 
820                 /* if an expected exit code was specified display it */
821                 if(NULL == command->context->signal)
822                         printf("          no expected signal specified\n");
823                 else
824                 {
825                         if(NULL != command->signal)
826                                 printf("          signal                      : %s\n",command->signal);
827                         
828                         printf("          expected signal             : %s\n",command->context->signal);
829                 }
830                 
831                 /* if the command has out put and the metacommand display output is specified display it  */
832                 if(command->output && (0 != command->output->used) && (oh_display == command->context->output_handling))
833                 {
834                         xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
835                         char *out = xbt_str_join(a,"\n||");
836                         xbt_dynar_free(&a);
837                         printf("          output :\n||%s",out);
838                         free(out);
839                 }
840         }
841
842         printf("\n");
843         
844         /*printf("\033[0m");*/
845                 
846
847 }
848
849
850
851
852 void
853 command_handle_failure(command_t command, cs_reason_t reason)
854 {
855         
856         unit_t unit = command->unit;
857         
858         xbt_os_mutex_acquire(command->mutex);
859
860         if((command->status != cs_interrupted) && (command->status != cs_failed))
861         {
862                 command->status = cs_failed;
863                 command->reason = reason;
864                 command->failed = 1;
865                 
866                 xbt_os_mutex_acquire(unit->mutex);
867                 
868                 /* increment the number of failed command of the unit */
869                 unit->number_of_failed_commands++;
870                 
871                 /* if the --ignore-failures option is not specified */
872                 if(!want_keep_going_unit)
873                 {
874                         if(!unit->interrupted)
875                         {
876                                 /* the unit interrupted (exit for the loop) */
877                                 unit->interrupted = 1;
878
879                                 /* release the unit */
880                                 xbt_os_sem_release(unit->sem);
881                         }
882                         
883                         /* if the --keep-going option is not specified */
884                         if(!want_keep_going)
885                         {
886                                 if(!interrupted)
887                                 {
888                                         /* request an global interruption by the runner */
889                                         interrupted = 1;
890                                         
891                                         /* release the runner */
892                                         xbt_os_sem_release(units_sem);
893                                 }
894                         }
895                 }
896
897                 xbt_os_mutex_release(unit->mutex);
898         }
899
900         xbt_os_mutex_release(command->mutex);
901 }
902
903 void
904 command_free(command_t* command)
905 {
906         /* close the stdin and the stdout pipe handles */
907
908         #ifdef WIN32
909         if((*command)->stdin_fd != INDEFINITE_FD)
910                 CloseHandle((*command)->stdin_fd);
911         if((*command)->stdout_fd != INDEFINITE_FD)
912                 CloseHandle((*command)->stdout_fd);
913         #else
914         if((*command)->stdin_fd != INDEFINITE_FD)
915                 close((*command)->stdin_fd);
916         
917         if((*command)->stdout_fd != INDEFINITE_FD)      
918                 close((*command)->stdout_fd);
919         #endif
920
921         timer_free(&((*command)->timer));
922         writer_free(&((*command)->writer));
923         reader_free(&((*command)->reader));
924         xbt_strbuff_free((*command)->output);
925         context_free(&((*command)->context));
926
927         if((*command)->signal)
928                 free((*command)->signal);
929
930         free(*command);
931         *command = NULL;
932 }
933
934
935