diff --git a/apps/cli/cli_pipe.c b/apps/cli/cli_pipe.c index 9c653a2b..f2759027 100644 --- a/apps/cli/cli_pipe.c +++ b/apps/cli/cli_pipe.c @@ -72,15 +72,12 @@ #include "clixon_cli_api.h" -/* Grep pipe output function +/* General-purpose pipe output function * * @param[in] h Clixon handle * @param[in] cmd Command to exec * @param[in] option Option to command (or NULL) * @param[in] value Command argument value (or NULL) - * @code - * grep , grep_fn("-e", "arg"); - * @endcode */ int pipe_arg_fn(clixon_handle h, @@ -344,6 +341,57 @@ pipe_showas_fn(clixon_handle h, return retval; } +/*! pipe function: save to file + * + * @param[in] h Clixon handle + * @param[in] cvv Vector of cli string and instantiated variables + * @param[in] argv String vector of options. Format: + * @retval 0 OK + * @retval -1 Error + */ +int +pipe_save_file(clixon_handle h, + cvec *cvv, + cvec *argv) +{ + int retval = -1; + cg_var *cv; + char *str; + char *argname = NULL; + char *filename = NULL; + int fd; + + if (cvec_len(argv) != 1){ + clixon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: ", cvec_len(argv)); + goto done; + } + if ((cv = cvec_i(argv, 0)) != NULL && + (str = cv_string_get(cv)) != NULL && + strlen(str)){ + argname = str; + } + if (argname && strlen(argname)){ + if ((cv = cvec_find_var(cvv, argname)) != NULL && + (str = cv_string_get(cv)) != NULL && + strlen(str)) + filename = str; + } + if (filename){ + if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0){ + clixon_err(OE_CFG, errno, "creat(%s)", filename); + goto done; + } + close(1); + if (dup2(fd, STDOUT_FILENO) < 0){ + clixon_err(OE_UNIX, errno, "dup2(STDOUT)"); + return -1; + } + return pipe_arg_fn(h, CAT_BIN, NULL, NULL); + } + done: + return retval; +} + /*! Test cli callback calls cligen_output with output lines as given by function arguments * * Only for test or debugging to generate output to eg cligen_output scrolling diff --git a/configure b/configure index 8c972c87..fda5ea2f 100755 --- a/configure +++ b/configure @@ -651,6 +651,7 @@ LIBOBJS CLICON_GROUP CLICON_USER CLIGEN_DIR +CAT_BIN WC_BIN TAIL_BIN GREP @@ -5904,6 +5905,54 @@ fi printf "%s\n" "#define WC_BIN \"$WC_BIN\"" >>confdefs.h +# Extract the first word of "cat", so it can be a program name with args. +set dummy cat; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_CAT_BIN+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $CAT_BIN in + [\\/]* | ?:[\\/]*) + ac_cv_path_CAT_BIN="$CAT_BIN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_CAT_BIN="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CAT_BIN=$ac_cv_path_CAT_BIN +if test -n "$CAT_BIN"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CAT_BIN" >&5 +printf "%s\n" "$CAT_BIN" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +printf "%s\n" "#define CAT_BIN \"$CAT_BIN\"" >>confdefs.h + # Get "bison" from bison -y or other string if test "$YACC" = "${YACC##bison}" ; then diff --git a/configure.ac b/configure.ac index ecba85d4..77820bb4 100644 --- a/configure.ac +++ b/configure.ac @@ -162,6 +162,8 @@ AC_PATH_PROG(TAIL_BIN, tail) AC_DEFINE_UNQUOTED(TAIL_BIN, "$TAIL_BIN", [tail binary]) AC_PATH_PROG(WC_BIN, wc) AC_DEFINE_UNQUOTED(WC_BIN, "$WC_BIN", [wc binary]) +AC_PATH_PROG(CAT_BIN, cat) +AC_DEFINE_UNQUOTED(CAT_BIN, "$CAT_BIN", [cat binary]) # Get "bison" from bison -y or other string if test "$YACC" = "${YACC##bison}" ; then diff --git a/example/main/README.md b/example/main/README.md index 82cca145..957ac7a4 100644 --- a/example/main/README.md +++ b/example/main/README.md @@ -111,6 +111,17 @@ cli> show configuration 42 +cli> show configuration | show json +{ + "clixon-example:table": { + "parameter": [ + { + "name": "a", + "value": "42" + } + ] + } +} cli> delete interfaces interface eth1table parameter a cli> commit ``` diff --git a/example/main/example_pipe.cli b/example/main/example_pipe.cli index 7ea49e85..3b85329d 100644 --- a/example/main/example_pipe.cli +++ b/example/main/example_pipe.cli @@ -43,5 +43,5 @@ CLICON_MODE="|example_pipe"; # Must start with | json("JSON"), pipe_showas_fn("json"); text("Text curly braces"), pipe_showas_fn("text"); } -# save("Save configuration to file") ("Filename (local filename)"), save_config_file("candidate","filename", "xml"); # XXX + save("Save configuration to file") ("Filename (local filename)"), pipe_save_file("filename"); } diff --git a/include/clixon_config.h.in b/include/clixon_config.h.in index 32b8430e..bc265017 100644 --- a/include/clixon_config.h.in +++ b/include/clixon_config.h.in @@ -1,5 +1,8 @@ /* include/clixon_config.h.in. Generated from configure.ac by autoheader. */ +/* cat binary */ +#undef CAT_BIN + /* Pass-through $bindir */ #undef CLIXON_CONFIG_BINDIR