From 54842afbb7202b341fd232f62644fb1f47a15118 Mon Sep 17 00:00:00 2001 From: cherierm Date: Fri, 6 Jun 2008 15:55:38 +0000 Subject: [PATCH] last change of Tesh2 git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@5561 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- tools/tesh2/examples/IO-orders.tesh | 8 +- tools/tesh2/examples/background.tesh | 4 + .../tesh2/examples/catch-global-timeout.tesh | 8 +- tools/tesh2/examples/catch-return.tesh | 2 +- tools/tesh2/examples/catch-signal.tesh | 2 +- tools/tesh2/examples/catch-timeout.tesh | 2 +- tools/tesh2/examples/catch-wrong-output.tesh | 2 +- tools/tesh2/examples/cd.tesh | 4 +- tools/tesh2/examples/jobs.tesh | 2 +- tools/tesh2/examples/keep-going-unit.tesh | 4 +- tools/tesh2/examples/keep-going.tesh | 6 +- tools/tesh2/examples/set-ignore-output.tesh | 2 +- tools/tesh2/examples/suite-usage.tesh | 5 - tools/tesh2/examples/var.tesh | 4 +- tools/tesh2/src/command.c | 102 +++++++++++-- tools/tesh2/src/fstream.c | 2 + tools/tesh2/src/getpath.c | 123 ++++++++++++++- tools/tesh2/src/is_cmd.c | 35 +---- tools/tesh2/src/main.c | 141 +++++++----------- tools/tesh2/src/reader.c | 2 + tools/tesh2/src/runner.c | 52 ++++--- tools/tesh2/src/unit.c | 4 +- tools/tesh2/src/units.c | 1 + tools/tesh2/src/writer.c | 4 +- tools/tesh2/tesh/tesh.vcproj | 11 +- tools/tesh2/w32/Cat/Cat.vcproj | 2 +- tools/tesh2/w32/src/getopt.c | 102 +++++++++++-- 27 files changed, 432 insertions(+), 204 deletions(-) diff --git a/tools/tesh2/examples/IO-orders.tesh b/tools/tesh2/examples/IO-orders.tesh index ab0c9f3d77..3cc8033bfd 100644 --- a/tools/tesh2/examples/IO-orders.tesh +++ b/tools/tesh2/examples/IO-orders.tesh @@ -8,7 +8,7 @@ p Order: in, out, cmd > 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 @@ -17,7 +17,7 @@ p Order: out, in, cmd > 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 @@ -26,7 +26,7 @@ p Order: out, cmd, in > 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 @@ -35,5 +35,5 @@ p Order: in, cmd, out > 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" diff --git a/tools/tesh2/examples/background.tesh b/tools/tesh2/examples/background.tesh index a416496aef..6838a013b3 100644 --- a/tools/tesh2/examples/background.tesh +++ b/tools/tesh2/examples/background.tesh @@ -9,6 +9,10 @@ $ cd temp_testdir < #include < #include < #include +< +< #ifdef __MINGW32__ +< #define sleep _sleep +< #endif < < int main() { < char buff[2048]; diff --git a/tools/tesh2/examples/catch-global-timeout.tesh b/tools/tesh2/examples/catch-global-timeout.tesh index 15285c4ec5..c361e93501 100644 --- a/tools/tesh2/examples/catch-global-timeout.tesh +++ b/tools/tesh2/examples/catch-global-timeout.tesh @@ -3,9 +3,9 @@ ! expect return $ELEADTIME -< $ sleep 30 -$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' --timeout=3 +< $ sleep 10 +$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" --timeout=1 > Test unit from stdin -> [stdin:1] sleep 30 +> [stdin:1] sleep 10 > Test unit from stdin INTR -> Tesh timed out after `(3)' seconds +> Tesh timed out after `(1)' seconds diff --git a/tools/tesh2/examples/catch-return.tesh b/tools/tesh2/examples/catch-return.tesh index 41d84336d8..00a37509e0 100644 --- a/tools/tesh2/examples/catch-return.tesh +++ b/tools/tesh2/examples/catch-return.tesh @@ -1 +1 @@ -#! ./tesh # This suite builds and uses a program returning 1. # tesh must detect this condition and report the issue. $ rm -rf temp_testdir $ mkdir temp_testdir $ cd temp_testdir < #include < int main(void) { < exit(1); < } $ cat > return1.c $ gcc -o return1 return1.c ! expect return $EEXITCODENOTMATCH < $ ./return1 $ ../tesh --log='log.thresh:info tesh.fmt:%m%n' > Test unit from stdin > [stdin:1] ./return1 > [stdin:1] ./return1 : NOK (returned code `1' instead `0') > Output of so far: > || > Test unit `(stdin)' : NOK (exit code mismatch) $ cd .. $ rm -rf temp_testdir \ No newline at end of file +#! ./tesh # This suite builds and uses a program returning 1. # tesh must detect this condition and report the issue. $ rm -rf temp_testdir $ mkdir temp_testdir $ cd temp_testdir < #include < int main(void) { < exit(1); < } $ cat > return1.c $ gcc -o return1 return1.c ! expect return $EEXITCODENOTMATCH < $ ./return1 $ ../tesh --log="log.thresh:info tesh.fmt:%m%n" > Test unit from stdin > [stdin:1] ./return1 > [stdin:1] ./return1 : NOK (returned code `1' instead `0') > Output of so far: > || > Test unit `(stdin)' : NOK (exit code mismatch) $ cd .. $ rm -rf temp_testdir \ No newline at end of file diff --git a/tools/tesh2/examples/catch-signal.tesh b/tools/tesh2/examples/catch-signal.tesh index 5a11512cbf..b633b8acd8 100644 --- a/tools/tesh2/examples/catch-signal.tesh +++ b/tools/tesh2/examples/catch-signal.tesh @@ -17,7 +17,7 @@ $ gcc -o segfault segfault.c ! 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) diff --git a/tools/tesh2/examples/catch-timeout.tesh b/tools/tesh2/examples/catch-timeout.tesh index 8a16fb5459..d2a669ec13 100644 --- a/tools/tesh2/examples/catch-timeout.tesh +++ b/tools/tesh2/examples/catch-timeout.tesh @@ -12,4 +12,4 @@ > [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" diff --git a/tools/tesh2/examples/catch-wrong-output.tesh b/tools/tesh2/examples/catch-wrong-output.tesh index 8774a773d0..3883f2647f 100644 --- a/tools/tesh2/examples/catch-wrong-output.tesh +++ b/tools/tesh2/examples/catch-wrong-output.tesh @@ -6,7 +6,7 @@ p This tests whether TESH detects wrong outputs < > 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): diff --git a/tools/tesh2/examples/cd.tesh b/tools/tesh2/examples/cd.tesh index c1e52c92cc..6b804a17f3 100644 --- a/tools/tesh2/examples/cd.tesh +++ b/tools/tesh2/examples/cd.tesh @@ -16,11 +16,11 @@ $ ls > [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 diff --git a/tools/tesh2/examples/jobs.tesh b/tools/tesh2/examples/jobs.tesh index 4e9a0dab31..4198bb3499 100644 --- a/tools/tesh2/examples/jobs.tesh +++ b/tools/tesh2/examples/jobs.tesh @@ -20,7 +20,7 @@ $ gcc -o job job.c # Ignore output of the command because we can't known the order of the execution of the Tesh files. ! output ignore -$ ./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 +$ ./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 $ rm -f job diff --git a/tools/tesh2/examples/keep-going-unit.tesh b/tools/tesh2/examples/keep-going-unit.tesh index 22ce9dc2a8..61f179dd64 100644 --- a/tools/tesh2/examples/keep-going-unit.tesh +++ b/tools/tesh2/examples/keep-going-unit.tesh @@ -39,7 +39,7 @@ $ gcc -o job job.c < ! expect return 0 < > Hello Tesh < $ ./job -$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' +$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" > Test unit from stdin > [stdin:3] ./job > [stdin:3] ./job : NOK (returned code `0' instead `1') @@ -71,7 +71,7 @@ $ ./tesh --log='log.thresh:info tesh.fmt:%m%n' < ! expect return 0 < > Hello Tesh < $ ./job -$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' --keep-going-unit +$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" --keep-going-unit > Test unit from stdin > [stdin:3] ./job > [stdin:3] ./job : NOK (returned code `0' instead `1') diff --git a/tools/tesh2/examples/keep-going.tesh b/tools/tesh2/examples/keep-going.tesh index a1a203267a..345ec50b76 100644 --- a/tools/tesh2/examples/keep-going.tesh +++ b/tools/tesh2/examples/keep-going.tesh @@ -63,7 +63,7 @@ $ cat > file2.tesh ! expect return $EEXITCODENOTMATCH # in this case the option `keep-going' is not specified so Tesh detects the error and interrupt all the folowing units. -$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' file1.tesh file2.tesh +$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" file1.tesh file2.tesh > Test unit from file1.tesh > [file1.tesh:3] ./job > [file1.tesh:3] ./job : NOK (returned code `0' instead `1') @@ -71,8 +71,6 @@ $ ./tesh --log='log.thresh:info tesh.fmt:%m%n' file1.tesh file2.tesh > ||Hello Tesh > || > Test unit `(file1.tesh)' : NOK (exit code mismatch) -> Test unit from file2.tesh -> Test unit from file2.tesh INTR < ! expect return 1 < > Hello Tesh @@ -119,7 +117,7 @@ $ cat > file2.tesh ! expect return $EEXITCODENOTMATCH # in this case the option `keep-going' is specified so, Tesh execute all the other units. -$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' file1.tesh file2.tesh --keep-going +$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" file1.tesh file2.tesh --keep-going > Test unit from file1.tesh > [file1.tesh:3] ./job > [file1.tesh:3] ./job : NOK (returned code `0' instead `1') diff --git a/tools/tesh2/examples/set-ignore-output.tesh b/tools/tesh2/examples/set-ignore-output.tesh index 285bd3a334..818cf3859c 100644 --- a/tools/tesh2/examples/set-ignore-output.tesh +++ b/tools/tesh2/examples/set-ignore-output.tesh @@ -6,7 +6,7 @@ p This tests whether TESH accepts to ignore command output < > 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 as requested) diff --git a/tools/tesh2/examples/suite-usage.tesh b/tools/tesh2/examples/suite-usage.tesh index 140234b501..bc0465bd14 100644 --- a/tools/tesh2/examples/suite-usage.tesh +++ b/tools/tesh2/examples/suite-usage.tesh @@ -9,11 +9,6 @@ ! include catch-signal.tesh ! include set-timeout.tesh - -# a command -$ echo Hello Tesh -> Hello Tesh - # some includes ! include catch-wrong-output.tesh diff --git a/tools/tesh2/examples/var.tesh b/tools/tesh2/examples/var.tesh index 631d60887f..bcf40a3224 100644 --- a/tools/tesh2/examples/var.tesh +++ b/tools/tesh2/examples/var.tesh @@ -23,7 +23,7 @@ D Usage of tesh variables ! 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) @@ -100,7 +100,7 @@ p On this platform ENOENT is: $ENOENT ! 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) diff --git a/tools/tesh2/src/command.c b/tools/tesh2/src/command.c index bb78758d47..ab86d56a28 100644 --- a/tools/tesh2/src/command.c +++ b/tools/tesh2/src/command.c @@ -23,6 +23,52 @@ #include #include #include +#else +char * +tow32cmd(const char* cmd) +{ + static char w32cmd[PATH_MAX + 1] = {0}; + char cmd_buf[PATH_MAX + 1] = {0}; + size_t i,j, len; + + if(!cmd) + { + errno = EINVAL; + return NULL; + } + + /* TODO : if ~*/ + if(cmd[0] != '.') + { + strcpy(w32cmd, cmd); + return w32cmd; + } + + i = j = 0; + len = strlen(cmd); + + while(i < len) + { + if(cmd[i] != ' ' && cmd[i] != '\t' && cmd[i] != '>') + cmd_buf[j++] = cmd[i]; + else + break; + + i++; + } + + _fullpath(w32cmd, cmd_buf, sizeof(w32cmd)); + + if(!strstr(w32cmd, ".exe")) + strcat(w32cmd, ".exe "); + + strcat(w32cmd, cmd + i); + + + /*printf("w32cmd : %s", w32cmd);*/ + + return w32cmd; +} #endif #include @@ -116,7 +162,6 @@ command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex) int command_run(command_t command) { - if(!silent_flag) INFO2("[%s] %s",command->context->pos, command->context->command_line); @@ -140,6 +185,8 @@ command_run(command_t command) { command_interrupt(command); } + + } return 0; @@ -205,6 +252,10 @@ command_start(void* p) } #ifdef WIN32 + +#ifndef BUFSIZE +#define BUFSIZE 4096 +#endif void command_exec(command_t command, const char* command_line) { @@ -216,6 +267,7 @@ 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 */ @@ -300,10 +352,10 @@ command_exec(command_t command, const char* command_line) return; } - CloseHandle(child_stdin_handle[0]); CloseHandle(child_stdout_handle[1]); + if(command->timer) { @@ -324,6 +376,18 @@ command_exec(command_t command, const char* command_line) 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; @@ -334,7 +398,7 @@ command_exec(command_t command, const char* command_line) /* launch the process */ if(!CreateProcess( NULL, - (char*)command_line, + tow32cmd(command_line), NULL, NULL, TRUE, @@ -345,11 +409,21 @@ command_exec(command_t command, const char* command_line) &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 { @@ -968,7 +1042,7 @@ command_summarize(command_t command) 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 : @@ -1007,15 +1081,22 @@ command_summarize(command_t command) 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 */ @@ -1035,7 +1116,6 @@ command_summarize(command_t command) void command_handle_failure(command_t command, cs_reason_t reason) { - unit_t root = command->root; xbt_os_mutex_acquire(command->mutex); diff --git a/tools/tesh2/src/fstream.c b/tools/tesh2/src/fstream.c index 403d184df0..166e256271 100644 --- a/tools/tesh2/src/fstream.c +++ b/tools/tesh2/src/fstream.c @@ -149,7 +149,9 @@ fstream_open(fstream_t fstream) #endif if(!(fstream->stream = fopen(path, "r"))) + { return -1; + } return 0; } diff --git a/tools/tesh2/src/getpath.c b/tools/tesh2/src/getpath.c index fc40068ac1..a46c4feb39 100644 --- a/tools/tesh2/src/getpath.c +++ b/tools/tesh2/src/getpath.c @@ -335,10 +335,127 @@ getpath(const char* file, char** path) int translatepath(const char* totranslate, char** translated) { - - return 0; + char buffer1[PATH_MAX + 1] = {0}; + char buffer2[PATH_MAX + 1] = {0}; + char *p1; + int i, j, len; + + struct stat stat_buf = {0}; + + /* return the current directory */ + if(!strcmp(totranslate,".") || !strcmp(totranslate,"./")) + { + *translated = getcwd(NULL,0); + return (int)strlen(*translated); + } + /* return the previous directory */ + else if(!strcmp(totranslate,"..") || !strcmp(totranslate,"../")) + { + getcwd(buffer1, PATH_MAX + 1); + p1 = strrchr(buffer1, '\\'); + *translated = (char*) calloc((p1 - buffer1) + 1, sizeof(char)); + strncpy(*translated, buffer1, (p1 - buffer1)); + + return (int)strlen(*translated); + } + /* return the root directory */ + else if(!strcmp(totranslate, "/")) + { + *translated = getcwd(NULL,0); + (*translated)[2] = '\0'; + return (int)strlen(*translated); + } + /* it's a relative directory name build the full directory name */ + else if(!strchr(totranslate, '/') && !strchr(totranslate, '\\') && !stat(totranslate, &stat_buf) || S_ISDIR(stat_buf.st_mode)) + { + getcwd(buffer1, PATH_MAX + 1); + strcat(buffer1,"\\"); + strcat(buffer1,totranslate); + + *translated = (char*) calloc(strlen(buffer1) + 1, sizeof(char)); + strcpy(*translated, buffer1); + return (int)strlen(*translated); + } + + len = (int)strlen(totranslate); + + strncpy(buffer1, totranslate, len); + + if(buffer1[strlen(buffer1) - 1] == '/' || buffer1[strlen(buffer1) - 1] == '\\') + buffer1[strlen(buffer1) - 1] = '\0'; + + while((p1 = strstr(buffer1, "//"))) + if(p1[2]) + strcpy(p1, p1 + 1); + else + p1[1] = '\0'; + + for(i = 0, j = 0; buffer1[i] !='\0'; i++) + { + if(buffer1[i] == '/') + { + j++; + + if(j > 1) + break; + } + } + + if(j == 1 && buffer1[i - 1] == '/') + { + /* perhaps it's a relative directory : `dir/' */ + strncpy(buffer2, buffer1, strlen(buffer1) - 1); + + if(!stat(buffer2, &stat_buf) || S_ISDIR(stat_buf.st_mode)) + { + getcwd(buffer1, PATH_MAX + 1); + strcat(buffer1,"\\"); + strcat(buffer1,buffer2); + + *translated = (char*) calloc(strlen(buffer1) + 1, sizeof(char)); + strcpy(*translated, buffer1); + return (int)strlen(*translated); + } + else + memset(buffer2, 0, PATH_MAX + 1); + + } + + if(buffer1[0] == '~') + { + /* TODO */ + *translated = NULL; + errno = ENOSYS; + return -1; + } + else if (*buffer1 == '.') + { + _fullpath(buffer2, buffer1, sizeof(buffer1)); + } + else + strcpy(buffer2, buffer1); + + if(stat(buffer2, &stat_buf) || !S_ISDIR(stat_buf.st_mode)) + { + *translated = NULL; + errno = ENOTDIR; + return -1; + } + + len = (int)strlen(buffer2); + + *translated = (char*) calloc(len + 1, sizeof(char)); + + if(!(*translated)) + { + *translated = NULL; + return -1; + } + + strncpy(*translated, buffer2, len); + + return len; } - #endif diff --git a/tools/tesh2/src/is_cmd.c b/tools/tesh2/src/is_cmd.c index fd46515fbb..528bc509c7 100644 --- a/tools/tesh2/src/is_cmd.c +++ b/tools/tesh2/src/is_cmd.c @@ -2,20 +2,6 @@ #include -#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) { @@ -26,12 +12,12 @@ 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] != '>') @@ -42,6 +28,7 @@ is_cmd(char** path, char** builtin, const char* p) i++; } + /* check first if it's a shell buitin */ if(builtin) @@ -59,34 +46,26 @@ is_cmd(char** path, char** builtin, const char* p) { 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; diff --git a/tools/tesh2/src/main.c b/tools/tesh2/src/main.c index cc4bcae5ee..c171590027 100644 --- a/tools/tesh2/src/main.c +++ b/tools/tesh2/src/main.c @@ -197,10 +197,10 @@ static const struct s_optentry opt_entries[] = { '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" }, @@ -289,20 +289,29 @@ print_readme(void); 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) @@ -443,33 +452,28 @@ init(void) * 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))) @@ -567,7 +571,6 @@ load(void) static void finalize(void) { - /* delete the fstreams object */ if(fstreams) fstreams_free((void**)&fstreams); @@ -604,8 +607,10 @@ finalize(void) #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"); @@ -615,9 +620,12 @@ finalize(void) /* 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 */ @@ -816,17 +824,6 @@ process_command_line(int argc, char** argv) /* --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) @@ -842,15 +839,11 @@ process_command_line(int argc, char** argv) return -1; } - #endif else { - #ifdef WIN32 - directory = directory_new(optarg); - #else + directory = directory_new(path); free(path); - #endif if(directories_contains(directories, directory)) { @@ -865,17 +858,6 @@ process_command_line(int argc, char** argv) } 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) @@ -890,20 +872,10 @@ process_command_line(int argc, char** argv) 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); @@ -912,11 +884,8 @@ process_command_line(int argc, char** argv) chdir(path); free(path); - #endif - + free(buffer); - - } } @@ -1019,17 +988,7 @@ process_command_line(int argc, char** argv) /* --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) @@ -1044,18 +1003,14 @@ process_command_line(int argc, char** argv) 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) { @@ -1180,6 +1135,16 @@ print_usage(void) 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"); @@ -1192,6 +1157,16 @@ print_usage(void) 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); diff --git a/tools/tesh2/src/reader.c b/tools/tesh2/src/reader.c index b3fcb1b9f4..291d058188 100644 --- a/tools/tesh2/src/reader.c +++ b/tools/tesh2/src/reader.c @@ -79,6 +79,8 @@ reader_start_routine(void* p) char* clean = (char*)calloc(number_of_bytes_to_read + 1,sizeof(char)); size_t i, j; + xbt_os_sem_release(reader->started); + while(!command->failed && !command->interrupted && !command->successeded && !reader->failed && !reader->broken_pipe) { if(!ReadFile(stdout_fd, buffer, number_of_bytes_to_read, &number_of_bytes_readed, NULL) || (0 == number_of_bytes_readed)) diff --git a/tools/tesh2/src/runner.c b/tools/tesh2/src/runner.c index 80b2a5f016..098efe8766 100644 --- a/tools/tesh2/src/runner.c +++ b/tools/tesh2/src/runner.c @@ -28,11 +28,14 @@ #include #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", @@ -129,7 +132,7 @@ runner_start_routine(void* p) /* wait for the timer */ WaitForSingleObject(timer_handle, INFINITE); - + if(runner->waiting) { exit_code = ELEADTIME; @@ -187,11 +190,12 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) 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; @@ -246,13 +250,10 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) /* 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') @@ -269,9 +270,10 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) 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 */ @@ -282,6 +284,7 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) len = strlen(p); for(j = len - 1; p[j] == '/' || p[j] == ' '; j--) + p[j] = '\0'; } } @@ -308,6 +311,11 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) 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); @@ -333,7 +341,6 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) xbt_dynar_push(runner->variables, &variable); - i = 0; /* add the errors variables */ @@ -350,24 +357,28 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) 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) @@ -395,8 +406,6 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) if(!is_blank) n++; - - } fsetpos(s, &begin); @@ -453,13 +462,8 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams) 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++) diff --git a/tools/tesh2/src/unit.c b/tools/tesh2/src/unit.c index ddd362a999..06a276b78b 100644 --- a/tools/tesh2/src/unit.c +++ b/tools/tesh2/src/unit.c @@ -66,7 +66,7 @@ unit_start(void* p) xbt_os_mutex_release(root->mutex); /* must acquire the jobs semaphore to start */ - xbt_os_sem_acquire(jobs_sem); + /*xbt_os_sem_acquire(jobs_sem);*/ /* initialize the mutex used to synchronize the access to the properties of this unit */ mutex = xbt_os_mutex_init(); @@ -409,7 +409,7 @@ unit_run(unit_t unit, xbt_os_mutex_t mutex) errno = EINVAL; return -1; } - + if(!interrupted) { unit->mutex = mutex; diff --git a/tools/tesh2/src/units.c b/tools/tesh2/src/units.c index a9f67c98ce..b590f22348 100644 --- a/tools/tesh2/src/units.c +++ b/tools/tesh2/src/units.c @@ -64,6 +64,7 @@ units_run_all(units_t units, xbt_os_mutex_t mutex) xbt_dynar_foreach(units->items, i, unit) { + xbt_os_sem_acquire(jobs_sem); unit_run(unit, mutex); } diff --git a/tools/tesh2/src/writer.c b/tools/tesh2/src/writer.c index bb9b445340..5d632ac61e 100644 --- a/tools/tesh2/src/writer.c +++ b/tools/tesh2/src/writer.c @@ -74,6 +74,8 @@ writer_start_routine(void* p) DWORD number_of_bytes_to_write = command->context->input->used; DWORD number_of_bytes_written = 0; + xbt_os_sem_release(writer->written); + while(!command->failed && !command->interrupted && !command->successeded && ! writer->failed && ! writer->broken_pipe && number_of_bytes_to_write) { if(!WriteFile(writer->command->stdin_fd, input, number_of_bytes_to_write, &number_of_bytes_written, NULL)) @@ -108,7 +110,7 @@ writer_start_routine(void* p) command_kill(command); command_handle_failure(command, csr_write_pipe_broken); }*/ - + CloseHandle(command->stdin_fd); command->stdin_fd = INDEFINITE_FD; diff --git a/tools/tesh2/tesh/tesh.vcproj b/tools/tesh2/tesh/tesh.vcproj index 8c7fe76541..e765046ffb 100644 --- a/tools/tesh2/tesh/tesh.vcproj +++ b/tools/tesh2/tesh/tesh.vcproj @@ -40,7 +40,7 @@ - - @@ -332,10 +329,6 @@ RelativePath="..\include\getpath.h" > - - diff --git a/tools/tesh2/w32/Cat/Cat.vcproj b/tools/tesh2/w32/Cat/Cat.vcproj index 1459f09393..b1d1d308c4 100644 --- a/tools/tesh2/w32/Cat/Cat.vcproj +++ b/tools/tesh2/w32/Cat/Cat.vcproj @@ -62,7 +62,7 @@ /> name; p++, option_index++) { if(!strncmp (p->name, nextchar, nameend - nextchar)) { - if ((nameend - nextchar) == strlen (p->name)) + if (nameend - nextchar == strlen (p->name)) { + /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; @@ -161,19 +206,27 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str } else if (pfound == NULL) { + /* First nonexact match found. */ exact = 0; + /* begin change + pfound = p; + indfound = option_index; + end change */ break; } else + { + + /* Second or later nonexact match found. */ ambig = 1; - + } } } if (ambig && !exact) { if (opterr) - fprintf (stderr, "ERROR : %s: option `%s' is ambiguous\n",argv[0], argv[optind]); + fprintf (stderr, "error : %s: option `%s' is ambiguous\n",argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; @@ -187,6 +240,8 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str if (*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else @@ -233,6 +288,10 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str return pfound->val; } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-'|| strchr (optstring, *nextchar) == NULL) { if (opterr) @@ -251,6 +310,8 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str } } + /* Look at and handle the next short option-character. */ + { char c = *nextchar++; char *temp = strchr (optstring, c); @@ -272,7 +333,7 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str { if (temp[2] == ':') { - /* it's an option that accepts an argument optionally. */ + /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; @@ -285,10 +346,12 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str } else { - /* it's an option that requires an argument. */ + /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ optind++; } else if (optind == argc) @@ -296,7 +359,7 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str if (opterr) { /* 1003.2 specifies the format of this message. */ - fprintf (stderr, "ERROR : %s: option requires an argument -- %c\n",argv[0], c); + fprintf (stderr, "error : %s: option requires an argument -- %c\n",argv[0], c); } optopt = c; @@ -306,6 +369,8 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str c = '?'; } else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; @@ -325,38 +390,49 @@ __exchange (char **argv) int top = optind; char *tem; + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { + /* Bottom segment is the short one. */ int len = middle - bottom; register int i; + /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; } + /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { + /* Top segment is the short one. */ int len = top - middle; register int i; + /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } - + /* Exclude the moved top segment from further swapping. */ bottom += len; } } + /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; -- 2.20.1