Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
s/NOTRECEIPT/NOTRECEIVED/ (plus some reindent)
[simgrid.git] / tools / tesh2 / src / command.c
index 16c7ea5..3f911f6 100644 (file)
@@ -1,9 +1,9 @@
 /*\r
  * src/command.c - type representing a command.\r
  *\r
- * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved. \r
+ * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved.\r
  *\r
- * This program is free software; you can redistribute it and/or modify it \r
+ * This program is free software; you can redistribute it and/or modify it\r
  * under the terms of the license (GNU LGPL) which comes with this package.\r
  *\r
  * Purpose:\r
@@ -11,7 +11,7 @@
  *             the tesh command type.\r
  *\r
  */\r
\r
+#include <unit.h>\r
 #include <command.h>\r
 #include <context.h>\r
 #include <writer.h>\r
 #ifndef WIN32\r
 #include <sys/types.h>\r
 #include <sys/wait.h>\r
+#include <sys/stat.h>\r
+#include <unistd.h>\r
+#else\r
+char *\r
+tow32cmd(const char* cmd)\r
+{\r
+       static char w32cmd[PATH_MAX + 1] = {0};\r
+       char cmd_buf[PATH_MAX + 1] = {0};\r
+    size_t i,j, len;\r
+\r
+    if(!cmd)\r
+    {\r
+       errno = EINVAL;\r
+               return NULL;\r
+       }\r
+\r
+       /* TODO : if ~*/\r
+       if(cmd[0] != '.')\r
+       {\r
+               strcpy(w32cmd, cmd);\r
+               return w32cmd;\r
+       }\r
+\r
+       i = j = 0;\r
+       len = strlen(cmd);\r
+\r
+       while(i < len)\r
+       {\r
+               if(cmd[i] != ' ' && cmd[i] != '\t' && cmd[i] != '>')\r
+                       cmd_buf[j++] = cmd[i];\r
+               else\r
+                       break;\r
+\r
+               i++;\r
+       }\r
+\r
+   _fullpath(w32cmd, cmd_buf, sizeof(w32cmd));\r
+\r
+   if(!strstr(w32cmd, ".exe"))\r
+               strcat(w32cmd, ".exe ");\r
+\r
+   strcat(w32cmd, cmd + i);\r
+\r
+\r
+   /*printf("w32cmd : %s", w32cmd);*/\r
+\r
+   return w32cmd;\r
+}\r
 #endif\r
 \r
+#include <com.h>\r
+\r
 #include <xsignal.h>\r
 \r
+#include <is_cmd.h>\r
+\r
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
 \r
 static void*\r
 command_start(void* p);\r
 \r
+\r
 command_t\r
 command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)\r
 {\r
        command_t command;\r
-       /* TODO : check the parameters */\r
-       \r
+\r
        command = xbt_new0(s_command_t, 1);\r
-       \r
+\r
        /* get the context of the execution of the command */\r
        if(!(command->context = context_dup(context)))\r
        {\r
                free(command);\r
                return NULL;\r
        }\r
-       \r
+\r
        /* the exit code of the command is indefinite */\r
        command->exit_code = INDEFINITE;\r
-       \r
+\r
        /* the signal of the command is indefinite */\r
        command->signal = INDEFINITE_SIGNAL;\r
-       \r
+\r
        command->failed = 0;\r
        command->interrupted = 0;\r
-       \r
+\r
        /* the mutex used to safetly access to the command unit properties */\r
        command->mutex = mutex;\r
-       \r
-       if(context->output->used)\r
-               command->output = xbt_strbuff_new();\r
-       else\r
-               command->output = NULL;\r
+\r
+       command->output = xbt_strbuff_new();\r
 \r
        command->pid = INDEFINITE_PID;\r
-       \r
+\r
        command->stat_val = -1;\r
-       \r
+\r
        /* set the unit of the command */\r
-       command->unit = unit->root ? unit->root : unit; \r
-       \r
+       command->root = unit->root ? unit->root : unit;\r
+       command->unit = unit;\r
+\r
        /* all the commands are runned in a thread */\r
        command->thread = NULL;\r
-       \r
+\r
        command->successeded = 0;\r
-       \r
-       if(context->output->used)\r
-               command->reader = reader_new(command);\r
-       else\r
-               command->reader = NULL;\r
+\r
+       command->reader = reader_new(command);\r
 \r
        if(context->input->used)\r
                command->writer = writer_new(command);\r
@@ -91,24 +138,23 @@ command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
 \r
        command->status = cs_initialized;\r
        command->reason = csr_unknown;\r
-       \r
+\r
        command->stdin_fd = INDEFINITE_FD;\r
        command->stdout_fd = INDEFINITE_FD;\r
-       \r
-       \r
+\r
+\r
        /* register the command */\r
        xbt_os_mutex_acquire(mutex);\r
-       \r
-       /*vector_push_back(unit->commands, command);*/\r
+\r
        xbt_dynar_push(unit->commands, &command);\r
-       command->unit->cmd_nb++;\r
+       command->root->cmd_nb++;\r
        xbt_os_mutex_release(mutex);\r
-       \r
+\r
        #ifndef WIN32\r
        command->killed = 0;\r
        command->execlp_errno = 0;\r
        #endif\r
-       \r
+\r
 \r
        return command;\r
 }\r
