mirror of
https://github.com/perk11/runwhenidle.git
synced 2026-01-08 05:13:57 -05:00
Add support of managing an external pid
This commit is contained in:
@@ -42,6 +42,7 @@ If you want to install it system-wide, run `sudo make install` or simply `sudo c
|
||||
| Option | Description | Default Value |
|
||||
|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
||||
| `--timeout\| -t <seconds>` | Set the user idle time after which the command can run in seconds. | 300 seconds |
|
||||
| `--pid\|-p <pid>` | Monitor an existing command rather than start a new one. When this option is used, shell_command_to_run should not be passed. | |
|
||||
| `--start-monitor-after\| -a <ms>` | Set an initial delay in milliseconds before monitoring starts. During this time command runs unrestricted. This helps to catch quick errors. | 300 ms |
|
||||
| `--pause-method\| -m <method>` | Specify method for pausing the command when the user is not idle. Available Options: SIGTSTP (can be ignored by the program), SIGSTOP (cannot be ignored). | SIGTSTP |
|
||||
| `--verbose\| -v` | Enable verbose output for monitoring. | Not verbose |
|
||||
|
||||
@@ -17,9 +17,10 @@ const long START_MONITOR_AFTER_MAX_SUPPORTED_VALUE = TIMEOUT_MAX_SUPPORTED_VALUE
|
||||
const long START_MONITOR_AFTER_MIN_SUPPORTED_VALUE = 0;
|
||||
|
||||
void print_usage(char *binary_name) {
|
||||
printf("Usage: %s [OPTIONS] shell_command_to_run [shell_command_arguments]\n", binary_name);
|
||||
printf("Usage: %s [OPTIONS] [shell_command_to_run] [shell_command_arguments]\n", binary_name);
|
||||
printf("\nOptions:\n");
|
||||
printf(" --timeout|-t <seconds> Set the user idle time after which the command can run in seconds (default: 300 seconds).\n");
|
||||
printf(" --pid|-p <pid> Monitor an existing command rather than start a new one. When this option is used, shell_command_to_run should not be passed.\n");
|
||||
printf(" --start-monitor-after|-a <ms> Set an initial delay in milliseconds before monitoring starts. During this time command runs unrestricted. This helps to catch errors happening shortly after the execution has started. (default: 300 ms).\n");
|
||||
printf(" --pause-method|-m <method> Specify method for pausing the command when user is not idle. Available parameters: SIGTSTP (can be ignored by the program), SIGSTOP (can not be ignored). (default: SIGTSTP).\n");
|
||||
printf(" --verbose|-v Enable verbose output for monitoring.\n");
|
||||
@@ -70,9 +71,10 @@ char *read_remaining_arguments_as_char(int argc,
|
||||
return remaining_arguments_string;
|
||||
}
|
||||
|
||||
char *parse_command_line_arguments(int argc, char *argv[]) {
|
||||
void parse_command_line_arguments(int argc, char *argv[]) {
|
||||
struct option long_options[] = {
|
||||
{"timeout", required_argument, NULL, 't'},
|
||||
{"pid", required_argument, NULL, 'p'},
|
||||
{"start-monitor-after", required_argument, NULL, 'a'},
|
||||
{"pause-method", required_argument, NULL, 'm'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
@@ -85,7 +87,7 @@ char *parse_command_line_arguments(int argc, char *argv[]) {
|
||||
|
||||
// Parse command line options
|
||||
int option;
|
||||
while ((option = getopt_long(argc, argv, "+hvqt:a:m:V", long_options, NULL)) != -1) {
|
||||
while ((option = getopt_long(argc, argv, "+hvqp:t:a:m:V", long_options, NULL)) != -1) {
|
||||
switch (option) {
|
||||
case 't': {
|
||||
long timeout_arg_value = strtol(optarg, NULL, 10);
|
||||
@@ -99,6 +101,16 @@ char *parse_command_line_arguments(int argc, char *argv[]) {
|
||||
user_idle_timeout_ms = timeout_arg_value * 1000;
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
external_pid = strtol(optarg, NULL, 10);
|
||||
if (external_pid < 1) {
|
||||
fprintf_error("Invalid pid value: \"%s\".", optarg);
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
start_monitor_after_ms = strtol(optarg, NULL, 10);
|
||||
|
||||
@@ -166,9 +178,21 @@ char *parse_command_line_arguments(int argc, char *argv[]) {
|
||||
user_idle_timeout_ms,
|
||||
start_monitor_after_ms
|
||||
);
|
||||
if (optind >= argc) {
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
if (external_pid) {
|
||||
if (optind < argc) {
|
||||
fprintf_error(
|
||||
"Running command is not supported when -p option is used. Found unexpected \"%s\"\n",
|
||||
read_remaining_arguments_as_char(argc, argv)
|
||||
);
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if (optind >= argc) {
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
shell_command_to_run = read_remaining_arguments_as_char(argc, argv);
|
||||
}
|
||||
if (quiet && debug) {
|
||||
fprintf_error("Incompatible options --quiet|-q and --debug used\n");
|
||||
@@ -181,5 +205,4 @@ char *parse_command_line_arguments(int argc, char *argv[]) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return read_remaining_arguments_as_char(argc, argv);
|
||||
}
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#define RUNWHENIDLE_ARGUMENTS_PARSING_H
|
||||
extern long start_monitor_after_ms;
|
||||
extern long unsigned user_idle_timeout_ms;
|
||||
extern char *shell_command_to_run;
|
||||
extern pid_t external_pid;
|
||||
|
||||
/**
|
||||
* Parses command line arguments and sets relevant program options.
|
||||
*
|
||||
* @param argc The number of command line arguments.
|
||||
* @param argv An array of strings representing the command line arguments.
|
||||
* @return A character pointer to the remaining command line arguments as a single string.
|
||||
*/
|
||||
char *parse_command_line_arguments(int argc, char *argv[]);
|
||||
void parse_command_line_arguments(int argc, char *argv[]);
|
||||
|
||||
#endif //RUNWHENIDLE_ARGUMENTS_PARSING_H
|
||||
|
||||
14
main.c
14
main.c
@@ -16,6 +16,8 @@
|
||||
#define VERSION 'unkown'
|
||||
#endif
|
||||
|
||||
char *shell_command_to_run;
|
||||
pid_t external_pid = 0;
|
||||
int verbose = 0;
|
||||
int quiet = 0;
|
||||
int debug = 0;
|
||||
@@ -59,6 +61,9 @@ int handle_interruption() {
|
||||
}
|
||||
resume_command_recursively(pid);
|
||||
}
|
||||
if (external_pid) {
|
||||
return 0;
|
||||
}
|
||||
//Wait for the child process to complete
|
||||
return wait_for_pid_to_exit_synchronously(pid);
|
||||
}
|
||||
@@ -149,7 +154,7 @@ long long pause_or_resume_command_depending_on_user_activity(
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *shell_command_to_run = parse_command_line_arguments(argc, argv);
|
||||
parse_command_line_arguments(argc, argv);
|
||||
|
||||
//Open display and initialize XScreensaverInfo for querying idle time
|
||||
x_display = XOpenDisplay(NULL);
|
||||
@@ -169,8 +174,11 @@ 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.\n");
|
||||
}
|
||||
|
||||
pid = run_shell_command(shell_command_to_run);
|
||||
if (external_pid == 0) {
|
||||
pid = run_shell_command(shell_command_to_run);
|
||||
} else {
|
||||
pid = external_pid;
|
||||
}
|
||||
free(shell_command_to_run);
|
||||
struct timespec time_when_command_started;
|
||||
clock_gettime(CLOCK_MONOTONIC, &time_when_command_started);
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <sys/wait.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "arguments_parsing.h"
|
||||
#include "sleep_utils.h"
|
||||
#include "process_handling.h"
|
||||
#include "output_settings.h"
|
||||
#include "pause_methods.h"
|
||||
@@ -280,11 +282,28 @@ int wait_for_pid_to_exit_synchronously(int pid) {
|
||||
|
||||
void exit_if_pid_has_finished(pid_t pid) {
|
||||
int status;
|
||||
int finished = 0;
|
||||
int exit_code;
|
||||
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 (external_pid) {
|
||||
if (kill(pid, 0) == -1) {
|
||||
finished = 1;
|
||||
exit_code = 0;
|
||||
}
|
||||
} else {
|
||||
if (waitpid(pid, &status, WNOHANG + WUNTRACED) == pid && WIFEXITED(status)) {
|
||||
finished = 1;
|
||||
exit_code = WEXITSTATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
if (verbose) {
|
||||
fprintf(stderr, "PID %i has finished with exit code %u\n", pid, exit_code);
|
||||
fprintf(stderr, "PID %i has finished", pid);
|
||||
if (!external_pid) {
|
||||
fprintf(stderr, " with exit code %u", exit_code);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
6
util/print_time.sh
Executable file
6
util/print_time.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#1/bin/sh
|
||||
while true
|
||||
do
|
||||
date
|
||||
sleep 1
|
||||
done
|
||||
Reference in New Issue
Block a user