diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a6f8316f64f3797d9d8fad784b80e872ad0ab3a..c7d294b2aaf918f6a0414c8243ac59b16d4ebb52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ find_package(blc_core REQUIRED) #source files set(sources src/blc_loop.cpp src/blc_program.cpp src/blc_command.cpp) -add_definitions(${BL_DEFINITIONS}) +add_definitions(${BL_DEFINITIONS} -std=c++14) include_directories(include ${BL_INCLUDE_DIRS}) #shared lib diff --git a/src/blc_loop.cpp b/src/blc_loop.cpp index dd895d0b9de01b46198d895f7c006735b85a972b..7cf82cec776e22598b4fc906ecfbbdc58eab5b97 100644 --- a/src/blc_loop.cpp +++ b/src/blc_loop.cpp @@ -1,6 +1,4 @@ -#include "blc_command.h" -#include "blc_realtime.h" #include <unistd.h> //sleep #include <errno.h> //errno #include <math.h> //pthread_mutex @@ -203,7 +201,6 @@ void blc_command_loop_init(long loop_period){ intermediate_iteration=0; blc_command_loop_period=loop_period; - //If blc_command_loop_period==2 we execute an iteration before stopping if (blc_command_loop_period==-2){ blc_command_loop_period=-1; } @@ -223,14 +220,13 @@ void blc_command_loop_init(long loop_period){ blc_command_add("s", (type_blc_command_cb)display_stats, NULL, "display time stats", NULL); //We did not do stat on keyboard fprintf(stderr, "=== %s: running ===\n", blc_program_id); } - blc_command_add("|", (type_blc_command_cb)blc_command_send_to_stdout, "command", "send the command to stdout", NULL); - blc_command_add("&", (type_blc_command_cb)blc_command_send_to_all, "command", "intepret caommdn and send it to stdout", NULL); + blc_command_add("|", (type_blc_command_cb)blc_command_send_to_stdout, "command", "sends the command to stdout", NULL); + blc_command_add("&", (type_blc_command_cb)blc_command_send_to_all, "command", "inteprets command and sends it to stdout", NULL); BLC_PTHREAD_CHECK(pthread_create(&loop_thread, NULL, command_thread_interpret_loop, NULL), NULL); } int blc_command_loop_start(){ - int continue_value; int i; //We wait before counting the duration time as the time for waiting does not matter diff --git a/src/blc_program.cpp b/src/blc_program.cpp index 627c3d25e430841c1e0262ab37d532081c72b998..5c00bcfd56c3037f18ded097a71262a92c19dfa9 100644 --- a/src/blc_program.cpp +++ b/src/blc_program.cpp @@ -105,7 +105,7 @@ void blc_program_add_parameter(char const**result, char const *name, int require parameter.required_nb=(required!=0); //At this moment only binary choices are possible parameter.help=help; parameter.default_value=default_value; - + APPEND_ITEM(&blc_program_parameters, &blc_program_parameters_nb, ¶meter); } @@ -113,18 +113,21 @@ void blc_program_add_multiple_parameters(char ***result_list, char const *name, { struct program_parameter parameter; + *result_list=nullptr; + parameter.type=STRING_LIST; parameter.string_list_pt=result_list; parameter.name=name; parameter.required_nb=required_nb; parameter.help=help; + parameter.default_value=nullptr; APPEND_ITEM(&blc_program_parameters, &blc_program_parameters_nb, ¶meter); } void blc_program_add_option(char const **result, char letter, char const *long_option, char const *parameter, char const *help, char const* default_value){ type_program_option tmp_program_option; - // if ((parameter) && (default_value)) EXIT_ON_ERROR("option '%s': you cannot required an parameter '%s' and having a default value '%s'", long_option, parameter, default_value); + // if ((parameter) && (default_value)) EXIT_ON_ERROR("option '%s': you cannot required an parameter '%s' and having a default value '%s'", long_option, parameter, default_value); tmp_program_option.type = STRING; tmp_program_option.string_pt = result; @@ -216,30 +219,30 @@ static void blc_program_option_interpret(int *argc, char **argv[]) } else{ switch (program_option->type){ - case STRING: + case STRING: *program_option->string_pt = optarg; break; //Pipe not in use anymore - case INPUT_PIPE: + case INPUT_PIPE: SPRINTF(pipe_name, "/tmp/blc_pipes/%s", optarg); SYSTEM_ERROR_CHECK(freopen(optarg, "r", program_option->pipe), NULL, NULL); break; - case OUTPUT_PIPE: + case OUTPUT_PIPE: mkdir("/tmp/blc_pipes", S_IRWXU); SPRINTF(pipe_name, "/tmp/blc_pipes/%s", optarg); if (mkfifo(pipe_name, S_IRWXU) !=0) + { + if (errno==EEXIST) { - if (errno==EEXIST) - { - SYSTEM_SUCCESS_CHECK(stat(pipe_name, &stat_data), 0, "Checking data of '%s'.", pipe_name); - if (stat_data.st_mode == S_IFIFO){ - SYSTEM_ERROR_CHECK(freopen(pipe_name, "w", program_option->pipe), NULL, NULL); - } - else EXIT_ON_ERROR("Cannot use '%s' as a output pipe.", pipe_name); + SYSTEM_SUCCESS_CHECK(stat(pipe_name, &stat_data), 0, "Checking data of '%s'.", pipe_name); + if (stat_data.st_mode == S_IFIFO){ + SYSTEM_ERROR_CHECK(freopen(pipe_name, "w", program_option->pipe), NULL, NULL); } - else EXIT_ON_SYSTEM_ERROR("Creating output pipe '%s'.", pipe_name); + else EXIT_ON_ERROR("Cannot use '%s' as a output pipe.", pipe_name); } + else EXIT_ON_SYSTEM_ERROR("Creating output pipe '%s'.", pipe_name); + } break; default:EXIT_ON_ERROR("Type %d not managed.", program_option->type); } @@ -257,7 +260,7 @@ static void blc_program_option_interpret(int *argc, char **argv[]) FOR_EACH_INV(program_option, blc_program_options, blc_program_options_nb) { switch (program_option->type){ - case STRING: + case STRING: if (*program_option->string_pt==NULL) *program_option->string_pt=(char*)program_option->default_value; break; } @@ -273,21 +276,22 @@ static void blc_program_interpret_parameters(int *argc, char **argv[]){ int i, j; size_t linecap; ssize_t parameter_read; + int list_parameters_nb=0; FOR(i, blc_program_parameters_nb){ switch(blc_program_parameters[i].type){ - case STRING : + case STRING : if ((*argc)==0){//There is no more argument to interpret if (blc_program_parameters[i].required_nb){ if (isatty(STDIN_FILENO)) fprintf(stderr, "%s: %s? ", blc_program_parameters[i].help, blc_program_parameters[i].name); - + parameter_read=getline(&tmp_parameter, &linecap, stdin); if (parameter_read==-1){ - if (errno==ENOTTY) { - color_eprintf(BLC_RED, "Quitting '%s': The standard input is not available. You probably have a program on an input pipe which has crashed\n", blc_program_id); - exit(1); - } - else EXIT_ON_SYSTEM_ERROR("Reading input for parameter"); + if (errno==ENOTTY) { + color_eprintf(BLC_RED, "Quitting '%s': The standard input is not available. You probably have a program on an input pipe which has crashed\n", blc_program_id); + exit(1); + } + else EXIT_ON_SYSTEM_ERROR("Reading input for parameter"); } tmp_parameter[parameter_read-1]=0;//Remove the last return; (*blc_program_parameters[i].string_pt)=tmp_parameter; @@ -304,7 +308,7 @@ static void blc_program_interpret_parameters(int *argc, char **argv[]){ } break; - case STRING_LIST: EXIT_ON_ERROR("STRING LIST is not yet managed"); + case STRING_LIST: if (isatty(STDIN_FILENO)) { missing_parameters_nb = blc_program_parameters[i].required_nb-(*argc-optind-i); if (missing_parameters_nb>0){ @@ -320,8 +324,35 @@ static void blc_program_interpret_parameters(int *argc, char **argv[]){ argc--;//The last NULL parameter does not count } } - else EXIT_ON_ERROR("Missing '%s' arguments : %s you must have %d arguments", blc_program_parameters[i].name, blc_program_parameters[i].help, missing_parameters_nb); - *(blc_program_parameters[i].string_list_pt)=&(*argv)[i+optind]; + else { + do{ + parameter_read=getline(&tmp_parameter, &linecap, stdin); + if (parameter_read==-1){ + if (errno==ENOTTY) { + color_eprintf(BLC_RED, "Quitting '%s': The standard input is not available. You probably have a program on an input pipe which has crashed\n", blc_program_id); + exit(1); + } + else EXIT_ON_SYSTEM_ERROR("Reading input for parameter"); + } + tmp_parameter[parameter_read-1]=0;//Remove the last return; + APPEND_ITEM(blc_program_parameters[i].string_list_pt, &list_parameters_nb, tmp_parameter); + linecap=0; + fprintf(stderr, "Parameters '%s' %ld\n", tmp_parameter, parameter_read ); + tmp_parameter=nullptr; + } + while(parameter_read>0); + }//EXIT_ON_ERROR("Missing '%s' arguments : %s you must have %d arguments", blc_program_parameters[i].name, blc_program_parameters[i].help, missing_parameters_nb); + + if (blc_program_parameters[i].required_nb==-1){ + while((*argc)){ + APPEND_ITEM((blc_program_parameters[i].string_list_pt), &list_parameters_nb, **argv); + (*argc)--; + (*argv)++; + } + } + else EXIT_ON_ERROR("Precise number of parameter is not managed"); + APPEND_ITEM(blc_program_parameters[i].string_pt, &list_parameters_nb, tmp_parameter); + break; } } @@ -399,9 +430,9 @@ void blc_program_args_display_help() fprintf(stderr, "%*c", option_length_max - tmp_length, ' '); fprintf(stderr, "%s", program_option->help); if (program_option->default_value) { - // if (program_option->type==BLC_CHANNEL) fprintf(stderr, " (default: %s<pid>)\n", program_option->default_value); - // else - fprintf(stderr, " (default: %s)\n", program_option->default_value); + // if (program_option->type==BLC_CHANNEL) fprintf(stderr, " (default: %s<pid>)\n", program_option->default_value); + // else + fprintf(stderr, " (default: %s)\n", program_option->default_value); } else fprintf(stderr, "\n"); } @@ -521,6 +552,6 @@ void blc_quit() fprintf(stderr, "Quitting %s\n", blc_program_id); FREE(blc_program_id); } - + } END_EXTERN_C diff --git a/t_interactive/CMakeLists.txt b/t_interactive/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ace3f53a53415963fc7c46e2aa5b196c5cf791d3 --- /dev/null +++ b/t_interactive/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2016) +# Author: Arnaud Blanchard (November 2016) +# +# 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(t_interactive) + +find_package(blc_program REQUIRED) + +#Add your definitions, include directories, sources and libraries now +add_definitions(${BL_DEFINITIONS}) +include_directories(${BL_INCLUDE_DIRS}) +add_executable(t_interactive t_interactive.cpp) +target_link_libraries(t_interactive ${BL_LIBRARIES}) diff --git a/t_interactive/t_interactive.cpp b/t_interactive/t_interactive.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ea4eec092acdee7e09295a6f5ec0e81e64ea895 --- /dev/null +++ b/t_interactive/t_interactive.cpp @@ -0,0 +1,32 @@ +/*Demonstration of blc_program API*/ + +#include "blc_program.h" + +void display_test_text(char const*, void*user_data){ + char const* text_to_display=(char const*)user_data; + + fprintf(stderr, "\nTEST:%s\n\n", text_to_display); +} + +void display_argument(char const* argument, void*user_data){ + fprintf(stderr, "\nARGUMENT:%s\n\n", argument); +} + +int main( int argc, char **argv){ + char const*data_to_pass="Here the text to display"; + + fprintf(stderr, "Test BLC_COMMAND_LOOP\n"); + + blc_command_add("t", display_test_text, NULL, "Call a function which display the test text", (void*)data_to_pass); + blc_command_add("a", display_argument, "argument to display", "Call a function which display the text passed as argument", NULL); + + //Wait for keyboard and loop till 'q' or Ctrl-C + //-2 execute the loop once and wait for keboard + //-1 wait for keyboard + //>=0 loop without blocking at the period given in µs (0 as fast as possible) + + BLC_COMMAND_LOOP(-2){ + blc_command_display_help(); + } + return EXIT_SUCCESS; +} diff --git a/t_interactive/test_result.log b/t_interactive/test_result.log new file mode 100644 index 0000000000000000000000000000000000000000..aa121f4a14453f8d1aa9b3c0f787b1429d76d5b8 --- /dev/null +++ b/t_interactive/test_result.log @@ -0,0 +1,19 @@ +Display help: + +usage: t_parse_args [-f] [-s string] string [string] + +Program to show how to parse arguments. + +positional arguments: + string Required parameter + string Show how to accept simple text as option + +optional arguments: + -f, --flag Show how to read a flag + -s, --simple string Simple text as option (default: Default text) + +Parsed arguments: +- The simple option text is: 'Default text' +- The flag is not activated. +- The first argument is: 'arg1' +- The optional argument is: 'arg2'