Introduce CLI
main: Parse args using getopt_long() in main(). Begin implementation of a CLI. It can be launched using ./qswiki config --cli. Allow connecting to another instance using "attach" command. This uses Unix domain sockets, and in the future can be used to drop caches, reload template, etc. Closes: #21
Bu işleme şunda yer alıyor:
137
cliconsole.cpp
Normal dosya
137
cliconsole.cpp
Normal dosya
@@ -0,0 +1,137 @@
|
||||
#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";
|
||||
}
|
Yeni konuda referans
Bir kullanıcı engelle