2 Commits

Author SHA1 Message Date
ODNADev
2118fb3b55 Remove accidental file 'tatus' 2025-08-04 13:46:43 +05:30
ODNADev
5713e6f88b lcpex enhancement - initial commit 2025-08-04 13:44:56 +05:30
7 changed files with 89 additions and 141 deletions

View File

@@ -13,10 +13,6 @@ static Logger logger(E_INFO, "lcpex");
std::string user = logger.get_user_name(); std::string user = logger.get_user_name();
std::string group = logger.get_group_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) { void signal_handler(int sig) {
std::string command = "signal_handler"; // Command context std::string command = "signal_handler"; // Command context
@@ -24,24 +20,20 @@ void signal_handler(int sig) {
// Log the signal handling // Log the signal handling
if (sig == SIGCHLD) { if (sig == SIGCHLD) {
// Log that SIGCHLD was received, but leave the exit status to the parent // 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); logger.log_to_json_file("E_INFO", "SIGCHLD received. A child process ended.", user, group, command);
} else if (sig == SIGINT) { } else if (sig == SIGINT) {
logger.log_to_json_file("E_FATAL", "SIGINT received. Gracefully terminating...", user, group, command, g_task_context, g_log_directory); logger.log_to_json_file("E_FATAL", "SIGINT received. Gracefully terminating...", user, group, command);
} else if (sig == SIGTERM) { } else if (sig == SIGTERM) {
logger.log_to_json_file("E_FATAL", "SIGTERM received. Terminating...", user, group, command, g_task_context, g_log_directory); logger.log_to_json_file("E_FATAL", "SIGTERM received. Terminating...", user, group, command);
} else if (sig == SIGSEGV) { } 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); logger.log_to_json_file("E_FATAL", "SIGSEGV received. Possible segmentation fault.", user, group, command);
} else { } else {
logger.log_to_json_file("E_FATAL", "Unhandled signal received", user, group, command, g_task_context, g_log_directory); logger.log_to_json_file("E_FATAL", "Unhandled signal received", user, group, command);
} }
} }
// Setup signal registrations // Setup signal registrations
void setup_signal_handlers(std::string task_context = "", std::string log_directory = "") { void setup_signal_handlers() {
// Set global variables for signal handler context
g_task_context = task_context;
g_log_directory = log_directory;
struct sigaction sa; struct sigaction sa;
sa.sa_handler = signal_handler; // <-- handler function sa.sa_handler = signal_handler; // <-- handler function
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
@@ -51,25 +43,25 @@ void setup_signal_handlers(std::string task_context = "", std::string log_direct
// SIGCHLD // SIGCHLD
if (sigaction(SIGCHLD, &sa, nullptr) == -1) { if (sigaction(SIGCHLD, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGCHLD handler: " + std::string(strerror(errno)); 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 logger.log_to_json_file("E_FATAL", error_message, user, group, command); // Log to JSON file
} }
// SIGINT // SIGINT
if (sigaction(SIGINT, &sa, nullptr) == -1) { if (sigaction(SIGINT, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGINT handler: " + std::string(strerror(errno)); 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 logger.log_to_json_file("E_FATAL", error_message, user, group, command); // Log to JSON file
} }
// SIGTERM // SIGTERM
if (sigaction(SIGTERM, &sa, nullptr) == -1) { if (sigaction(SIGTERM, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGTERM handler: " + std::string(strerror(errno)); 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 logger.log_to_json_file("E_FATAL", error_message, user, group, command); // Log to JSON file
} }
// SIGSEGV // SIGSEGV
if (sigaction(SIGSEGV, &sa, nullptr) == -1) { if (sigaction(SIGSEGV, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGSEGV handler: " + std::string(strerror(errno)); 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 logger.log_to_json_file("E_FATAL", error_message, user, group, command); // Log to JSON file
} }
} }
@@ -80,9 +72,7 @@ std::string prefix_generator(
std::string shell_execution_arg, std::string shell_execution_arg,
bool supply_environment, bool supply_environment,
std::string shell_source_subcommand, std::string shell_source_subcommand,
std::string environment_file_path, std::string environment_file_path
std::string task_context,
std::string log_directory
) { ) {
std::string prefix = ""; std::string prefix = "";
if ( is_shell_command ) { if ( is_shell_command ) {
@@ -113,7 +103,7 @@ std::string prefix_generator(
} }
// Log the message to JSON file // Log the message to JSON file
logger.log_to_json_file("E_INFO", "LAUNCHER: " + prefix, user, group, command, task_context, log_directory); logger.log_to_json_file("E_INFO", "LAUNCHER: " + prefix, user, group, command);
//logger.log(E_INFO, "LAUNCHER: " + prefix); //logger.log(E_INFO, "LAUNCHER: " + prefix);
return prefix; return prefix;
@@ -133,9 +123,7 @@ int lcpex(
std::string shell_execution_arg, std::string shell_execution_arg,
bool supply_environment, bool supply_environment,
std::string shell_source_subcommand, std::string shell_source_subcommand,
std::string environment_file_path, std::string environment_file_path
std::string task_context,
std::string log_directory
) { ) {
// generate the prefix // generate the prefix
@@ -146,21 +134,19 @@ int lcpex(
shell_execution_arg, shell_execution_arg,
supply_environment, supply_environment,
shell_source_subcommand, shell_source_subcommand,
environment_file_path, environment_file_path
task_context,
log_directory
); );
command = prefix; command = prefix;
setup_signal_handlers(task_context, log_directory); setup_signal_handlers();
// if we are forcing a pty, then we will use the vpty library // if we are forcing a pty, then we will use the vpty library
if( force_pty ) 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 // 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,14 +158,14 @@ int lcpex(
* *
* @param fd The file descriptor for which to set the close-on-exec flag * @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"; std::string command = "set_cloexec_flag";
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
{ {
std::string error_message = "fcntl(F_SETFD) failed for fd " + std::to_string(fd); 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); logger.log_to_json_file("E_FATAL", error_message, user, group, command);
throw std::runtime_error("fcntl(F_SETFD) failed for fd " + std::to_string(fd)); throw std::runtime_error("fcntl(F_SETFD) failed for fd " + std::to_string(fd));
} }
@@ -209,7 +195,7 @@ 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. * 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. * 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_stdout_pipe[WRITE_END], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
while ((dup2(fd_child_stderr_pipe[WRITE_END], STDERR_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 unused pipe ends to avoid leaks
@@ -227,33 +213,33 @@ void run_child_process(bool context_override, const char* context_user, const ch
break; break;
case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_USER: case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_USER:
logger.log(E_FATAL, "Aborting: context user not found: " + std::string(context_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); logger.log_to_json_file("E_FATAL", "Aborting: context user not found: " + std::string(context_user), user, group, command);
_exit(1); _exit(1);
break; break;
case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_GROUP: case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_GROUP:
logger.log(E_FATAL, "Aborting: context group not found: " + std::string(context_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); logger.log_to_json_file("E_FATAL", "Aborting: context group not found: " + std::string(context_group), user, group, command);
_exit(1); _exit(1);
break; break;
case IDENTITY_CONTEXT_ERRORS::ERROR_SETGID_FAILED: 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(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); logger.log_to_json_file("E_FATAL", "Aborting: Setting GID failed: " + std::string(context_user) + "/" + std::string(context_group), user, group, command);
_exit(1); _exit(1);
break; break;
case IDENTITY_CONTEXT_ERRORS::ERROR_SETUID_FAILED: 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(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); logger.log_to_json_file("E_FATAL", "Aborting: Setting UID failed: " + std::string(context_user) + "/" + std::string(context_group), user, group, command);
_exit(1); _exit(1);
break; break;
default: default:
logger.log(E_FATAL, "Aborting: Unknown error while setting identity context."); 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); logger.log_to_json_file("E_FATAL", "Aborting: Unknown error while setting identity context.", user, group, command);
_exit(1); _exit(1);
break; break;
} }
} }
int exit_code = execvp(processed_command[0], processed_command); 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_to_json_file("E_FATAL", "failed on execvp in child", user, group, command);
logger.log(E_FATAL, "failed on execvp in child"); logger.log(E_FATAL, "failed on execvp in child");
_Exit(exit_code); _Exit(exit_code);
} }
@@ -265,9 +251,7 @@ int execute(
bool context_override, bool context_override,
std::string context_user, std::string context_user,
std::string context_group, std::string context_group,
bool environment_supplied, bool environment_supplied
std::string task_context,
std::string log_directory
){ ){
try { try {
@@ -302,10 +286,10 @@ int execute(
} }
// using O_CLOEXEC to ensure that the child process closes the file descriptors // 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_stdout_pipe[READ_END] );
set_cloexec_flag( fd_child_stderr_pipe[READ_END], task_context, log_directory ); set_cloexec_flag( fd_child_stderr_pipe[READ_END] );
set_cloexec_flag( fd_child_stdout_pipe[WRITE_END], task_context, log_directory ); set_cloexec_flag( fd_child_stdout_pipe[WRITE_END] );
set_cloexec_flag( fd_child_stderr_pipe[WRITE_END], task_context, log_directory ); set_cloexec_flag( fd_child_stderr_pipe[WRITE_END] );
// status result basket for the parent process to capture the child's exit status // status result basket for the parent process to capture the child's exit status
int status; int status;
@@ -316,7 +300,7 @@ int execute(
{ {
// fork failed // fork failed
logger.log(E_FATAL, "fork failure: " + std::string(strerror(errno))); 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); logger.log_to_json_file("E_FATAL", "fork failure: " + std::string(strerror(errno)), user, group, command);
close(fd_child_stdout_pipe[0]); // Pipe Leaks on Error Paths 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_stdout_pipe[1]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[0]); // Pipe Leaks on Error Paths close(fd_child_stderr_pipe[0]); // Pipe Leaks on Error Paths
@@ -333,9 +317,7 @@ int execute(
context_group.c_str(), context_group.c_str(),
processed_command, processed_command,
fd_child_stdout_pipe, fd_child_stdout_pipe,
fd_child_stderr_pipe, fd_child_stderr_pipe
task_context,
log_directory
); );
} }
@@ -394,7 +376,7 @@ int execute(
if (num_files_readable == -1) { if (num_files_readable == -1) {
// error occurred in poll() // error occurred in poll()
logger.log(E_FATAL, "poll() failed: " + std::string(strerror(errno))); 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); logger.log_to_json_file("E_FATAL", "poll() failed", user, group, command);
throw std::runtime_error("poll() failed"); throw std::runtime_error("poll() failed");
} }
if (num_files_readable == 0) { if (num_files_readable == 0) {
@@ -411,7 +393,7 @@ int execute(
if (errno == EAGAIN) { continue; } else { if (errno == EAGAIN) { continue; } else {
// error reading from pipe // error reading from pipe
logger.log(E_FATAL, "Error while reading: " + std::string(strerror(errno))); 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); logger.log_to_json_file("E_FATAL", "Error while reading from pipe", user, group, command);
stdout_read_guard.reset(-1); stdout_read_guard.reset(-1);
stderr_read_guard.reset(-1); stderr_read_guard.reset(-1);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@@ -475,13 +457,13 @@ int execute(
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
int exit_code = WEXITSTATUS(status); int exit_code = WEXITSTATUS(status);
logger.log(E_INFO, "Child exited with status " + std::to_string(exit_code)); 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); logger.log_to_json_file("E_INFO", "Child exited with status " + std::to_string(exit_code), user, group, command);
} }
// Check if the child process was terminated by a signal // Check if the child process was terminated by a signal
else if (WIFSIGNALED(status)) { else if (WIFSIGNALED(status)) {
int signal_number = WTERMSIG(status); int signal_number = WTERMSIG(status);
logger.log(E_FATAL, "Process terminated by signal: " + std::to_string(signal_number)); 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); logger.log_to_json_file("E_FATAL", "Process terminated by signal: " + std::to_string(signal_number), user, group, command);
// Reset signal handler to default before exiting // Reset signal handler to default before exiting
signal(signal_number, SIG_DFL); signal(signal_number, SIG_DFL);
// Return 128 + signal number as the exit code for signal termination // Return 128 + signal number as the exit code for signal termination
@@ -490,7 +472,7 @@ int execute(
// Handle unexpected exit conditions // Handle unexpected exit conditions
else { else {
logger.log(E_WARN, "Unknown child exit condition."); 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); logger.log_to_json_file("E_WARN", "Unknown child exit condition", user, group, command);
} }
} }
} }

View File

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

View File

@@ -12,9 +12,6 @@ static Logger tty_logger(E_INFO, "lcpex_tty");
std::string tty_user = tty_logger.get_user_name(); std::string tty_user = tty_logger.get_user_name();
std::string tty_group = tty_logger.get_group_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) { void tty_signal_handler(int sig) {
std::string command = "tty_signal_handler"; // Command context std::string command = "tty_signal_handler"; // Command context
@@ -22,23 +19,19 @@ void tty_signal_handler(int sig) {
// Log the signal handling // Log the signal handling
if (sig == SIGCHLD) { if (sig == SIGCHLD) {
// Log that SIGCHLD was received, but leave the exit status to the parent // 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); tty_logger.log_to_json_file("E_INFO", "SIGCHLD received. A child process ended.", tty_user, tty_group, command);
} else if (sig == SIGINT) { } 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); tty_logger.log_to_json_file("E_FATAL", "SIGINT received. Gracefully terminating...", tty_user, tty_group, command);
} else if (sig == SIGTERM) { } 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); tty_logger.log_to_json_file("E_FATAL", "SIGTERM received. Terminating...", tty_user, tty_group, command);
} else if (sig == SIGSEGV) { } 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); tty_logger.log_to_json_file("E_FATAL", "SIGSEGV received. Possible segmentation fault.", tty_user, tty_group, command);
} else { } 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); tty_logger.log_to_json_file("E_FATAL", "Unhandled signal received", tty_user, tty_group, command);
} }
} }
// Setup signal registrations // Setup signal registrations
void setup_tty_signal_handlers(std::string task_context = "", std::string log_directory = "") { void setup_tty_signal_handlers() {
// Set global variables for signal handler context
g_tty_task_context = task_context;
g_tty_log_directory = log_directory;
struct sigaction sa; struct sigaction sa;
sa.sa_handler = tty_signal_handler; // <-- handler function sa.sa_handler = tty_signal_handler; // <-- handler function
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
@@ -48,25 +41,25 @@ void setup_tty_signal_handlers(std::string task_context = "", std::string log_di
// SIGCHLD // SIGCHLD
if (sigaction(SIGCHLD, &sa, nullptr) == -1) { if (sigaction(SIGCHLD, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGCHLD handler: " + std::string(strerror(errno)); 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 tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command); // Log to JSON file
} }
// SIGINT // SIGINT
if (sigaction(SIGINT, &sa, nullptr) == -1) { if (sigaction(SIGINT, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGINT handler: " + std::string(strerror(errno)); 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 tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command); // Log to JSON file
} }
// SIGTERM // SIGTERM
if (sigaction(SIGTERM, &sa, nullptr) == -1) { if (sigaction(SIGTERM, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGTERM handler: " + std::string(strerror(errno)); 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 tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command); // Log to JSON file
} }
// SIGSEGV // SIGSEGV
if (sigaction(SIGSEGV, &sa, nullptr) == -1) { if (sigaction(SIGSEGV, &sa, nullptr) == -1) {
std::string error_message = "Failed to set SIGSEGV handler: " + std::string(strerror(errno)); 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 tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command); // Log to JSON file
} }
} }
@@ -82,21 +75,21 @@ void setup_tty_signal_handlers(std::string task_context = "", std::string log_di
* Finally, the function exits the program with exit code 1. * 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 set_tty_cloexec_flag(int fd)
{ {
std::string command = "set_tty_cloexec_flag"; std::string command = "set_tty_cloexec_flag";
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
{ {
std::string error_message = "fcntl(F_SETFD) failed for fd " + std::to_string(fd); 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); tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command);
throw std::runtime_error("fcntl(F_SETFD) failed for fd " + std::to_string(fd)); 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 = "" ) void safe_perror( const char * msg, struct termios * ttyOrig )
{ {
std::string command = "safe_perror"; // Command context 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 tty_logger.log_to_json_file("E_FATAL", msg, tty_user, tty_group, command); // Log the message before exiting
std::cerr << msg << std::endl; std::cerr << msg << std::endl;
ttyResetExit( ttyOrig ); ttyResetExit( ttyOrig );
throw std::runtime_error(std::string("TTY Error: ") + msg); throw std::runtime_error(std::string("TTY Error: ") + msg);
@@ -125,7 +118,7 @@ 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()`. * 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. * 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 std::string command = "run_child_process_tty"; // Command context
// redirect stderr to the write end of the stderr pipe // redirect stderr to the write end of the stderr pipe
@@ -145,27 +138,27 @@ void run_child_process( int fd_child_stderr_pipe[2], char * processed_command[],
break; break;
case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_USER: case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_USER:
tty_logger.log(E_FATAL, "Aborting: context user not found: " + context_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); tty_logger.log_to_json_file("E_FATAL", "Context user not found: " + context_user, tty_user, tty_group, command);
_exit(1); _exit(1);
break; break;
case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_GROUP: case IDENTITY_CONTEXT_ERRORS::ERROR_NO_SUCH_GROUP:
tty_logger.log(E_FATAL, "Aborting: context group not found: " + context_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); tty_logger.log_to_json_file("E_FATAL", "Context group not found: " + context_group, tty_user, tty_group, command);
_exit(1); _exit(1);
break; break;
case IDENTITY_CONTEXT_ERRORS::ERROR_SETGID_FAILED: case IDENTITY_CONTEXT_ERRORS::ERROR_SETGID_FAILED:
tty_logger.log(E_FATAL, "Aborting: Setting GID failed: " + context_user + "/" + context_group); 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); tty_logger.log_to_json_file("E_FATAL", "Setting GID failed for: " + context_user + "/" + context_group, tty_user, tty_group, command);
_exit(1); _exit(1);
break; break;
case IDENTITY_CONTEXT_ERRORS::ERROR_SETUID_FAILED: case IDENTITY_CONTEXT_ERRORS::ERROR_SETUID_FAILED:
tty_logger.log(E_FATAL, "Aborting: Setting UID failed: " + context_user + "/" + context_group); 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); tty_logger.log_to_json_file("E_FATAL", "Setting UID failed for: " + context_user + "/" + context_group, tty_user, tty_group, command);
_exit(1); _exit(1);
break; break;
default: default:
tty_logger.log(E_FATAL, "Aborting: Unknown error while setting identity context."); 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); tty_logger.log_to_json_file("E_FATAL", "Unknown error while setting identity context.", tty_user, tty_group, command);
_exit(1); _exit(1);
break; break;
} }
@@ -174,7 +167,7 @@ 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!!!! // execute the dang command, print to stdout, stderr (of parent), and dump to file for each!!!!
// (and capture exit code in parent) // (and capture exit code in parent)
int exit_code = execvp( processed_command[0], processed_command ); 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_to_json_file("E_FATAL", "failed on execvp in child", tty_user, tty_group, command);
tty_logger.log(E_FATAL, "failed on execvp in child"); tty_logger.log(E_FATAL, "failed on execvp in child");
_Exit(exit_code); _Exit(exit_code);
@@ -191,15 +184,13 @@ int exec_pty(
bool context_override, bool context_override,
std::string context_user, std::string context_user,
std::string context_group, std::string context_group,
bool environment_supplied, bool environment_supplied
std::string task_context,
std::string log_directory
) { ) {
try { try {
std::string exec_command = "exec_pty"; // Command context 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); tty_logger.log_to_json_file("E_INFO", "TTY LAUNCHER: " + command, tty_user, tty_group, exec_command);
// Setup signal handlers // Setup signal handlers
setup_tty_signal_handlers(task_context, log_directory); setup_tty_signal_handlers();
// initialize the terminal settings obj // initialize the terminal settings obj
struct termios ttyOrig; struct termios ttyOrig;
@@ -214,12 +205,12 @@ int exec_pty(
char ** processed_command = expand_env( command ); char ** processed_command = expand_env( command );
if ( stdout_log_fh == NULL ) { 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); tty_logger.log_to_json_file("E_FATAL", "Error opening STDOUT log file. Aborting.", tty_user, tty_group, exec_command);
throw std::runtime_error("Error opening STDOUT log file"); throw std::runtime_error("Error opening STDOUT log file");
} }
if ( stderr_log_fh == NULL ) { 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); tty_logger.log_to_json_file("E_FATAL", "Error opening STDERR log file. Aborting.", tty_user, tty_group, exec_command);
throw std::runtime_error("Error opening STDERR log file"); throw std::runtime_error("Error opening STDERR log file");
} }
@@ -229,12 +220,12 @@ int exec_pty(
if ( pipe( fd_child_stderr_pipe ) == -1 ) { if ( pipe( fd_child_stderr_pipe ) == -1 ) {
std::string error_message = "Failed to create stderr pipe: " + std::string(strerror(errno)); 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); tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, exec_command);
throw std::runtime_error("Failed to create stderr pipe"); throw std::runtime_error("Failed to create stderr pipe");
} }
// using O_CLOEXEC to ensure that the child process closes the file descriptors // 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[READ_END] );
set_tty_cloexec_flag( fd_child_stderr_pipe[WRITE_END], task_context, log_directory ); set_tty_cloexec_flag( fd_child_stderr_pipe[WRITE_END] );
// status result basket for the parent process to capture the child's exit status // status result basket for the parent process to capture the child's exit status
int status = 616; int status = 616;
@@ -245,14 +236,14 @@ int exec_pty(
/* Retrieve the attributes of terminal on which we are started */ /* Retrieve the attributes of terminal on which we are started */
if (tcgetattr(STDIN_FILENO, &ttyOrig) == -1){ 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); tty_logger.log_to_json_file("E_FATAL", "tcgetattr failed", tty_user, tty_group, exec_command);
close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[WRITE_END]); // Pipe Leaks on Error Paths close(fd_child_stderr_pipe[WRITE_END]); // Pipe Leaks on Error Paths
throw std::runtime_error("tcgetattr failed"); throw std::runtime_error("tcgetattr failed");
} }
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) 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); tty_logger.log_to_json_file("E_FATAL", "ioctl-TIOCGWINSZ failed", tty_user, tty_group, exec_command);
close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[WRITE_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"); throw std::runtime_error("ioctl-TIOCGWINSZ failed");
@@ -263,7 +254,7 @@ int exec_pty(
{ {
// fork failed // fork failed
tty_logger.log(E_FATAL, "ptyfork failure: " + std::string(strerror(errno))); 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); tty_logger.log_to_json_file("E_FATAL", "ptyfork failure: " + std::string(strerror(errno)), tty_user, tty_group, exec_command);
close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths close(fd_child_stderr_pipe[READ_END]); // Pipe Leaks on Error Paths
close(fd_child_stderr_pipe[WRITE_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))); throw std::runtime_error("ptyfork() failed: " + std::string(strerror(errno)));
@@ -271,7 +262,7 @@ int exec_pty(
case 0: case 0:
{ {
// child process // 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: default:
{ {
@@ -329,7 +320,7 @@ int exec_pty(
if (num_files_readable == -1) { if (num_files_readable == -1) {
// error occurred in poll() // error occurred in poll()
tty_logger.log(E_FATAL, "poll() failed: " + std::string(strerror(errno))); 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); tty_logger.log_to_json_file("E_FATAL", "poll() failed", tty_user, tty_group, exec_command);
ttyResetExit( &ttyOrig); ttyResetExit( &ttyOrig);
throw std::runtime_error("poll() failed"); throw std::runtime_error("poll() failed");
} }
@@ -349,7 +340,7 @@ int exec_pty(
if (errno == EAGAIN) { continue; } else { if (errno == EAGAIN) { continue; } else {
// error reading from pipe // error reading from pipe
tty_logger.log(E_FATAL, "Error while reading: " + std::string(strerror(errno))); 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); tty_logger.log_to_json_file("E_FATAL", "Error while reading from pipe", tty_user, tty_group, exec_command);
ttyResetExit( &ttyOrig); ttyResetExit( &ttyOrig);
stderr_read_guard.reset(-1); stderr_read_guard.reset(-1);
master_fd_guard.reset(-1); master_fd_guard.reset(-1);
@@ -424,7 +415,7 @@ int exec_pty(
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
int exit_code = WEXITSTATUS(status); int exit_code = WEXITSTATUS(status);
tty_logger.log(E_INFO, "Child exited with status " + std::to_string(exit_code)); 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); tty_logger.log_to_json_file("E_INFO", "Child exited with status " + std::to_string(exit_code), tty_user, tty_group, exec_command);
ttyResetExit( &ttyOrig); ttyResetExit( &ttyOrig);
return exit_code; return exit_code;
} }
@@ -432,7 +423,7 @@ int exec_pty(
else if (WIFSIGNALED(status)) { else if (WIFSIGNALED(status)) {
int signal_number = WTERMSIG(status); int signal_number = WTERMSIG(status);
tty_logger.log(E_FATAL, "Process terminated by signal: " + std::to_string(signal_number)); 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); tty_logger.log_to_json_file("E_FATAL", "Process terminated by signal: " + std::to_string(signal_number), tty_user, tty_group, exec_command);
// Reset signal handler to default before exiting // Reset signal handler to default before exiting
signal(signal_number, SIG_DFL); signal(signal_number, SIG_DFL);
ttyResetExit( &ttyOrig); ttyResetExit( &ttyOrig);
@@ -441,7 +432,7 @@ int exec_pty(
// Handle unexpected exit conditions // Handle unexpected exit conditions
else { else {
tty_logger.log(E_WARN, "Unknown child exit condition."); 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); tty_logger.log_to_json_file("E_WARN", "Unknown child exit condition", tty_user, tty_group, exec_command);
} }
} }

View File

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

View File

@@ -129,8 +129,7 @@ std::string Logger::get_current_timestamp()
//Log to JSON file //Log to JSON file
void Logger::log_to_json_file(const std::string& log_level, const std::string& message, 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& user, const std::string& group,
const std::string& command, const std::string& task_context, const std::string& command, bool log_to_console)
const std::string& log_directory, bool log_to_console)
{ {
// Log to console if requested // Log to console if requested
const char* log_level_str = "UNKNOWN"; const char* log_level_str = "UNKNOWN";
@@ -149,22 +148,9 @@ void Logger::log_to_json_file(const std::string& log_level, const std::string& m
char json_log[2048]; 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()); 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 // 3. Generate filename
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(); std::string timestamp = get_current_timestamp();
filename = "log_" + timestamp + ".json"; std::string filename = "log_" + timestamp + ".json";
}
// 4. Use FdGuard for file handling (to manage file opening and closing) // 4. Use FdGuard for file handling (to manage file opening and closing)
FdGuard check_file(open(filename.c_str(), O_RDONLY)); FdGuard check_file(open(filename.c_str(), O_RDONLY));
@@ -214,3 +200,5 @@ void Logger::log_to_json_file(const std::string& log_level, const std::string& m
free(content); free(content);
} }
} }
} // namespace lcpex

View File

@@ -51,8 +51,7 @@ class Logger {
void log_task(int LOG_LEVEL, std::string task_name, 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, 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& user, const std::string& group,
const std::string& command, const std::string& task_context = "", const std::string& command, bool log_to_console = true);
const std::string& log_directory = "", bool log_to_console = true);
// Helper methods // Helper methods
std::string get_current_timestamp(); std::string get_current_timestamp();
std::string get_user_name(); std::string get_user_name();

View File

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