mirror of
https://github.com/perk11/runwhenidle.git
synced 2026-01-08 21:27:57 -05:00
Move argument parsing to a separate file
This commit is contained in:
2
Makefile
2
Makefile
@@ -4,7 +4,7 @@ CC=gcc
|
||||
ifeq ($(PREFIX),)
|
||||
PREFIX := /usr
|
||||
endif
|
||||
SOURCES = time_utils.c sleep_utils.c tty_utils.c main.c process_handling.c
|
||||
SOURCES = time_utils.c sleep_utils.c tty_utils.c process_handling.c arguments_parsing.c main.c
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
all: executable
|
||||
|
||||
|
||||
147
arguments_parsing.c
Normal file
147
arguments_parsing.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "output_settings.h"
|
||||
#include "arguments_parsing.h"
|
||||
#include "tty_utils.h"
|
||||
|
||||
const long TIMEOUT_MAX_SUPPORTED_VALUE = 100000000; //~3 years
|
||||
const long TIMEOUT_MIN_SUPPORTED_VALUE = 1;
|
||||
const long START_MONITOR_AFTER_MAX_SUPPORTED_VALUE = TIMEOUT_MAX_SUPPORTED_VALUE*1000;
|
||||
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("\nOptions:\n");
|
||||
printf(" --timeout, -t <timeout_value_in_seconds> Set the user idle time after which the command can run in seconds (default: 300 seconds).\n");
|
||||
printf(" --start-monitor-after, -a <delay_in_ms> Set an initial delay in milliseconds before monitoring starts. During this time command runs unrestricted. This helps to catch quick errors. (default: 300 ms).\n");
|
||||
printf(" --verbose, -v Enable verbose output for monitoring.\n");
|
||||
printf(" --debug Enable debugging output.\n");
|
||||
printf(" --quiet, -q Suppress all program output except errors.\n");
|
||||
printf(" --version, -V Print the program version information.\n");
|
||||
}
|
||||
void print_version() {
|
||||
printf("runwhenidle %s\n", VERSION);
|
||||
}
|
||||
|
||||
char *read_remaining_arguments_as_char(int argc,
|
||||
char *const *argv) {
|
||||
if (optind == argc) { //there is one argument remaining
|
||||
char *last_and_only_argument = strdup(argv[optind]);
|
||||
return last_and_only_argument;
|
||||
}
|
||||
|
||||
size_t memory_to_be_allocated_for_remaining_arguments_string = 0;
|
||||
for (int i = optind; i < argc; i++) {
|
||||
memory_to_be_allocated_for_remaining_arguments_string +=
|
||||
strlen(argv[i]) + 1; // +1 for space separator or null terminator
|
||||
}
|
||||
|
||||
char *remaining_arguments_string = NULL; // Variable to store the remaining_arguments_string
|
||||
|
||||
// Allocate memory for the remaining_arguments_string
|
||||
remaining_arguments_string = malloc(memory_to_be_allocated_for_remaining_arguments_string);
|
||||
if (remaining_arguments_string == NULL) {
|
||||
//not using fprintf_error here intentionally
|
||||
fprintf(stderr, "Failed to allocate memory while parsing command to be ran.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t current_length_of_all_arguments = 0;
|
||||
for (int i = optind; i < argc; i++) {
|
||||
size_t current_argument_length = strlen(argv[i]);
|
||||
memcpy(remaining_arguments_string + current_length_of_all_arguments, argv[i], current_argument_length);
|
||||
current_length_of_all_arguments += current_argument_length;
|
||||
remaining_arguments_string[current_length_of_all_arguments++] = ' '; // Add space separator
|
||||
}
|
||||
assert(current_length_of_all_arguments == memory_to_be_allocated_for_remaining_arguments_string);
|
||||
remaining_arguments_string[current_length_of_all_arguments - 1] = '\0'; // Replace the last space separator with a null terminator
|
||||
|
||||
return remaining_arguments_string;
|
||||
}
|
||||
|
||||
char *parse_command_line_arguments(int argc, char *argv[]) {
|
||||
struct option long_options[] = {
|
||||
{"timeout", required_argument, NULL, 't'},
|
||||
{"start-monitor-after", required_argument, NULL, 'a'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{"debug", no_argument, NULL, 'd'},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'V'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
// Parse command line options
|
||||
int option;
|
||||
while ((option = getopt_long(argc, argv, "+hvqt:a:V", long_options, NULL)) != -1) {
|
||||
switch (option) {
|
||||
case 't': {
|
||||
|
||||
long timeout_arg_value = strtol(optarg, NULL, 10);
|
||||
if (timeout_arg_value < TIMEOUT_MIN_SUPPORTED_VALUE ||
|
||||
timeout_arg_value > TIMEOUT_MAX_SUPPORTED_VALUE || errno != 0) {
|
||||
fprintf_error("Invalid timeout value: \"%s\". Range supported: %ld-%ld", optarg,
|
||||
TIMEOUT_MIN_SUPPORTED_VALUE, TIMEOUT_MAX_SUPPORTED_VALUE);
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
user_idle_timeout_ms = timeout_arg_value * 1000;
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
start_monitor_after_ms = strtol(optarg, NULL, 10);
|
||||
|
||||
if (start_monitor_after_ms < START_MONITOR_AFTER_MIN_SUPPORTED_VALUE || errno != 0) {
|
||||
fprintf_error( "Invalid start-monitor-after time value: \"%s\" Range supported: %ld-%ld.\n", optarg,
|
||||
START_MONITOR_AFTER_MIN_SUPPORTED_VALUE, START_MONITOR_AFTER_MAX_SUPPORTED_VALUE
|
||||
);
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(0);
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'd':
|
||||
debug = 1;
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (debug) fprintf(stderr, "verbose: %i, debug: %i, quiet: %i, user_idle_timeout_ms: %i, start_monitoring_after_ms: %lld\n", verbose, debug, quiet, user_idle_timeout_ms, start_monitor_after_ms);
|
||||
if (optind >= argc) {
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (quiet && debug) {
|
||||
fprintf_error("Incompatible options --quiet|-q and --debug used");
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (quiet && verbose) {
|
||||
fprintf_error("Incompatible options --quiet|-q and --verbose|-v used");
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return read_remaining_arguments_as_char(argc, argv);
|
||||
}
|
||||
14
arguments_parsing.h
Normal file
14
arguments_parsing.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef RUNWHENIDLE_ARGUMENTS_PARSING_H
|
||||
#define RUNWHENIDLE_ARGUMENTS_PARSING_H
|
||||
extern long start_monitor_after_ms;
|
||||
extern long unsigned user_idle_timeout_ms;
|
||||
|
||||
/**
|
||||
* 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[]);
|
||||
#endif //RUNWHENIDLE_ARGUMENTS_PARSING_H
|
||||
139
main.c
139
main.c
@@ -3,15 +3,13 @@
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "sleep_utils.h"
|
||||
#include "time_utils.h"
|
||||
#include "tty_utils.h"
|
||||
#include "process_handling.h"
|
||||
#include "arguments_parsing.h"
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION 'unkown'
|
||||
@@ -25,10 +23,6 @@ long start_monitor_after_ms = 300;
|
||||
long unsigned user_idle_timeout_ms = 300000;
|
||||
long long polling_interval_ms = 1000;
|
||||
const long long POLLING_INTERVAL_BEFORE_STARTING_MONITORING_MS = 100;
|
||||
const long TIMEOUT_MAX_SUPPORTED_VALUE = 100000000; //~3 years
|
||||
const long TIMEOUT_MIN_SUPPORTED_VALUE = 1;
|
||||
const long START_MONITOR_AFTER_MAX_SUPPORTED_VALUE = TIMEOUT_MAX_SUPPORTED_VALUE*1000;
|
||||
const long START_MONITOR_AFTER_MIN_SUPPORTED_VALUE = 0;
|
||||
|
||||
int xscreensaver_is_available;
|
||||
Display *x_display;
|
||||
@@ -40,55 +34,6 @@ volatile sig_atomic_t command_paused = 0;
|
||||
pid_t pid;
|
||||
|
||||
|
||||
void print_usage(char *binary_name) {
|
||||
printf("Usage: %s [OPTIONS] shell_command_to_run [shell_command_arguments]\n", binary_name);
|
||||
printf("\nOptions:\n");
|
||||
printf(" --timeout, -t <timeout_value_in_seconds> Set the user idle time after which the command can run in seconds (default: 300 seconds).\n");
|
||||
printf(" --start-monitor-after, -a <delay_in_ms> Set an initial delay in milliseconds before monitoring starts. During this time command runs unrestricted. This helps to catch quick errors. (default: 300 ms).\n");
|
||||
printf(" --verbose, -v Enable verbose output for monitoring.\n");
|
||||
printf(" --debug Enable debugging output.\n");
|
||||
printf(" --quiet, -q Suppress all program output except errors.\n");
|
||||
printf(" --version, -V Print the program version information.\n");
|
||||
}
|
||||
void print_version() {
|
||||
printf("runwhenidle %s\n", VERSION);
|
||||
}
|
||||
|
||||
char *read_remaining_arguments_as_char(int argc,
|
||||
char *const *argv) {
|
||||
if (optind == argc) { //there is one argument remaining
|
||||
char *last_and_only_argument = strdup(argv[optind]);
|
||||
return last_and_only_argument;
|
||||
}
|
||||
|
||||
size_t memory_to_be_allocated_for_remaining_arguments_string = 0;
|
||||
for (int i = optind; i < argc; i++) {
|
||||
memory_to_be_allocated_for_remaining_arguments_string +=
|
||||
strlen(argv[i]) + 1; // +1 for space separator or null terminator
|
||||
}
|
||||
|
||||
char *remaining_arguments_string = NULL; // Variable to store the remaining_arguments_string
|
||||
|
||||
// Allocate memory for the remaining_arguments_string
|
||||
remaining_arguments_string = malloc(memory_to_be_allocated_for_remaining_arguments_string);
|
||||
if (remaining_arguments_string == NULL) {
|
||||
//not using fprintf_error here intentionally
|
||||
fprintf(stderr, "Failed to allocate memory while parsing command to be ran.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t current_length_of_all_arguments = 0;
|
||||
for (int i = optind; i < argc; i++) {
|
||||
size_t current_argument_length = strlen(argv[i]);
|
||||
memcpy(remaining_arguments_string + current_length_of_all_arguments, argv[i], current_argument_length);
|
||||
current_length_of_all_arguments += current_argument_length;
|
||||
remaining_arguments_string[current_length_of_all_arguments++] = ' '; // Add space separator
|
||||
}
|
||||
assert(current_length_of_all_arguments == memory_to_be_allocated_for_remaining_arguments_string);
|
||||
remaining_arguments_string[current_length_of_all_arguments - 1] = '\0'; // Replace the last space separator with a null terminator
|
||||
|
||||
return remaining_arguments_string;
|
||||
}
|
||||
long unsigned query_user_idle_time()
|
||||
{
|
||||
if (xscreensaver_is_available) {
|
||||
@@ -186,88 +131,6 @@ long long pause_or_resume_command_depending_on_user_activity(
|
||||
return sleep_time_ms;
|
||||
}
|
||||
|
||||
char *parse_command_line_arguments(int argc, char *argv[]) {// Define command line options
|
||||
struct option long_options[] = {
|
||||
{"timeout", required_argument, NULL, 't'},
|
||||
{"start-monitor-after", required_argument, NULL, 'a'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{"debug", no_argument, NULL, 'd'},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'V'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
// Parse command line options
|
||||
int option;
|
||||
while ((option = getopt_long(argc, argv, "+hvqt:a:V", long_options, NULL)) != -1) {
|
||||
switch (option) {
|
||||
case 't': {
|
||||
|
||||
long timeout_arg_value = strtol(optarg, NULL, 10);
|
||||
if (timeout_arg_value < TIMEOUT_MIN_SUPPORTED_VALUE ||
|
||||
timeout_arg_value > TIMEOUT_MAX_SUPPORTED_VALUE || errno != 0) {
|
||||
fprintf_error("Invalid timeout value: \"%s\". Range supported: %ld-%ld", optarg,
|
||||
TIMEOUT_MIN_SUPPORTED_VALUE, TIMEOUT_MAX_SUPPORTED_VALUE);
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
user_idle_timeout_ms = timeout_arg_value * 1000;
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
start_monitor_after_ms = strtol(optarg, NULL, 10);
|
||||
|
||||
if (start_monitor_after_ms < START_MONITOR_AFTER_MIN_SUPPORTED_VALUE || errno != 0) {
|
||||
fprintf_error( "Invalid start-monitor-after time value: \"%s\" Range supported: %ld-%ld.\n", optarg,
|
||||
START_MONITOR_AFTER_MIN_SUPPORTED_VALUE, START_MONITOR_AFTER_MAX_SUPPORTED_VALUE
|
||||
);
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(0);
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'd':
|
||||
debug = 1;
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (debug) fprintf(stderr, "verbose: %i, debug: %i, quiet: %i, user_idle_timeout_ms: %i, start_monitoring_after_ms: %lld\n", verbose, debug, quiet, user_idle_timeout_ms, start_monitor_after_ms);
|
||||
if (optind >= argc) {
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (quiet && debug) {
|
||||
fprintf_error("Incompatible options --quiet|-q and --debug used");
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (quiet && verbose) {
|
||||
fprintf_error("Incompatible options --quiet|-q and --verbose|-v used");
|
||||
print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return read_remaining_arguments_as_char(argc, argv);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *shell_command_to_run = parse_command_line_arguments(argc, argv);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user