@@ -116,31 +162,33 @@ command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
 int\r
 command_run(command_t command)\r
 {\r
-       /* TODO : check the parameter */\r
-       \r
-       if(!silent_flag)\r
-               INFO1("tesh %s",command->context->command_line);\r
-       \r
+       if(!silent_flag && !interrupted)\r
+               INFO2("[%s] %s",command->context->pos, command->context->command_line);\r
+\r
        if(!just_print_flag)\r
-       {       \r
+       {\r
                if(!interrupted)\r
                {\r
-                       /* start the command */\r
-                       \r
+                       /* start the command in a thread*/\r
                        if(command->context->async)\r
                        {\r
                                command->thread = xbt_os_thread_create("", command_start, command);\r
-                       \r
+\r
                        }\r
                        else\r
+                       {\r
+                               /* start the command in the main thread */\r
                                command_start(command);\r
+                       }\r
                }\r
                else\r
                {\r
-                       command_interrupt(command);             \r
+                       command_interrupt(command);\r
                }\r
+\r
+\r
        }\r
-       \r
+\r
        return 0;\r
 \r
 }\r
@@ -149,117 +197,132 @@ static void*
 command_start(void* p)\r
 {\r
        command_t command = (command_t)p;\r
-       unit_t unit = command->unit;\r
-       \r
+       unit_t root = command->root;\r
+\r
        /* the command is started */\r
        command->status = cs_started;\r
-       \r
+\r
        /* increment the number of started commands of the unit */\r
        xbt_os_mutex_acquire(command->mutex);\r
-       (command->unit->started_cmd_nb)++;\r
+       (root->started_cmd_nb)++;\r
        xbt_os_mutex_release(command->mutex);\r
-       \r
+\r
        /* execute the command of the test */\r
+\r
+       #ifndef WIN32\r
        command_exec(command, command->context->command_line);\r
-       \r
+       #else\r
+       /* play the translated command line on Windows */\r
+       command_exec(command, command->context->t_command_line);\r
+       #endif\r
+\r
        if(cs_in_progress == command->status)\r
        {\r
-               \r
-               /* on attend la fin de la commande.\r
-                * la command peut soit se terminée normalement,\r
-                * 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\r
-                * soit à la suit d'une demande d'interruption\r
-                */\r
-               \r
+               /* wait the process if it is in progress */\r
                command_wait(command);\r
-       \r
+\r
                if(cs_failed != command->status && cs_interrupted != command->status)\r
                        command_check(command);\r
        }\r
-       \r
+\r
        xbt_os_mutex_acquire(command->mutex);\r
-       \r
-       /* if it's the last command release its unit */\r
-       if(!unit->interrupted && unit->parsed && (unit->started_cmd_nb == (unit->failed_cmd_nb + unit->interrupted_cmd_nb + unit->successeded_cmd_nb)))\r
+\r
+       /* if it's the last command of the root unit */\r
+       if(!root->interrupted && root->parsed && (root->started_cmd_nb == (root->failed_cmd_nb + root->interrupted_cmd_nb + root->successeded_cmd_nb)))\r
        {\r
                /* first release the mutex */\r
-               unit->released = 1;\r
+               root->released = 1;\r
                xbt_os_mutex_release(command->mutex);\r
                /* the last command release the unit */\r
-               xbt_os_sem_release(command->unit->sem);\r
+               xbt_os_sem_release(root->sem);\r
        }\r
        else\r
                xbt_os_mutex_release(command->mutex);\r
-               \r
-       \r
+\r
+\r
        /* wait the end of the timer, the reader and the writer */\r
        if(command->timer && command->timer->thread)\r
                timer_wait(command->timer);\r
 \r
+       /* wait the end of the writer */\r
        if(command->writer && command->writer->thread)\r
                writer_wait(command->writer);\r
 \r
+       /* wait the end of the reader */\r
        if(command->reader && command->reader->thread)\r
                reader_wait(command->reader);\r
-       \r
+\r
+\r
+\r
        return NULL;\r
 }\r
 \r
 #ifdef WIN32\r
+\r
+#ifndef BUFSIZE\r
+#define BUFSIZE        4096\r
+#endif\r
 void\r
 command_exec(command_t command, const char* command_line)\r
 {\r
-       \r
+\r
        STARTUPINFO si = {0};                                   /* contains the informations about the child process windows*/\r
        PROCESS_INFORMATION pi = {0};                   /* contains child process informations                                          */\r
        SECURITY_ATTRIBUTES sa = {0};                   /* contains the security descriptor for the pipe handles        */\r
        HANDLE child_stdin_handle[2] = {NULL};  /* child_stdin_handle[1]        <-> stdout of the child process */\r
        HANDLE child_stdout_handle[2] = {NULL}; /* child_stdout_handle[0]       <-> stdin of the child process  */\r
        HANDLE child_stderr = NULL;\r
-       \r
+\r
+\r
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);\r
     sa.lpSecurityDescriptor = NULL;                    /* use default security for the pipe handles                            */\r
-       \r
+\r
        sa.bInheritHandle = TRUE;                               /* the pipe handles can be inherited                                            */\r
-       \r
+\r
        if(!CreatePipe(&(child_stdin_handle[0]),&(child_stdin_handle[1]),&sa,0))\r
     {\r
-               error_register("CreatePipe() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);\r
+               ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));\r
+\r
+               unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);\r
+\r
                command->failed = 1;\r
-               command->status = cs_failed;    \r
+               command->status = cs_failed;\r
 \r
                return;\r
     }\r
-       \r
-       \r
+\r
+\r
        if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[1]),GetCurrentProcess(),&(child_stderr),0,TRUE,DUPLICATE_SAME_ACCESS))\r
     {\r
-               error_register("DuplicateHandle() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);\r
-               \r
+               ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));\r
+\r
+               unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);\r
+\r
                CloseHandle(child_stdin_handle[0]);\r
                CloseHandle(child_stdin_handle[1]);\r
 \r
                command->failed = 1;\r
-               command->status = cs_failed;    \r
+               command->status = cs_failed;\r
 \r
                return;\r
     }\r
-       \r
+\r
        if(!CreatePipe(&(child_stdout_handle[0]),&(child_stdout_handle[1]),&sa,0))\r
     {\r
-               error_register("CreatePipe() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);\r
-               \r
+               ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));\r
+               unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);\r
+\r
                CloseHandle(child_stdout_handle[0]);\r
                CloseHandle(child_stdout_handle[1]);\r
                CloseHandle(child_stdin_handle[0]);\r
                CloseHandle(child_stdin_handle[1]);\r
 \r
                command->failed = 1;\r
-               command->status = cs_failed;    \r
+               command->status = cs_failed;\r
 \r
                return;\r
     }\r
