-
+/*
+ * src/main.c - this file contains the main function of tesh.
+ *
+ * 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.
+ *
+ *
+ */
#include <runner.h>
#include <fstream.h>
#include <fstreams.h>
#include <directory.h>
#include <directories.h>
#include <excludes.h>
-#include <error.h>
-
#include <getopt.h>
#include <getpath.h>
+#include <locale.h>
+
/*
* entry used to define the parameter of a tesh option.
*/
}s_optentry_t,* optentry_t;
-
+/* logs */
XBT_LOG_NEW_DEFAULT_CATEGORY(tesh,"TEst SHell utility");
#ifdef WIN32
prev_error_mode = 0;
#endif
+/* this object represents the root directory */
directory_t
root_directory = NULL;
-/*int
-exit_code = 0;
-*/
-
-int
-want_detail_summary = 0;
-
/* the current version of tesh */
static const char*
version = "1.0";
/* --jobs is specified with arg */
static int
-number_of_jobs = -2;
+jobs_nb = -2;
/* --jobs option is not specified (use the default job count) */
static int
-default_number_of_jobs = 1;
+default_jobs_nb = 1;
/* --jobs is specified but has no arg (one job per unit) */
static int
-optional_number_of_jobs = -1;
+optional_jobs_nb = -1;
/* the global timeout */
static int
timeout = INDEFINITE;
/* ------------------------------------------------------------ */
-/* strings dlists */
+/* strings */
/* ------------------------------------------------------------ */
/* --C change the directory before running the units */
directories = NULL;
/* the include directories : see the !i metacommand */
-vector_t
+xbt_dynar_t
include_dirs = NULL;
/* the list of tesh files to run */
static fstreams_t
fstreams = NULL;
-/* xbt logs */
-static lstrings_t
-logs = NULL;
+/* the list of tesh file suffixes */
+static xbt_dynar_t
+suffixes = NULL;
static excludes_t
excludes = NULL;
-/* the ddlist of tesh file suffixes */
-static lstrings_t
-suffixes = NULL;
/* ------------------------------------------------------------ */
/* flags */
* default value 0 : not keep going
*/
int
-want_keep_going = 0;
+keep_going_flag = 0;
/* if 1, ignore failures from commands
* default value : do not ignore failures
*/
int
-want_keep_going_unit = 0;
+keep_going_unit_flag = 0;
/* if 1, display tesh usage */
static int
-want_display_usage = 0;
+print_usage_flag = 0;
/* if 1, display the tesh version */
static int
-want_display_version = 0;
-
-/* if 1, the syntax of all tesh files is checked
- * before running them
- */
-static int
-want_check_syntax = 0;
+print_version_flag = 0;
/* if 1, the status of all the units is display at
* the end.
*/
static int
-want_verbose = 0;
+summary_flag = 0;
+
+/* if 1 and the flag want_summay is set to 1 tesh display the detailed summary of the run */
+int
+detail_summary_flag = 0;
/* if 1, the directories are displayed */
int
-dont_want_display_directory = 0;
+print_directory_flag = 0;
/* if 1, just check the syntax of all the tesh files
* do not run them.
*/
int
-want_dry_run = 0;
+dry_run_flag = 0;
/* if 1, display the tesh files syntax and exit */
static int
-want_display_semantic = 0;
+print_readme_flag = 0;
int
-want_silent = 0;
+silent_flag = 0;
int
-want_just_display = 0;
-
-static int
-env_overrides = 0;
-
-static int
-display_data_base = 0;
-
-static int
-question = 0;
+just_print_flag = 0;
/* the semaphore used to synchronize the jobs */
xbt_os_sem_t
int
exit_code = 0;
+int
+err_kind = 0;
+
+char*
+err_line = NULL;
+
+
pid_t
pid =0;
+int
+is_tesh_root = 1;
+
/* the table of the entries of the options */
static const struct s_optentry opt_entries[] =
{
{ 'C', string, (byte*)NULL, 0, "directory" },
{ 'x', string, (byte*)&suffixes, 0, "suffix" },
- { 'e', flag, (byte*)&env_overrides, 0, "environment-overrides", },
{ 'f', string, (byte*)&fstreams, 0, "file" },
- { 'h', flag, (byte*)&want_display_usage, 0, "help" },
- { 'a', flag, (byte*)&want_display_semantic, 0, "semantic" },
- { 'i', flag, (byte*)&want_keep_going_unit, 0, "keep-going-unit" },
+ { 'h', flag, (byte*)&print_usage_flag, 0, "help" },
+ { 'a', flag, (byte*)&print_readme_flag, 0, "README" },
+ { '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*)&number_of_jobs, (byte*) &optional_number_of_jobs, "jobs" },
- { 'k', flag, (byte*)&want_keep_going, 0, "keep-going" },
- { 'm', flag, (byte*)&want_detail_summary, 0, "detail-summary" },
- { 'c', flag, (byte*)&want_just_display, 0, "just-display" },
- { 'd', flag, (byte*)&display_data_base, 0,"display-data-base" },
- { 'q', flag, (byte*)&question, 0, "question" },
- { 's', flag, (byte*)&want_silent, 0, "silent" },
- { 'V', flag, (byte*)&want_display_version, 0, "version" },
- { 'w', flag, (byte*)&dont_want_display_directory, 0,"dont-display-directory" },
- { 'n', flag, (byte*)&want_dry_run, 0, "dry-run"},
+ { 'j', number, (byte*)&jobs_nb, (byte*) &optional_jobs_nb, "jobs" },
+ { '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" },
+ { 'V', flag, (byte*)&print_version_flag, 0, "version" },
+ { 'w', flag, (byte*)&print_directory_flag, 0,"dont-print-directory" },
+ { 'n', flag, (byte*)&dry_run_flag, 0, "dry-run"},
{ 't', number, (byte*)&timeout, 0, "timeout" },
- { 'S', flag, (byte*)&want_check_syntax, 0, "check-syntax"},
{ 'r', string, (byte*)&directories, 0, "load-directory"},
- { 'v', flag, (byte*)&want_verbose, 0, "verbose"},
+ { 'v', flag, (byte*)&summary_flag, 0, "summary"},
{ 'F', string,(byte*)&excludes, 0, "exclude"},
- { 'l', string,(byte*)&logs,0,"log"},
+ { 'l', string, (byte*)NULL, 0, "log" },
{ 0, 0, 0, 0, 0}
-
};
/* the tesh usage */
" remark :\n",
" all argument of the command line without\n",
" option is dealed as a tesh file.\n",
- " -h, --help Display this message and exit.\n",
+ " -h, --help Print this message and exit.\n",
" -i, --keep-going-unit Ignore failures from commands.\n",
" The possible failures are :\n",
" - the exit code differ from the expected\n",
" - the write pipe is broken\n",
" - the command assigned delay is outdated\n",
" -I DIRECTORY, --include-dir=DIRECTORY Search DIRECTORY for included files.\n",
- " -j [N], --jobs[=N] Allow N commands at once; infinite commands with\n"
+ " -j [N], --jobs[=N] Allow N units at once; infinite units with\n"
" no arg.\n",
" -k, --keep-going Keep going when some commands can't be made or\n",
" failed.\n",
- " -c, --just-display Don't actually run any commands; just display them.\n",
- " -p, --display-data-base Display tesh's internal database.\n",
- " -q, --question Run no commands; exit status says if up to date.\n",
+ " -c, --just-print Don't actually run any commands; just print them.\n",
" -s, --silent, Don't echo commands.\n",
- " -V, --version Display the version number of tesh and exit.\n",
- " -d, --dont-display-directory Don't display the current directory.\n",
+ " -V, --version Print the version number of tesh and exit.\n",
+ " -d, --dont-print-directory Don't display the current directory.\n",
" -n, --dry-run Check the syntax of the specified tesh files, display the result and exit.\n",
" -t, --timeout Wait the end of the commands at most timeout seconds.\n",
- " -S, --check-syntax Check the syntax of the tesh files before run them. \n",
" -x, --suffix Consider the new suffix for the tesh files.\n"
" remark :\n",
" the default suffix for the tesh files is \".tesh\".\n",
- " -a, --semantic Display the tesh file metacommands syntax and exit.\n",
- " -b, --build-file Build a tesh file.\n",
+ " -a, --README Print the read me file and exit.\n",
" -r, --load-directory Run all the tesh files located in the directories specified by the option --directory.\n",
- " -v, --verbose Display the status of the commands.\n",
+ " -v, --summary Display the status of the commands.\n",
" -m, --detail-summary Detail the summary of the run.\n",
" -F file , --exclude=FILE Ignore the tesh file FILE.\n",
" -l format, --log Format of the xbt logs.\n",
load(void);
static void
-display_usage(void);
+print_usage(void);
static void
-display_version(void);
+print_version(void);
static void
finalize(void);
static void
-display_semantic(void);
+print_readme(void);
static int
init(void);
+static int
+screen_cleaned;
+
+static int
+finalized = 0;
+
+static int
+sig_int = 0;
+#ifdef WIN32
+static void
+sig_int_handler(int signum)
+{
+
+ if(!finalized)
+ {
+ sig_int = 1;
+ runner_interrupt();
+ while(!finalized);
+ }
+
+}
+#endif
+
+static void
+free_string(void* str)
+{
+ free(*(void**)str);
+}
int
main(int argc, char* argv[])
{
+ /* set the locale to the default*/
+ setlocale(LC_ALL,"");
+
+ /* xbt initialization */
+ xbt_init(&argc, argv);
+
+ /* initialize tesh */
if(init() < 0)
finalize();
/* move to the root directory (the directory may change during the command line processing) */
chdir(root_directory->name);
- /* initialize the xbt library
- * for thread portability layer
- */
-
- /* xbt initialization */
- if(!lstrings_is_empty(logs))
+ /* the user wants to display the usage of tesh */
+ if(print_version_flag)
{
- int size = lstrings_get_size(logs);
- char** cstr = lstrings_to_cstr(logs);
-
- xbt_init(&size, cstr);
-
- free(cstr);
-
+ print_version();
+
+ if(!print_usage_flag)
+ finalize();
}
- else
- xbt_init(&argc, argv);
/* the user wants to display the usage of tesh */
- if(want_display_usage)
- finalize();
-
- /* the user wants to display the version of tesh */
- if(want_display_version)
+ if(print_usage_flag)
{
- display_version();
+ print_usage();
finalize();
}
/* the user wants to display the semantic of the tesh file metacommands */
- if(want_display_semantic)
+ if(print_readme_flag)
{
- display_semantic();
+ print_readme();
finalize();
}
/* use by the finalize function to known if it must display the tesh usage */
loaded = 1;
- if(-2 == number_of_jobs)
+ if(-2 == jobs_nb)
{/* --jobs is not specified (use the default value) */
- number_of_jobs = default_number_of_jobs;
+ jobs_nb = default_jobs_nb;
}
- else if(optional_number_of_jobs == number_of_jobs)
+ else if(optional_jobs_nb == jobs_nb)
{/* --jobs option is specified with no args (use one job per unit) */
- number_of_jobs = fstreams_get_size(fstreams);
+ jobs_nb = fstreams_get_size(fstreams);
}
- if(number_of_jobs > fstreams_get_size(fstreams))
+ if(jobs_nb > fstreams_get_size(fstreams))
{/* --jobs = N is specified and N is more than the number of tesh files */
WARN0("Number of requested jobs exceed the number of files to run");
/* assume one job per file */
- number_of_jobs = fstreams_get_size(fstreams);
+ jobs_nb = fstreams_get_size(fstreams);
+ }
+
+ if(jobs_nb != 1 && dry_run_flag)
+ {
+ jobs_nb = 1;
+ INFO0("Dry run specified : force jobs count to 1");
}
/* initialize the semaphore used to synchronize all the units */
- jobs_sem = xbt_os_sem_init(number_of_jobs);
+ jobs_sem = xbt_os_sem_init(jobs_nb);
/* initialize the semaphore used by the runner to wait for the end of all units */
units_sem = xbt_os_sem_init(0);
/* initialize the runner */
- if(runner_init(want_check_syntax, timeout, fstreams))
+ if(runner_init(/*check_syntax_flag,*/ timeout, fstreams) < 0)
finalize();
- if(want_just_display && want_silent)
- want_silent = 0;
+ if(just_print_flag && silent_flag)
+ silent_flag = 0;
- if(want_just_display && want_dry_run)
+ if(just_print_flag && dry_run_flag)
WARN0("mismatch in the syntax : --just-check-syntax and --just-display options at same time");
/* run all the units */
runner_run();
-
+ if(runner_is_timedout())
+ ERROR1("Tesh timed out after `(%d)' seconds", timeout);
+
/* show the result of the units */
- if(want_verbose || want_dry_run)
- runner_display_status();
+ if(detail_summary_flag ||summary_flag || dry_run_flag)
+ runner_summarize();
/* all the test are runned, destroy the runner */
runner_destroy();
init(void)
{
char* buffer;
-
-
+ char* suffix = strdup(".tesh");
#ifdef WIN32
/* Windows specific : don't display the general-protection-fault message box and
* to the calling process : tesh)
*/
prev_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
- #endif
+
+ /* handle the interrupt signal */
+ signal(SIGINT, sig_int_handler);
+ #else
+ /* 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
+ */
+ /*
+ 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_int_handler;
+ sigaction(SIGINT, &act, NULL);*/
+
+ #endif
+
+
+
/* used to store the files to run */
- if(!(fstreams = fstreams_new(DEFAULT_FSTREAMS_CAPACITY, fstream_free)))
+ if(!(fstreams = fstreams_new((void_f_pvoid_t)fstream_free)))
{
- ERROR0("Insufficient memory is available to initialize tesh : system error");
+ ERROR1("(system error) %s", strerror(errno));
return -1;
}
/* register the current directory */
if(!(buffer = getcwd(NULL, 0)))
{
- exit_code = errno;
-
- if(EACCES == errno)
- ERROR0("tesh initialization failed - Insufficient permission to read the current directory");
- else
- ERROR0("Insufficient memory is available to initialize tesh : system error");
-
+ ERROR1("(system error) %s", strerror(errno));
return -1;
}
/* save the root directory */
if(!(root_directory = directory_new(buffer)))
{
- ERROR0("Insufficient memory is available to initialize tesh : system error");
+ ERROR1("(system error) %s", strerror(errno));
return -1;
}
/* the directories to loads */
if(!(directories = directories_new()))
{
- ERROR0("Insufficient memory is available to initialize tesh : system error");
+ ERROR1("(system error) %s", strerror(errno));
return -1;
}
/* the include directories */
- if(!(include_dirs = vector_new(DEFAULT_INCLUDE_DIRS_CAPACITY, directory_free)))
- {
- ERROR0("Insufficient memory is available to initialize tesh : system error");
- return -1;
- }
-
- /* xbt logs option */
- if(!(logs = lstrings_new()))
- {
- ERROR0("Insufficient memory is available to initialize tesh : system error");
- return -1;
- }
+ include_dirs = xbt_dynar_new(sizeof(directory_t), (void_f_pvoid_t)directory_free);
/* the excluded files */
if(!(excludes = excludes_new()))
{
- ERROR0("Insufficient memory is available to initialize tesh : system error");
+ ERROR1("(system error) %s", strerror(errno));
return -1;
}
/* the suffixes */
- if(!(suffixes = lstrings_new()))
- {
- ERROR0("Insufficient memory is available to initialize tesh : system error");
- return -1;
- }
+ suffixes = xbt_dynar_new(sizeof(char*),free_string);
/* register the default suffix ".tesh" */
- if(lstrings_push_back(suffixes,".tesh"))
- {
- ERROR0("Insufficient memory is available to initialize tesh : system error");
- return -1;
- }
-
- pid = getpid();
+ xbt_dynar_push(suffixes, &suffix);
return 0;
}
/* if the fstreams object is empty use the stdin */
if(fstreams_is_empty(fstreams))
- fstreams_add(fstreams, fstream_new(NULL, "stdin"));
+ fstreams_add(fstreams, fstream_new(NULL, "stdin"));
/* load the tesh files (open them) */
fstreams_load(fstreams);
static void
finalize(void)
{
- /* if there is not an error and the user wants display the usage or
- * if there is an error and all the files to load are loaded, display the usage
- */
- if((!exit_code && want_display_usage) || (!exit_code && !loaded))
- display_usage();
-
/* delete the fstreams object */
if(fstreams)
fstreams_free((void**)&fstreams);
/* delete the include directories object */
if(include_dirs)
- vector_free(&include_dirs);
+ xbt_dynar_free(&include_dirs);
/* delete the list of tesh files suffixes */
if(suffixes)
- lstrings_free(&suffixes);
-
- /* delete the xbt log options list */
- if(logs)
- lstrings_free(&logs);
+ xbt_dynar_free(&suffixes);
-
/* destroy the semaphore used to synchronize the units */
if(jobs_sem)
xbt_os_sem_destroy(jobs_sem);
if(units_sem)
xbt_os_sem_destroy(units_sem);
- /* exit from the xbt framework */
- xbt_exit();
-
/* Windows specific (restore the previouse error mode */
#ifdef WIN32
SetErrorMode(prev_error_mode);
#endif
+
+ if(sig_int)
+ INFO0("Tesh interrupted (receive a SIGINT)");
+ else if(!summary_flag && !detail_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");
+ else
+ {
+ if(err_line)
+ ERROR3("Tesh terminated with exit code `(<%s> %s)' (%d)",err_line, error_to_string(exit_code, err_kind), exit_code);
+ else
+ ERROR2("Tesh terminated with exit code `(%s)' (%d)", error_to_string(exit_code, err_kind), exit_code);
+
+ }
+ }
+
+ if(err_line)
+ free(err_line);
- if(!want_verbose && !want_dry_run && !want_silent && !want_just_display)
- INFO2("tesh terminated with exit code %d : %s",exit_code, (!exit_code ? "success" : error_to_string(exit_code)));
+ /* 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 */
p = optstring;
-
*p++ = '-';
for (i = 0; opt_entries[i].c != '\0'; ++i)
if(getpath(optarg, &path) < 0)
{
exit_code = errno;
+ err_kind = 0;
if(ENOENT == errno)
ERROR1("File %s does not exist", optarg);
/* get to the last / (if any) to get the short name of the file */
delimiter = strrchr(optarg,'/');
+ #ifdef WIN32
+ if(!delimiter)
+ delimiter = strrchr(optarg,'\\');
+ #endif
+
/* create a new file stream which represents the tesh file to run */
fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
*/
if(fstreams_contains(fstreams, fstream))
{
- fstream_free((void**)&fstream);
+ fstream_free(&fstream);
WARN1("File %s already specified to be run", optarg);
}
else
fstreams_add(fstreams, fstream);
-
-
-
}
else if (c == '?')
{
/* unknown option, let getopt_long() displays the error */
+ ERROR0("Command line processing failed : invalid command line");
+ exit_code = EINVCMDLINE;
+ err_kind = 1;
return -1;
}
else
default:
ERROR0("Command line processing failed : internal error");
exit_code = EPROCCMDLINE;
+ err_kind = 1;
return -1;
/* a non optional argument is not specified */
ERROR2("Option %c \"%s\"requires an argument",entry->c,entry->long_name);
exit_code = ENOARG;
+ err_kind = 1;
return -1;
}
if(translatepath(optarg, &path) < 0)
{
exit_code = errno;
+ err_kind = 0;
if(ENOTDIR == errno)
ERROR1("%s is not a directory",optarg);
}
else
{
+
directory = directory_new(path);
free(path);
if(translatepath(optarg, &path) < 0)
{
exit_code = errno;
+ err_kind = 0;
if(ENOTDIR == errno)
ERROR1("%s is not a directory",optarg);
}
else
{
- if(!dont_want_display_directory)
- INFO1("Entering directory \"%s\"",path);
+ char* buffer = getcwd(NULL, 0);
+
+ if(!strcmp(buffer, path))
+ WARN1("Already in the directory %s", optarg);
+ else if(!print_directory_flag)
+ INFO1("Entering directory \"%s\"",path);
+
chdir(path);
free(path);
-
-
+
+ free(buffer);
}
}
if(strlen(optarg) > MAX_SUFFIX)
{
ERROR1("Suffix %s too long",optarg);
- exit_code = ESUFFIXTOOLONG;
+ exit_code = ESUFFIXTOOLONG;
+ err_kind = 1;
return -1;
}
if(optarg[0] == '.')
{
- char suffix[MAX_SUFFIX + 2] = {0};
+ char* cur;
+ unsigned int i;
+ int exists = 0;
+
+ char* suffix = xbt_new0(char, MAX_SUFFIX + 2);
sprintf(suffix,".%s",optarg);
- if(lstrings_contains(suffixes, suffix))
+ xbt_dynar_foreach(suffixes, i, cur)
+ {
+ if(!strcmp(suffix, cur))
+ {
+ exists = 1;
+ break;
+ }
+ }
+
+ if(exists)
WARN1("Suffix %s already specified to be used", optarg);
else
- lstrings_push_back(suffixes, suffix);
+ xbt_dynar_push(suffixes, &suffix);
}
else
{
- if(lstrings_contains(suffixes, optarg))
+ char* cur;
+ unsigned int i;
+ int exists = 0;
+
+ xbt_dynar_foreach(suffixes, i, cur)
+ {
+ if(!strcmp(optarg, cur))
+ {
+ exists = 1;
+ break;
+ }
+ }
+
+ if(exists)
WARN1("Suffix %s already specified to be used", optarg);
else
- lstrings_push_back(suffixes, optarg);
+ {
+ char* suffix = strdup(optarg);
+ xbt_dynar_push(suffixes, &suffix);
+ }
}
}
/* --file option */
if(getpath(optarg, &path) < 0)
{
exit_code = errno;
+ err_kind = 0;
if(ENOENT == errno)
ERROR1("File %s does not exist", optarg);
else
- ERROR0("Insufficient memory is available to process the command line - system error");
+ ERROR1("System error :`(%s)'", strerror(errno));
return -1;
}
delimiter = strrchr(optarg,'/');
+
+ #ifdef WIN32
+ if(!delimiter)
+ delimiter = strrchr(optarg,'\\');
+ #endif
fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
if(fstreams_contains(fstreams, fstream))
{
- fstream_free((void**)&fstream);
+ fstream_free(&fstream);
WARN1("File %s already specified to run", optarg);
}
else
if(translatepath(optarg, &path) < 0)
{
exit_code = errno;
+ err_kind = 0;
if(ENOTDIR == errno)
ERROR1("%s is not a directory",optarg);
return -1;
}
+
else
{
-
+ int exists = 0;
+ unsigned int i;
+ directory_t cur;
directory = directory_new(path);
free(path);
-
- if(vector_contains(include_dirs, directory))
+
+ xbt_dynar_foreach(include_dirs, i , cur)
+ {
+ if(!strcmp(cur->name, optarg))
+ {
+ exists = 1;
+ break;
+ }
+ }
+
+ if(exists)
{
directory_free((void**)&directory);
WARN1("Include directory %s already specified to be used",optarg);
}
else
- vector_push_back(include_dirs, directory);
+ xbt_dynar_push(include_dirs, &directory);
+
}
}
/* --exclude option */
else if(!strcmp(entry->long_name,"exclude"))
{
-
char* path;
char* delimiter;
if(getpath(optarg, &path) < 0)
{
exit_code = errno;
+ err_kind = 0;
if(ENOENT == errno)
ERROR1("file %s does not exist", optarg);
}
delimiter = strrchr(optarg,'/');
+
+ #ifdef WIN32
+ if(!delimiter)
+ delimiter = strrchr(optarg,'\\');
+ #endif
fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
free(path);
if(excludes_contains(excludes, fstream))
{
- fstream_free((void**)&fstream);
+ fstream_free(&fstream);
WARN1("File %s already specified to be exclude", optarg);
}
else
excludes_add(excludes, fstream);
}
- /* --log option */
else if(!strcmp(entry->long_name,"log"))
{
- lstrings_push_back(logs, optarg);
+ /* NOTHING TODO : log for xbt */
}
else
{
{
ERROR2("Option %c \"%s\" requires an strictly positive integer as argument",entry->c, entry->long_name);
exit_code = ENOTPOSITIVENUM;
+ err_kind = 1;
return -1;
}
else
}
static void
-display_usage(void)
+print_usage(void)
{
const char **cpp;
FILE* stream;
- if (want_display_version)
- display_version();
-
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
-display_version(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);
printf(" This program is free software; you can redistribute it and/or modify it\n");
printf(" under the terms of the license (GNU LGPL) which comes with this package.\n\n");
- if(!want_display_usage)
+ if(!print_usage_flag)
printf("Report bugs to <martin.quinson@loria.fr | malek.cherier@loria.fr>");
}
static void
-display_semantic(void)
+print_readme(void)
{
size_t len;
char * line = NULL;
- FILE* stream = fopen("README.txt", "r");
+ FILE* stream = fopen("examples/README.tesh", "r");
if(!stream)
{
ERROR0("Unable to locate the README.txt file");
exit_code = EREADMENOTFOUND;
+ err_kind = 1;
return;
}