Files
runwhenidle/process_handling.c
Konstantin Pereiaslov de8b698545 Pass errno to handle_kill_error rather than reading it there and use strerror() rather than parsing error manually.
This fixes the compilation warning where reason was possibly undefined.
2023-09-21 01:44:07 -05:00

107 lines
2.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include "process_handling.h"
#include "output_settings.h"
#include "pause_methods.h"
#include "tty_utils.h"
pid_t run_shell_command(const char *shell_command_to_run) {
if (verbose) {
printf("Starting \"%s\"\n", shell_command_to_run);
}
pid_t pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
} else if (pid == 0) {
// Child process
execl("/bin/sh", "sh", "-c", shell_command_to_run, (char *) NULL);
perror("execl");
exit(1);
}
if (!quiet) {
printf("Started \"%s\" with PID %i\n", shell_command_to_run, pid);
}
return pid;
}
/**
* Handles errors that may occur while sending a signal to a process.
*
* @param signal_name The name of the signal being sent.
* @param pid The process ID of the target process.
* @param kill_errno errno of kill function
*/
void handle_kill_error(char *signal_name, pid_t pid, int kill_errno) {
fprintf(stderr, "Failed to send %s signal to PID %i: %s\n", signal_name, pid, strerror(kill_errno));
}
void send_signal_to_pid(pid_t pid, int signal, char *signal_name) {
if (debug) {
printf("Sending %s to %i\n",signal_name, pid);
}
int kill_result = kill(pid, signal);
if (kill_result == -1) {
handle_kill_error(signal_name, pid, errno);
exit(1);
} else {
if (debug) fprintf(stderr, "kill function sending %s returned %i\n",signal_name, kill_result);
}
}
void pause_command(pid_t pid) {
if (!quiet) {
printf("User activity is detected, pausing PID %i\n", pid);
}
switch (pause_method) {
case PAUSE_METHOD_SIGTSTP:
send_signal_to_pid(pid, SIGTSTP, "SIGTSTP");
break;
case PAUSE_METHOD_SIGSTOP:
send_signal_to_pid(pid, SIGSTOP, "SIGSTOP");
break;
default:
fprintf_error("Unsupported pause method: %i\n", pause_method);
exit(1);
}
}
void resume_command(pid_t pid) {
if (!quiet) {
printf("Resuming PID %i\n", pid);
}
send_signal_to_pid(pid, SIGCONT, "SIGCONT");
}
int wait_for_pid_to_exit_synchronously(int pid) {
int status;
waitpid(pid, &status, 0);
int exit_code = WEXITSTATUS(status);
if (verbose) {
fprintf(stderr, "PID %i has finished with exit code %u\n", pid, exit_code);
}
return exit_code;
}
void exit_if_pid_has_finished(pid_t pid) {
int status;
if (debug) fprintf(stderr, "Checking if PID %i has finished\n", pid);
if (waitpid(pid, &status, WNOHANG + WUNTRACED) == pid && WIFEXITED(status)) {
int exit_code = WEXITSTATUS(status);
if (verbose) {
fprintf(stderr, "PID %i has finished with exit code %u\n", pid, exit_code);
}
exit(exit_code);
}
}