-               \r
+\r
        /* Read handle for read operations on the child std output. */\r
        if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[0]),GetCurrentProcess(),&(command->stdout_fd),0,FALSE, DUPLICATE_SAME_ACCESS))\r
     {\r
@@ -269,14 +332,15 @@ command_exec(command_t command, const char* command_line)
                CloseHandle(child_stdin_handle[1]);\r
 \r
                command->failed = 1;\r
-               command->status = cs_failed;    \r
+               command->status = cs_failed;\r
+\r
+               ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));\r
+               unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);\r
 \r
-               error_register("DuplicateHandle() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);\r
-               \r
                return;\r
        }\r
-       \r
-       \r
+\r
+\r
        /* Write handle for write operations on the child std input. */\r
        if(!DuplicateHandle(GetCurrentProcess(),(child_stdout_handle[1]),GetCurrentProcess(),&(command->stdin_fd), 0,FALSE,DUPLICATE_SAME_ACCESS))\r
     {\r
@@ -286,28 +350,31 @@ command_exec(command_t command, const char* command_line)
                CloseHandle(child_stdin_handle[1]);\r
 \r
                command->failed = 1;\r
-               command->status = cs_failed;    \r
+               command->status = cs_failed;\r
+\r
+               ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));\r
+\r
+               unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);\r
 \r
-               error_register("DuplicateHandle() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);\r
                return;\r
     }\r
 \r
-       \r
        CloseHandle(child_stdin_handle[0]);\r
        CloseHandle(child_stdout_handle[1]);\r
-       \r
+\r
+\r
        if(command->timer)\r
        {\r
                /* launch the timer */\r
                timer_time(command->timer);\r
        }\r
-       \r
+\r
        if(command->reader)\r
        {\r
                /* launch the reader */\r
                reader_read(command->reader);\r
        }\r
-    \r
+\r
 \r
        if(command->writer)\r
        {\r
@@ -315,8 +382,20 @@ command_exec(command_t command, const char* command_line)
                writer_write(command->writer);\r
        }\r
 \r
+       /* if there is a reader wait for its starting */\r
+       if(command->reader)\r
+               xbt_os_sem_acquire(command->reader->started);\r
+\r
+       /* if there is a reader wait for its ending */\r
+       if(command->writer)\r
+               xbt_os_sem_acquire(command->writer->written);\r
+\r
+       /* if there is a reader wait for its starting */\r
+       if(command->timer)\r
+               xbt_os_sem_acquire(command->timer->started);\r
+\r
     si.cb = sizeof(STARTUPINFO);\r
-       \r
+\r
        si.dwFlags |= STARTF_USESTDHANDLES;\r
        si.hStdOutput = child_stdin_handle[1];\r
        si.hStdInput  = child_stdout_handle[0];\r
@@ -325,7 +404,7 @@ command_exec(command_t command, const char* command_line)
        /* launch the process */\r
        if(!CreateProcess(\r
                                                NULL,\r
-                                               (char*)command_line,\r
+                                               tow32cmd(command_line),\r
                                                NULL,\r
                                                NULL,\r
                                                TRUE,\r
@@ -336,8 +415,21 @@ command_exec(command_t command, const char* command_line)
                                                &pi)\r
        )\r
        {\r
-               error_register("CreateProcess() function failed", (int)GetLastError(), command->context->command_line, command->unit->fstream->name);\r
-               command_handle_failure(command,csr_create_process_function_failure);\r
+\r
+               if(ERROR_FILE_NOT_FOUND == GetLastError())\r
+               {\r
+                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(ECMDNOTFOUND, 1));\r
+                       unit_set_error(command->unit, ECMDNOTFOUND, 1, command->context->pos);\r
+                       command_handle_failure(command, csr_command_not_found);\r
+               }\r
+               else\r
+               {\r
+                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));\r
+\r
+                       unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);\r
+                       command_handle_failure(command, csr_create_process_function_failure);\r
+               }\r
+\r
     }\r
        else\r
        {\r
@@ -349,10 +441,10 @@ command_exec(command_t command, const char* command_line)
 \r
                /* close non used thread handle */\r
                CloseHandle(pi.hThread);\r
-               \r
+\r
        }\r
 \r
-       \r
+\r
        /* close non used handles */\r
        CloseHandle(child_stdin_handle[1]);\r
     CloseHandle(child_stdout_handle[0]);\r
@@ -366,164 +458,206 @@ command_exec(command_t command, const char* command_line)
 {\r
        int child_stdin_fd[2] ;\r
        int child_stdout_fd[2];\r
-       \r
+\r
+       #ifdef __CHKCMD\r
+       int rv = is_cmd(command->unit->runner->path, command->unit->runner->builtin, command_line);\r
+\r
+       if(rv != 0)\r
+       {\r
+\r
+               if(rv == EINVAL)\r
+               {\r
+                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(rv, 0));\r
+                       unit_set_error(command->unit, rv, 0, command->context->pos);\r
+               }\r
+               else\r
+               {\r
+                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(rv, 1));\r
+                       unit_set_error(command->unit, rv, 1, command->context->pos);\r
+               }\r
+\r
+               command_handle_failure(command, csr_command_not_found);\r
+\r
+               return;\r
+       }\r
+\r
+       #endif\r
+\r
+\r
        if(command->writer)\r
        {\r
-               if(pipe(child_stdin_fd)) \r
+               if(pipe(child_stdin_fd))\r
                {\r
-                       error_register("pipe() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
-                       command_handle_failure(command, csr_pipe_function_failed);      \r
-       \r
+                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));\r
+\r
+                       unit_set_error(command->unit, errno, 0, command->context->pos);\r
+\r
+                       command_handle_failure(command, csr_pipe_function_failed);\r
+\r
+\r
+\r
                        return;\r
                }\r
