Line data Source code
1 : // Copyright (c) 2022 The Bitcoin Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #if defined(HAVE_CONFIG_H) 6 : #include <config/bitcoin-config.h> 7 : #endif 8 : 9 : #include <common/run_command.h> 10 : 11 : #include <tinyformat.h> 12 : #include <univalue.h> 13 : 14 : #ifdef ENABLE_EXTERNAL_SIGNER 15 : #include <util/subprocess.hpp> 16 : #endif // ENABLE_EXTERNAL_SIGNER 17 : 18 7 : UniValue RunCommandParseJSON(const std::string& str_command, const std::string& str_std_in) 19 : { 20 : #ifdef ENABLE_EXTERNAL_SIGNER 21 : namespace sp = subprocess; 22 : 23 7 : UniValue result_json; 24 7 : std::istringstream stdout_stream; 25 7 : std::istringstream stderr_stream; 26 : 27 7 : if (str_command.empty()) return UniValue::VNULL; 28 : 29 6 : auto c = sp::Popen(str_command, sp::input{sp::PIPE}, sp::output{sp::PIPE}, sp::error{sp::PIPE}); 30 5 : if (!str_std_in.empty()) { 31 1 : c.send(str_std_in); 32 1 : } 33 15 : auto [out_res, err_res] = c.communicate(); 34 10 : stdout_stream.str(std::string{out_res.buf.begin(), out_res.buf.end()}); 35 10 : stderr_stream.str(std::string{err_res.buf.begin(), err_res.buf.end()}); 36 : 37 5 : std::string result; 38 5 : std::string error; 39 5 : std::getline(stdout_stream, result); 40 5 : std::getline(stderr_stream, error); 41 : 42 5 : const int n_error = c.retcode(); 43 5 : if (n_error) throw std::runtime_error(strprintf("RunCommandParseJSON error: process(%s) returned %d: %s\n", str_command, n_error, error)); 44 3 : if (!result_json.read(result)) throw std::runtime_error("Unable to parse JSON: " + result); 45 : 46 2 : return result_json; 47 : #else 48 : throw std::runtime_error("Compiled without external signing support (required for external signing)."); 49 : #endif // ENABLE_EXTERNAL_SIGNER 50 6 : }