#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/climanager.h" #include "../include/jsonhandler.h" using namespace std; namespace CliManager { QMLHandler *qmlHandler; bool programActive = true; int inpipefd[2]; int outpipefd[2]; char buf[1025]; pid_t childpid; } // namespace CliManager void CliManager::writeToCli(QString command) { command += "\n"; write(outpipefd[1], command.toUtf8().constData(), strlen(command.toUtf8().constData())); } void CliManager::onExit() { writeToCli("exit"); } void CliManager::setQmlHandler(QMLHandler *q) { qmlHandler = q; } void CliManager::startCli() { pipe(inpipefd); pipe(outpipefd); childpid = fork(); if (childpid == 0) { // Child dup2(outpipefd[0], STDIN_FILENO); dup2(inpipefd[1], STDOUT_FILENO); // dup2(inpipefd[1], STDERR_FILENO); // ask kernel to deliver SIGTERM in case the parent dies prctl(PR_SET_PDEATHSIG, SIGTERM); execl(Config::getValue("CLI-Path").c_str(), "ccats-cli", "--machine", (char *)NULL); exit(1); } close(outpipefd[0]); close(inpipefd[1]); std::thread(&CliManager::readPipeLoop).detach(); } std::vector tokenizeByNewlines(std::string in) { vector res; size_t index; for (index = in.find("\n"); index != std::string::npos; index = in.find("\n")) { if (index != 0) res.push_back(in.substr(0, index)); in = in.substr(index + 1); } if (in.length() > 0) res.push_back(in); return res; } void CliManager::readPipeLoop() { unsigned int readOffset = 0; unsigned int pollCount = 0; struct pollfd inPipeStatus; inPipeStatus.fd = inpipefd[0]; inPipeStatus.events = POLLIN; vector inputs; string pipeInput; while (programActive) { inputs = vector(); poll(&inPipeStatus, 1, 100); if (inPipeStatus.revents & POLLIN) { readOffset += read(inpipefd[0], buf + readOffset, 1); pollCount = 0; } else { pollCount++; } if (pollCount > 4 && (readOffset || pipeInput.size())) { pipeInput.append(buf); inputs = tokenizeByNewlines(pipeInput); for (string s : inputs) { emit qmlHandler->log(QString::fromStdString(s)); qInfo() << QString::fromStdString(s); // handleJSON(s); JsonHandler::parseJSON(s); } pipeInput = string(); memset(buf, 0, 1025); pollCount = 0; readOffset = 0; if (waitpid(childpid, NULL, WNOHANG)) { // nonzero means error or childid has changed state // for us that means child has exited -> CLI is dead break; } } if (readOffset >= 1024) { pipeInput.append(buf); readOffset = 0; pollCount = 0; memset(buf, 0, 1025); } } } void CliManager::setProgramActive(bool active) { programActive = active; }