device_manager_4_linux/lib/libsources/cns.cpp

216 lines
7.6 KiB
C++
Executable File

//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//
//
// Copyright © 2019 Sasko Usinov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//
#include "api.h"
#include "liblogman/log_manager.h"
#include <iostream>
#include <string>
#include <sstream>
#include <sys/klog.h>
#include <sys/stat.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <array>
api::log_manager api::cns::g_out, api::cns::g_err(api::log_manager::level_err);;
//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Returns a list of supported terminals that we can use
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
std::vector<std::string> api::cns::get_supported_terminals()
{
std::vector<std::string> term_list;
term_list.push_back("xterm");
term_list.push_back("xfce4-terminal");
term_list.push_back("gnome-terminal");
term_list.push_back("konsole");
term_list.push_back("terminator");
term_list.push_back("tilix");
term_list.push_back("mate-terminal");
return term_list;
}
//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Returns a terminal that we can use
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
std::string api::cns::get_preferred_terminal()
{
std::string out;
//------------------------------------------------------------------------------------------------
// Warning! Do not add lxterminal - the version I tested did not work properly with "-e"
// when you add quotations etc
//------------------------------------------------------------------------------------------------
std::vector<std::string> term_list = get_supported_terminals();
for (size_t i = 0; i < term_list.size(); i++)
{
std::string t = "which " + term_list[i] + " > /dev/null";
if (!system(t.c_str()))
out = term_list[i];
}
return out;
}
//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Runs a console command, waits for the process to finish and returns the output
// output_dir is the destination path for the temporary files
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
api::cns::runstruct api::cns::exec(const std::string & cmd, const std::string & output_dir)
{
runstruct out;
out.tmp_dir = output_dir;
std::string tmpname_out {api::fs::generate_unique_filename(out.tmp_dir, "tmpfile_out")};
std::string tmpname_err {api::fs::generate_unique_filename(out.tmp_dir, "tmpfile_err")};
std::string run_cmd {std::string("bash -c \"" + SHELL_PATH + " && " + cmd + " > " + tmpname_out + " 2>" + tmpname_err + "\"").c_str()};
out.exit_code = system(run_cmd.c_str());
out.std_out = api::fs::load_from_file(tmpname_out);
out.std_err = api::fs::load_from_file(tmpname_err);
return out;
}
//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Runs a console command, waits for the process to finish and returns the output
// output_dir is the destination path for the temporary files
//
// Remarks: Something experimental I was working on.
//
// I have a real-time version using forkpty and execvp but we don't need it here.
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
api::cns::runstruct api::cns::exec_ext(const std::string & cmd, const std::string & output_dir)
{
runstruct out;
out.tmp_dir = output_dir;
std::string tmpname_out = api::fs::generate_unique_filename(out.tmp_dir, "tmpfile_out");
std::string tmpname_err = api::fs::generate_unique_filename(out.tmp_dir, "tmpfile_err");
std::string script_path {api::fs::generate_unique_filename(out.tmp_dir, "_tmpfile_s_")};
std::vector<std::string> script {};
script.push_back("#!/bin/bash");
script.push_back(SHELL_PATH);
script.push_back(std::string(cmd + " > " + tmpname_out + " 2>" + tmpname_err).c_str());
if (!api::fs::save_to_file(script_path, api::vct::to_string(script, '\n')))
return out; // perhaps raise an exception
if (system(("chmod u+x " + script_path).c_str()))
return out; // perhaps raise an exception
out.exit_code = system(script_path.c_str());
out.std_out = api::fs::load_from_file(tmpname_out);
out.std_err = api::fs::load_from_file(tmpname_err);
return out;
}
//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Runs a console command and returns its output
//
// Remarks: I have a version that's using forkpty and execvp that captures
// the output in real time but it's not currently needed in this project...
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
std::string api::cns::run(const std::string & cmd)
{
std::array <char, 256> buffer;
std::string result;
std::shared_ptr <FILE> sptr(popen(cmd.c_str(), "r"), pclose);
if (!sptr) return std::string("");
while (!feof(sptr.get()))
{
if (fgets(buffer.data(), 128, sptr.get()) != nullptr)
result += buffer.data();
}
return result;
}