lcpex enhancements - modified json log file format
parent
08c9d5bf07
commit
bd8191c2d2
|
@ -13,6 +13,10 @@ 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
|
||||||
|
|
||||||
|
@ -20,20 +24,24 @@ 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);
|
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) {
|
} else if (sig == SIGINT) {
|
||||||
logger.log_to_json_file("E_FATAL", "SIGINT received. Gracefully terminating...", user, group, command);
|
logger.log_to_json_file("E_FATAL", "SIGINT received. Gracefully terminating...", user, group, command, g_task_context, g_log_directory);
|
||||||
} else if (sig == SIGTERM) {
|
} else if (sig == SIGTERM) {
|
||||||
logger.log_to_json_file("E_FATAL", "SIGTERM received. Terminating...", user, group, command);
|
logger.log_to_json_file("E_FATAL", "SIGTERM received. Terminating...", user, group, command, g_task_context, g_log_directory);
|
||||||
} else if (sig == SIGSEGV) {
|
} else if (sig == SIGSEGV) {
|
||||||
logger.log_to_json_file("E_FATAL", "SIGSEGV received. Possible segmentation fault.", user, group, command);
|
logger.log_to_json_file("E_FATAL", "SIGSEGV received. Possible segmentation fault.", user, group, command, g_task_context, g_log_directory);
|
||||||
} else {
|
} else {
|
||||||
logger.log_to_json_file("E_FATAL", "Unhandled signal received", user, group, command);
|
logger.log_to_json_file("E_FATAL", "Unhandled signal received", user, group, command, g_task_context, g_log_directory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup signal registrations
|
// Setup signal registrations
|
||||||
void setup_signal_handlers() {
|
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;
|
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);
|
||||||
|
@ -43,25 +51,25 @@ void setup_signal_handlers() {
|
||||||
// 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); // Log to JSON file
|
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory); // 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); // Log to JSON file
|
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory); // 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); // Log to JSON file
|
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory); // 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); // Log to JSON file
|
logger.log_to_json_file("E_FATAL", error_message, user, group, command, task_context, log_directory); // Log to JSON file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +80,9 @@ 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 ) {
|
||||||
|
@ -103,7 +113,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);
|
logger.log_to_json_file("E_INFO", "LAUNCHER: " + prefix, user, group, command, task_context, log_directory);
|
||||||
//logger.log(E_INFO, "LAUNCHER: " + prefix);
|
//logger.log(E_INFO, "LAUNCHER: " + prefix);
|
||||||
return prefix;
|
return prefix;
|
||||||
|
|
||||||
|
@ -123,7 +133,9 @@ 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
|
||||||
|
@ -134,19 +146,21 @@ 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();
|
setup_signal_handlers(task_context, log_directory);
|
||||||
|
|
||||||
// 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 );
|
return exec_pty( command, stdout_log_fh, stderr_log_fh, context_override, context_user, context_group, supply_environment, task_context, log_directory );
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 );
|
return execute( command, stdout_log_fh, stderr_log_fh, context_override, context_user, context_group, supply_environment, task_context, log_directory );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,14 +172,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)
|
void set_cloexec_flag(int fd, std::string task_context = "", std::string log_directory = "")
|
||||||
{
|
{
|
||||||
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);
|
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));
|
throw std::runtime_error("fcntl(F_SETFD) failed for fd " + std::to_string(fd));
|
||||||
}
|
}
|
||||||
|
@ -195,7 +209,7 @@ void set_cloexec_flag(int fd)
|
||||||
* 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[]) {
|
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 = "") {
|
||||||
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
|
||||||
|
@ -213,33 +227,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);
|
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);
|
_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);
|
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);
|
_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);
|
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);
|
_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);
|
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);
|
_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);
|
logger.log_to_json_file("E_FATAL", "Aborting: Unknown error while setting identity context.", user, group, command, task_context, log_directory);
|
||||||
_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);
|
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");
|
logger.log(E_FATAL, "failed on execvp in child");
|
||||||
_Exit(exit_code);
|
_Exit(exit_code);
|
||||||
}
|
}
|
||||||
|
@ -251,7 +265,9 @@ 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 {
|
||||||
|
@ -286,10 +302,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] );
|
set_cloexec_flag( fd_child_stdout_pipe[READ_END], task_context, log_directory );
|
||||||
set_cloexec_flag( fd_child_stderr_pipe[READ_END] );
|
set_cloexec_flag( fd_child_stderr_pipe[READ_END], task_context, log_directory );
|
||||||
set_cloexec_flag( fd_child_stdout_pipe[WRITE_END] );
|
set_cloexec_flag( fd_child_stdout_pipe[WRITE_END], task_context, log_directory );
|
||||||
set_cloexec_flag( fd_child_stderr_pipe[WRITE_END] );
|
set_cloexec_flag( fd_child_stderr_pipe[WRITE_END], task_context, log_directory );
|
||||||
|
|
||||||
// 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;
|
||||||
|
@ -300,7 +316,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);
|
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[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
|
||||||
|
@ -317,7 +333,9 @@ 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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +394,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);
|
logger.log_to_json_file("E_FATAL", "poll() failed", user, group, command, task_context, log_directory);
|
||||||
throw std::runtime_error("poll() failed");
|
throw std::runtime_error("poll() failed");
|
||||||
}
|
}
|
||||||
if (num_files_readable == 0) {
|
if (num_files_readable == 0) {
|
||||||
|
@ -393,7 +411,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);
|
logger.log_to_json_file("E_FATAL", "Error while reading from pipe", user, group, command, task_context, log_directory);
|
||||||
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);
|
||||||
|
@ -457,13 +475,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);
|
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
|
// 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);
|
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
|
// 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
|
||||||
|
@ -472,7 +490,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);
|
logger.log_to_json_file("E_WARN", "Unknown child exit condition", user, group, command, task_context, log_directory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,9 @@ 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 = ""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,7 +89,9 @@ 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 = ""
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,6 +12,9 @@ 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
|
||||||
|
@ -19,19 +22,23 @@ 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);
|
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) {
|
} else if (sig == SIGINT) {
|
||||||
tty_logger.log_to_json_file("E_FATAL", "SIGINT received. Gracefully terminating...", tty_user, tty_group, command);
|
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) {
|
} else if (sig == SIGTERM) {
|
||||||
tty_logger.log_to_json_file("E_FATAL", "SIGTERM received. Terminating...", tty_user, tty_group, command);
|
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) {
|
} else if (sig == SIGSEGV) {
|
||||||
tty_logger.log_to_json_file("E_FATAL", "SIGSEGV received. Possible segmentation fault.", tty_user, tty_group, command);
|
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 {
|
} else {
|
||||||
tty_logger.log_to_json_file("E_FATAL", "Unhandled signal received", tty_user, tty_group, command);
|
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
|
// Setup signal registrations
|
||||||
void setup_tty_signal_handlers() {
|
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;
|
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);
|
||||||
|
@ -41,25 +48,25 @@ void setup_tty_signal_handlers() {
|
||||||
// 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); // Log to JSON file
|
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory); // 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); // Log to JSON file
|
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory); // 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); // Log to JSON file
|
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory); // 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); // Log to JSON file
|
tty_logger.log_to_json_file("E_FATAL", error_message, tty_user, tty_group, command, task_context, log_directory); // Log to JSON file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,21 +82,21 @@ void setup_tty_signal_handlers() {
|
||||||
* 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)
|
void set_tty_cloexec_flag(int fd, std::string task_context = "", std::string log_directory = "")
|
||||||
{
|
{
|
||||||
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);
|
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));
|
throw std::runtime_error("fcntl(F_SETFD) failed for fd " + std::to_string(fd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void safe_perror( const char * msg, struct termios * ttyOrig )
|
void safe_perror( const char * msg, struct termios * ttyOrig, std::string task_context = "", std::string log_directory = "" )
|
||||||
{
|
{
|
||||||
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); // Log the message before exiting
|
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;
|
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);
|
||||||
|
@ -118,7 +125,7 @@ void safe_perror( const char * msg, struct termios * ttyOrig )
|
||||||
* 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 )
|
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 = "" )
|
||||||
{
|
{
|
||||||
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
|
||||||
|
@ -138,27 +145,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);
|
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);
|
_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);
|
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);
|
_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);
|
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);
|
_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);
|
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);
|
_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);
|
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);
|
_exit(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +174,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);
|
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");
|
tty_logger.log(E_FATAL, "failed on execvp in child");
|
||||||
_Exit(exit_code);
|
_Exit(exit_code);
|
||||||
|
|
||||||
|
@ -184,13 +191,15 @@ 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);
|
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 signal handlers
|
||||||
setup_tty_signal_handlers();
|
setup_tty_signal_handlers(task_context, log_directory);
|
||||||
// initialize the terminal settings obj
|
// initialize the terminal settings obj
|
||||||
struct termios ttyOrig;
|
struct termios ttyOrig;
|
||||||
|
|
||||||
|
@ -205,12 +214,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);
|
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");
|
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);
|
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");
|
throw std::runtime_error("Error opening STDERR log file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,12 +229,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);
|
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");
|
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] );
|
set_tty_cloexec_flag( fd_child_stderr_pipe[READ_END], task_context, log_directory );
|
||||||
set_tty_cloexec_flag( fd_child_stderr_pipe[WRITE_END] );
|
set_tty_cloexec_flag( fd_child_stderr_pipe[WRITE_END], task_context, log_directory );
|
||||||
// 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;
|
||||||
|
|
||||||
|
@ -236,14 +245,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);
|
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[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);
|
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[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");
|
||||||
|
@ -254,7 +263,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);
|
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[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)));
|
||||||
|
@ -262,7 +271,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 );
|
run_child_process( fd_child_stderr_pipe, processed_command, &ttyOrig, context_override, context_user, context_group, task_context, log_directory );
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -320,7 +329,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);
|
tty_logger.log_to_json_file("E_FATAL", "poll() failed", tty_user, tty_group, exec_command, task_context, log_directory);
|
||||||
ttyResetExit( &ttyOrig);
|
ttyResetExit( &ttyOrig);
|
||||||
throw std::runtime_error("poll() failed");
|
throw std::runtime_error("poll() failed");
|
||||||
}
|
}
|
||||||
|
@ -340,7 +349,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);
|
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);
|
ttyResetExit( &ttyOrig);
|
||||||
stderr_read_guard.reset(-1);
|
stderr_read_guard.reset(-1);
|
||||||
master_fd_guard.reset(-1);
|
master_fd_guard.reset(-1);
|
||||||
|
@ -415,7 +424,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);
|
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);
|
ttyResetExit( &ttyOrig);
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
@ -423,7 +432,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);
|
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
|
// Reset signal handler to default before exiting
|
||||||
signal(signal_number, SIG_DFL);
|
signal(signal_number, SIG_DFL);
|
||||||
ttyResetExit( &ttyOrig);
|
ttyResetExit( &ttyOrig);
|
||||||
|
@ -432,7 +441,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);
|
tty_logger.log_to_json_file("E_WARN", "Unknown child exit condition", tty_user, tty_group, exec_command, task_context, log_directory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,9 @@ 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 = ""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,8 @@ 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, bool log_to_console)
|
const std::string& command, const std::string& task_context,
|
||||||
|
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";
|
||||||
|
@ -148,9 +149,22 @@ 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
|
// 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();
|
std::string timestamp = get_current_timestamp();
|
||||||
std::string filename = "log_" + timestamp + ".json";
|
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));
|
||||||
|
|
|
@ -51,7 +51,8 @@ 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, bool log_to_console = true);
|
const std::string& command, const std::string& task_context = "",
|
||||||
|
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();
|
||||||
|
|
|
@ -470,7 +470,9 @@ 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
|
||||||
);
|
);
|
||||||
|
|
||||||
// **********************************************
|
// **********************************************
|
||||||
|
@ -539,7 +541,9 @@ 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
|
||||||
);
|
);
|
||||||
|
|
||||||
// **********************************************
|
// **********************************************
|
||||||
|
@ -591,7 +595,9 @@ 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
|
||||||
);
|
);
|
||||||
|
|
||||||
// **********************************************
|
// **********************************************
|
||||||
|
|
Loading…
Reference in New Issue