-       }       \r
-       \r
+       }\r
+\r
        if(command->reader)\r
        {\r
-               if(pipe(child_stdout_fd)) \r
+               if(pipe(child_stdout_fd))\r
                {\r
-                       error_register("write() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
-                               \r
+                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));\r
+\r
                        if(command->writer)\r
                        {\r
                                close(child_stdin_fd[0]);\r
                                close(child_stdin_fd[1]);\r
                        }\r
-                       \r
+\r
+                       unit_set_error(command->unit, errno, 0, command->context->pos);\r
+\r
                        command_handle_failure(command, csr_pipe_function_failed);\r
-                       \r
+\r
                        return;\r
                }\r
        }\r
-       \r
+\r
        if(command->writer)\r
        {\r
                if(fcntl(child_stdin_fd[1], F_SETFL, fcntl(child_stdin_fd[1], F_GETFL) | O_NONBLOCK) < 0)\r
                {\r
-                       error_register("fcntl() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
-                       \r
+\r
+                       ERROR3("[%s] `%s'  : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));\r
+\r
                        close(child_stdin_fd[0]);\r
                        close(child_stdin_fd[1]);\r
-                       \r
+\r
                        if(command->reader)\r
                        {\r
                                close(child_stdout_fd[0]);\r
                                close(child_stdout_fd[1]);\r
                        }\r
-                       \r
-                       command_handle_failure(command, csr_fcntl_function_failed);     \r
-                               \r
+\r
+                       unit_set_error(command->unit, errno, 0, command->context->pos);\r
+\r
+                       command_handle_failure(command, csr_fcntl_function_failed);\r
+\r
                        return;\r
                }\r
        }\r
-       \r
+\r
        /* to write to the child stdin */\r
        command->stdin_fd = child_stdin_fd[1];\r
-       \r
+\r
        /* to read from the child stdout */\r
        command->stdout_fd = child_stdout_fd[0];\r
-       \r
+\r
        /* launch the reader if any*/\r
        if(command->reader)\r
                reader_read(command->reader);\r
-    \r
+\r
     /* launch the writer if any */\r
        if(command->writer)\r
                writer_write(command->writer);\r
-       \r
+\r
        /* launch the timer if any */\r
        if(command->timer)\r
                timer_time(command->timer);\r
-               \r
+\r
        /* if there is a reader wait for its starting */\r
        if(command->reader)\r
                xbt_os_sem_acquire(command->reader->started);\r
-       \r
+\r
        /* if there is a reader wait for its ending */\r
        if(command->writer)\r
                xbt_os_sem_acquire(command->writer->written);\r
-       \r
+\r
        /* if there is a reader wait for its starting */\r
        if(command->timer)\r
                xbt_os_sem_acquire(command->timer->started);\r
-       \r
+\r
        /* update the state of the command, assume it is in progress */\r
        command->status = cs_in_progress;\r
-                               \r
+\r
        command->pid= fork();\r
-                               \r
-       if(command->pid < 0) \r
+\r
+       if(command->pid < 0)\r
        {/* error */\r
                if(command->writer)\r
                {\r
                        close(child_stdin_fd[0]);\r
                        close(child_stdin_fd[1]);\r
                }\r
-               \r
+\r
                if(command->reader)\r
                {\r
                        close(child_stdout_fd[0]);\r
                        close(child_stdout_fd[1]);\r
                }\r
-               \r
-               error_register("fcntl() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
+\r
+               ERROR2("[%s] Cannot fork the command `%s'", command->context->pos, command->context->command_line);\r
+               unit_set_error(command->unit, errno, 0, command->context->pos);\r
                command_handle_failure(command,csr_fork_function_failure);\r
        }\r
        else\r
        {\r
-               if(command->pid) \r
+               if(command->pid)\r
                {/* father */\r
-                       \r
+\r
                        /* close unused file descriptors */\r
                        if(command->writer)\r
                                close(child_stdin_fd[0]);\r
-                               \r
+\r
                        if(command->reader)\r
                                close(child_stdout_fd[1]);\r
-               } \r
-               else \r
+               }\r
+               else\r
                {/* child */\r
-                       \r
+\r
                        /* close unused file descriptors */\r
                        if(command->writer)\r
                                close(child_stdin_fd[1]);\r
-                               \r
+\r
                        if(command->reader)\r
                                close(child_stdout_fd[0]);\r
-                       \r
+\r
                        if(command->writer)\r
                        {\r
-                               /* redirect stdin to child_stdin_fd[0] (now fgets(), getchar() ... read from the pipe */  \r
+                               /* redirect stdin to child_stdin_fd[0] (now fgets(), getchar() ... read from the pipe */\r
                                if(dup2(child_stdin_fd[0],STDIN_FILENO) < 0)\r
                                {\r
-                                       error_register("dup2() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
+                                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));\r
+                                       command->unit->exit_code = errno;\r
+\r
+                                       unit_set_error(command->unit, errno, 0, command->context->pos);\r
                                        command_handle_failure(command,csr_dup2_function_failure);\r
                                }\r
-                       \r
+\r
                                /* close the unused file descriptor  */\r
                                close(child_stdin_fd[0]);\r
                        }\r
-                       \r
+\r
                        if(command->reader)\r
                        {\r
-                       \r
-                               /* redirect stdout and stderr to child_stdout_fd[1] (now printf(), perror()... write to the pipe */  \r
+\r
+                               /* redirect stdout and stderr to child_stdout_fd[1] (now printf(), perror()... write to the pipe */\r
                                if(dup2(child_stdout_fd[1],STDOUT_FILENO) < 0)\r
                                {\r
-                                       error_register("dup2() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
+                                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));\r
+\r
+                                       unit_set_error(command->unit, errno, 0, command->context->pos);\r
                                        command_handle_failure(command, csr_dup2_function_failure);\r
                                }\r
-                               \r
+\r
                                if(dup2(child_stdout_fd[1], STDERR_FILENO) < 0)\r
                                {\r
-                                       error_register("dup2() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
+                                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));\r
+                                       unit_set_error(command->unit, errno, 0, command->context->pos);\r
                                        command_handle_failure(command, csr_dup2_function_failure);\r
                                }\r
-                       \r
+\r
                                /* close the unused file descriptor  */\r
                                close(child_stdout_fd[1]);\r
                        }\r
-                       \r
+\r
                        /* launch the command */\r
                        if(execlp("/bin/sh", "sh", "-c", command->context->command_line, NULL) < 0)\r
                                command->execlp_errno = errno;\r
@@ -541,8 +675,12 @@ command_wait(command_t command)
 \r
        if(WAIT_FAILED == WaitForSingleObject(command->pid, INFINITE))\r
        {\r
-               ERROR0("WaitForSingleObject() failed");\r
-               /* TODO : see for the interruption      */      \r
+               ERROR2("[%s] Cannot wait for the child`%s'", command->context->pos, command->context->command_line);\r
+\r
+               unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);\r
+\r
+               command_handle_failure(command, csr_wait_failure );\r
+               /* TODO : see for the interruption      */\r
        }\r
        else\r
        {\r
@@ -551,8 +689,11 @@ command_wait(command_t command)
                {\r
                        if(!GetExitCodeProcess(command->pid,&rv))\r
                        {\r
-                               ERROR1("GetExitCodeProcess() failed for the child %s",command->context->command_line);\r
-                               /* TODO : see for the interruption      */      \r
+                               ERROR2("[%s] Cannot get the exit code of the process `%s'",command->context->pos, command->context->command_line);\r
+\r
+                               unit_set_error(command->unit, (int)GetLastError(), 0, command->context->pos);\r
+\r
+                               command_handle_failure(command, csr_get_exit_code_process_function_failure );\r
                        }\r
                        else\r
                                command->stat_val = command->exit_code = rv;\r
@@ -565,24 +706,29 @@ command_wait(command_t command)
 {\r
        if(!command->execlp_errno)\r
        {\r
-               \r
                /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */\r
                int pid = waitpid(command->pid, &(command->stat_val), 0);\r
-       \r
-               if(pid != command->pid) \r
+\r
+               if(pid != command->pid)\r
                {\r
-                       error_register("waitpid() function failed", errno, command->context->command_line, command->unit->fstream->name);\r
+                       ERROR2("[%s] Cannot wait for the child`%s'", command->context->pos, command->context->command_line);\r
+\r
+                       unit_set_error(command->unit, errno, 0, command->context->pos);\r
+\r
                        command_handle_failure(command, csr_waitpid_function_failure);\r
                }\r
                else\r
                {\r
                        if(WIFEXITED(command->stat_val))\r
-                               command->exit_code = WEXITSTATUS(command->stat_val);    \r
+                               command->exit_code = WEXITSTATUS(command->stat_val);\r
                }\r
        }\r
        else\r
        {\r
-               error_register("execlp() function failed", command->execlp_errno, command->context->command_line, command->unit->fstream->name);\r
+               ERROR2("[%s] Cannot execute the command `%s'", command->context->pos, command->context->command_line);\r
+\r
+               unit_set_error(command->unit, command->execlp_errno, 0, command->context->pos);\r
+\r
                command_handle_failure(command, csr_execlp_function_failure);\r
        }\r
 }\r
@@ -593,98 +739,153 @@ command_check(command_t command)
 {\r
        int success = 1;\r
        cs_reason_t reason;\r
-       \r
+\r
        /* we have a signal, store it */\r
        if(WIFSIGNALED(command->stat_val))\r
        {\r
                command->signal = strdup(signal_name(WTERMSIG(command->stat_val),command->context->signal));\r
        }\r
-       \r
-       /* we have a signal and not signal is expected */\r
-       if(WIFSIGNALED(command->stat_val) && !command->context->signal) \r
+\r
+       /* we have a signal and no signal is expected */\r
+       if(WIFSIGNALED(command->stat_val) && !command->context->signal)\r
        {\r
                success = 0;\r
-               error_register("Command failure", EUNXPSIG, command->context->command_line, command->unit->fstream->name);\r
+               ERROR3("[%s] `%s' : NOK (unexpected signal `%s' caught)", command->context->pos, command->context->command_line, command->signal);\r
+\r
+               unit_set_error(command->unit, EUNXPSIG, 1, command->context->pos);\r
+\r
                reason = csr_unexpected_signal_caught;\r
        }\r
-       \r
+\r
        /* we have a signal that differ form the expected signal */\r
-       if(success && WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal)) \r
+       if(WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal))\r
        {\r
-               success = 0;\r
-               error_register("Command failure", ESIGNOTMATCH, command->context->command_line, command->unit->fstream->name);\r
+\r
+               ERROR4("[%s] `%s' : NOK (got signal `%s' instead of `%s')", command->context->pos, command->context->command_line, command->signal, command->context->signal);\r
+\r
+               if(success)\r
+               {\r
+                       success = 0;\r
+                       unit_set_error(command->unit, ESIGNOTMATCH, 1, command->context->pos);\r
+               }\r
+\r
                reason = csr_signals_dont_match;\r
        }\r
-       \r
-       /* we don't receipt the expected signal */\r
-       if(success && !WIFSIGNALED(command->stat_val) && command->context->signal) \r
+\r
+       /* we don't receive the expected signal */\r
+       if(!WIFSIGNALED(command->stat_val) && command->context->signal)\r
        {\r
-               success = 0;\r
-               error_register("Command failure", ESIGNOTRECEIPT, command->context->command_line, command->unit->fstream->name);\r
-               reason = csr_expected_signal_not_receipt;\r
+\r
+               ERROR3("[%s] `%s' : NOK (expected `%s' not received)", command->context->pos, command->context->command_line, command->context->signal);\r
+\r
+               if(success)\r
+               {\r
+                       success = 0;\r
+                       unit_set_error(command->unit, ESIGNOTRECEIVED, 1, command->context->pos);\r
+               }\r
+\r
+               reason = csr_expected_signal_not_received;\r
        }\r
-       \r
+\r
        /* if the command exit normaly and we expect a exit code : test it */\r
-       if(success && WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)\r
+       if(WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)\r
        {\r
                /* the exit codes don't match */\r
                if(WEXITSTATUS(command->stat_val) != command->context->exit_code)\r
                {\r
-                       success = 0;\r
-                       error_register("Command failure", EEXITCODENOTMATCH, command->context->command_line, command->unit->fstream->name);\r
+                       ERROR4("[%s] %s : NOK (returned code `%d' instead `%d')", command->context->pos, command->context->command_line, WEXITSTATUS(command->stat_val), command->context->exit_code);\r
+\r
+                       if(success)\r
+                       {\r
+                               success = 0;\r
+                               unit_set_error(command->unit, EEXITCODENOTMATCH, 1, command->context->pos);\r
+                       }\r
+\r
                        reason = csr_exit_codes_dont_match;\r
                }\r
        }\r
-       \r
-       /* if ouput handling flag is specified check the output */\r
-       if(success && oh_check == command->context->output_handling && command->reader)\r
-       {\r
-               /* make sure the reader done */\r
-               while(!command->reader->done)\r
-                       xbt_os_thread_yield();\r
-               \r
-               #ifdef WIN32\r
-               CloseHandle(command->stdout_fd);\r
-               #else\r
-               close(command->stdout_fd);\r
-               #endif\r
 \r
-               command->stdout_fd = INDEFINITE_FD;\r
+       /* make sure the reader done */\r
+       while(!command->reader->done)\r
+               xbt_os_thread_yield();\r
+\r
+       #ifdef WIN32\r
+       CloseHandle(command->stdout_fd);\r
+       #else\r
+       close(command->stdout_fd);\r
+       #endif\r
+\r
+       command->stdout_fd = INDEFINITE_FD;\r
 \r
-               xbt_strbuff_chomp(command->output);\r
-               xbt_strbuff_chomp(command->context->output);\r
-               xbt_strbuff_trim(command->output);\r
-               xbt_strbuff_trim(command->context->output);\r
+       xbt_strbuff_chomp(command->output);\r
+       xbt_strbuff_chomp(command->context->output);\r
+       xbt_strbuff_trim(command->output);\r
+       xbt_strbuff_trim(command->context->output);\r
 \r
+       if(!success &&  !strcmp(command->output->data, command->context->output->data))\r
+       {\r
+               xbt_dynar_t a = xbt_str_split(command->output->data, "\n");\r
+               char *out = xbt_str_join(a,"\n||");\r
+               xbt_dynar_free(&a);\r
+               INFO2("Output of <%s> so far: \n||%s", command->context->pos,out);\r
+               free(out);\r
+       }\r
+       /* if ouput handling flag is specified check the output */\r
+       else if(oh_check == command->context->output_handling && command->reader)\r
+       {\r
                if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))\r
                {\r
-                       success = 0;\r
-                       error_register("Command failure", EOUTPUTNOTMATCH, command->context->command_line, command->unit->fstream->name);\r
+                       char *diff;\r
+\r
+\r
+                       ERROR2("[%s] `%s' : NOK (outputs mismatch):", command->context->pos, command->context->command_line);\r
+\r
+                       if(success)\r
+                       {\r
+                               unit_set_error(command->unit, EOUTPUTNOTMATCH, 1, command->context->pos);\r
+                               success = 0;\r
+                       }\r
+\r
                        reason = csr_outputs_dont_match;\r
+\r
+                       /* display the diff */\r
+                       diff = xbt_str_diff(command->context->output->data,command->output->data);\r
+                       INFO1("%s",diff);\r
+                       free(diff);\r
                }\r
        }\r
