mirror of
https://github.com/EvernodeXRPL/sashimono.git
synced 2026-04-29 15:38:00 +00:00
Sashimono CLI implementation (#38)
This commit is contained in:
143
sashi-cli/cli-manager.cpp
Normal file
143
sashi-cli/cli-manager.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "pchheader.hpp"
|
||||
#include "cli-manager.hpp"
|
||||
|
||||
namespace cli
|
||||
{
|
||||
constexpr const char *SOCKET_NAME = "sa.sock"; // Name of the sashimono socket.
|
||||
constexpr const char *DATA_DIR = "/etc/sashimono"; // Sashimono data directory.
|
||||
constexpr const int BUFFER_SIZE = 1024; // Max read buffer size.
|
||||
|
||||
cli_context ctx;
|
||||
|
||||
bool init_success = false;
|
||||
|
||||
/**
|
||||
* Initialize the socket and connect.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int init(std::string_view sashi_dir)
|
||||
{
|
||||
ctx.sashi_dir = sashi_dir;
|
||||
|
||||
// Get the socket path from available location.
|
||||
if (get_socket_path(ctx.socket_path) == -1)
|
||||
return -1;
|
||||
|
||||
// Create the seq paket socket.
|
||||
ctx.socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
|
||||
if (ctx.socket_fd == -1)
|
||||
{
|
||||
std::cerr << errno << " :Error while creating the sashimono socket.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_un addr;
|
||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, ctx.socket_path.data(), sizeof(addr.sun_path) - 1);
|
||||
|
||||
if (connect(ctx.socket_fd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1)
|
||||
{
|
||||
// If permission denied, show a custom error.
|
||||
if (errno == EACCES)
|
||||
std::cerr << "Permission denied: Only root or users in 'sashiadmin' group can access the sashimono socket.\n";
|
||||
else
|
||||
std::cerr << errno << " :Error while connecting to the sashimono socket.\n";
|
||||
close(ctx.socket_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
init_success = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate and return the sashimono agent socket path according predefined rules.
|
||||
* If sa.sock found on the same path as the cli binary, use that. (to support dev testing)
|
||||
* Else sa.sock found on /etc/sashimono, use that.
|
||||
* Else show error.
|
||||
* @param socket_path Socket path to be populated.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int get_socket_path(std::string &socket_path)
|
||||
{
|
||||
// Check whether socket exists in exec path.
|
||||
std::string path = ctx.sashi_dir + std::string("/") + SOCKET_NAME;
|
||||
struct stat st;
|
||||
if (stat(path.data(), &st) == 0 && S_ISSOCK(st.st_mode))
|
||||
{
|
||||
socket_path = path;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Otherwise check in the data dir.
|
||||
path = DATA_DIR + std::string("/") + SOCKET_NAME;
|
||||
memset(&st, 0, sizeof(struct stat));
|
||||
if (stat(path.data(), &st) == 0 && S_ISSOCK(st.st_mode))
|
||||
{
|
||||
socket_path = path;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cerr << SOCKET_NAME << " is not found.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a given message into the sashimono socket.
|
||||
* @param message Message to be write.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int write_to_socket(std::string_view message)
|
||||
{
|
||||
if (!init_success)
|
||||
{
|
||||
std::cerr << "Sashimono socket is not initialized.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write(ctx.socket_fd, message.data(), message.size()) == -1)
|
||||
{
|
||||
std::cerr << errno << " :Error while wrting to the sashimono socket.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read message from the sashimono socket.
|
||||
* @param message Message to be read.
|
||||
* @return Read message length on success, -1 on error.
|
||||
*/
|
||||
int read_from_socket(std::string &message)
|
||||
{
|
||||
if (!init_success)
|
||||
{
|
||||
std::cerr << "Sashimono socket is not initialized.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Resize the message to max length and resize to original read length after reading.
|
||||
message.resize(BUFFER_SIZE);
|
||||
const int res = read(ctx.socket_fd, message.data(), message.length());
|
||||
if (res == -1)
|
||||
{
|
||||
std::cerr << errno << " :Error while reading from the sashimono socket.\n";
|
||||
return -1;
|
||||
}
|
||||
message.resize(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the socket and deinitialize.
|
||||
*/
|
||||
void deinit()
|
||||
{
|
||||
if (init_success)
|
||||
close(ctx.socket_fd);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user