Commit cb3132f7 authored by Arnaud Blanchard's avatar Arnaud Blanchard
Browse files

Inintial files to make program helpers

parents
# Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2016)
# Author: Arnaud Blanchard
# This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
# You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
# As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
# users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
# In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
# Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured  and, more generally, to use and operate it in the same conditions as regards security.
# The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms.
cmake_minimum_required(VERSION 2.6)
project(blc_program)
add_definitions(-Wall -Wextra -Wno-multichar)
get_filename_component(BLAAR_DIR ${CMAKE_SOURCE_DIR} PATH)
if (NOT TARGET shared_blc_core)
add_subdirectory(${BLAAR_DIR}/blc/blc_core blc_core)
endif()
include_directories(include ${BLC_CORE_INCLUDE_DIR}) #see if we can separate blc_channel
#source files
set(blc_sources src/blc_program.cpp src/blc_command.cpp)
find_library(BLC_CORE_LIBRARY blc_core)
add_library(shared_blc_program SHARED ${blc_sources})
add_library(static_blc_program STATIC ${blc_sources})
target_link_libraries(shared_blc_program shared_blc_core)
set(BLC_PROGRAM_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
#Both librairies have the same name only the extension will change depending on the OS
set_target_properties(shared_blc_program PROPERTIES OUTPUT_NAME blc_program)
set_target_properties(static_blc_program PROPERTIES OUTPUT_NAME blc_program)
#Describe what will be to install or in the package
install(DIRECTORY include/ DESTINATION include)
install(TARGETS shared_blc_program shared_blc_program DESTINATION lib)
set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Arnaud Blanchard")
include(CPack)
#Building examples
#add_executable(blc_demo examples/blc_demo.c)
#Add a target to generate documentation
#find_package(Doxygen)
#if(DOXYGEN_FOUND)
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxyfile.in doxyfile.doxy) #Replace the CMAKE variables in the Doxyfile
#add_custom_target(doc_${PROJECT_NAME} ALL ${DOXYGEN_EXECUTABLE} doxyfile.doxy COMMENT "Generating API documentation with Doxygen" VERBATIM )
#else(DOXYGEN_FOUND)
#message("You need to install doxygen to generate the doc.")
#endif(DOXYGEN_FOUND)
PROJECT_NAME = "BLC"
OUTPUT_DIRECTORY = ${CMAKE_BINARY_DIR}/../../doc/blc
OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_LOCAL_CLASSES = NO
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = YES
HIDE_IN_BODY_DOCS = YES
CASE_SENSE_NAMES = NO
SORT_MEMBER_DOCS = NO
QUIET = YES
INPUT = ${CMAKE_CURRENT_SOURCE_DIR}
RECURSIVE = YES
# USE_MDFILE_AS_MAINPAGE = ${CMAKE_CURRENT_SOURCE_DIR}/README.md
ALPHABETICAL_INDEX = NO
HTML_OUTPUT = html
LATEX_OUTPUT = latex
MACRO_EXPANSION = YES
PREDEFINED = __cplusplus = 1
REPEAT_BRIEF = YES
SKIP_FUNCTION_MACROS = NO
CLASS_DIAGRAMS = NO
/* Basic Library for C/C++ (blclib)
Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2015)
Author: Arnaud Blanchard
This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
 users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
 In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
 that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured
 and, more generally, to use and operate it in the same conditions as regards security.
 The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms. */