-       \r
+       else if (oh_ignore == command->context->output_handling)\r
+       {\r
+               INFO1("(ignoring the output of <%s> as requested)",command->context->line);\r
+       }\r
+       else if (oh_display == command->context->output_handling)\r
+       {\r
+               xbt_dynar_t a = xbt_str_split(command->output->data, "\n");\r
+               char *out = xbt_str_join(a,"\n||");\r
+               xbt_dynar_free(&a);\r
+               INFO3("[%s] Here is the (ignored) command `%s' output: \n||%s",command->context->pos, command->context->command_line, out);\r
+               free(out);\r
+       }\r
+\r
        if(success)\r
        {\r
                xbt_os_mutex_acquire(command->mutex);\r
-               \r
+\r
                if(command->status != cs_interrupted)\r
                {\r
-               \r
                        /* signal the success of the command */\r
                        command->status = cs_successeded;\r
                        command->successeded = 1;\r
 \r
                        /* increment the number of successeded command of the unit */\r
-                       (command->unit->successeded_cmd_nb)++;\r
+                       (command->root->successeded_cmd_nb)++;\r
                }\r
-               \r
+\r
                xbt_os_mutex_release(command->mutex);\r
-                       \r
        }\r
        else\r
        {\r
-               command_handle_failure(command,reason);\r
+               command_handle_failure(command, reason);\r
        }\r
 }\r
 \r
