lundi 20 juin 2022

How to store command output and exitcode from terminal in a variable

From here I have the code that gives me the command line output and the exit code. Unfortunately I don't understand much of that operator overloading and if I try to rewrite it to the simple code I know (with global variables i.e.) I always get the wrong exit code status of 0.

So how can I modify the following code so I can store the output and the exit code status for future use?

#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>


struct CommandResult {
    std::string output;
    int exitstatus;

    friend std::ostream &operator<<(std::ostream &os, const CommandResult &result) {
        os << "command exitstatus: " << result.exitstatus << " output: " << result.output;
        return os;
    }
    bool operator==(const CommandResult &rhs) const {
        return output == rhs.output &&
               exitstatus == rhs.exitstatus;
    }
    bool operator!=(const CommandResult &rhs) const {
        return !(rhs == *this);
    }
};


class Command {

public:
    /**
     * Execute system command and get STDOUT result.
     * Like system() but gives back exit status and stdout.
     * @param command system command to execute
     * @return CommandResult containing STDOUT (not stderr) output & exitstatus
     * of command. Empty if command failed (or has no output). If you want stderr,
     * use shell redirection (2&>1).
     */
    static CommandResult exec(const std::string &command) {
        int exitcode = 255;
        std::array<char, 1048576> buffer {};
        std::string result;
#ifdef _WIN32
#define popen _popen
#define pclose _pclose
#define WEXITSTATUS
#endif
        FILE *pipe = popen(command.c_str(), "r");
        if (pipe == nullptr) {
            throw std::runtime_error("popen() failed!");
        }
        try {
            std::size_t bytesread;
            while ((bytesread = fread(buffer.data(), sizeof(buffer.at(0)), sizeof(buffer), pipe)) != 0) {
                result += std::string(buffer.data(), bytesread);
            }
        } catch (...) {
            pclose(pipe);
            throw;
        }
        exitcode = WEXITSTATUS(pclose(pipe));
        return CommandResult{result, exitcode};
    }
};

int main ()
{
    std::cout << Command::exec("echo blablub") << std::endl;
}

Here is my code, the global variable is correct in the function but is overwritten afterwards.

#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>

int exitcode = 555;

std::string exec(const std::string cmd) {
    
    int exitcode = 255;
    std::array<char, 128> buffer {};
    std::string result;
    
    
    #ifdef _WIN32
    #define popen _popen
    #define pclose _pclose
    #define WEXITSTATUS
    #endif
    
    
    FILE *pipe = popen(cmd.c_str(), "r");
    if (pipe == nullptr) {
        throw std::runtime_error("popen() failed!");
    }
    try {
        std::size_t bytesread;
        while ((bytesread = fread(buffer.data(), sizeof(buffer.at(0)), sizeof(buffer), pipe)) != 0) {
            result += std::string(buffer.data(), bytesread);
        }
    } catch (...) {
        pclose(pipe);
        throw;
    }    
    
    exitcode = WEXITSTATUS(pclose(pipe));
    std::cout<<exitcode<<'\n';
    return result;
}



int main (){
    exec("echo bla");
    std::cout<<exitcode<<'\n';
}

Aucun commentaire:

Enregistrer un commentaire