diff --git a/Makefile b/Makefile index 4bbee13..b0d1093 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CC=gcc ifeq ($(PREFIX),) PREFIX := /usr endif -SOURCES = time_utils.c sleep_utils.c tty_utils.c main.c +SOURCES = time_utils.c sleep_utils.c tty_utils.c main.c process_handling.c OBJECTS = $(SOURCES:.c=.o) all: executable diff --git a/main.c b/main.c index 4b6279d..536985d 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,6 @@ #include #include -#include -#include #include -#include #include #include #include @@ -14,6 +11,7 @@ #include "sleep_utils.h" #include "time_utils.h" #include "tty_utils.h" +#include "process_handling.h" #ifndef VERSION #define VERSION 'unkown' @@ -41,44 +39,6 @@ volatile sig_atomic_t interruption_received = 0; volatile sig_atomic_t command_paused = 0; pid_t pid; -void handle_kill_error(char *signal_name, pid_t pid) { - const char *reason; - if (errno == EPERM) { - reason = "Operation not permitted"; - } else if (errno == EINVAL) { - reason = "Invalid signal number"; - } else if (errno == ESRCH) { - reason = "No such process"; - } - - printf("Failed to send %s signal to PID %i: %s\n", signal_name, pid, reason); -} -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); - 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); - } - send_signal_to_pid(pid, SIGTSTP, "SIGTSTP"); -} - -void resume_command(pid_t pid) { - if (!quiet) { - printf("Resuming PID %i\n", pid); - } - send_signal_to_pid(pid, SIGCONT, "SIGCONT"); -} void print_usage(char *binary_name) { printf("Usage: %s [OPTIONS] shell_command_to_run [shell_command_arguments]\n", binary_name); @@ -94,26 +54,6 @@ void print_version() { printf("runwhenidle %s\n", VERSION); } -pid_t run_shell_command(const char *shell_command_to_run, pid_t pid) { - if (verbose) { - printf("Starting \"%s\"\n", shell_command_to_run); - } - 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; -} - void exit_if_pid_has_finished(pid_t pid) { int status; if (debug) fprintf(stderr, "Checking if PID %i has finished\n", pid); @@ -370,7 +310,7 @@ int main(int argc, char *argv[]) { fprintf_error("No available method for detecting user idle time on the system, user will be considered idle to allow the command to finish."); } - pid = run_shell_command(shell_command_to_run, pid); + pid = run_shell_command(shell_command_to_run); free(shell_command_to_run); struct timespec time_when_command_started; clock_gettime(CLOCK_MONOTONIC, &time_when_command_started); diff --git a/output_settings.h b/output_settings.h new file mode 100644 index 0000000..5b3e098 --- /dev/null +++ b/output_settings.h @@ -0,0 +1,7 @@ +#ifndef RUNWHENIDLE_OUTPUT_SETTINGS_H +#define RUNWHENIDLE_OUTPUT_SETTINGS_H +extern int verbose; +extern int quiet; +extern int debug; + +#endif //RUNWHENIDLE_OUTPUT_SETTINGS_H diff --git a/process_handling.c b/process_handling.c new file mode 100644 index 0000000..69f3d19 --- /dev/null +++ b/process_handling.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include + +#include "process_handling.h" +#include "output_settings.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. + */ +void handle_kill_error(char *signal_name, pid_t pid) { + const char *reason; + if (errno == EPERM) { + reason = "Operation not permitted"; + } else if (errno == EINVAL) { + reason = "Invalid signal number"; + } else if (errno == ESRCH) { + reason = "No such process"; + } + + fprintf(stderr, "Failed to send %s signal to PID %i: %s\n", signal_name, pid, reason); +} + +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); + 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); + } + send_signal_to_pid(pid, SIGTSTP, "SIGTSTP"); +} + +void resume_command(pid_t pid) { + if (!quiet) { + printf("Resuming PID %i\n", pid); + } + send_signal_to_pid(pid, SIGCONT, "SIGCONT"); +} diff --git a/process_handling.h b/process_handling.h new file mode 100644 index 0000000..55aaea7 --- /dev/null +++ b/process_handling.h @@ -0,0 +1,33 @@ +#ifndef RUNWHENIDLE_PROCESS_HANDLING_H +#define RUNWHENIDLE_PROCESS_HANDLING_H +/** + * Sends a signal to a specified process and handles any errors that occur during the process. + * + * @param pid The process ID of the target process. + * @param signal The signal to send. + * @param signal_name The name of the signal being sent. + */ +void send_signal_to_pid(pid_t pid, int signal, char *signal_name); +/** + * Pauses a specified process by sending the SIGTSTP signal. + * + * @param pid The process ID of the target process. + */ +void pause_command(pid_t pid); + +/** + * Resumes a specified process by sending the SIGCONT signal. + * + * @param pid The process ID of the target process. + */ +void resume_command(pid_t pid); + +/** + * Executes a shell command in a new process and returns the process ID of the child process. + * On failure will exit. + * + * @param shell_command_to_run The shell command to execute. + * @return The PID of the child process on success, + */ +pid_t run_shell_command(const char *shell_command_to_run); +#endif //RUNWHENIDLE_PROCESS_HANDLING_H