> Test unit from stdin
> [stdin:3] cat
> Test unit from stdin OK
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
p Order: out, in, cmd
< > TOTO
> Test unit from stdin
> [stdin:3] cat
> Test unit from stdin OK
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
p Order: out, cmd, in
< > TOTO
> Test unit from stdin
> [stdin:2] cat
> Test unit from stdin OK
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
p Order: in, cmd, out
< < TOTO
> Test unit from stdin
> [stdin:2] cat
> Test unit from stdin OK
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
< #include <sys/types.h>
< #include <sys/stat.h>
< #include <fcntl.h>
+<
+< #ifdef __MINGW32__
+< #define sleep _sleep
+< #endif
<
< int main() {
< char buff[2048];
\r
! expect return $ELEADTIME\r
\r
-< $ sleep 30\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' --timeout=3\r
+< $ sleep 10\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" --timeout=1\r
> Test unit from stdin\r
-> [stdin:1] sleep 30\r
+> [stdin:1] sleep 10\r
> Test unit from stdin INTR\r
-> Tesh timed out after `(3)' seconds\r
+> Tesh timed out after `(1)' seconds\r
-#! ./tesh\r# This suite builds and uses a program returning 1.\r# tesh must detect this condition and report the issue.\r\r$ rm -rf temp_testdir\r$ mkdir temp_testdir\r\r$ cd temp_testdir\r\r< #include <stdlib.h>\r< int main(void) {\r< exit(1);\r< }\r$ cat > return1.c\r\r$ gcc -o return1 return1.c\r\r\r\r! expect return $EEXITCODENOTMATCH\r< $ ./return1\r$ ../tesh --log='log.thresh:info tesh.fmt:%m%n'\r> Test unit from stdin\r> [stdin:1] ./return1\r> [stdin:1] ./return1 : NOK (returned code `1' instead `0')\r> Output of <stdin:1> so far: \r> ||\r> Test unit `(stdin)' : NOK (exit code mismatch)\r\r\r\r$ cd ..\r$ rm -rf temp_testdir\r
\ No newline at end of file
+#! ./tesh\r# This suite builds and uses a program returning 1.\r# tesh must detect this condition and report the issue.\r\r$ rm -rf temp_testdir\r$ mkdir temp_testdir\r\r$ cd temp_testdir\r\r< #include <stdlib.h>\r< int main(void) {\r< exit(1);\r< }\r$ cat > return1.c\r\r$ gcc -o return1 return1.c\r\r\r\r! expect return $EEXITCODENOTMATCH\r< $ ./return1\r$ ../tesh --log="log.thresh:info tesh.fmt:%m%n"\r> Test unit from stdin\r> [stdin:1] ./return1\r> [stdin:1] ./return1 : NOK (returned code `1' instead `0')\r> Output of <stdin:1> so far: \r> ||\r> Test unit `(stdin)' : NOK (exit code mismatch)\r\r\r\r$ cd ..\r$ rm -rf temp_testdir\r
\ No newline at end of file
! expect return $EUNXPSIG
< $ ./segfault
-$ ../tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ../tesh --log="log.thresh:info tesh.fmt:%m%n"
> Test unit from stdin
> [stdin:1] ./segfault
> [stdin:1] `./segfault' : NOK (unexpected signal `SIGSEGV' caught)
> [stdin:2] Kill the process `sleep 6'
> [stdin:2] No output before timeout
> Test unit `(stdin)' : NOK (command timed out)
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
< > TOTO
< < TUTU
< $ cat
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
> Test unit from stdin
> [stdin:3] cat
> [stdin:3] `cat' : NOK (outputs mismatch):
> [stdin:1] cd toto
> [stdin:1] Chdir to toto failed: no such file or directory
> Test unit `(stdin)' : NOK (no such file or directory)
-$ ../tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ../tesh --log="log.thresh:info tesh.fmt:%m%n"
# The next command checks that there is a testdir_temp in the upper directory,
# ie that mkdir and cd both worked.
-$ test -e ../testdir_temp
+#$ test -e ../testdir_temp
$ cd ..
$ rmdir testdir_temp
# Ignore output of the command because we can't known the order of the execution of the Tesh files.\r
! output ignore\r
\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' --silent --jobs --directory=examples jobs1.tesh jobs2.tesh jobs3.tesh jobs4.tesh jobs5.tesh jobs6.tesh jobs7.tesh jobs8.tesh jobs9.tesh \r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" --silent --jobs --directory=examples jobs1.tesh jobs2.tesh jobs3.tesh jobs4.tesh jobs5.tesh jobs6.tesh jobs7.tesh jobs8.tesh jobs9.tesh \r
\r
\r
$ rm -f job\r
< ! expect return 0\r
< > Hello Tesh\r
< $ ./job\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"\r
> Test unit from stdin\r
> [stdin:3] ./job\r
> [stdin:3] ./job : NOK (returned code `0' instead `1')\r
< ! expect return 0\r
< > Hello Tesh\r
< $ ./job\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' --keep-going-unit\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" --keep-going-unit\r
> Test unit from stdin\r
> [stdin:3] ./job\r
> [stdin:3] ./job : NOK (returned code `0' instead `1')\r
! expect return $EEXITCODENOTMATCH\r
\r
# in this case the option `keep-going' is not specified so Tesh detects the error and interrupt all the folowing units.\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' file1.tesh file2.tesh\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" file1.tesh file2.tesh\r
> Test unit from file1.tesh\r
> [file1.tesh:3] ./job\r
> [file1.tesh:3] ./job : NOK (returned code `0' instead `1')\r
> ||Hello Tesh\r
> ||\r
> Test unit `(file1.tesh)' : NOK (exit code mismatch)\r
-> Test unit from file2.tesh\r
-> Test unit from file2.tesh INTR\r
\r
< ! expect return 1\r
< > Hello Tesh\r
! expect return $EEXITCODENOTMATCH\r
\r
# in this case the option `keep-going' is specified so, Tesh execute all the other units.\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' file1.tesh file2.tesh --keep-going\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" file1.tesh file2.tesh --keep-going\r
> Test unit from file1.tesh\r
> [file1.tesh:3] ./job\r
> [file1.tesh:3] ./job : NOK (returned code `0' instead `1')\r
< > TOTO
< < TUTU
< $ cat
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
> Test unit from stdin
> [stdin:4] cat
> (ignoring the output of <stdin:4> as requested)
! include catch-signal.tesh
! include set-timeout.tesh
-
-# a command
-$ echo Hello Tesh
-> Hello Tesh
-
# some includes
! include catch-wrong-output.tesh
! expect return $ESYNTAX
< ! include-file=
< ! include $include-file
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
> Test unit from stdin
> [stdin:1] Undefined variable `(include-file)'
> Test unit `(stdin)' : NOK (syntax error)
! expect return $ESYNTAX
< ! ENOENT=300
< $ echo $ENOENT
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
> Test unit from stdin
> [stdin:1] A system variable named `(ENOENT)' already exists
> Test unit `(stdin)' : NOK (syntax error)
#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 <com.h>
int
command_run(command_t command)
{
-
if(!silent_flag)
INFO2("[%s] %s",command->context->pos, command->context->command_line);
{
command_interrupt(command);
}
+
+
}
return 0;
}
#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 */
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)
)
{
- ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
- command_handle_failure(command,csr_create_process_function_failure);
+ if(ERROR_FILE_NOT_FOUND == GetLastError())
+ {
+ 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
+ {
+ 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);
+ unit_set_error(command->unit, (int)GetLastError(), 0);
+ command_handle_failure(command, csr_create_process_function_failure);
+ }
+
}
else
{
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 :
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 */
void
command_handle_failure(command_t command, cs_reason_t reason)
{
-
unit_t root = command->root;
xbt_os_mutex_acquire(command->mutex);
#endif\r
\r
if(!(fstream->stream = fopen(path, "r")))\r
+ {\r
return -1;\r
+ }\r
\r
return 0;\r
}\r
int\r
translatepath(const char* totranslate, char** translated)\r
{\r
-\r
- return 0;\r
+ char buffer1[PATH_MAX + 1] = {0}; \r
+ char buffer2[PATH_MAX + 1] = {0};\r
+ char *p1;\r
+ int i, j, len;\r
+ \r
+ struct stat stat_buf = {0};\r
+ \r
+ /* return the current directory */\r
+ if(!strcmp(totranslate,".") || !strcmp(totranslate,"./"))\r
+ {\r
+ *translated = getcwd(NULL,0);\r
+ return (int)strlen(*translated);\r
+ }\r
+ /* return the previous directory */\r
+ else if(!strcmp(totranslate,"..") || !strcmp(totranslate,"../"))\r
+ {\r
+ getcwd(buffer1, PATH_MAX + 1);\r
+ p1 = strrchr(buffer1, '\\');\r
+ *translated = (char*) calloc((p1 - buffer1) + 1, sizeof(char));\r
+ strncpy(*translated, buffer1, (p1 - buffer1));\r
+ \r
+ return (int)strlen(*translated);\r
+ }\r
+ /* return the root directory */\r
+ else if(!strcmp(totranslate, "/"))\r
+ {\r
+ *translated = getcwd(NULL,0);\r
+ (*translated)[2] = '\0';\r
+ return (int)strlen(*translated);\r
+ }\r
+ /* it's a relative directory name build the full directory name */\r
+ else if(!strchr(totranslate, '/') && !strchr(totranslate, '\\') && !stat(totranslate, &stat_buf) || S_ISDIR(stat_buf.st_mode))\r
+ {\r
+ getcwd(buffer1, PATH_MAX + 1);\r
+ strcat(buffer1,"\\");\r
+ strcat(buffer1,totranslate);\r
+ \r
+ *translated = (char*) calloc(strlen(buffer1) + 1, sizeof(char));\r
+ strcpy(*translated, buffer1);\r
+ return (int)strlen(*translated);\r
+ }\r
+ \r
+ len = (int)strlen(totranslate); \r
+ \r
+ strncpy(buffer1, totranslate, len); \r
+ \r
+ if(buffer1[strlen(buffer1) - 1] == '/' || buffer1[strlen(buffer1) - 1] == '\\')\r
+ buffer1[strlen(buffer1) - 1] = '\0';\r
+ \r
+ while((p1 = strstr(buffer1, "//"))) \r
+ if(p1[2]) \r
+ strcpy(p1, p1 + 1); \r
+ else \r
+ p1[1] = '\0';\r
+ \r
+ for(i = 0, j = 0; buffer1[i] !='\0'; i++)\r
+ {\r
+ if(buffer1[i] == '/')\r
+ {\r
+ j++;\r
+ \r
+ if(j > 1)\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if(j == 1 && buffer1[i - 1] == '/')\r
+ {\r
+ /* perhaps it's a relative directory : `dir/' */\r
+ strncpy(buffer2, buffer1, strlen(buffer1) - 1);\r
+ \r
+ if(!stat(buffer2, &stat_buf) || S_ISDIR(stat_buf.st_mode))\r
+ {\r
+ getcwd(buffer1, PATH_MAX + 1);\r
+ strcat(buffer1,"\\");\r
+ strcat(buffer1,buffer2);\r
+ \r
+ *translated = (char*) calloc(strlen(buffer1) + 1, sizeof(char));\r
+ strcpy(*translated, buffer1);\r
+ return (int)strlen(*translated);\r
+ }\r
+ else\r
+ memset(buffer2, 0, PATH_MAX + 1);\r
+ \r
+ }\r
+ \r
+ if(buffer1[0] == '~') \r
+ {\r
+ /* TODO */\r
+ *translated = NULL;\r
+ errno = ENOSYS;\r
+ return -1;\r
+ }\r
+ else if (*buffer1 == '.') \r
+ {\r
+ _fullpath(buffer2, buffer1, sizeof(buffer1)); \r
+ } \r
+ else \r
+ strcpy(buffer2, buffer1); \r
+ \r
+ if(stat(buffer2, &stat_buf) || !S_ISDIR(stat_buf.st_mode))\r
+ {\r
+ *translated = NULL;\r
+ errno = ENOTDIR;\r
+ return -1;\r
+ }\r
+ \r
+ len = (int)strlen(buffer2);\r
+ \r
+ *translated = (char*) calloc(len + 1, sizeof(char));\r
+ \r
+ if(!(*translated))\r
+ {\r
+ *translated = NULL;\r
+ return -1;\r
+ }\r
+ \r
+ strncpy(*translated, buffer2, len);\r
+ \r
+ return len;\r
}\r
-\r
#endif\r
\r
\r
#include <explode.h>
-#ifdef WIN32
-static int is_w32_binary(const char* cmd)
-{
- DWORD binary_type;
-
- GetBinaryType(cmd, &binary_type);
-
- if(SCS_32BIT_BINARY == binary_type || SCS_64BIT_BINARY == binary_type || SCS_64BIT_BINARY == binary_type)
- return 1;
-
- return 0;
-}
-#endif
-
int
is_cmd(char** path, char** builtin, const char* p)
{
struct stat stat_buff = {0};
char command[PATH_MAX + 1] = {0};
char buff[PATH_MAX + 1] = {0};
-
- size_t len = strlen(p);
-
+ size_t len;
+
if(!p)
return EINVAL;
+ len = strlen(p);
while(i < len)
{
if(p[i] != ' ' && p[i] != '\t' && p[i] != '>')
i++;
}
+
/* check first if it's a shell buitin */
if(builtin)
{
for (i = 0; path[i] != NULL; i++)
{
+
sprintf(buff,"%s/%s",path[i], command);
if(!stat(buff, &stat_buff) && S_ISREG(stat_buff.st_mode))
{
- #ifdef WIN32
- if(is_w32_binary(buff))
- yes = 1;
- break;
- #else
+
if(!access(buff, X_OK))
{
yes = 1;
break;
}
- #endif
}
}
}
}
else
{
- #ifdef WIN32
- if(is_w32_binary(command))
- yes = 1;
- #else
+
if(!access(command, X_OK))
yes = 1;
- #endif
}
return yes ? 0 : ECMDNOTFOUND;
{ 'f', string, (byte*)&fstreams, 0, "file" },
{ 'h', flag, (byte*)&print_usage_flag, 0, "help" },
{ 'a', flag, (byte*)&print_readme_flag, 0, "README" },
- { 'i', flag, (byte*)&keep_going_unit_flag, 0, "keep-going-unit" },
+ { 'k', flag, (byte*)&keep_going_flag, 0, "keep-going" },
+ { 'i', flag, (byte*)&keep_going_unit_flag, 0, "keep-going-unit"},
{ 'I', string, (byte*)&include_dirs, 0, "include-dir" },
{ 'j', number, (byte*)&jobs_nb, (byte*) &optional_jobs_nb, "jobs" },
- { 'k', flag, (byte*)&keep_going_flag, 0, "keep-going" },
{ 'm', flag, (byte*)&detail_summary_flag, 0, "detail-summary" },
{ 'c', flag, (byte*)&just_print_flag, 0, "just-print" },
{ 's', flag, (byte*)&silent_flag, 0, "silent" },
static int
init(void);
+static int
+screen_cleaned;
-static void
-sig_abort_handler(int signum)
-{
- /* TODO : implement this function */
- INFO0("sig_abort_handler() called");
-}
+static int
+finalized = 0;
+
+static int
+sig_int = 0;
+#ifdef WIN32
static void
sig_int_handler(int signum)
{
- /* TODO : implement this function */
- INFO0("sig_int_handler() called");
+
+ if(!finalized)
+ {
+ sig_int = 1;
+ runner_interrupt();
+ while(!finalized);
+ }
+
}
+#endif
static void
free_string(void* str)
* to the calling process : tesh)
*/
prev_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+
+ /* handle the interrupt signal */
+ signal(SIGINT, sig_int_handler);
#else
- struct sigaction act;
/* Ignore pipe issues.
* They will show up when we try to send data to dead buddies,
* but we will stop doing so when we're done with provided input
*/
- memset(&act,0, sizeof(struct sigaction));
+ /*
+ struct sigaction act;
+ memset(&act,0, sizeof(struct sigaction));
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
-
- memset(&act,0, sizeof(struct sigaction));
- act.sa_handler = sig_abort_handler;
- sigaction(SIGABRT, &act, NULL);
-
memset(&act,0, sizeof(struct sigaction));
act.sa_handler = sig_int_handler;
- sigaction(SIGINT, &act, NULL);
+ sigaction(SIGINT, &act, NULL);*/
#endif
- /* handle the abort signal */
- /*signal(SIGABRT, sig_abort_handler);*/
- /* handle the interrupt signal */
- /*signal(SIGINT, sig_int_handler);*/
/* used to store the files to run */
if(!(fstreams = fstreams_new((void_f_pvoid_t)fstream_free)))
static void
finalize(void)
{
-
/* delete the fstreams object */
if(fstreams)
fstreams_free((void**)&fstreams);
#ifdef WIN32
SetErrorMode(prev_error_mode);
#endif
-
- if(!summary_flag && !dry_run_flag && !silent_flag && !just_print_flag && !print_version_flag && !print_usage_flag && is_tesh_root)
+
+ if(sig_int)
+ INFO0("Tesh interrupted (receive a SIGINT)");
+ else if(!summary_flag && !dry_run_flag && !silent_flag && !just_print_flag && !print_version_flag && !print_usage_flag && is_tesh_root)
{
if(!exit_code)
INFO2("Tesh terminated with exit code %d : %s",exit_code, "success");
/* exit from the xbt framework */
xbt_exit();
+
+ finalized = 1;
/* exit with the last error code */
- exit(exit_code);
+ if(!sig_int)
+ exit(exit_code);
}
/* init_options -- initialize the options string */
/* --load-directory option */
if(!strcmp(entry->long_name,"load-directory"))
{
- #ifdef WIN32
- struct stat info = {0};
- if(stat(optarg, &info) || !S_ISDIR(info.st_mode))
- {
- ERROR1("%s is not a directory",optarg);
- exit_code = ENOTDIR;
- err_kind = 0;
- return -1;
- }
-
- #else
char* path;
if(translatepath(optarg, &path) < 0)
return -1;
}
- #endif
else
{
- #ifdef WIN32
- directory = directory_new(optarg);
- #else
+
directory = directory_new(path);
free(path);
- #endif
if(directories_contains(directories, directory))
{
}
else if(!strcmp(entry->long_name,"directory"))
{
- #ifdef WIN32
- struct stat info = {0};
- if(stat(optarg, &info) || !S_ISDIR(info.st_mode))
- {
- ERROR1("%s is not a directory",optarg);
- exit_code = ENOTDIR;
- err_kind = 0;
- return -1;
- }
-
- #else
char* path ;
if(translatepath(optarg, &path) < 0)
return -1;
}
- #endif
else
{
char* buffer = getcwd(NULL, 0);
- #ifdef WIN32
-
- if(!strcmp(buffer, optarg))
- WARN1("Already in the directory %s", optarg);
- else if(!print_directory_flag)
- INFO1("Entering directory \"%s\"",optarg);
-
- chdir(optarg);
- #else
if(!strcmp(buffer, path))
WARN1("Already in the directory %s", optarg);
chdir(path);
free(path);
- #endif
-
+
free(buffer);
-
-
}
}
/* --include-dir option */
else if(!strcmp(entry->long_name,"include-dir"))
{
- #ifdef WIN32
- struct stat info = {0};
- if(stat(optarg, &info) || !S_ISDIR(info.st_mode))
- {
- ERROR1("%s is not a directory",optarg);
- exit_code = ENOTDIR;
- err_kind = 0;
- return -1;
- }
-
- #else
+
char* path ;
if(translatepath(optarg, &path) < 0)
return -1;
}
- #endif
+
else
{
int exists = 0;
unsigned int i;
directory_t cur;
- #ifdef WIN32
- directory = directory_new(optarg);
- #else
directory = directory_new(path);
free(path);
- #endif
xbt_dynar_foreach(include_dirs, i , cur)
{
FILE* stream;
stream = exit_code ? stderr : stdout;
+
+ if(!screen_cleaned)
+ {
+ #ifdef WIN32
+ system("cls");
+ #else
+ system("clear");
+ #endif
+ screen_cleaned = 1;
+ }
fprintf (stream, "Usage: tesh [options] [file] ...\n");
static void
print_version(void)
{
+ if(!screen_cleaned)
+ {
+ #ifdef WIN32
+ system("cls");
+ #else
+ system("clear");
+ #endif
+ screen_cleaned = 1;
+ }
+
/* TODO : display the version of tesh */
printf("Version :\n");
printf(" tesh version %s : Mini shell specialized in running test units by Martin Quinson \n", version);
char* clean = (char*)calloc(number_of_bytes_to_read + 1,sizeof(char));\r
size_t i, j;\r
\r
+ xbt_os_sem_release(reader->started);\r
+\r
while(!command->failed && !command->interrupted && !command->successeded && !reader->failed && !reader->broken_pipe)\r
{\r
if(!ReadFile(stdout_fd, buffer, number_of_bytes_to_read, &number_of_bytes_readed, NULL) || (0 == number_of_bytes_readed))\r
#include <explode.h>
#endif
+
+
+
#define _RUNNER_HASHCODE 0xFEFEAAAA
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
-#if (!defined(__BUILTIN) && defined(__CHKCMD))
+#if (!defined(__BUILTIN) && defined(__CHKCMD) && !defined(WIN32))
static const char* builtin[] =
{
"alias",
/* wait for the timer */
WaitForSingleObject(timer_handle, INFINITE);
-
+
if(runner->waiting)
{
exit_code = ELEADTIME;
int i;
char* val;
char buffer[PATH_MAX + 1] = {0};
+
int code;
const char* cstr;
variable_t variable;
- #if (defined(__CHKCMD) && defined(__BUILTIN))
+ #if (defined(__CHKCMD) && defined(__BUILTIN) && !defined(WIN32))
FILE* s;
int n = 0;
size_t len;
/* add the environment variables in the vector */
for(i = 0; environ[i] != NULL; i++)
{
-
val = strchr(environ[i], '=');
if(val)
{
-
-
val++;
if(val[0] != '\0')
if(!strcmp("PATH", buffer))
{
char* p;
- int j,k, len;
+ size_t j,k, len;
/* get the list of paths */
+
runner->path = explode(':', val);
/* remove spaces and backslahes at the end of the path */
len = strlen(p);
for(j = len - 1; p[j] == '/' || p[j] == ' '; j--)
+
p[j] = '\0';
}
}
variable = variable_new("TESH_PPID", buffer);
variable->err = 1;
+ xbt_dynar_push(runner->variables, &variable);
+
+ variable = variable_new("TESH_DIR", tesh_dir);
+ variable->err = 1;
+
xbt_dynar_push(runner->variables, &variable);
free(tesh_dir);
xbt_dynar_push(runner->variables, &variable);
-
i = 0;
/* add the errors variables */
check_syntax();
*/
-
- #if defined(__CHKCMD)
+ #if (!defined(WIN32) && defined(__CHKCMD))
#if defined(__BUILTIN)
+
if(!is_tesh_root)
{
/* compute the full path the builtin.def file */
- #ifndef WIN32
sprintf(buffer,"%s/builtin.def",getenv("TESH_DIR"));
- #else
- GetEnvironmentVariable("TESH_DIR",buffer,PATH_MAX + 1);
- #endif
- s = fopen(buffer, "r");
+ if(!(s = fopen(buffer, "r")))
+ {
+ ERROR1("File `(%s)' not found", buffer);
+ return -1;
+ }
}
else
{
- s = fopen("builtin.def", "r");
+ if(!(s = fopen("builtin.def", "r")))
+ {
+ ERROR0("File `(builtin.def)' not found");
+ return -1;
+ }
}
if(s)
if(!is_blank)
n++;
-
-
}
fsetpos(s, &begin);
free(line);
}
- else
- {
- ERROR0("File `(builtin.def)' not found");
- return -1;
- }
- #else
+ #else
runner->builtin = xbt_new0(char*, __BUILTIN_MAX + 1); /* (char**) calloc(__BUILTIN_MAX + 1, sizeof(char*));*/
for(i = 0; i < __BUILTIN_MAX; i++)
xbt_os_mutex_release(root->mutex);\r
\r
/* must acquire the jobs semaphore to start */\r
- xbt_os_sem_acquire(jobs_sem);\r
+ /*xbt_os_sem_acquire(jobs_sem);*/\r
\r
/* initialize the mutex used to synchronize the access to the properties of this unit */\r
mutex = xbt_os_mutex_init();\r
errno = EINVAL;\r
return -1;\r
}\r
- \r
+\r
if(!interrupted)\r
{\r
unit->mutex = mutex;\r
\r
xbt_dynar_foreach(units->items, i, unit)\r
{\r
+ xbt_os_sem_acquire(jobs_sem);\r
unit_run(unit, mutex);\r
}\r
\r
DWORD number_of_bytes_to_write = command->context->input->used;\r
DWORD number_of_bytes_written = 0;\r
\r
+ xbt_os_sem_release(writer->written);\r
+\r
while(!command->failed && !command->interrupted && !command->successeded && ! writer->failed && ! writer->broken_pipe && number_of_bytes_to_write)\r
{\r
if(!WriteFile(writer->command->stdin_fd, input, number_of_bytes_to_write, &number_of_bytes_written, NULL))\r
command_kill(command);\r
command_handle_failure(command, csr_write_pipe_broken);\r
}*/\r
- \r
+\r
CloseHandle(command->stdin_fd);\r
command->stdin_fd = INDEFINITE_FD;\r
\r
<Tool\r
Name="VCCLCompilerTool"\r
Optimization="0"\r
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;__CHKCMD;__BUILTIN"\r
MinimalRebuild="true"\r
BasicRuntimeChecks="3"\r
RuntimeLibrary="2"\r
<Tool\r
Name="VCLinkerTool"\r
AdditionalDependencies="simgrid.lib"\r
+ OutputFile="../$(ProjectName).exe"\r
LinkIncremental="2"\r
GenerateDebugInformation="true"\r
SubSystem="1"\r
RelativePath="..\src\getpath.c"\r
>\r
</File>\r
- <File\r
- RelativePath="..\src\is_cmd.c"\r
- >\r
- </File>\r
<File\r
RelativePath="..\src\main.c"\r
>\r
RelativePath="..\include\getpath.h"\r
>\r
</File>\r
- <File\r
- RelativePath="..\include\is_cmd.h"\r
- >\r
- </File>\r
<File\r
RelativePath="..\include\reader.h"\r
>\r
/>\r
<Tool\r
Name="VCLinkerTool"\r
- OutputFile="..\..\tesh\Debug\cat.exe"\r
+ OutputFile="..\..\$(ProjectName).exe"\r
LinkIncremental="2"\r
GenerateDebugInformation="true"\r
SubSystem="1"\r
static const char *\r
__getopt_initialize (const char *optstring)\r
{\r
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0\r
+ is the program name); the sequence of previously skipped\r
+ non-option ARGV-elements is empty. */\r
+ \r
first_nonopt = last_nonopt = optind = 1;\r
nextchar = NULL;\r
\r
+ /* Determine how to handle the ordering of options and nonoptions. */\r
+ \r
if (optstring[0] == '-')\r
{\r
ordering = RETURN_IN_ORDER;\r
++optstring;\r
}\r
- \r
- /* if the optstring begining with the character +, the getopt() function\r
- * stop when an argument of the command line is not an option.\r
+ /* si la chaîne d'options commence par un + alors la fonction getopt() s'arrête\r
+ * dès qu'un argument de la ligne de commande n'est pas une option\r
*/\r
else if (optstring[0] == '+')\r
{\r
\r
if (nextchar == NULL || *nextchar == '\0')\r
{\r
+ /* Advance to the next ARGV-element. */\r
+ \r
if (ordering == PERMUTE)\r
{\r
+ /* If we have just processed some options following some non-options,\r
+ __exchange them so that the options come first. */\r
+ \r
if (first_nonopt != last_nonopt && last_nonopt != optind)\r
__exchange ((char **) argv);\r
else if (last_nonopt != optind)\r
first_nonopt = optind;\r
\r
- \r
+ /* Skip any additional non-options\r
+ and extend the range of non-options previously skipped. */\r
\r
while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0'))\r
optind++;\r
\r
last_nonopt = optind;\r
}\r
-\r
+ \r
+ /* The special ARGV-element `--' means premature end of options.\r
+ Skip it like a null option,\r
+ then __exchange with previous non-options as if it were an option,\r
+ then skip everything else like a non-option. */\r
\r
if (optind != argc && !strcmp (argv[optind], "--"))\r
{\r
optind = argc;\r
}\r
\r
+ /* If we have done all the ARGV-elements, stop the scan\r
+ and back over any non-options that we skipped and permuted. */\r
+ \r
if (optind == argc)\r
{\r
+ /* Set the next-arg-index to point at the non-options\r
+ that we previously skipped, so the caller will digest them. */\r
if (first_nonopt != last_nonopt)\r
optind = first_nonopt;\r
\r
return EOF;\r
}\r
\r
+ /* If we have come to a non-option and did not permute it,\r
+ either stop the scan or describe it to the caller and pass it by. */\r
+ \r
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))\r
{\r
if (ordering == REQUIRE_ORDER)\r
return 1;\r
}\r
\r
+ /* We have found another option-ARGV-element.\r
+ Skip the initial punctuation. */\r
+ \r
nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-'));\r
}\r
\r
+ /* Decode the current option-ARGV-element. */\r
+ \r
+ /* Check whether the ARGV-element is a long option.\r
+ \r
+ If long_only and the ARGV-element has the form "-f", where f is\r
+ a valid short option, don't consider it an abbreviated form of\r
+ a long option that starts with f. Otherwise there would be no\r
+ way to give the -f short option.\r
+ \r
+ On the other hand, if there's a long option "fubar" and\r
+ the ARGV-element is "-fu", do consider that an abbreviation of\r
+ the long option, just like "--fu", and not "-f" with arg "u".\r
+ \r
+ This distinction seems to be the most useful approach. */\r
+ \r
if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !strchr (optstring, argv[optind][1])))))\r
{\r
char *nameend;\r
int option_index;\r
\r
for (nameend = nextchar; *nameend !='\0' && *nameend != '='; nameend++)\r
- \r
+ /* Do nothing. */ ;\r
+ \r
+ /* Test all long options for either exact match\r
+ or abbreviated matches. */\r
for (p = longopts, option_index = 0; p->name; p++, option_index++)\r
{\r
if(!strncmp (p->name, nextchar, nameend - nextchar))\r
{\r
\r
- if ((nameend - nextchar) == strlen (p->name))\r
+ if (nameend - nextchar == strlen (p->name))\r
{\r
+ /* Exact match found. */\r
pfound = p;\r
indfound = option_index;\r
exact = 1;\r
}\r
else if (pfound == NULL)\r
{\r
+ /* First nonexact match found. */\r
exact = 0;\r
+ /* begin change\r
+ pfound = p;\r
+ indfound = option_index;\r
+ end change */\r
break;\r
}\r
else\r
+ {\r
+\r
+ /* Second or later nonexact match found. */\r
ambig = 1;\r
- \r
+ }\r
}\r
}\r
\r
if (ambig && !exact)\r
{\r
if (opterr)\r
- fprintf (stderr, "ERROR : %s: option `%s' is ambiguous\n",argv[0], argv[optind]);\r
+ fprintf (stderr, "error : %s: option `%s' is ambiguous\n",argv[0], argv[optind]);\r
\r
nextchar += strlen (nextchar);\r
optind++;\r
\r
if (*nameend)\r
{\r
+ /* Don't test has_arg with >, because some C compilers don't\r
+ allow it to be used on enums. */\r
if (pfound->has_arg)\r
optarg = nameend + 1;\r
else\r
return pfound->val;\r
}\r
\r
+ /* Can't find it as a long option. If this is not getopt_long_only,\r
+ or the option starts with '--' or is not a valid short\r
+ option, then it's an error.\r
+ Otherwise interpret it as a short option. */\r
if (!long_only || argv[optind][1] == '-'|| strchr (optstring, *nextchar) == NULL)\r
{\r
if (opterr)\r
}\r
}\r
\r
+ /* Look at and handle the next short option-character. */\r
+ \r
{\r
char c = *nextchar++;\r
char *temp = strchr (optstring, c);\r
{\r
if (temp[2] == ':')\r
{\r
- /* it's an option that accepts an argument optionally. */\r
+ /* This is an option that accepts an argument optionally. */\r
if (*nextchar != '\0')\r
{\r
optarg = nextchar;\r
}\r
else\r
{\r
- /* it's an option that requires an argument. */\r
+ /* This is an option that requires an argument. */\r
if (*nextchar != '\0')\r
{\r
optarg = nextchar;\r
+ /* If we end this ARGV-element by taking the rest as an arg,\r
+ we must advance to the next element now. */\r
optind++;\r
}\r
else if (optind == argc)\r
if (opterr)\r
{\r
/* 1003.2 specifies the format of this message. */\r
- fprintf (stderr, "ERROR : %s: option requires an argument -- %c\n",argv[0], c);\r
+ fprintf (stderr, "error : %s: option requires an argument -- %c\n",argv[0], c);\r
}\r
optopt = c;\r
\r
c = '?';\r
}\r
else\r
+ /* We already incremented `optind' once;\r
+ increment it again when taking next ARGV-elt as argument. */\r
optarg = argv[optind++];\r
\r
nextchar = NULL;\r
int top = optind;\r
char *tem;\r
\r
+ /* Exchange the shorter segment with the far end of the longer segment.\r
+ That puts the shorter segment into the right place.\r
+ It leaves the longer segment in the right place overall,\r
+ but it consists of two parts that need to be swapped next. */\r
+ \r
while (top > middle && middle > bottom)\r
{\r
if (top - middle > middle - bottom)\r
{\r
+ /* Bottom segment is the short one. */\r
int len = middle - bottom;\r
register int i;\r
\r
+ /* Swap it with the top part of the top segment. */\r
for (i = 0; i < len; i++)\r
{\r
tem = argv[bottom + i];\r
argv[bottom + i] = argv[top - (middle - bottom) + i];\r
argv[top - (middle - bottom) + i] = tem;\r
}\r
+ /* Exclude the moved bottom segment from further swapping. */\r
\r
top -= len;\r
}\r
else\r
{\r
+ /* Top segment is the short one. */\r
int len = top - middle;\r
register int i;\r
\r
+ /* Swap it with the bottom part of the bottom segment. */\r
for (i = 0; i < len; i++)\r
{\r
tem = argv[bottom + i];\r
argv[bottom + i] = argv[middle + i];\r
argv[middle + i] = tem;\r
}\r
-\r
+ /* Exclude the moved top segment from further swapping. */\r
bottom += len;\r
}\r
}\r
\r
+ /* Update records for the slots the non-options now occupy. */\r
\r
first_nonopt += (optind - last_nonopt);\r
last_nonopt = optind;\r