/*
The usage formating follows the format of argparse in Python ( https://docs.python.org/3/library/argparse.html ).
Otherwise, we can be inspired from http://docopt.org
*/
/**
@defgroup blc_command command
Few functions helping for pseudo realtime applications.
@{*/
#ifndef BLC_COMMAND_H
#define BLC_COMMAND_H
#include "blc_tools.h"
#define BLC_COMMAND_LOOP_THREAD() for(blc_command_loop_init(-2); blc_command_loop_start();blc_command_loop_end())
/** Warning the period can be till 10ms longer than, asked. Problem of usleep/nano sleep */
#define BLC_COMMAND_LOOP(period) for(blc_command_loop_init(period); blc_command_loop_start();blc_command_loop_end())
#define BLC_COMMAND_LOOP_NON_STOP() for(blc_command_loop_init(0); blc_command_loop_start();blc_command_loop_end())
#define BLC_COMMAND_LOOP_BLOCK() for(blc_command_loop_init(-1); blc_command_loop_start();blc_command_loop_end())
typedef void (*type_blc_command_cb)(char const *arguement, void *user_data);
extern long blc_command_loop_period;
START_EXTERN_C
///Add a command in the list of possible command lines from the user.
void blc_command_add(const char *command_name, type_blc_command_cb callback, const char *prompt, const char *help, void *user_data);
///Wait a input from the user (this id blocking) and interprets it depending on the blc_command list.
void blc_command_interpret();
///Like blc_command_interpret but does not block if there is nothing to read (return 0 in this case).
int blc_command_try_to_interpret();
//May not be useful
void *blc_command_interpret_loop(char const *option);
///Start a thread listinning to the user entry without blocking.
void blc_command_interpret_thread(char const *option);
///Display the list of blc_command with help.
void blc_command_display_help();
/// Loop period in ms. If loop period = BLC_LOOP_NON_STOP the system is as fast as possible, if it is BLC_LOOP_BLOCK , it is command with return on stdin. If itis BLC_LLOP_THREAD it starts a parrallel thread to interpret command. In this latter case do not use stdin yourself.
void blc_command_loop_init(long loop_period);
int blc_command_loop_start();
void blc_command_loop_end();
/** Stop a textual program
* - Send a quitting message with the name of the app on stderr.
* - Send 'q' and flush on stdout if it is a piped output
* - quit with no error (0).
*/
void blc_quit();
END_EXTERN_C
#endif
///@}
/* Basic Library for C/C++ (blclib)
Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2015)
Author: Arnaud Blanchard
This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
 users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
 In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
 that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured
 and, more generally, to use and operate it in the same conditions as regards security.
 The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms. */
/*
The usage formating follows the format of argparse in Python ( https://docs.python.org/3/library/argparse.html ).
Otherwise, we can be inspired from http://docopt.org
*/
/**
@defgroup blc_program Program
Functions to parse and manage arguments
@{*/
#ifndef BLC_PROGRAM_H
#define BLC_PROGRAM_H
#include "blc_tools.h"
//#include "blc_channel.h"
typedef enum {BLC_QUIT=0, BLC_RUN, BLC_PAUSE} type_blc_status;
extern int blc_input_terminal, blc_output_terminal;
extern type_blc_status blc_status;
START_EXTERN_C
///Add an argument to the list argv of arguments. Add eventually a value as well.
void blc_add_arg( int *argc, char ***argv, char const *arg, char const *value);
///Allocate and fill a command line with the array of argument. The array must be terminated by a NULL argument and must the returned command line me be freed after use.
///It does not handle spaces in argument !!!
char *blc_create_command_line_from_argv(char const *const *argv);
///Allocate and fill an array of argument by spiting the command_line. The array is terminated by a NULL argument and it must be freed after used.
///It does not handle spaces in argument !!!
char * const*blc_create_argv_from_command_line(char const *command_line);
///Set the desciption of the program used for help. A copy of desciption is done (strdup).
void blc_program_set_description(char const *description);
/// Add parameter required or not after the program name
void blc_program_add_parameter(char const **result, char const *name, int required_nb, char const *help);
//void blc_program_add_channel_parameter(blc_channel *channel, int required_nb, char const *help);
//void blc_program_add_channel_option(blc_channel *channel, char letter, char const *long_option, char const *help, char const* default_value);
void blc_program_add_input_pipe_option(FILE *file, char letter, char const *long_option, char const *help, char const* default_value);
void blc_program_add_output_pipe_option(FILE *file, char letter, char const *long_option, char const *help, char const* default_value);
//void blc_program_add_channel_parameter(blc_channel *channel, int required_nb, char const *help);
///Add a possible option to the program. The argument following the option, if any, it will be put in result otherwise "1" will be put in result.
void blc_program_add_option( char const**result, char letter, char const *long_option, char const *parameter_type, const char *help, char const* default_value);
///Interpret the program arguments and update the results values as it should.
void blc_program_option_interpret(int *argc, char **argv[]);
///Do program_option_interpret but print the name of the program (argv[0]) underlined with '='.
void blc_program_option_interpret_and_print_title(int *argc, char ***argv);
///Display the different possible argument for the program.
void blc_program_option_display_help();
/** Start a textual program.
* This has to be called after defining the parameters of the program
* - Parse the arguments of the programs
* - display the title
* - check the color possibility of the terminal stderr
* - associate the blc_quit function at exit and eventually your 'exit_cb' if it not NULL.
* - set internal variables setting if the input and output terminal are tty*/
void blc_program_init(int *argc, char ***argv, void(*exit_cb)(void));
/** Stop a textual program
* - Send a quitting message with the name of the app on stderr.
* - Send 'q' and flush on stdout if it is a piped output
* - quit with no error (0).
*/
void blc_quit();
END_EXTERN_C
#endif
///@}
/* Basic Library for C/C++ (blclib)
Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2015)
Author: Arnaud Blanchard
This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
 users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
 In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
 that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured
 and, more generally, to use and operate it in the same conditions as regards security.
 The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms. */
