diff options
author | John Estabrook <jestabro@vyos.io> | 2024-10-23 19:48:31 -0500 |
---|---|---|
committer | John Estabrook <jestabro@vyos.io> | 2024-10-23 19:48:31 -0500 |
commit | 9d4787256f6b300927e7892047313d725787d828 (patch) | |
tree | 670a9875fdec008ff7f5089d5e930eaf04299ad4 | |
parent | 3e16a23768680d95090e5c1d75a19395980e0a91 (diff) | |
download | vyatta-cfg-9d4787256f6b300927e7892047313d725787d828.tar.gz vyatta-cfg-9d4787256f6b300927e7892047313d725787d828.zip |
T6717: add redirect_stdout
Legacy set/delete methods write errors to stdout; capture for
redirection in return value.
-rw-r--r-- | src/vy_adapter.cpp | 104 | ||||
-rw-r--r-- | src/vy_adapter.h | 4 |
2 files changed, 99 insertions, 9 deletions
diff --git a/src/vy_adapter.cpp b/src/vy_adapter.cpp index 793728f..dd66dfb 100644 --- a/src/vy_adapter.cpp +++ b/src/vy_adapter.cpp @@ -21,12 +21,83 @@ #include <iostream> #include <cstdint> #include <cassert> +#include <fcntl.h> +#include <unistd.h> #include <cstore/cstore.hpp> #include <vy_adapter.h> using namespace cstore; +enum PIPES { READ, WRITE }; + +extern FILE *out_stream; + +class stdout_redirect { + public: + stdout_redirect(): old_stdout(0), redirecting(false) { + out_pipe[READ] = 0; + out_pipe[WRITE] = 0; + if (pipe(out_pipe) == -1) { + return; + } + + old_stdout = dup(fileno(stdout)); + setbuf(stdout, NULL); + dup2(out_pipe[WRITE], fileno(stdout)); + + redirecting = true; + } + + std::string get_redirected_output() { + if (!redirecting) { + return ""; + } + + char buffer[1024]; + ssize_t bytesRead = 0; + std::string redirected_output = "\n"; + fcntl(out_pipe[READ], F_SETFL, O_NONBLOCK); + while ((bytesRead = read(out_pipe[READ], buffer, sizeof(buffer))) > 0) { + redirected_output.append(buffer, bytesRead); + } + + return redirected_output; + } + + ~stdout_redirect() { + if (!redirecting) { + return; + } + + dup2(old_stdout, fileno(stdout)); + + if (old_stdout > 0) { + close(old_stdout); + } + if (out_pipe[READ] > 0) { + close(out_pipe[READ]); + } + if (out_pipe[WRITE] > 0) { + close(out_pipe[WRITE]); + } + } + + private: + int out_pipe[2]; + int old_stdout; + bool redirecting; +}; + +const char *out_data_copy(std::string msg) +{ + size_t len = msg.length(); + char *out_data = (char *) malloc(len + 1); + msg.copy(out_data, len); + out_data[len] = '\0'; + return out_data; +} + static uint64_t uint_of_voidptr(void* p) { assert (((uintptr_t) p & 1) == 0); @@ -64,39 +135,58 @@ vy_in_session(uint64_t handle) return h->inSession() ? 1 : 0; } -int +const char * vy_set_path(uint64_t handle, const void** path_ptr, size_t len) { Cstore *cstore = cstore_of_handle(handle); const char **path = (const char **) path_ptr; Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; int res; + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + res = cstore->validateSetPath(path_comps); if (!res) { - return 1; + out_str = "\nInvalid set path: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + goto out; } res = cstore->setCfgPath(path_comps); if (!res) { - return 2; + out_str = "\nSet config path failed: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); } - return 0; +out: + out_data = out_data_copy(out_str); + out_stream = NULL; + return out_data; } -int +const char * vy_delete_path(uint64_t handle, const void** path_ptr, size_t len) { Cstore *cstore = cstore_of_handle(handle); const char **path = (const char **) path_ptr; Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; int res; + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + res = cstore->deleteCfgPath(path_comps); if (!res) { - return 1; + out_str = "\nDelete failed: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); } - return 0; + out_data = out_data_copy(out_str); + out_stream = NULL; + return out_data; } diff --git a/src/vy_adapter.h b/src/vy_adapter.h index 8e0f376..fba6368 100644 --- a/src/vy_adapter.h +++ b/src/vy_adapter.h @@ -22,8 +22,8 @@ extern "C" { uint64_t vy_cstore_init(void); void vy_cstore_free(uint64_t); int vy_in_session(uint64_t); -int vy_set_path(uint64_t, const void **, size_t); -int vy_delete_path(uint64_t, const void **, size_t); +const char *vy_set_path(uint64_t, const void **, size_t); +const char *vy_delete_path(uint64_t, const void **, size_t); #ifdef __cplusplus } |