Compare commits

..

No commits in common. "lcpex_enhancements" and "master" have entirely different histories.

9 changed files with 124 additions and 672 deletions

View File

@ -3,5 +3,4 @@ project(rex)
set(CMAKE_CXX_STANDARD 14)
add_executable(rex Rex.cpp src/json_support/jsoncpp/json.h src/json_support/jsoncpp/json-forwards.h src/json_support/jsoncpp/jsoncpp.cpp src/logger/Logger.cpp src/logger/Logger.h src/json_support/JSON.cpp src/json_support/JSON.h src/misc/helpers.cpp src/misc/helpers.h src/config/Config.cpp src/config/Config.h src/suite/Suite.cpp src/suite/Suite.h src/suite/Unit.cpp src/suite/Unit.h src/shells/shells.cpp src/shells/shells.h src/plan/Plan.cpp src/plan/Plan.h src/plan/Task.cpp src/plan/Task.h src/lcpex/helpers.h src/lcpex/helpers.cpp src/lcpex/liblcpex.h src/lcpex/liblcpex.cpp src/lcpex/vpty/libclpex_tty.h src/lcpex/vpty/libclpex_tty.cpp src/lcpex/Contexts.h src/lcpex/Contexts.cpp src/lcpex/helpers.h src/lcpex/string_expansion/string_expansion.h src/lcpex/string_expansion/string_expansion.cpp src/lcpex/vpty/pty_fork_mod/pty_fork.h src/lcpex/vpty/pty_fork_mod/pty_fork.cpp src/lcpex/vpty/pty_fork_mod/pty_master_open.h src/lcpex/vpty/pty_fork_mod/pty_master_open.cpp src/lcpex/vpty/pty_fork_mod/tty_functions.h src/lcpex/vpty/pty_fork_mod/tty_functions.cpp
src/lcpex/FileHandle.h)
add_executable(rex Rex.cpp src/json_support/jsoncpp/json.h src/json_support/jsoncpp/json-forwards.h src/json_support/jsoncpp/jsoncpp.cpp src/logger/Logger.cpp src/logger/Logger.h src/json_support/JSON.cpp src/json_support/JSON.h src/misc/helpers.cpp src/misc/helpers.h src/config/Config.cpp src/config/Config.h src/suite/Suite.cpp src/suite/Suite.h src/suite/Unit.cpp src/suite/Unit.h src/shells/shells.cpp src/shells/shells.h src/plan/Plan.cpp src/plan/Plan.h src/plan/Task.cpp src/plan/Task.h src/lcpex/helpers.h src/lcpex/helpers.cpp src/lcpex/liblcpex.h src/lcpex/liblcpex.cpp src/lcpex/vpty/libclpex_tty.h src/lcpex/vpty/libclpex_tty.cpp src/lcpex/Contexts.h src/lcpex/Contexts.cpp src/lcpex/helpers.h src/lcpex/string_expansion/string_expansion.h src/lcpex/string_expansion/string_expansion.cpp src/lcpex/vpty/pty_fork_mod/pty_fork.h src/lcpex/vpty/pty_fork_mod/pty_fork.cpp src/lcpex/vpty/pty_fork_mod/pty_master_open.h src/lcpex/vpty/pty_fork_mod/pty_master_open.cpp src/lcpex/vpty/pty_fork_mod/tty_functions.h src/lcpex/vpty/pty_fork_mod/tty_functions.cpp )

View File

@ -1,54 +0,0 @@
#pragma once
#include <unistd.h> // for close()
// Simplified RAII wrapper for file descriptors (C-style compatible)
class FdGuard {
int fd_;
public:
// Constructor
explicit FdGuard(int fd = -1) : fd_(fd) {}
// Disable copy semantics
FdGuard(const FdGuard&) = delete;
FdGuard& operator=(const FdGuard&) = delete;
// Move constructor
FdGuard(FdGuard&& other) /* no noexcept */ {
fd_ = other.fd_;
other.fd_ = -1;
}
// Move assignment
FdGuard& operator=(FdGuard&& other) /* no noexcept */ {
if (this != &other) {
reset(); // Close current if valid
fd_ = other.fd_;
other.fd_ = -1;
}
return *this;
}
// Destructor
~FdGuard() {
close_if_valid();
}
// Reset with new fd (or close if -1)
void reset(int new_fd = -1) {
close_if_valid();
fd_ = new_fd;
}
// Get the raw fd
int get() const {
return fd_;
}
private:
void close_if_valid() {
if (fd_ != -1) {
::close(fd_);
fd_ = -1;
}
}
};

View File