/*
The usage formating follows the format of argparse in Python ( https://docs.python.org/3/library/argparse.html ).
Otherwise, we can be inspired from http://docopt.org
*/
/**
@defgroup blc_program Program
Functions to parse and manage arguments
@{*/
#ifndef BLC_PROGRAM_H
#define BLC_PROGRAM_H
#include "blc_tools.h"
//#include "blc_channel.h"
typedef enum {BLC_QUIT=0, BLC_RUN, BLC_PAUSE} type_blc_status;
extern int blc_input_terminal, blc_output_terminal;
extern type_blc_status blc_status;
START_EXTERN_C
///Add an argument to the list argv of arguments. Add eventually a value as well.
void blc_add_arg( int *argc, char ***argv, char const *arg, char const *value);
///Allocate and fill a command line with the array of argument. The array must be terminated by a NULL argument and must the returned command line me be freed after use.
///It does not handle spaces in argument !!!
char *blc_create_command_line_from_argv(char const *const *argv);
///Allocate and fill an array of argument by spiting the command_line. The array is terminated by a NULL argument and it must be freed after used.
///It does not handle spaces in argument !!!
char * const*blc_create_argv_from_command_line(char const *command_line);
///Set the desciption of the program used for help. A copy of desciption is done (strdup).
void blc_program_set_description(char const *description);
/// Add parameter required or not after the program name
void blc_program_add_parameter(char const **result, char const *name, int required_nb, char const *help);
void blc_program_add_channel_parameter(blc_channel *channel, int required_nb, char const *help);
void blc_program_add_channel_option(blc_channel *channel, char letter, char const *long_option, char const *help, char const* default_value);
void blc_program_add_input_pipe_option(FILE *file, char letter, char const *long_option, char const *help, char const* default_value);
void blc_program_add_output_pipe_option(FILE *file, char letter, char const *long_option, char const *help, char const* default_value);
void blc_program_add_channel_parameter(blc_channel *channel, int required_nb, char const *help);
///Add a possible option to the program. The argument following the option, if any, it will be put in result otherwise "1" will be put in result.
void blc_program_option_add( char const**result, char letter, char const *long_option, char const *parameter_type, const char *help, char const* default_value);
///Interpret the program arguments and update the results values as it should.
void blc_program_option_interpret(int *argc, char **argv[]);
///Do program_option_interpret but print the name of the program (argv[0]) underlined with '='.
void blc_program_option_interpret_and_print_title(int *argc, char ***argv);
///Display the different possible argument for the program.
void blc_program_option_display_help();
/** Start a textual program.
* This has to be called after defining the parameters of the program
* - Parse the arguments of the programs
* - display the title
* - check the color possibility of the terminal stderr
* - associate the blc_quit function at exit and eventually your 'exit_cb' if it not NULL.
* - set internal variables setting if the input and output terminal are tty*/
void blc_program_init(int *argc, char ***argv, void(*exit_cb)(void));
/** Stop a textual program
* - Send a quitting message with the name of the app on stderr.
* - Send 'q' and flush on stdout if it is a piped output
* - quit with no error (0).
*/
void blc_quit();
END_EXTERN_C
#endif
///@}
/* Basic Library for C/C++ (blclib)
Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2014)
Author: Arnaud Blanchard
This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
 users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
 In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
 that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured
 and, more generally, to use and operate it in the same conditions as regards security.
 The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms. */
