138 satır
2.9 KiB
C++
138 satır
2.9 KiB
C++
|
#include "cliconsole.h"
|
||
|
|
||
|
CLIConsole::CLIConsole(CLIHandler &cliHandler, std::string socketPath)
|
||
|
{
|
||
|
this->handler = &cliHandler;
|
||
|
this->socketPath = socketPath;
|
||
|
}
|
||
|
|
||
|
std::pair<bool, std::string> CLIConsole::send(std::string input)
|
||
|
{
|
||
|
ssize_t ret =
|
||
|
sendto(this->sock, input.c_str(), input.size(), 0, (const sockaddr *)&this->server, sizeof(this->server));
|
||
|
if((size_t)ret != input.size())
|
||
|
{
|
||
|
return {false, "sendto failed: " + std::to_string(ret) + " " + std::string(strerror(errno))};
|
||
|
}
|
||
|
char buffer[1024] = {0};
|
||
|
ret = recvfrom(this->sock, buffer, sizeof(buffer) - 1, 0, NULL, NULL);
|
||
|
if(ret == -1)
|
||
|
{
|
||
|
return {false, "recvfrom failed: " + std::string(strerror(errno))};
|
||
|
}
|
||
|
|
||
|
bool success = false;
|
||
|
std::string_view view = buffer;
|
||
|
if(view[0] == '1')
|
||
|
{
|
||
|
success = true;
|
||
|
}
|
||
|
view.remove_prefix(1);
|
||
|
std::string msg = std::string{view};
|
||
|
|
||
|
return {success, msg};
|
||
|
}
|
||
|
|
||
|
void CLIConsole::attach()
|
||
|
{
|
||
|
if(attached)
|
||
|
{
|
||
|
std::cout << "Already attached" << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
if(socketPath.size() > sizeof(this->server.sun_path) - 1)
|
||
|
{
|
||
|
std::cout << "Socket path too long" << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
memset(&this->server, 0, sizeof(this->server));
|
||
|
this->server.sun_family = AF_UNIX;
|
||
|
memcpy(&this->server.sun_path, socketPath.c_str(), socketPath.size());
|
||
|
this->server.sun_path[socketPath.size()] = 0;
|
||
|
|
||
|
int s = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||
|
if(s == -1)
|
||
|
{
|
||
|
std::cout << "Failed to create socket" << strerror(errno) << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
this->sock = s;
|
||
|
|
||
|
struct sockaddr_un client;
|
||
|
client.sun_family = AF_UNIX;
|
||
|
client.sun_path[0] = '\0';
|
||
|
|
||
|
int ret = bind(this->sock, (struct sockaddr *)&client, sizeof(client));
|
||
|
if(ret != 0)
|
||
|
{
|
||
|
std::cout << "bind() failed: " << strerror(errno) << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
auto result = this->send("attach");
|
||
|
if(result.first)
|
||
|
{
|
||
|
std::cout << "Attached successfully: " << result.second << std::endl;
|
||
|
this->attached = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
std::cout << "Attached unsuccessfully: " << result.second << std::endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CLIConsole::startInteractive()
|
||
|
{
|
||
|
std::cout << "qswiki CLI" << std::endl;
|
||
|
std::cout << "not attached - use 'attach' to connect to running instance" << std::endl;
|
||
|
|
||
|
while(true)
|
||
|
{
|
||
|
std::string input;
|
||
|
std::cout << "> ";
|
||
|
std::getline(std::cin, input);
|
||
|
|
||
|
if(std::cin.bad() || std::cin.eof())
|
||
|
{
|
||
|
std::cout << "Exiting" << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
if(input.empty())
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
auto pair = CLIHandler::splitCommand(input);
|
||
|
if(pair.first == "exit")
|
||
|
{
|
||
|
std::cout << "Exiting CLI";
|
||
|
exit(EXIT_SUCCESS);
|
||
|
}
|
||
|
if(pair.first == "attach")
|
||
|
{
|
||
|
attach();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
std::pair<bool, std::string> result;
|
||
|
if(!attached)
|
||
|
{
|
||
|
result = handler->processCommand(pair.first, pair.second);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result = this->send(input);
|
||
|
}
|
||
|
|
||
|
if(!result.second.empty())
|
||
|
{
|
||
|
std::cout << result.second << std::endl;
|
||
|
}
|
||
|
if(!result.first)
|
||
|
{
|
||
|
std::cout << "Command failed" << std::endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::cout << "\n";
|
||
|
}
|