-
+/*
+ * src/command.c - type representing a command.
+ *
+ * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package.
+ *
+ * Purpose:
+ * This file contains all the definitions of the functions related with
+ * the tesh command type.
+ *
+ */
+#include <unit.h>
#include <command.h>
#include <context.h>
#include <writer.h>
#ifndef WIN32
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#else
+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
+}
#endif
-#include "../include/_signal.h"
+#include <com.h>
+#include <xsignal.h>
+#include <is_cmd.h>
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
-static void sig_io_handler(int status)
-{
- INFO0("*************************Got a SIGIO**************************************");
-}
-
static void*
command_start(void* p);
+
command_t
command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
{
- command_t command = xbt_new0(s_command_t, 1);
+ command_t command;
+
+ command = xbt_new0(s_command_t, 1);
/* get the context of the execution of the command */
- command->context = context_dup(context);
+ if(!(command->context = context_dup(context)))
+ {
+ free(command);
+ return NULL;
+ }
/* the exit code of the command is indefinite */
command->exit_code = INDEFINITE;
/* the mutex used to safetly access to the command unit properties */
command->mutex = mutex;
-
- if(context->output->used)
- /* instantiate the buffer filled with the content of the command stdout */
- command->output = xbt_strbuff_new();
- else
- command->output = NULL;
+
+ command->output = xbt_strbuff_new();
command->pid = INDEFINITE_PID;
command->stat_val = -1;
/* set the unit of the command */
- command->unit = unit->root ? unit->root : unit;
+ command->root = unit->root ? unit->root : unit;
+ command->unit = unit;
/* all the commands are runned in a thread */
command->thread = NULL;
command->successeded = 0;
- if(context->output->used)
- command->reader = reader_new(command);
- else
- command->reader = NULL;
+ command->reader = reader_new(command);
if(context->input->used)
command->writer = writer_new(command);
/* register the command */
xbt_os_mutex_acquire(mutex);
- vector_push_back(unit->commands, command);
-
- (command->unit->number_of_commands)++;
-
+ xbt_dynar_push(unit->commands, &command);
+ command->root->cmd_nb++;
xbt_os_mutex_release(mutex);
- command->fn_sig_io_handler = sig_io_handler;
-
#ifndef WIN32
command->killed = 0;
+ command->execlp_errno = 0;
#endif
-
return command;
}
-void
+int
command_run(command_t command)
{
- if(!want_silent)
- INFO1("tesh %s",command->context->command_line);
+ if(!silent_flag)
+ INFO2("[%s] %s",command->context->pos, command->context->command_line);
- if(!want_just_display)
+ if(!just_print_flag)
{
if(!interrupted)
{
- /* start the command */
-
+ /* start the command in a thread*/
if(command->context->async)
{
command->thread = xbt_os_thread_create("", command_start, command);
- if(!command->thread)
- ERROR0("xbt_os_thread_create() failed\n");
}
else
+ {
+ /* start the command in the main thread */
command_start(command);
+ }
}
else
{
command_interrupt(command);
}
+
+
}
+
+ return 0;
}
command_start(void* p)
{
command_t command = (command_t)p;
- unit_t unit = command->unit;
+ unit_t root = command->root;
/* the command is started */
command->status = cs_started;
/* increment the number of started commands of the unit */
xbt_os_mutex_acquire(command->mutex);
- (command->unit->number_of_started_commands)++;
+ (root->started_cmd_nb)++;
xbt_os_mutex_release(command->mutex);
/* execute the command of the test */
if(cs_in_progress == command->status)
{
- /*printf("the command %p is in progress\n",command);*/
-
- /* on attend la fin de la commande.
- * la command peut soit se terminée normalement,
- * 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
- * soit à la suit d'une demande d'interruption
- */
-
+ /* wait the process if it is in progress */
command_wait(command);
if(cs_failed != command->status && cs_interrupted != command->status)
- {
- /*printf("checking the command %p\n",command);*/
command_check(command);
- }
}
-
xbt_os_mutex_acquire(command->mutex);
- /* if it's the last command release its unit */
- 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)))
+ /* if it's the last command of the root unit */
+ if(!root->interrupted && root->parsed && (root->started_cmd_nb == (root->failed_cmd_nb + root->interrupted_cmd_nb + root->successeded_cmd_nb)))
{
/* first release the mutex */
- unit->released = 1;
+ root->released = 1;
xbt_os_mutex_release(command->mutex);
/* the last command release the unit */
- xbt_os_sem_release(command->unit->sem);
+ xbt_os_sem_release(root->sem);
}
else
xbt_os_mutex_release(command->mutex);
/* wait the end of the timer, the reader and the writer */
if(command->timer && command->timer->thread)
timer_wait(command->timer);
-
+
+ /* wait the end of the writer */
if(command->writer && command->writer->thread)
writer_wait(command->writer);
-
+
+ /* wait the end of the reader */
if(command->reader && command->reader->thread)
reader_wait(command->reader);
+
+
return NULL;
}
#ifdef WIN32
+
+#ifndef BUFSIZE
+#define BUFSIZE 4096\r
+#endif
void
command_exec(command_t command, const char* command_line)
{
HANDLE child_stdout_handle[2] = {NULL}; /* child_stdout_handle[0] <-> stdin of the child process */
HANDLE child_stderr = NULL;
+
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; /* use default security for the pipe handles */
if(!CreatePipe(&(child_stdin_handle[0]),&(child_stdin_handle[1]),&sa,0))
{
- ERROR1("CreatePipe1() failed (%lu)",GetLastError());
- command->failed = 1;
- command->status = cs_failed;
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
+
+ unit_set_error(command->unit, (int)GetLastError(), 0);
+ command->failed = 1;
+ command->status = cs_failed;
+
return;
}
if(!DuplicateHandle(GetCurrentProcess(),(child_stdin_handle[1]),GetCurrentProcess(),&(child_stderr),0,TRUE,DUPLICATE_SAME_ACCESS))
{
- ERROR1("DuplicateHandle1() failed (%lu)",GetLastError());
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
+
+ unit_set_error(command->unit, (int)GetLastError(), 0);
CloseHandle(child_stdin_handle[0]);
CloseHandle(child_stdin_handle[1]);
if(!CreatePipe(&(child_stdout_handle[0]),&(child_stdout_handle[1]),&sa,0))
{
- ERROR1("CreatePipe2() failed (%lu)",GetLastError());
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
+ unit_set_error(command->unit, (int)GetLastError(), 0);
CloseHandle(child_stdout_handle[0]);
CloseHandle(child_stdout_handle[1]);
command->failed = 1;
command->status = cs_failed;
-
- ERROR1("DuplicateHandle2() failed (%lu)",GetLastError());
- }
+
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
+ unit_set_error(command->unit, (int)GetLastError(), 0);
+
+ return;
+ }
/* Write handle for write operations on the child std input. */
command->failed = 1;
command->status = cs_failed;
+
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
- ERROR1("DuplicateHandle3() failed (%lu)",GetLastError());
- }
+ unit_set_error(command->unit, (int)GetLastError(), 0);
+ return;
+ }
CloseHandle(child_stdin_handle[0]);
CloseHandle(child_stdout_handle[1]);
+
if(command->timer)
{
writer_write(command->writer);
}
+ /* if there is a reader wait for its starting */
+ if(command->reader)
+ xbt_os_sem_acquire(command->reader->started);
+
+ /* if there is a reader wait for its ending */
+ if(command->writer)
+ xbt_os_sem_acquire(command->writer->written);
+
+ /* if there is a reader wait for its starting */
+ if(command->timer)
+ xbt_os_sem_acquire(command->timer->started);
+
si.cb = sizeof(STARTUPINFO);
si.dwFlags |= STARTF_USESTDHANDLES;
/* launch the process */
if(!CreateProcess(
NULL,
- (char*)command_line,
+ tow32cmd(command_line),
NULL,
NULL,
TRUE,
&pi)
)
{
-
+
if(ERROR_FILE_NOT_FOUND == GetLastError())
{
- exit_code = ECMDNOTFOUND;
- command_handle_failure(command,csr_command_not_found);
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(ECMDNOTFOUND, 1));
+ unit_set_error(command->unit, ECMDNOTFOUND, 1);
+ command_handle_failure(command, csr_command_not_found);
}
else
{
- exit_code = EEXEC;
- command_handle_failure(command,csr_exec_failure);
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
+
+ unit_set_error(command->unit, (int)GetLastError(), 0);
+ command_handle_failure(command, csr_create_process_function_failure);
}
+
}
else
{
int child_stdin_fd[2] ;
int child_stdout_fd[2];
- if(pipe(child_stdin_fd) || pipe(child_stdout_fd))
+ #ifdef __CHKCMD
+ int rv = is_cmd(command->unit->runner->path, command->unit->runner->builtin, command_line);
+
+ if(rv != 0)
{
- ERROR1("pipe() failed (%d)",errno);
- command_handle_failure(command, csr_pipe_function_failed);
+ if(rv == EINVAL)
+ {
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(rv, 0));
+ unit_set_error(command->unit, rv, 0);
+ }
+ else
+ {
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(rv, 1));
+ unit_set_error(command->unit, rv, 1);
+ }
+
+ command_handle_failure(command, csr_command_not_found);
+
return;
}
- command->pid= fork();
-
- if(command->pid < 0)
- {
- close(child_stdin_fd[0]);
- close(child_stdin_fd[1]);
- close(child_stdout_fd[0]);
- close(child_stdout_fd[1]);
-
- exit_code = EEXEC;
- ERROR1("fork() failed (%d)",errno);
- command_handle_failure(command,csr_exec_failure);
- }
- else
+ #endif
+
+
+ if(command->writer)
{
- if(command->pid)
- {/* father */
+ if(pipe(child_stdin_fd))
+ {
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
+ unit_set_error(command->unit, errno, 0);
+
+ command_handle_failure(command, csr_pipe_function_failed);
+
- close(child_stdin_fd[0]);
- close(child_stdout_fd[1]);
+
+ return;
+ }
+ }
+
+ if(command->reader)
+ {
+ if(pipe(child_stdout_fd))
+ {
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
+
+ if(command->writer)
+ {
+ close(child_stdin_fd[0]);
+ close(child_stdin_fd[1]);
+ }
- command->stdin_fd = child_stdin_fd[1];
+ unit_set_error(command->unit, errno, 0);
+
+ command_handle_failure(command, csr_pipe_function_failed);
- command->stdout_fd = child_stdout_fd[0];
+ return;
+ }
+ }
+
+ if(command->writer)
+ {
+ if(fcntl(child_stdin_fd[1], F_SETFL, fcntl(child_stdin_fd[1], F_GETFL) | O_NONBLOCK) < 0)
+ {
+
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
- /* on indique que c'est le processus parent qui doit recevoir le signal */
- /*fcntl(command->stdin_fd,F_SETOWN, pid);*/
+ close(child_stdin_fd[0]);
+ close(child_stdin_fd[1]);
if(command->reader)
{
- /* launch the reader */
- reader_read(command->reader);
- }
-
- if(command->writer)
- {
- /* launch the writer */
- writer_write(command->writer);
- }
-
- if(command->timer)
- {
- /* launch the timer */
- timer_time(command->timer);
+ close(child_stdout_fd[0]);
+ close(child_stdout_fd[1]);
}
- /* the command is running */
- command->status = cs_in_progress;
+ unit_set_error(command->unit, errno, 0);
+
+ command_handle_failure(command, csr_fcntl_function_failed);
+
+ return;
+ }
+ }
+
+ /* to write to the child stdin */
+ command->stdin_fd = child_stdin_fd[1];
+
+ /* to read from the child stdout */
+ command->stdout_fd = child_stdout_fd[0];
+
+ /* launch the reader if any*/
+ if(command->reader)
+ reader_read(command->reader);
+
+ /* launch the writer if any */
+ if(command->writer)
+ writer_write(command->writer);
+
+ /* launch the timer if any */
+ if(command->timer)
+ timer_time(command->timer);
- }
- else
- {/* child */
-
-
+ /* if there is a reader wait for its starting */
+ if(command->reader)
+ xbt_os_sem_acquire(command->reader->started);
+
+ /* if there is a reader wait for its ending */
+ if(command->writer)
+ xbt_os_sem_acquire(command->writer->written);
+
+ /* if there is a reader wait for its starting */
+ if(command->timer)
+ xbt_os_sem_acquire(command->timer->started);
+
+ /* update the state of the command, assume it is in progress */
+ command->status = cs_in_progress;
+
+ command->pid= fork();
+
+ if(command->pid < 0)
+ {/* error */
+ if(command->writer)
+ {
+ close(child_stdin_fd[0]);
close(child_stdin_fd[1]);
+ }
+
+ if(command->reader)
+ {
close(child_stdout_fd[0]);
+ close(child_stdout_fd[1]);
+ }
+
+ ERROR2("[%s] Cannot fork the command `%s'", command->context->pos, command->context->command_line);
+ unit_set_error(command->unit, errno, 0);
+ command_handle_failure(command,csr_fork_function_failure);
+ }
+ else
+ {
+ if(command->pid)
+ {/* father */
- if(dup2(child_stdin_fd[0],STDIN_FILENO/*0*/) < 0)
- {
- exit_code = EEXEC;
- ERROR1("dup2() failed (%d)",errno);
- command_handle_failure(command,csr_exec_failure);
- }
+ /* close unused file descriptors */
+ if(command->writer)
+ close(child_stdin_fd[0]);
+
+ if(command->reader)
+ close(child_stdout_fd[1]);
+ }
+ else
+ {/* child */
- /*close(child_stdin_fd[0]);
- */
+ /* close unused file descriptors */
+ if(command->writer)
+ close(child_stdin_fd[1]);
+
+ if(command->reader)
+ close(child_stdout_fd[0]);
- if(dup2(child_stdout_fd[1],STDOUT_FILENO/*1*/) < 0)
+ if(command->writer)
{
- exit_code = EEXEC;
- ERROR1("dup2() failed (%d)",errno);
- command_handle_failure(command,csr_exec_failure);
- }
+ /* redirect stdin to child_stdin_fd[0] (now fgets(), getchar() ... read from the pipe */
+ if(dup2(child_stdin_fd[0],STDIN_FILENO) < 0)
+ {
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
+ command->unit->exit_code = errno;
+
+ unit_set_error(command->unit, errno, 0);
+ command_handle_failure(command,csr_dup2_function_failure);
+ }
- if(dup2(child_stdout_fd[1], STDERR_FILENO/*2*/) < 0)
- {
- exit_code = EEXEC;
- ERROR1("dup2() failed (%d)",errno);
- command_handle_failure(command,csr_exec_failure);
+ /* close the unused file descriptor */
+ close(child_stdin_fd[0]);
}
- fcntl(command->stdin_fd, F_SETFL, fcntl(command->stdin_fd, F_GETFL) | O_NONBLOCK);
-
-
- if(command->writer)
- xbt_os_sem_release(command->writer->can_write);
-
- /*close(child_stdout_fd[1]);*/
-
if(command->reader)
- xbt_os_sem_acquire(command->reader->started);
+ {
- if(command->writer)
- xbt_os_sem_acquire(command->writer->written);
+ /* redirect stdout and stderr to child_stdout_fd[1] (now printf(), perror()... write to the pipe */
+ if(dup2(child_stdout_fd[1],STDOUT_FILENO) < 0)
+ {
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
+
+ unit_set_error(command->unit, errno, 0);
+ command_handle_failure(command, csr_dup2_function_failure);
+ }
- if(command->timer)
- xbt_os_sem_acquire(command->timer->started);
+ if(dup2(child_stdout_fd[1], STDERR_FILENO) < 0)
+ {
+ ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(errno, 0));
+ unit_set_error(command->unit, errno, 0);
+ command_handle_failure(command, csr_dup2_function_failure);
+ }
- if(execlp("/bin/sh", "sh", "-c", command->context->command_line, NULL) < 0)
- {
- exit_code = EEXEC;
- ERROR1("execlp() failed (%d)",errno);
- command_handle_failure(command,csr_exec_failure);
+ /* close the unused file descriptor */
+ close(child_stdout_fd[1]);
}
+
+ /* launch the command */
+ if(execlp("/bin/sh", "sh", "-c", command->context->command_line, NULL) < 0)
+ command->execlp_errno = errno;
}
}
}
if(WAIT_FAILED == WaitForSingleObject(command->pid, INFINITE))
{
- ERROR0("WaitForSingleObject() failed");
+ ERROR2("[%s] Cannot wait for the child`%s'", command->context->pos, command->context->command_line);
+
+ unit_set_error(command->unit, (int)GetLastError(), 0);
+
+ command_handle_failure(command, csr_wait_failure );
/* TODO : see for the interruption */
}
else
{
if(!GetExitCodeProcess(command->pid,&rv))
{
- ERROR1("GetExitCodeProcess() failed for the child %s",command->context->command_line);
- /* TODO : see for the interruption */
+ ERROR2("[%s] Cannot get the exit code of the process `%s'",command->context->pos, command->context->command_line);
+
+ unit_set_error(command->unit, (int)GetLastError(), 0);
+
+ command_handle_failure(command, csr_get_exit_code_process_function_failure );
}
else
command->stat_val = command->exit_code = rv;
void
command_wait(command_t command)
{
-
- int pid;
-
- /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
-
-
- xbt_os_mutex_acquire(command->unit->mutex);
- command->unit->number_of_waiting_commands++;
- xbt_os_mutex_release(command->unit->mutex);
-
- pid = waitpid(command->pid, &(command->stat_val), 0);
-
-
- xbt_os_mutex_acquire(command->unit->mutex);
- command->unit->number_of_waiting_commands--;
- xbt_os_mutex_release(command->unit->mutex);
-
- /*printf("The %p command ended\n",command);*/
- if(pid != command->pid)
+ if(!command->execlp_errno)
{
- ERROR1("waitpid() failed for the child %s",command->context->command_line);
- exit_code = EWAIT;
- command_handle_failure(command, csr_wait_failure);
+ /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
+ int pid = waitpid(command->pid, &(command->stat_val), 0);
+
+ if(pid != command->pid)
+ {
+ ERROR2("[%s] Cannot wait for the child`%s'", command->context->pos, command->context->command_line);
+
+ unit_set_error(command->unit, errno, 0);
+
+ command_handle_failure(command, csr_waitpid_function_failure);
+ }
+ else
+ {
+ if(WIFEXITED(command->stat_val))
+ command->exit_code = WEXITSTATUS(command->stat_val);
+ }
}
else
{
- if(WIFEXITED(command->stat_val))
- command->exit_code = WEXITSTATUS(command->stat_val);
+ ERROR2("[%s] Cannot execute the command `%s'", command->context->pos, command->context->command_line);
+
+ unit_set_error(command->unit, command->execlp_errno, 0);
+
+ command_handle_failure(command, csr_execlp_function_failure);
}
-
-
}
#endif
if(WIFSIGNALED(command->stat_val))
{
command->signal = strdup(signal_name(WTERMSIG(command->stat_val),command->context->signal));
- /*INFO3("the command -PID %d %s receive the signal : %s",command->pid, command->context->command_line, command->signal);*/
}
- /* we have a signal and not signal is expected */
+ /* we have a signal and no signal is expected */
if(WIFSIGNALED(command->stat_val) && !command->context->signal)
{
success = 0;
- exit_code = EUNEXPECTEDSIG;
+ ERROR3("[%s] `%s' : NOK (unexpected signal `%s' caught)", command->context->pos, command->context->command_line, command->signal);
+
+ unit_set_error(command->unit, EUNXPSIG, 1);
+
reason = csr_unexpected_signal_caught;
}
/* we have a signal that differ form the expected signal */
- if(success && WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal))
+ if(WIFSIGNALED(command->stat_val) && command->context->signal && strcmp(signal_name(WTERMSIG(command->stat_val),command->context->signal),command->context->signal))
{
- success = 0;
- exit_code = ESIGNOTMATCH;
+
+ ERROR4("[%s] `%s' : NOK (got signal `%s' instead of `%s')", command->context->pos, command->context->command_line, command->signal, command->context->signal);
+
+ if(success)
+ {
+ success = 0;
+ unit_set_error(command->unit, ESIGNOTMATCH, 1);
+ }
+
reason = csr_signals_dont_match;
}
/* we don't receipt the expected signal */
- if(success && !WIFSIGNALED(command->stat_val) && command->context->signal)
+ if(!WIFSIGNALED(command->stat_val) && command->context->signal)
{
- success = 0;
- exit_code = ESIGNOTRECEIPT;
+
+ ERROR3("[%s] `%s' : NOK (expected `%s' not receipt)", command->context->pos, command->context->command_line, command->context->signal);
+
+ if(success)
+ {
+ success = 0;
+ unit_set_error(command->unit, ESIGNOTRECEIPT, 1);
+ }
+
reason = csr_expected_signal_not_receipt;
}
/* if the command exit normaly and we expect a exit code : test it */
- if(success && WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)
+ if(WIFEXITED(command->stat_val) /* && INDEFINITE != command->context->exit_code*/)
{
/* the exit codes don't match */
if(WEXITSTATUS(command->stat_val) != command->context->exit_code)
{
- success = 0;
- exit_code = EEXITCODENOTMATCH;
+ ERROR4("[%s] %s : NOK (returned code `%d' instead `%d')", command->context->pos, command->context->command_line, WEXITSTATUS(command->stat_val), command->context->exit_code);
+
+ if(success)
+ {
+ success = 0;
+ unit_set_error(command->unit, EEXITCODENOTMATCH, 1);
+ }
+
reason = csr_exit_codes_dont_match;
}
}
+
+ /* make sure the reader done */
+ while(!command->reader->done)
+ xbt_os_thread_yield();
- /* if ouput handling flag is specified check the output */
- if(success && oh_check == command->context->output_handling && command->reader)
- {
- /* make sure the reader done */
- while(!command->reader->done)
- xbt_os_thread_yield();
-
- close(command->stdout_fd);
- command->stdout_fd = INDEFINITE_FD;
+ #ifdef WIN32
+ CloseHandle(command->stdout_fd);
+ #else
+ close(command->stdout_fd);
+ #endif
- xbt_strbuff_chomp(command->output);
- xbt_strbuff_chomp(command->context->output);
- xbt_strbuff_trim(command->output);
- xbt_strbuff_trim(command->context->output);
+ command->stdout_fd = INDEFINITE_FD;
+ xbt_strbuff_chomp(command->output);
+ xbt_strbuff_chomp(command->context->output);
+ xbt_strbuff_trim(command->output);
+ xbt_strbuff_trim(command->context->output);
+
+ if(!success)
+ {
+ xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
+ char *out = xbt_str_join(a,"\n||");
+ xbt_dynar_free(&a);
+ INFO2("Output of <%s> so far: \n||%s", command->context->pos,out);
+ free(out);
+ }
+ /* if ouput handling flag is specified check the output */
+ else if(oh_check == command->context->output_handling && command->reader)
+ {
if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))
{
- success = 0;
- exit_code = EOUTPUTNOTMATCH;
+ char *diff;
+
+ ERROR2("[%s] `%s' : NOK (outputs mismatch):", command->context->pos, command->context->command_line);
+
+ if(success)
+ {
+ unit_set_error(command->unit, EOUTPUTNOTMATCH, 1);
+ success = 0;
+ }
+
reason = csr_outputs_dont_match;
+
+ /* display the diff */
+ diff = xbt_str_diff(command->context->output->data,command->output->data);
+ INFO1("%s",diff);
+ free(diff);
}
}
+ else if (oh_ignore == command->context->output_handling)
+ {
+ INFO1("(ignoring the output of <%s> as requested)",command->context->line);
+ }
+ else if (oh_display == command->context->output_handling)
+ {
+ xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
+ char *out = xbt_str_join(a,"\n||");
+ xbt_dynar_free(&a);
+ INFO3("[%s] Here is the (ignored) command `%s' output: \n||%s",command->context->pos, command->context->command_line, out);
+ free(out);
+ }
if(success)
{
if(command->status != cs_interrupted)
{
-
/* signal the success of the command */
command->status = cs_successeded;
command->successeded = 1;
/* increment the number of successeded command of the unit */
- /*xbt_os_mutex_acquire(command->mutex);*/
- (command->unit->number_of_successeded_commands)++;
+ (command->root->successeded_cmd_nb)++;
}
- xbt_os_mutex_release(command->mutex);
-
+ xbt_os_mutex_release(command->mutex);
}
else
{
- command_handle_failure(command,reason);
+ command_handle_failure(command, reason);
}
}
command_kill(command_t command)
{
if(INDEFINITE_PID != command->pid)
+ {
+ INFO2("[%s] Kill the process `%s'", command->context->pos, command->context->command_line);
TerminateProcess(command->pid, INDEFINITE);
+ }
}
#else
void
{
if(INDEFINITE_PID != command->pid)
{
- /*INFO1("Kill the command - PID %d",command->pid);*/
-
kill(command->pid,SIGTERM);
if(!command->context->signal)
command->killed = 1;
usleep(100);
+
+ INFO2("[%s] Kill the process `%s'", command->context->pos, command->context->command_line);
kill(command->pid,SIGKILL);
if((command->status != cs_interrupted) && (command->status != cs_failed) && (command->status != cs_successeded))
{
- /*INFO1("Begin interrupt the command - PID %d",command->pid);*/
-
command->status = cs_interrupted;
command->reason = csr_interruption_request;
command->interrupted = 1;
- xbt_os_mutex_acquire(command->unit->mutex);
- (command->unit->number_of_interrupted_commands)++;
- xbt_os_mutex_release(command->unit->mutex);
+ command->unit->interrupted = 1;
+
+ xbt_os_mutex_acquire(command->root->mutex);
+ (command->root->interrupted_cmd_nb)++;
+ xbt_os_mutex_release(command->root->mutex);
if(command->pid != INDEFINITE_PID)
command_kill(command);
-
-
- /*INFO1("End interrupt the command - PID %d",command->pid);*/
}
xbt_os_mutex_release(command->mutex);
}
void
-command_display_status(command_t command)
+command_summarize(command_t command)
{
-
- /*printf("\033[1m");*/
-
if(cs_successeded != command->status)
{
printf(" reason : pipe() or CreatePipe() function failed (system error)\n");
break;
+ case csr_shell_failed :
+ printf(" reason : shell failed (may be command not found)\n");
+ break;
+
+ case csr_get_exit_code_process_function_failure :
+ printf(" reason : ExitCodeProcess() function failed (system error)\n");
+ break;
+
/* reader failure reasons*/
case csr_read_pipe_broken :
printf(" reason : command read pipe broken\n");
printf(" reason : exit codes don't match\n");
break;
-
+
+ /* dup2 function failure reasons */
+ case csr_dup2_function_failure :
+ printf(" reason : dup2() function failed\n");
+
+ break;
+
+ /* execlp function failure reasons */
+ case csr_execlp_function_failure :
+ printf(" reason : execlp() function failed\n");
+
+ break;
+
+ /* waitpid function failure reasons */
+ case csr_waitpid_function_failure :
+ printf(" reason : waitpid() function failed\n");
+
+ break;
+
+ /* CreateProcess function failure reasons */
+ case csr_create_process_function_failure :
+ printf(" reason : CreateProcesss() function failed\n");
+
+ break;
+
case csr_outputs_dont_match :
{
char *diff;
break;
case csr_unexpected_signal_caught:
- printf(" reason : unexpected signal caught\n");
+ printf(" reason : unexpected signal caught\n");
break;
case csr_expected_signal_not_receipt :
break;
/* system failure reasons */
- case csr_exec_failure :
- printf(" reason : can't excute the command\n");
+ case csr_fork_function_failure :
+ printf(" reason : fork function failed\n");
break;
case csr_wait_failure :
}
}
- if(csr_command_not_found != command->reason && csr_exec_failure != command->reason)
+ if(csr_command_not_found != command->reason && csr_fork_function_failure != command->reason && csr_execlp_function_failure != command->reason)
{
if(INDEFINITE != command->exit_code)
/* the command exit code */
else
printf(" no expected exit code specified\n");
- /* if an expected exit code was specified display it */
+ /* no expected signal expected */
if(NULL == command->context->signal)
+ {
printf(" no expected signal specified\n");
+
+ if(command->signal)
+ printf(" but got signal : %s\n",command->signal);
+
+ }
+ /* if an expected exit code was specified display it */
else
{
if(NULL != command->signal)
printf(" signal : %s\n",command->signal);
-
- printf(" expected signal : %s\n",command->context->signal);
+ else
+ printf(" no signal caugth\n");
}
/* if the command has out put and the metacommand display output is specified display it */
}
printf("\n");
-
- /*printf("\033[0m");*/
-
-
}
-
-
-
void
command_handle_failure(command_t command, cs_reason_t reason)
{
-
- unit_t unit = command->unit;
+ unit_t root = command->root;
xbt_os_mutex_acquire(command->mutex);
command->status = cs_failed;
command->reason = reason;
command->failed = 1;
+
+ command->unit->failed = 1;
- xbt_os_mutex_acquire(unit->mutex);
+ xbt_os_mutex_acquire(root->mutex);
/* increment the number of failed command of the unit */
- unit->number_of_failed_commands++;
+ root->failed_cmd_nb++;
/* if the --ignore-failures option is not specified */
- if(!want_keep_going_unit)
+ if(!keep_going_unit_flag)
{
- if(!unit->interrupted)
+ if(!root->interrupted)
{
/* the unit interrupted (exit for the loop) */
- unit->interrupted = 1;
+ root->interrupted = 1;
/* release the unit */
- xbt_os_sem_release(unit->sem);
+ xbt_os_sem_release(root->sem);
}
/* if the --keep-going option is not specified */
- if(!want_keep_going)
+ if(!keep_going_flag)
{
if(!interrupted)
{
}
}
- xbt_os_mutex_release(unit->mutex);
+ xbt_os_mutex_release(root->mutex);
}
xbt_os_mutex_release(command->mutex);
}
-void
-command_free(command_t* command)
+int
+command_free(command_t* ptr)
{
/* close the stdin and the stdout pipe handles */
#ifdef WIN32
- if((*command)->stdin_fd != INDEFINITE_FD)
- CloseHandle((*command)->stdin_fd);
- if((*command)->stdout_fd != INDEFINITE_FD)
- CloseHandle((*command)->stdout_fd);
+ if((*ptr)->stdin_fd != INDEFINITE_FD)
+ CloseHandle((*ptr)->stdin_fd);
+
+ if((*ptr)->stdout_fd != INDEFINITE_FD)
+ CloseHandle((*ptr)->stdout_fd);
+
#else
- if((*command)->stdin_fd != INDEFINITE_FD)
- close((*command)->stdin_fd);
- if((*command)->stdout_fd != INDEFINITE_FD)
- close((*command)->stdout_fd);
+ if((*ptr)->stdin_fd != INDEFINITE_FD)
+ close((*ptr)->stdin_fd);
+
+ if((*ptr)->stdout_fd != INDEFINITE_FD)
+ close((*ptr)->stdout_fd);
#endif
+
+ if((*ptr)->timer)
+ {
+ if(timer_free(&((*ptr)->timer)) < 0)
+ return -1;
+ }
+
+ if((*ptr)->writer)
+ {
+ if(writer_free(&((*ptr)->writer)) < 0)
+ return -1;
+ }
+
+ if((*ptr)->reader)
+ {
+ if(reader_free(&((*ptr)->reader)) < 0)
+ return -1;
+ }
+
+ if((*ptr)->output)
+ xbt_strbuff_free((*ptr)->output);
+
+ if((*ptr)->context)
+ {
+ if(context_free(&((*ptr)->context)) < 0)
+ return -1;
+ }
- timer_free(&((*command)->timer));
- writer_free(&((*command)->writer));
- reader_free(&((*command)->reader));
- xbt_strbuff_free((*command)->output);
- context_free(&((*command)->context));
-
- if((*command)->signal)
- free((*command)->signal);
+ if((*ptr)->signal)
+ free((*ptr)->signal);
- free(*command);
- *command = NULL;
+ free(*ptr);
+
+ *ptr = NULL;
+
+ return 0;
}