@@ -693,7 +894,10 @@ void
 command_kill(command_t command)\r
 {\r
        if(INDEFINITE_PID != command->pid)\r
+       {\r
+               INFO2("[%s] Kill the process `%s'", command->context->pos, command->context->command_line);\r
                TerminateProcess(command->pid, INDEFINITE);\r
+       }\r
 }\r
 #else\r
 void\r
@@ -702,17 +906,19 @@ command_kill(command_t command)
        if(INDEFINITE_PID != command->pid)\r
        {\r
                kill(command->pid,SIGTERM);\r
-               \r
+\r
                if(!command->context->signal)\r
                        command->context->signal = strdup("SIGTERM");\r
-                       \r
+\r
                command->exit_code = INDEFINITE;\r
                command->killed = 1;\r
-               \r
+\r
                usleep(100);\r
-               kill(command->pid,SIGKILL); \r
 \r
-               \r
+               INFO2("[%s] Kill the process `%s'", command->context->pos, command->context->command_line);\r
+               kill(command->pid,SIGKILL);\r
+\r
+\r
        }\r
 }\r
 #endif\r
@@ -721,23 +927,25 @@ void
 command_interrupt(command_t command)\r
 {\r
        xbt_os_mutex_acquire(command->mutex);\r
-       \r
+\r
        if((command->status != cs_interrupted) && (command->status != cs_failed) && (command->status != cs_successeded))\r
        {\r
-               command->status = cs_interrupted;       \r
+               command->status = cs_interrupted;\r
                command->reason = csr_interruption_request;\r
                command->interrupted = 1;\r
-               xbt_os_mutex_acquire(command->unit->mutex);\r
-               (command->unit->interrupted_cmd_nb)++;\r
-               xbt_os_mutex_release(command->unit->mutex);\r
-               \r
+               command->unit->interrupted = 1;\r
+\r
+               xbt_os_mutex_acquire(command->root->mutex);\r
+               (command->root->interrupted_cmd_nb)++;\r
+               xbt_os_mutex_release(command->root->mutex);\r
+\r
                if(command->pid != INDEFINITE_PID)\r
                        command_kill(command);\r
        }\r
-       \r
+\r
        xbt_os_mutex_release(command->mutex);\r
-       \r
-       \r
+\r
+\r
 }\r
 \r
 void\r