@ -1,78 +1,6 @@
#include "liblcpex.h"
#include <cstring>
#include <stdexcept>
#include <signal.h>
#include <string>
#include "../logger/Logger.h"
#include "FileHandle.h"
#define BUFFER_SIZE 1024
// Initialize logger
static Logger logger(E_INFO, "lcpex");
std::string user = logger.get_user_name();
std::string group = logger.get_group_name();
// Global variables for signal handler context
static std::string g_task_context = "";
static std::string g_log_directory = "";
void signal_handler(int sig) {
std::string command = "signal_handler"; // Command context
// Create an instance of Logger (you can change the log level and mask accordingly)
// Log the signal handling
if (sig == SIGCHLD) {
// Log that SIGCHLD was received, but leave the exit status to the parent
logger.log_to_json_file("E_INFO", "SIGCHLD received. A child process ended.", user, group, command, g_task_context, g_log_directory);
} else if (sig == SIGINT) {
logger.log_to_json_file("E_FATAL", "SIGINT received. Gracefully terminating...", user, group, command, g_task_context, g_log_directory);
} else if (sig == SIGTERM) {
logger.log_to_json_file("E_FATAL", "SIGTERM received. Terminating...", user, group, command, g_task_context, g_log_directory);
} else if (sig == SIGSEGV) {
logger.log_to_json_file("E_FATAL", "SIGSEGV received. Possible segmentation fault.", user, group, command, g_task_context, g_log_directory);
} else {
logger.log_to_json_file("E_FATAL", "Unhandled signal received", user, group, command, g_task_context, g_log_directory);
}
}
// Setup signal registrations
void setup_signal_handlers(std::string task_context = "", std::string log_directory = "") {
// Set global variables for signal handler context
g_task_context = task_context;
g_log_directory = log_directory;
struct sigaction sa;
sa.sa_handler = signal_handler; // <-- handler function
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
std::string command = "setup_signal_handlers"; // Command context
// SIGCHLD
if (sigaction(SIGCHLD, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGCHLD handler: " + std::string(strerror(errno));
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory); // Log to JSON file
}
// SIGINT
if (sigaction(SIGINT, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGINT handler: " + std::string(strerror(errno));
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory); // Log to JSON file
}
// SIGTERM
if (sigaction(SIGTERM, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGTERM handler: " + std::string(strerror(errno));
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory); // Log to JSON file
}
// SIGSEGV
if (sigaction(SIGSEGV, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGSEGV handler: " + std::string(strerror(errno));
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory); // Log to JSON file
}
}
std::string prefix_generator(
std::string command,
bool is_shell_command,
@ -80,9 +8,7 @@ std::string prefix_generator(
std::string shell_execution_arg,
bool supply_environment,
std::string shell_source_subcommand,
std::string environment_file_path,
std::string task_context,
std::string log_directory
std::string environment_file_path
) {
std::string prefix = "";
if ( is_shell_command ) {
@ -111,12 +37,8 @@ std::string prefix_generator(
// it's not a shell command, so we can just execute it directly
prefix = command;
}
// Log the message to JSON file
logger.log_to_json_file("E_INFO", "LAUNCHER: " + prefix, user, group, command, task_context, log_directory);
//logger.log(E_INFO, "LAUNCHER: " + prefix);
std::cout << "LAUNCHER: " << prefix << std::endl;
return prefix;
}
@ -133,9 +55,7 @@ int lcpex(
std::string shell_execution_arg,
bool supply_environment,
std::string shell_source_subcommand,
std::string environment_file_path,
std::string task_context,
std::string log_directory
std::string environment_file_path
) {
// generate the prefix
@ -146,21 +66,18 @@ int lcpex(
shell_execution_arg,
supply_environment,
shell_source_subcommand,
environment_file_path,
task_context,
log_directory
environment_file_path
);
command = prefix;
setup_signal_handlers(task_context, log_directory);
// if we are forcing a pty, then we will use the vpty library
if( force_pty )
{
return exec_pty( command, stdout_log_fh, stderr_log_fh, context_override, context_user, context_group, supply_environment, task_context, log_directory );
return exec_pty( command, stdout_log_fh, stderr_log_fh, context_override, context_user, context_group, supply_environment );
}
// otherwise, we will use the execute function
return execute( command, stdout_log_fh, stderr_log_fh, context_override, context_user, context_group, supply_environment, task_context, log_directory );
return execute( command, stdout_log_fh, stderr_log_fh, context_override, context_user, context_group, supply_environment );
}
/**
@ -172,16 +89,12 @@ int lcpex(
*
* @param fd The file descriptor for which to set the close-on-exec flag
*/
void set_cloexec_flag(int fd, std::string task_context = "", std::string log_directory = "")
void set_cloexec_flag(int fd)
{
std::string command = "set_cloexec_flag";
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
{
std::string error_message = "fcntl(F_SETFD) failed for fd " + std::to_string(fd);
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory);
throw std::runtime_error("fcntl(F_SETFD) failed for fd " + std::to_string(fd));
perror("fcntl");
exit(1);
}
}
@ -209,16 +122,9 @@ void set_cloexec_flag(int fd, std::string task_context = "", std::string log_dir
* Finally, the child process calls execvp() with the processed_command to run the shell command.
* If the execvp() function fails, an error message is displayed.
*/
void run_child_process(bool context_override, const char* context_user, const char* context_group, char* processed_command[], int fd_child_stdout_pipe[], int fd_child_stderr_pipe[], std::string task_context = "", std::string log_directory = "") {
void run_child_process(bool context_override, const char* context_user, const char* context_group, char* processed_command[], int fd_child_stdout_pipe[], int fd_child_stderr_pipe[]) {
while ((dup2(fd_child_stdout_pipe[WRITE_END], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
while ((dup2(fd_child_stderr_pipe[WRITE_END], STDERR_FILENO) == -1) && (errno == EINTR)) {}
// Close unused pipe ends to avoid leaks
close(fd_child_stdout_pipe[READ_END]);
close(fd_child_stdout_pipe[WRITE_END]);
close(fd_child_stderr_pipe[READ_END]);
close(fd_child_stderr_pipe[WRITE_END]);
std::string command = "run_child_process"; // Command context
if ( context_override ) {
int context_result = set_identity_context(context_user, context_group);
@ -226,38 +132,34 @@ void run_child_process(bool context_override, const char* context_user, const ch
case IDENTITY_CONTEXT_ERRORS::ERROR_NONE:
break;
case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_USER:
logger.log(E_FATAL, "Aborting: context user not found: " + std::string(context_user));
logger.log_to_json_file("E_FATAL", "Aborting: context user not found: " + std::string(context_user), user, group, command, task_context, log_directory);
_exit(1);
std::cerr << "REX: Aborting: context user not found: " << context_user << std::endl;
exit(1);
break;
case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_GROUP:
logger.log(E_FATAL, "Aborting: context group not found: " + std::string(context_group));
logger.log_to_json_file("E_FATAL", "Aborting: context group not found: " + std::string(context_group), user, group, command, task_context, log_directory);
_exit(1);
std::cerr << "REX: Aborting: context group not found: " << context_group << std::endl;
exit(1);
break;
case IDENTITY_CONTEXT_ERRORS::ERROR_SETGID_FAILED:
logger.log(E_FATAL, "Aborting: Setting GID failed: " + std::string(context_user) + "/" + std::string(context_group));
logger.log_to_json_file("E_FATAL", "Aborting: Setting GID failed: " + std::string(context_user) + "/" + std::string(context_group), user, group, command, task_context, log_directory);
_exit(1);
std::cerr << "REX: Aborting: Setting GID failed: " << context_user << "/" << context_group << std::endl;
exit(1);
break;
case IDENTITY_CONTEXT_ERRORS::ERROR_SETUID_FAILED:
logger.log(E_FATAL, "Aborting: Setting UID failed: " + std::string(context_user) + "/" + std::string(context_group));
logger.log_to_json_file("E_FATAL", "Aborting: Setting UID failed: " + std::string(context_user) + "/" + std::string(context_group), user, group, command, task_context, log_directory);
_exit(1);
std::cerr << "REX: Aborting: Setting UID failed: " << context_user << "/" << context_group << std::endl;
exit(1);
break;
default:
logger.log(E_FATAL, "Aborting: Unknown error while setting identity context.");
logger.log_to_json_file("E_FATAL", "Aborting: Unknown error while setting identity context.", user, group, command, task_context, log_directory);
_exit(1);
std::cerr << "REX: Aborting: Unknown error while setting identity context." << std::endl;
exit(1);
break;
}
}
int exit_code = execvp(processed_command[0], processed_command);
logger.log_to_json_file("E_FATAL", "failed on execvp in child", user, group, command, task_context, log_directory);
logger.log(E_FATAL, "failed on execvp in child");
_Exit(exit_code);
perror("failed on execvp in child");
exit(exit_code);
}
int execute(
std::string command,
FILE * stdout_log_fh,
@ -265,12 +167,8 @@ int execute(
bool context_override,
std::string context_user,
std::string context_group,
bool environment_supplied,
std::string task_context,
std::string log_directory
bool environment_supplied
){
try {
// this does three things:
// - execute a dang string as a subprocess command
// - capture child stdout/stderr to respective log files
@ -292,36 +190,31 @@ int execute(
int fd_child_stderr_pipe[2];
if ( pipe(fd_child_stdout_pipe ) == -1 ) {
throw std::runtime_error("Failed to create stdout pipe");
perror( "child stdout pipe" );
exit( 1 );
}
if ( pipe( fd_child_stderr_pipe ) == -1 ) {
close(fd_child_stdout_pipe[0]);
close(fd_child_stdout_pipe[1]);
throw std::runtime_error("Failed to create stderr pipe");
perror( "child stderr pipe" );
exit( 1 );
}
// using O_CLOEXEC to ensure that the child process closes the file descriptors
set_cloexec_flag( fd_child_stdout_pipe[READ_END], task_context, log_directory );
set_cloexec_flag( fd_child_stderr_pipe[READ_END], task_context, log_directory );
set_cloexec_flag( fd_child_stdout_pipe[WRITE_END], task_context, log_directory );
set_cloexec_flag( fd_child_stderr_pipe[WRITE_END], task_context, log_directory );
set_cloexec_flag( fd_child_stdout_pipe[READ_END] );
set_cloexec_flag( fd_child_stderr_pipe[READ_END] );
set_cloexec_flag( fd_child_stdout_pipe[WRITE_END] );
set_cloexec_flag( fd_child_stderr_pipe[WRITE_END] );
// status result basket for the parent process to capture the child's exit status
int status;
int status = 616;
pid_t pid = fork();
switch( pid ) {
case -1:
{
// fork failed
logger.log(E_FATAL, "fork failure: " + std::string(strerror(errno)));
logger.log_to_json_file("E_FATAL", "fork failure: " + std::string(strerror(errno)), user, group, command, task_context, log_directory);
close(fd_child_stdout_pipe[0]); // Pipe Leaks on Error Paths
close(fd_child_stdout_pipe[1]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[0]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[1]); // Pipe Leaks on Error Paths
throw std::runtime_error("fork() failed: " + std::string(strerror(errno)));
perror("fork failure");
exit(1);
}
case 0:
@ -333,9 +226,7 @@ int execute(
context_group.c_str(),
processed_command,
fd_child_stdout_pipe,
fd_child_stderr_pipe,
task_context,
log_directory
fd_child_stderr_pipe
);
}
@ -343,23 +234,14 @@ int execute(
{
// parent process
FdGuard stdout_read_guard(fd_child_stdout_pipe[READ_END]);
FdGuard stderr_read_guard(fd_child_stderr_pipe[READ_END]);
FdGuard stdout_write_guard(fd_child_stdout_pipe[WRITE_END]);
FdGuard stderr_write_guard(fd_child_stderr_pipe[WRITE_END]);
// We don't need WRITE_ENDs in parent, close them now
stdout_write_guard.reset(); // Closes and sets fd to -1
stderr_write_guard.reset();
// The parent process has no need to access the entrance to the pipe, so fd_child_*_pipe[1|0] should be closed
// within that process too:
close(fd_child_stdout_pipe[WRITE_END]);
close(fd_child_stderr_pipe[WRITE_END]);
// attempt to write to stdout,stderr from child as well as to write each to file
char buf[BUFFER_SIZE] = {0};
std::strncpy(buf, command.c_str(), BUFFER_SIZE - 1);
buf[BUFFER_SIZE - 1] = '\0';
char buf[BUFFER_SIZE];
// contains the byte count of the last read from the pipe
ssize_t byte_count;
@ -369,11 +251,11 @@ int execute(
// populate the watched_fds array
// child STDOUT to parent
watched_fds[CHILD_PIPE_NAMES::STDOUT_READ].fd = stdout_read_guard.get();
watched_fds[CHILD_PIPE_NAMES::STDOUT_READ].fd = fd_child_stdout_pipe[READ_END];
watched_fds[CHILD_PIPE_NAMES::STDOUT_READ].events = POLLIN;
// child STDERR to parent
watched_fds[CHILD_PIPE_NAMES::STDERR_READ].fd = stderr_read_guard.get();
watched_fds[CHILD_PIPE_NAMES::STDERR_READ].fd = fd_child_stderr_pipe[READ_END];
watched_fds[CHILD_PIPE_NAMES::STDERR_READ].events = POLLIN;
// number of files poll() reports as ready
@ -393,9 +275,8 @@ int execute(
if (num_files_readable == -1) {
// error occurred in poll()
logger.log(E_FATAL, "poll() failed: " + std::string(strerror(errno)));
logger.log_to_json_file("E_FATAL", "poll() failed", user, group, command, task_context, log_directory);
throw std::runtime_error("poll() failed");
perror("poll");
exit(1);
}
if (num_files_readable == 0) {
// poll reports no files readable
@ -410,10 +291,7 @@ int execute(
if (byte_count == -1) {
if (errno == EAGAIN) { continue; } else {
// error reading from pipe
logger.log(E_FATAL, "Error while reading: " + std::string(strerror(errno)));
logger.log_to_json_file("E_FATAL", "Error while reading from pipe", user, group, command, task_context, log_directory);
stdout_read_guard.reset(-1);
stderr_read_guard.reset(-1);
perror("read");
exit(EXIT_FAILURE);
}
@ -434,17 +312,13 @@ int execute(
write_all(STDERR_FILENO, buf, byte_count);
} else {
// this should never happen
logger.log(E_FATAL, "Logic error: unexpected pipe index.");
perror("Logic error!");
exit(EXIT_FAILURE);
}
}
}
if (watched_fds[this_fd].revents & POLLERR) {
if (this_fd == CHILD_PIPE_NAMES::STDOUT_READ) {
stdout_read_guard.reset(-1);
} else if (this_fd == CHILD_PIPE_NAMES::STDERR_READ) {
stderr_read_guard.reset(-1);
}
close(watched_fds[this_fd].fd);
break_out = true;
}
if (watched_fds[this_fd].revents & POLLHUP) {
@ -459,46 +333,21 @@ int execute(
waitpid(pid, &status, 0);
// Drain the pipes before exiting
while ((byte_count = read(stdout_read_guard.get(), buf, BUFFER_SIZE)) > 0) {
while ((byte_count = read(fd_child_stdout_pipe[READ_END], buf, BUFFER_SIZE)) > 0) {
write_all(stdout_log_fh->_fileno, buf, byte_count);
write_all(STDOUT_FILENO, buf, byte_count);
}
while ((byte_count = read(stderr_read_guard.get(), buf, BUFFER_SIZE)) > 0) {
while ((byte_count = read(fd_child_stderr_pipe[READ_END], buf, BUFFER_SIZE)) > 0) {
write_all(stderr_log_fh->_fileno, buf, byte_count);
write_all(STDERR_FILENO, buf, byte_count);
}
int status;
pid_t pid = waitpid(-1, &status, WNOHANG); // Non-blocking wait for child process
if (pid > 0) { // If a child process has terminated
// Check if the child process exited normally
if (WIFEXITED(status)) {
int exit_code = WEXITSTATUS(status);
logger.log(E_INFO, "Child exited with status " + std::to_string(exit_code));
logger.log_to_json_file("E_INFO", "Child exited with status " + std::to_string(exit_code), user, group, command, task_context, log_directory);
}
// Check if the child process was terminated by a signal
else if (WIFSIGNALED(status)) {
int signal_number = WTERMSIG(status);
logger.log(E_FATAL, "Process terminated by signal: " + std::to_string(signal_number));
logger.log_to_json_file("E_FATAL", "Process terminated by signal: " + std::to_string(signal_number), user, group, command, task_context, log_directory);
// Reset signal handler to default before exiting
signal(signal_number, SIG_DFL);
// Return 128 + signal number as the exit code for signal termination
return 128 + signal_number; // POSIX exit code format
}
// Handle unexpected exit conditions
else {
logger.log(E_WARN, "Unknown child exit condition.");
logger.log_to_json_file("E_WARN", "Unknown child exit condition", user, group, command, task_context, log_directory);
if WIFEXITED(status) {
return WEXITSTATUS(status);
} else {
return -617;
}
}
}
}
return 0;
} catch (const std::exception& ex) {
std::cerr << "[LCPEX ERROR] " << ex.what() << std::endl;
return -999;
}
}

View File

@ -44,9 +44,7 @@ int execute(
bool context_override,
std::string context_user,
std::string context_group,
bool environment_supplied,
std::string task_context = "",
std::string log_directory = ""
bool environment_supplied
);
@ -89,9 +87,7 @@ int lcpex(
std::string shell_execution_arg,
bool supply_environment,
std::string shell_source_subcommand,
std::string environment_file_path,
std::string task_context = "",
std::string log_directory = ""
std::string environment_file_path
);
/**

View File

@ -1,74 +1,4 @@
#include "libclpex_tty.h"
#include <cstring>
#include <stdexcept>
#include <signal.h>
#include <string>
#include "../../logger/Logger.h"
#include "../FileHandle.h"
#define BUFFER_SIZE 1024
// Initialize logger
static Logger tty_logger(E_INFO, "lcpex_tty");
std::string tty_user = tty_logger.get_user_name();
std::string tty_group = tty_logger.get_group_name();
// Global variables for signal handler context
static std::string g_tty_task_context = "";
static std::string g_tty_log_directory = "";
void tty_signal_handler(int sig) {
std::string command = "tty_signal_handler"; // Command context
// Create an instance of Logger (you can change the log level and mask accordingly)
// Log the signal handling
if (sig == SIGCHLD) {
// Log that SIGCHLD was received, but leave the exit status to the parent
tty_logger.log_to_json_file("E_INFO", "SIGCHLD received. A child process ended.", tty_user, tty_group, command, g_tty_task_context, g_tty_log_directory);
} else if (sig == SIGINT) {
tty_logger.log_to_json_file("E_FATAL", "SIGINT received. Gracefully terminating...", tty_user, tty_group, command, g_tty_task_context, g_tty_log_directory);
} else if (sig == SIGTERM) {
tty_logger.log_to_json_file("E_FATAL", "SIGTERM received. Terminating...", tty_user, tty_group, command, g_tty_task_context, g_tty_log_directory);
} else if (sig == SIGSEGV) {
tty_logger.log_to_json_file("E_FATAL", "SIGSEGV received. Possible segmentation fault.", tty_user, tty_group, command, g_tty_task_context, g_tty_log_directory);
} else {
tty_logger.log_to_json_file("E_FATAL", "Unhandled signal received", tty_user, tty_group, command, g_tty_task_context, g_tty_log_directory);
}
}
// Setup signal registrations
void setup_tty_signal_handlers(std::string task_context = "", std::string log_directory = "") {
// Set global variables for signal handler context
g_tty_task_context = task_context;
g_tty_log_directory = log_directory;
struct sigaction sa;
sa.sa_handler = tty_signal_handler; // <-- handler function
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
std::string command = "setup_tty_signal_handlers"; // Command context
// SIGCHLD
if (sigaction(SIGCHLD, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGCHLD handler: " + std::string(strerror(errno));
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory); // Log to JSON file
}
// SIGINT
if (sigaction(SIGINT, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGINT handler: " + std::string(strerror(errno));
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory); // Log to JSON file
}
// SIGTERM
if (sigaction(SIGTERM, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGTERM handler: " + std::string(strerror(errno));
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory); // Log to JSON file
}
// SIGSEGV
if (sigaction(SIGSEGV, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGSEGV handler: " + std::string(strerror(errno));
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory); // Log to JSON file
}
}
/**
* @brief Safely prints a message and exits the program
@ -81,27 +11,14 @@ void setup_tty_signal_handlers(std::string task_context = "", std::string log_di
* Then, it calls `ttyResetExit()` with `ttyOrig` as its argument to reset the terminal settings.
* Finally, the function exits the program with exit code 1.
*/
void set_tty_cloexec_flag(int fd, std::string task_context = "", std::string log_directory = "")
void safe_perror( const char * msg, struct termios * ttyOrig )
{
std::string command = "set_tty_cloexec_flag";
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
{
std::string error_message = "fcntl(F_SETFD) failed for fd " + std::to_string(fd);
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory);
throw std::runtime_error("fcntl(F_SETFD) failed for fd " + std::to_string(fd));
}
}
void safe_perror( const char * msg, struct termios * ttyOrig, std::string task_context = "", std::string log_directory = "" )
{
std::string command = "safe_perror"; // Command context
tty_logger.log_to_json_file("E_FATAL", msg, tty_user, tty_group, command, task_context, log_directory); // Log the message before exiting
std::cerr << msg << std::endl;
ttyResetExit( ttyOrig );
throw std::runtime_error(std::string("TTY Error: ") + msg);
exit(1);
}
/**
* @brief Executes the child process
*
@ -125,16 +42,14 @@ void safe_perror( const char * msg, struct termios * ttyOrig, std::string task_c
* Finally, the function executes the command specified in `processed_command` using `execvp()`.
* If the execution of `execvp()` fails, the function calls `safe_perror()` to print a message and exit the program.
*/
void run_child_process( int fd_child_stderr_pipe[2], char * processed_command[], struct termios * ttyOrig, bool context_override, std::string context_user, std::string context_group, std::string task_context = "", std::string log_directory = "" )
void run_child_process( int fd_child_stderr_pipe[2], char * processed_command[], struct termios * ttyOrig, bool context_override, std::string context_user, std::string context_group )
{
std::string command = "run_child_process_tty"; // Command context
// redirect stderr to the write end of the stderr pipe
// close the file descriptor STDERR_FILENO if it was previously open, then (re)open it as a copy of
while ((dup2(fd_child_stderr_pipe[WRITE_END], STDERR_FILENO) == -1) && (errno == EINTR)) {}
// close the write end of the stderr pipe and read end to avoid leaks
// close the write end of the stderr pipe
close( fd_child_stderr_pipe[WRITE_END] );
close( fd_child_stderr_pipe[READ_END] );
// if the user has specified a context override, set the context
if ( context_override )
@ -144,29 +59,24 @@ void run_child_process( int fd_child_stderr_pipe[2], char * processed_command[],
case IDENTITY_CONTEXT_ERRORS::ERROR_NONE:
break;
case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_USER:
tty_logger.log(E_FATAL, "Aborting: context user not found: " + context_user);
tty_logger.log_to_json_file("E_FATAL", "Context user not found: " + context_user, tty_user, tty_group, command, task_context, log_directory);
_exit(1);
std::cerr << "lcpex: Aborting: context user not found: " << context_user << std::endl;
exit(1);
break;
case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_GROUP:
tty_logger.log(E_FATAL, "Aborting: context group not found: " + context_group);
tty_logger.log_to_json_file("E_FATAL", "Context group not found: " + context_group, tty_user, tty_group, command, task_context, log_directory);
_exit(1);
std::cerr << "lcpex: Aborting: context group not found: " << context_group << std::endl;
exit(1);
break;
case IDENTITY_CONTEXT_ERRORS::ERROR_SETGID_FAILED:
tty_logger.log(E_FATAL, "Aborting: Setting GID failed: " + context_user + "/" + context_group);
tty_logger.log_to_json_file("E_FATAL", "Setting GID failed for: " + context_user + "/" + context_group, tty_user, tty_group, command, task_context, log_directory);
_exit(1);
std::cerr << "lcpex: Aborting: Setting GID failed: " << context_user << "/" << context_group << std::endl;
exit(1);
break;
case IDENTITY_CONTEXT_ERRORS::ERROR_SETUID_FAILED:
tty_logger.log(E_FATAL, "Aborting: Setting UID failed: " + context_user + "/" + context_group);
tty_logger.log_to_json_file("E_FATAL", "Setting UID failed for: " + context_user + "/" + context_group, tty_user, tty_group, command, task_context, log_directory);
_exit(1);
std::cerr << "lcpex: Aborting: Setting UID failed: " << context_user << "/" << context_group << std::endl;
exit(1);
break;
default:
tty_logger.log(E_FATAL, "Aborting: Unknown error while setting identity context.");
tty_logger.log_to_json_file("E_FATAL", "Unknown error while setting identity context.", tty_user, tty_group, command, task_context, log_directory);
_exit(1);
std::cerr << "lcpex: Aborting: Unknown error while setting identity context." << std::endl;
exit(1);
break;
}
}
@ -174,10 +84,8 @@ void run_child_process( int fd_child_stderr_pipe[2], char * processed_command[],
// execute the dang command, print to stdout, stderr (of parent), and dump to file for each!!!!
// (and capture exit code in parent)
int exit_code = execvp( processed_command[0], processed_command );
tty_logger.log_to_json_file("E_FATAL", "failed on execvp in child", tty_user, tty_group, command, task_context, log_directory);
tty_logger.log(E_FATAL, "failed on execvp in child");
_Exit(exit_code);
safe_perror("failed on execvp in child", ttyOrig );
exit(exit_code);
}
// this does three things:
@ -191,15 +99,8 @@ int exec_pty(
bool context_override,
std::string context_user,
std::string context_group,
bool environment_supplied,
std::string task_context,
std::string log_directory
bool environment_supplied
) {
try {
std::string exec_command = "exec_pty"; // Command context
tty_logger.log_to_json_file("E_INFO", "TTY LAUNCHER: " + command, tty_user, tty_group, exec_command, task_context, log_directory);
// Setup signal handlers
setup_tty_signal_handlers(task_context, log_directory);
// initialize the terminal settings obj
struct termios ttyOrig;
@ -214,13 +115,13 @@ int exec_pty(
char ** processed_command = expand_env( command );
if ( stdout_log_fh == NULL ) {
tty_logger.log_to_json_file("E_FATAL", "Error opening STDOUT log file. Aborting.", tty_user, tty_group, exec_command, task_context, log_directory);
throw std::runtime_error("Error opening STDOUT log file");
safe_perror( "Error opening STDOUT log file. Aborting.", &ttyOrig );
exit( 1 );
}
if ( stderr_log_fh == NULL ) {
tty_logger.log_to_json_file("E_FATAL", "Error opening STDERR log file. Aborting.", tty_user, tty_group, exec_command, task_context, log_directory);
throw std::runtime_error("Error opening STDERR log file");
safe_perror( "Error opening STDERR log file. Aborting.", &ttyOrig );
exit( 1 );
}
@ -228,13 +129,16 @@ int exec_pty(
int fd_child_stderr_pipe[2];
if ( pipe( fd_child_stderr_pipe ) == -1 ) {
std::string error_message = "Failed to create stderr pipe: " + std::string(strerror(errno));
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, exec_command, task_context, log_directory);
throw std::runtime_error("Failed to create stderr pipe");
safe_perror( "child stderr pipe", &ttyOrig );
exit( 1 );
}
// using O_CLOEXEC to ensure that the child process closes the file descriptors
set_tty_cloexec_flag( fd_child_stderr_pipe[READ_END], task_context, log_directory );
set_tty_cloexec_flag( fd_child_stderr_pipe[WRITE_END], task_context, log_directory );
if ( fcntl( fd_child_stderr_pipe[READ_END], F_SETFD, FD_CLOEXEC ) == -1 ) { perror("fcntl"); exit(1); }
// // same for stderr write
if ( fcntl( fd_child_stderr_pipe[WRITE_END], F_SETFD, FD_CLOEXEC ) == -1 ) { perror("fcntl"); exit(1); }
// status result basket for the parent process to capture the child's exit status
int status = 616;
@ -244,52 +148,39 @@ int exec_pty(
struct winsize ws;
/* Retrieve the attributes of terminal on which we are started */
if (tcgetattr(STDIN_FILENO, &ttyOrig) == -1){
tty_logger.log_to_json_file("E_FATAL", "tcgetattr failed", tty_user, tty_group, exec_command, task_context, log_directory);
close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[WRITE_END]); // Pipe Leaks on Error Paths
throw std::runtime_error("tcgetattr failed");
}
if (tcgetattr(STDIN_FILENO, &ttyOrig) == -1)
safe_perror("tcgetattr", &ttyOrig);
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0)
{
tty_logger.log_to_json_file("E_FATAL", "ioctl-TIOCGWINSZ failed", tty_user, tty_group, exec_command, task_context, log_directory);
close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[WRITE_END]); // Pipe Leaks on Error Paths
throw std::runtime_error("ioctl-TIOCGWINSZ failed");
}
safe_perror("ioctl-TIOCGWINSZ", &ttyOrig );
pid_t pid = ptyFork( &masterFd, slaveName, MAX_SNAME, &ttyOrig, &ws );
switch( pid ) {
case -1:
{
// fork failed
tty_logger.log(E_FATAL, "ptyfork failure: " + std::string(strerror(errno)));
tty_logger.log_to_json_file("E_FATAL", "ptyfork failure: " + std::string(strerror(errno)), tty_user, tty_group, exec_command, task_context, log_directory);
close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[WRITE_END]); // Pipe Leaks on Error Paths
throw std::runtime_error("ptyfork() failed: " + std::string(strerror(errno)));
safe_perror("ptyfork failure", &ttyOrig );
exit(1);
}
case 0:
{
// child process
run_child_process( fd_child_stderr_pipe, processed_command, &ttyOrig, context_override, context_user, context_group, task_context, log_directory );
run_child_process( fd_child_stderr_pipe, processed_command, &ttyOrig, context_override, context_user, context_group );
}
default:
{
// parent process
// start ptyfork integration
ttySetRaw(STDIN_FILENO, &ttyOrig);
// RAII guards for file descriptors
FdGuard stderr_read_guard(fd_child_stderr_pipe[READ_END]);
FdGuard stderr_write_guard(fd_child_stderr_pipe[WRITE_END]);
FdGuard master_fd_guard(masterFd);
// We don't need WRITE_END in parent, close it now
stderr_write_guard.reset(); // Closes and sets fd to -1
// The parent process has no need to access the entrance to the pipe
close(fd_child_stderr_pipe[WRITE_END]);
// attempt to write to stdout,stderr from child as well as to write each to file
char buf[BUFFER_SIZE] = {0};
std::strncpy(buf, command.c_str(), BUFFER_SIZE - 1);
buf[BUFFER_SIZE - 1] = '\0';
char buf[BUFFER_SIZE];
// contains the byte count of the last read from the pipe
ssize_t byte_count;
@ -304,11 +195,11 @@ int exec_pty(
watched_fds[0].events = POLLIN;
// child pty to parent (stdout)
watched_fds[1].fd = master_fd_guard.get();
watched_fds[1].fd = masterFd;
watched_fds[1].events = POLLIN;
// child stderr to parent
watched_fds[2].fd = stderr_read_guard.get();
watched_fds[2].fd = fd_child_stderr_pipe[READ_END];
watched_fds[2].events = POLLIN;
// number of files poll() reports as ready
@ -328,10 +219,8 @@ int exec_pty(
if (num_files_readable == -1) {
// error occurred in poll()
tty_logger.log(E_FATAL, "poll() failed: " + std::string(strerror(errno)));
tty_logger.log_to_json_file("E_FATAL", "poll() failed", tty_user, tty_group, exec_command, task_context, log_directory);
ttyResetExit( &ttyOrig);
throw std::runtime_error("poll() failed");
safe_perror("poll", &ttyOrig );
exit(1);
}
if (num_files_readable == 0) {
@ -348,11 +237,7 @@ int exec_pty(
if (byte_count == -1) {
if (errno == EAGAIN) { continue; } else {
// error reading from pipe
tty_logger.log(E_FATAL, "Error while reading: " + std::string(strerror(errno)));
tty_logger.log_to_json_file("E_FATAL", "Error while reading from pipe", tty_user, tty_group, exec_command, task_context, log_directory);
ttyResetExit( &ttyOrig);
stderr_read_guard.reset(-1);
master_fd_guard.reset(-1);
safe_perror("read", &ttyOrig );
exit(EXIT_FAILURE);
}
} else if (byte_count == 0) {
@ -376,17 +261,12 @@ int exec_pty(
write_all(STDERR_FILENO, buf, byte_count);
} else {
// this should never happen
tty_logger.log(E_FATAL, "Logic error: unexpected pipe index.");
perror("Logic error!");
exit(EXIT_FAILURE);
}
}
}
if (watched_fds[this_fd].revents & POLLERR) {
if (this_fd == 1) {
master_fd_guard.reset(-1);
} else if (this_fd == 2) {
stderr_read_guard.reset(-1);
}
//close(watched_fds[this_fd].fd);
break_out = true;
//continue;
@ -408,42 +288,15 @@ int exec_pty(
// wait for child to exit, capture status
waitpid(pid, &status, 0);
while ((byte_count = read(master_fd_guard.get(), buf, BUFFER_SIZE)) > 0) {
while ((byte_count = read(watched_fds[1].fd, buf, BUFFER_SIZE)) > 0) {
write_all(stdout_log_fh->_fileno, buf, byte_count);
write_all(STDOUT_FILENO, buf, byte_count);
}
while ((byte_count = read(stderr_read_guard.get(), buf, BUFFER_SIZE)) > 0) {
while ((byte_count = read(fd_child_stderr_pipe[READ_END], buf, BUFFER_SIZE)) > 0) {
write_all(stderr_log_fh->_fileno, buf, byte_count);
write_all(STDERR_FILENO, buf, byte_count);
}
// Handle child process status with proper signal handling
pid_t child_pid = waitpid(-1, &status, WNOHANG); // Non-blocking wait for child process
if (child_pid > 0) { // If a child process has terminated
// Check if the child process exited normally
if (WIFEXITED(status)) {
int exit_code = WEXITSTATUS(status);
tty_logger.log(E_INFO, "Child exited with status " + std::to_string(exit_code));
tty_logger.log_to_json_file("E_INFO", "Child exited with status " + std::to_string(exit_code), tty_user, tty_group, exec_command, task_context, log_directory);
ttyResetExit( &ttyOrig);
return exit_code;
}
// Check if the child process was terminated by a signal
else if (WIFSIGNALED(status)) {
int signal_number = WTERMSIG(status);
tty_logger.log(E_FATAL, "Process terminated by signal: " + std::to_string(signal_number));
tty_logger.log_to_json_file("E_FATAL", "Process terminated by signal: " + std::to_string(signal_number), tty_user, tty_group, exec_command, task_context, log_directory);
// Reset signal handler to default before exiting
signal(signal_number, SIG_DFL);
ttyResetExit( &ttyOrig);
return 128 + signal_number; // POSIX exit code format
}
// Handle unexpected exit conditions
else {
tty_logger.log(E_WARN, "Unknown child exit condition.");
tty_logger.log_to_json_file("E_WARN", "Unknown child exit condition", tty_user, tty_group, exec_command, task_context, log_directory);
}
}
ttyResetExit( &ttyOrig);
if WIFEXITED(status) {
@ -453,9 +306,4 @@ int exec_pty(
}
}
}
return 0;
} catch (const std::exception& ex) {
std::cerr << "[LCPEX TTY ERROR] " << ex.what() << std::endl;
return -999;
}
}

View File

@ -43,9 +43,7 @@ int exec_pty(
bool context_override,
std::string context_user,
std::string context_group,
bool environment_supplied,
std::string task_context = "",
std::string log_directory = ""
bool environment_supplied
);

View File

@ -19,13 +19,6 @@
*/
#include "Logger.h"
#include <string>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <unistd.h> // For FdGuard
#include <fcntl.h> // For O_RDONLY, O_WRONLY, open()
#include "../lcpex/FileHandle.h" // Include the FdGuard header
Logger::Logger( int LOG_LEVEL, std::string mask )
{
@ -33,11 +26,6 @@ Logger::Logger( int LOG_LEVEL, std::string mask )
this->mask = mask;
}
// Destructor added in the update
Logger::~Logger() {
}
void Logger::log( int LOG_LEVEL, std::string msg )
{
std::string ERR = "XXXX";
@ -54,7 +42,7 @@ void Logger::log( int LOG_LEVEL, std::string msg )
std::string s_msg = "[" + ERR + "] " + msg;
if ( LOG_LEVEL == E_FATAL || LOG_LEVEL == E_WARN )
if ( LOG_LEVEL == E_FATAL | LOG_LEVEL == E_WARN )
{
std::cerr << "[" << get_8601() << "] [" << ERR << "] " << "[" << this->mask << "] " << msg.c_str() << std::endl;
} else {
@ -65,152 +53,6 @@ void Logger::log( int LOG_LEVEL, std::string msg )
void Logger::log_task( int LOG_LEVEL, std::string task_name, std::string msg )
{
// Added memory management from the updated file
size_t task_msg_len = task_name.length() + msg.length() + 4;
char* task_msg = (char*)malloc(task_msg_len);
if (task_msg) {
snprintf(task_msg, task_msg_len, "[%s] %s", task_name.c_str(), msg.c_str());
log(LOG_LEVEL, task_msg);
free(task_msg);
}
}
// JSON logging method
void Logger::create_json_log_entry(char* buffer, size_t buffer_size,
const char* log_level, const char* message,
const char* user, const char* group,
const char* command)
{
std::string timestamp = get_current_timestamp();
snprintf(buffer, buffer_size,
"{\n"
" \"timestamp\": \"%s\",\n"
" \"log_level\": \"%s\",\n"
" \"message\": \"%s\",\n"
" \"context\": {\n"
" \"user\": \"%s\",\n"
" \"group\": \"%s\",\n"
" \"command\": \"%s\"\n"
" }\n"
"}",
timestamp.c_str(), log_level, message, user, group, command);
}
// Add methods for user/group name and timestamp
std::string Logger::get_user_name()
{
struct passwd* pw = getpwuid(getuid());
if (pw) {
return std::string(pw->pw_name);
}
return "unknown";
}
std::string Logger::get_group_name()
{
struct group* grp = getgrgid(getgid());
if (grp) {
return std::string(grp->gr_name);
}
return "unknown";
}
std::string Logger::get_current_timestamp()
{
time_t now = time(NULL);
struct tm* timeinfo = localtime(&now);
char buffer[64];
strftime(buffer, sizeof(buffer), "%Y-%m-%d_%H:%M:%S", timeinfo);
return std::string(buffer);
}
//Log to JSON file
void Logger::log_to_json_file(const std::string& log_level, const std::string& message,
const std::string& user, const std::string& group,
const std::string& command, const std::string& task_context,
const std::string& log_directory, bool log_to_console)
{
// Log to console if requested
const char* log_level_str = "UNKNOWN";
if (log_level == "E_INFO") log_level_str = "INFO";
else if (log_level == "E_FATAL") log_level_str = "FATAL";
else if (log_level == "E_WARN") log_level_str = "WARN";
else if (log_level == "E_DEBUG") log_level_str = "DEBUG";
if (log_to_console && (log_level_str == "INFO" || log_level_str == "FATAL")) {
std::string timestamp = get_current_timestamp();
printf("[%s] [%s] [%s] %s\n", timestamp.c_str(), log_level_str, this->mask.c_str(), message.c_str());
fflush(stdout);
}
// 2. Create JSON log entry
char json_log[2048];
create_json_log_entry(json_log, sizeof(json_log), log_level_str, message.c_str(), user.c_str(), group.c_str(), command.c_str());
// 3. Generate filename with format: YYYY-MM-DD_context.log.json
std::string filename;
if (!task_context.empty() && !log_directory.empty()) {
// Use task-specific directory and format
time_t now = time(NULL);
struct tm* timeinfo = localtime(&now);
char date_buffer[16];
strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", timeinfo);
std::string date_str = std::string(date_buffer);
filename = log_directory + "/" + task_context + "/" + date_str + "_" + task_context + ".log.json";
} else {
// Fallback to original format for backward compatibility
std::string timestamp = get_current_timestamp();
filename = "log_" + timestamp + ".json";
}
// 4. Use FdGuard for file handling (to manage file opening and closing)
FdGuard check_file(open(filename.c_str(), O_RDONLY));
bool file_empty = true;
if (check_file.get() != -1) {
off_t file_size = lseek(check_file.get(), 0, SEEK_END);
file_empty = (file_size == 0);
}
if (file_empty) {
// First entry - create new JSON array
FdGuard json_file(open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644));
if (json_file.get() != -1) {
dprintf(json_file.get(), "[\n %s\n]\n", json_log);
} else {
fprintf(stderr, "Failed to open log file for writing: %s\n", filename.c_str());
}
} else {
// Subsequent entries - handle JSON array properly
FdGuard read_file(open(filename.c_str(), O_RDONLY));
if (read_file.get() == -1) {
fprintf(stderr, "Failed to open log file for reading: %s\n", filename.c_str());
return;
}
off_t file_size = lseek(read_file.get(), 0, SEEK_END);
lseek(read_file.get(), 0, SEEK_SET);
char* content = (char*)malloc(file_size + 1);
if (!content) {
fprintf(stderr, "Failed to allocate memory for file content\n");
return;
}
read(read_file.get(), content, file_size);
content[file_size] = '\0';
// Find and remove the last ']'
char* last_bracket = strrchr(content, ']');
if (last_bracket) {
*last_bracket = '\0';
}
FdGuard write_file(open(filename.c_str(), O_WRONLY | O_TRUNC, 0644));
if (write_file.get() != -1) {
dprintf(write_file.get(), "%s,\n %s\n]\n", content, json_log);
} else {
fprintf(stderr, "Failed to open log file for writing: %s\n", filename.c_str());
}
free(content);
}
std::string final_msg = "[" + task_name + "] " + msg;
this->log( LOG_LEVEL, final_msg );
}

View File

@ -24,14 +24,8 @@
#include <string>
#include <iostream>
#include <fstream>
#include <fcntl.h> // For O_RDONLY, O_WRONLY, open()
#include <ctime>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <memory>
#include <cstdarg> // for va_list in FileGuard::printf
#include <iomanip>
#include <sstream>
#include "../misc/helpers.h"
enum L_LVL {
@ -43,29 +37,15 @@ enum L_LVL {
class Logger {
public:
// Constructor and Destructor
Logger( int LOG_LEVEL, std::string mask );
~Logger(); // Added Destructor
// Logging methods
void log( int LOG_LEVEL, std::string msg );
void log_task( int LOG_LEVEL, std::string task_name, std::string msg );
void log_to_json_file(const std::string& log_level, const std::string& message,
const std::string& user, const std::string& group,
const std::string& command, const std::string& task_context = "",
const std::string& log_directory = "", bool log_to_console = true);
// Helper methods
std::string get_current_timestamp();
std::string get_user_name();
std::string get_group_name();
private:
int LOG_LEVEL;
std::string mask;
// Internal helper methods
void create_json_log_entry(char* buffer, size_t buffer_size,
const char* log_level, const char* message,
const char* user, const char* group,
const char* command);
};
#endif //REX_LOGGER_H

View File

@ -470,9 +470,7 @@ void Task::execute( Conf * configuration )
shell_definition.execution_arg,
supply_environment,
shell_definition.source_cmd,
environment_file,
task_name,
logs_root
environment_file
);
// **********************************************
@ -541,9 +539,7 @@ void Task::execute( Conf * configuration )
shell_definition.execution_arg,
supply_environment,
shell_definition.source_cmd,
environment_file,
task_name,
logs_root
environment_file
);
// **********************************************
@ -595,9 +591,7 @@ void Task::execute( Conf * configuration )
shell_definition.execution_arg,
supply_environment,
shell_definition.source_cmd,
environment_file,
task_name,
logs_root
environment_file
);
// **********************************************