#include "blc_command.h"
#include "blc_realtime.h" //us_
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <termios.h>
#include <getopt.h>
#include <signal.h>
#include <errno.h> //errno and EINT
#include <libgen.h> //basename
#include <unistd.h> //usleep
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include "blc_text.h"
#include "blc_tools.h"
#include "blc_program.h"
//Identical to argparse in Python
#define POSITIONAL_ARGUMENTS_TITLE "\npositional arguments:\n"
#define OPTIONAL_ARGUMENTS_TITLE "\noptional arguments:\n"
typedef void*(*type_pthread_cb)(void*);
typedef struct
{
const char *name;
type_blc_command_cb callback;
const char *prompt;
const char *help;
void *user_data;
}blc_command;
//typedef type_program_option_result;
enum {STRING, BLC_CHANNEL, INPUT_PIPE, OUTPUT_PIPE};
// This is a bit redundant with struct option but has we need to send an array of struct option to getopt_long, we need two independant arrays: one with struct option and one with type_program_option.
typedef struct {
int type;
union{
// blc_channel *channel;
FILE *pipe;
char const **string_pt;
};
char letter;
char const *name;
char const *parameter;
char const *help;
char const *default_value;
}type_program_option;
struct program_parameter{
int type;
union{
// blc_channel *channel;
FILE *pipe;
char const **string_pt;
};
char const *name;
int required_nb;
char const *help;
};
// Static means it is only existing in this file
static blc_command *blc_commands = NULL;
static int blc_commands_nb = 0;
static struct timeval timer;
static int iterations_nb=0;
static uint blc_period=0;
static uint blc_duration=0;
static long blc_current_duration;
long blc_command_loop_period;
START_EXTERN_C
void blc_command_display_help()
{
const blc_command *command;
size_t command_length_max = 0;
size_t command_length=0;
FOR_EACH(command, blc_commands, blc_commands_nb)
{
command_length = strlen(command->name);
if (command->prompt) command_length+=strlen(command->prompt)+2;
command_length_max = MAX(command_length, command_length_max);
}
FOR_EACH(command, blc_commands, blc_commands_nb)
{
if (command->prompt) fprintf(stderr, "%s<%s>%*c:%s\n", command->name, command->prompt, (int)(command_length_max - strlen(command->name)-strlen(command->prompt)-1), ' ', command->help);
else fprintf(stderr, "%-*s :%s\n", (int)command_length_max, command->name, command->help);
}
}
void blc_fprint_stats(FILE *file)
{
fprintf(file, "%d iterations, average duration: %.3fms, average frequency: %.3fHz period: %.3fms\n", iterations_nb, blc_duration/(1000.*iterations_nb), 1000000.*iterations_nb/(double)blc_period, blc_period/(1000.*iterations_nb));
iterations_nb=0;
blc_period=0;
blc_duration=0;
us_time_diff(&timer);
}
static void pause_cb()
{
if (blc_status==BLC_RUN){
blc_status=BLC_PAUSE;
fprintf(stderr, "=== %s: pause ===\n", blc_program_name);
blc_command_interpret();
}else {
fprintf(stderr, "=== %s: running ===\n", blc_program_name);
blc_status=BLC_RUN;
}
}
static void ask_quit(){
fprintf(stderr, "=== %s: quitting ===\n", blc_program_name);
blc_status=BLC_QUIT;
if (blc_command_loop_period==-2){ //thread
sleep(2);
fprintf(stderr, "=== %s: error program not quitting ! We force it. ===\n", blc_program_name);
exit(EXIT_FAILURE);
}
}
static void display_stats()
{
blc_fprint_stats(stderr);
}
void blc_command_add(const char *command_name, type_blc_command_cb callback, const char *prompt, const char *help, void *user_data){
blc_command tmp_command;
int i;
tmp_command.name = command_name;
tmp_command.callback = callback;
tmp_command.prompt = prompt;
tmp_command.help = help;
tmp_command.user_data = user_data;
FOR_INV(i, blc_commands_nb)
if (strcmp(blc_commands[i].name, command_name) == 0) EXIT_ON_ERROR("Command '%s' is already defined.", command_name);
APPEND_ITEM(&blc_commands, &blc_commands_nb, &tmp_command);
}
static void blc_command_interpret_block(){
blc_mem line, parameter;
size_t line_capability=0;
ssize_t tmp_size;
const blc_command *command;
int name_size;
do{
tmp_size = getline(&line.chars, &line_capability, stdin);
}while ((tmp_size==-1) && (errno==EINTR));
if (tmp_size==-1)
{
if (errno==0) exit(EXIT_SUCCESS); //stdin closed
else EXIT_ON_SYSTEM_ERROR("Command interpret: getline");
}
line.size=tmp_size-1;
line.chars[line.size]=0; // Removing the last return char (\n)
FOR_EACH_INV(command, blc_commands, blc_commands_nb)
{
name_size = strlen(command->name);
if (strncmp(command->name, line.chars, name_size) == 0)
{
parameter.chars = line.chars + name_size;
parameter.size = line.size - name_size;
if (parameter.size == 0) //No text after the command
{
parameter.data = NULL;
if (command->prompt != NULL) //A text was expected
{
fprintf(stderr, "%s:\n", command->prompt);
parameter.size = getline(&parameter.chars, &line_capability, stdin)-1;
parameter.chars[parameter.size]=0;
}
if (command->callback) command->callback( parameter.chars, command->user_data);
FREE(parameter.chars);
line_capability=0;
break;
}
else
{
if (command->prompt == NULL) continue; // If we do not wait for parameter, the command must be exact.
else command->callback( parameter.chars, command->user_data);
break;
}
}
}
if (command < blc_commands) fprintf(stderr, "Unknown command in: %s\n", line.chars);
}
void blc_command_interpret(){
fd_set rfds;
int retval=-1;
/* Surveiller stdin (fd 0) en attente d'entrées */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
//Block until there is data or there is an interuption (Ctrl+C, Terminate, ..) which is not the case with getline.
while (retval==-1){
retval = select(1, &rfds, NULL, NULL, NULL);
if (retval!=-1) blc_command_interpret_block();
else if (errno!=EINTR) EXIT_ON_SYSTEM_ERROR("Waiting to interpret a command");
}
}
int blc_command_try_to_interpret(){
fd_set rfds;
struct timeval time_val={0,0};
int retval;
/* Surveiller stdin (fd 0) en attente d'entrées */
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
SYSTEM_ERROR_CHECK(retval = select(STDIN_FILENO+1, &rfds, NULL, NULL, &time_val), -1, NULL);
if (retval) blc_command_interpret_block();
else return 0;
return 1;
}
/// if the parameter is not null we should display the help at each command.
static void *command_thread_interpret_loop(char const *){
while(blc_status==BLC_RUN){
blc_command_interpret();
}
return NULL;
}
void blc_command_interpret_thread(char const *option){
pthread_t thread;
blc_command_loop_period=-2;
if (strchr(option, 'h')) blc_command_add("h", (type_blc_command_cb)blc_command_display_help, NULL, "display this help", NULL);
if (strchr(option, 'q')) blc_command_add("q", (type_blc_command_cb)ask_quit, NULL, "quit the application", NULL);
SYSTEM_ERROR_CHECK(pthread_create(&thread, NULL, (type_pthread_cb)command_thread_interpret_loop, NULL), -1, NULL);
}
void blc_command_loop_init(long loop_period)
{
iterations_nb=0;
blc_command_loop_period=loop_period;
if (blc_input_terminal && (blc_command_loop_period!=-1) && (blc_command_loop_period!=-2)) blc_command_add("", (type_blc_command_cb)pause_cb, NULL, "set on/off pause", NULL);