@@ -745,12 +953,12 @@ command_summarize(command_t command)
 {\r
        if(cs_successeded != command->status)\r
        {\r
-                       \r
+\r
                #ifndef WIN32\r
                if(command->killed)\r
                        printf("          <killed command>\n");\r
                #endif\r
-               \r
+\r
                /* display the reason of the status of the command */\r
                switch(command->reason)\r
                {\r
@@ -758,7 +966,15 @@ command_summarize(command_t command)
                        case csr_pipe_function_failed :\r
                        printf("          reason                      : pipe() or CreatePipe() function failed (system error)\n");\r
                        break;\r
-                       \r
+\r
+                       case csr_shell_failed :\r
+                       printf("          reason                      : shell failed (may be command not found)\n");\r
+                       break;\r
+\r
+                       case csr_get_exit_code_process_function_failure :\r
+                       printf("          reason                      : ExitCodeProcess() function failed (system error)\n");\r
+                       break;\r
+\r
                        /* reader failure reasons*/\r
                        case csr_read_pipe_broken :\r
                        printf("          reason                      : command read pipe broken\n");\r
@@ -767,7 +983,7 @@ command_summarize(command_t command)
                        case csr_read_failure :\r
                        printf("          reason                      : command stdout read failed\n");\r
                        break;\r
-       \r
+\r
                        /* writer failure reasons */\r
                        case csr_write_failure :\r
                        printf("          reason                      : command stdin write failed\n");\r
@@ -776,67 +992,67 @@ command_summarize(command_t command)
                        case csr_write_pipe_broken :\r
                        printf("          reason                      : command write pipe broken\n");\r
                        break;\r
-                       \r
+\r
                        /* timer reason */\r
                        case csr_timeout :\r
                        printf("          reason                      : command timeouted\n");\r
                        break;\r
-                       \r
+\r
                        /* command failure reason */\r
                        case csr_command_not_found :\r
                        printf("          reason                      : command not found\n");\r
                        break;\r
-                       \r
+\r
                        /* context failure reasons */\r
                        case csr_exit_codes_dont_match :\r
                        printf("          reason                      : exit codes don't match\n");\r
-                       \r
+\r
                        break;\r
-                       \r
+\r
                        /* dup2 function failure reasons */\r
                        case csr_dup2_function_failure :\r
                        printf("          reason                      : dup2() function failed\n");\r
-                       \r
+\r
                        break;\r
-                       \r
+\r
                        /* execlp function failure reasons */\r
                        case csr_execlp_function_failure :\r
                        printf("          reason                      : execlp() function failed\n");\r
-                       \r
+\r
                        break;\r
-                       \r
+\r
                        /* waitpid function failure reasons */\r
                        case csr_waitpid_function_failure :\r
                        printf("          reason                      : waitpid() function failed\n");\r
-                       \r
+\r
                        break;\r
-                       \r
+\r
                        /* CreateProcess function failure reasons */\r
                        case csr_create_process_function_failure :\r
                        printf("          reason                      : CreateProcesss() function failed\n");\r
-                       \r
+\r
                        break;\r
-                       \r
+\r
                        case csr_outputs_dont_match :\r
                        {\r
-                               char *diff;\r
+                               /*char *diff;*/\r
                                printf("          reason                      : ouputs don't match\n");\r
-                               diff = xbt_str_diff(command->context->output->data,command->output->data);              \r
+                               /*diff = xbt_str_diff(command->context->output->data,command->output->data);\r
                                printf("          output diff :\n%s\n",diff);\r
-                               free(diff);\r
-                       }     \r
+                               free(diff);*/\r
+                       }\r
 \r
                        break;\r
 \r
                        case csr_signals_dont_match :\r
-                       printf("          reason                      : signals don't match\n"); \r
+                       printf("          reason                      : signals don't match\n");\r
                        break;\r
-                       \r
+\r
                        case csr_unexpected_signal_caught:\r
-                       printf("                reason                      : unexpected signal caught\n");\r
+                       printf("          reason                      : unexpected signal caught\n");\r
                        break;\r
-                       \r
-                       case csr_expected_signal_not_receipt :\r
+\r
+                       case csr_expected_signal_not_received :\r
                        printf("          reason                      : expected signal not receipt\n");\r
                        break;\r
 \r
@@ -844,16 +1060,16 @@ command_summarize(command_t command)
                        case csr_fork_function_failure :\r
                        printf("          reason                      : fork function failed\n");\r
                        break;\r
-                       \r
+\r
                        case csr_wait_failure :\r
                        printf("          reason                      : wait command failure\n");\r
                        break;\r
-                       \r
+\r
                        /* global/local interruption */\r
                        case csr_interruption_request :\r
                        printf("          reason                      : the command receive a interruption request\n");\r
                        break;\r
-                       \r
+\r
                        /* unknown ? */\r
                        case csr_unknown :\r
                        printf("          reason                      : unknown \n");\r
@@ -865,24 +1081,31 @@ command_summarize(command_t command)
                if(INDEFINITE != command->exit_code)\r
                        /* the command exit code */\r
                        printf("          exit code                   : %d\n",command->exit_code);\r
-               \r
+\r
                /* if an expected exit code was specified display it */\r
                if(INDEFINITE != command->context->exit_code)\r
                        printf("          expected exit code          : %d\n",command->context->exit_code);\r
                else\r
                        printf("          no expected exit code specified\n");\r
-               \r
-               /* if an expected exit code was specified display it */\r
+\r
+               /* no expected signal expected */\r
                if(NULL == command->context->signal)\r
+               {\r
                        printf("          no expected signal specified\n");\r
+\r
+                       if(command->signal)\r
+                               printf("          but got signal              : %s\n",command->signal);\r
+\r
+               }\r
+               /* if an expected exit code was specified display it */\r
                else\r
                {\r
                        if(NULL != command->signal)\r
                                printf("          signal                      : %s\n",command->signal);\r
-                       \r
-                       printf("          expected signal             : %s\n",command->context->signal);\r
+                       else\r
+                               printf("          no signal caugth\n");\r
                }\r
-               \r
+\r
                /* if the command has out put and the metacommand display output is specified display it  */\r
                if(command->output && (0 != command->output->used) && (oh_display == command->context->output_handling))\r
                {\r
@@ -897,15 +1120,11 @@ command_summarize(command_t command)
        printf("\n");\r
 }\r
 \r
-\r
-\r
-\r
 void\r
 command_handle_failure(command_t command, cs_reason_t reason)\r
 {\r
-       \r
-       unit_t unit = command->unit;\r
-       \r
+       unit_t root = command->root;\r
+\r
        xbt_os_mutex_acquire(command->mutex);\r
 \r
        if((command->status != cs_interrupted) && (command->status != cs_failed))\r
@@ -913,24 +1132,26 @@ command_handle_failure(command_t command, cs_reason_t reason)
                command->status = cs_failed;\r
                command->reason = reason;\r
                command->failed = 1;\r
-               \r
-               xbt_os_mutex_acquire(unit->mutex);\r
-               \r
+\r
+               command->unit->failed = 1;\r
+\r
+               xbt_os_mutex_acquire(root->mutex);\r
+\r
                /* increment the number of failed command of the unit */\r
-               unit->failed_cmd_nb++;\r
-               \r
+               root->failed_cmd_nb++;\r
+\r
                /* if the --ignore-failures option is not specified */\r
                if(!keep_going_unit_flag)\r
                {\r
-                       if(!unit->interrupted)\r
+                       if(!root->interrupted)\r
                        {\r
                                /* the unit interrupted (exit for the loop) */\r
-                               unit->interrupted = 1;\r
+                               root->interrupted = 1;\r
 \r
                                /* release the unit */\r
-                               xbt_os_sem_release(unit->sem);\r
+                               xbt_os_sem_release(root->sem);\r
                        }\r
-                       \r
+\r
                        /* if the --keep-going option is not specified */\r
                        if(!keep_going_flag)\r
                        {\r
@@ -938,14 +1159,14 @@ command_handle_failure(command_t command, cs_reason_t reason)
                                {\r
                                        /* request an global interruption by the runner */\r
                                        interrupted = 1;\r
-                                       \r
+\r
                                        /* release the runner */\r
                                        xbt_os_sem_release(units_sem);\r
                                }\r
                        }\r
                }\r
 \r
-               xbt_os_mutex_release(unit->mutex);\r
+               xbt_os_mutex_release(root->mutex);\r
        }\r
 \r
        xbt_os_mutex_release(command->mutex);\r
@@ -954,47 +1175,45 @@ command_handle_failure(command_t command, cs_reason_t reason)
 int\r
 command_free(command_t* ptr)\r
 {\r
-       /* TODO : check the parameter */\r
-       \r
        /* close the stdin and the stdout pipe handles */\r
 \r
        #ifdef WIN32\r
        if((*ptr)->stdin_fd != INDEFINITE_FD)\r
                CloseHandle((*ptr)->stdin_fd);\r
-               \r
+\r
        if((*ptr)->stdout_fd != INDEFINITE_FD)\r
                CloseHandle((*ptr)->stdout_fd);\r
-       \r
+\r
        #else\r
-       \r
+\r
        if((*ptr)->stdin_fd != INDEFINITE_FD)\r
                close((*ptr)->stdin_fd);\r
-       \r
-       if((*ptr)->stdout_fd != INDEFINITE_FD)  \r
+\r
+       if((*ptr)->stdout_fd != INDEFINITE_FD)\r
                close((*ptr)->stdout_fd);\r
        #endif\r
-       \r
+\r
        if((*ptr)->timer)\r
        {\r
                if(timer_free(&((*ptr)->timer)) < 0)\r
                        return -1;\r
-                       \r
        }\r
-       \r
+\r
        if((*ptr)->writer)\r
        {\r
                if(writer_free(&((*ptr)->writer)) < 0)\r
                        return -1;\r
        }\r
-       \r
+\r
        if((*ptr)->reader)\r
        {\r
                if(reader_free(&((*ptr)->reader)) < 0)\r
                        return -1;\r
        }\r
-       \r
-       xbt_strbuff_free((*ptr)->output);\r
-       \r
+\r
+       if((*ptr)->output)\r
+               xbt_strbuff_free((*ptr)->output);\r
+\r
        if((*ptr)->context)\r
        {\r
                if(context_free(&((*ptr)->context)) < 0)\r
@@ -1005,9 +1224,9 @@ command_free(command_t* ptr)
                free((*ptr)->signal);\r
 \r
        free(*ptr);\r
-       \r
+\r
        *ptr = NULL;\r
-       \r
+\r
        return 0;\r
 }\r
 \r