summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-12-23 15:44:19 +0100
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2019-12-23 15:44:19 +0100
commit390576c3839ee7abb845e27b7267de45495e6b2f (patch)
treec481c37c868ccc65a3476f60b17369b21a90b79b /src/config
parent4355548f79375a62bb5e3bb5695190d48e4c0bc3 (diff)
Starting to turn relabsd into a proper daemon...
Diffstat (limited to 'src/config')
-rw-r--r--src/config/config_file.c821
-rw-r--r--src/config/parameters.c287
2 files changed, 1108 insertions, 0 deletions
diff --git a/src/config/config_file.c b/src/config/config_file.c
new file mode 100644
index 0000000..ad060a5
--- /dev/null
+++ b/src/config/config_file.c
@@ -0,0 +1,821 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <sys/time.h>
+
+#include "error.h"
+#include "pervasive.h"
+#include "axis.h"
+#include "config.h"
+
+#ifndef RELABSD_OPTION_MAX_SIZE
+ #define RELABSD_OPTION_MAX_SIZE 64
+#endif
+/*
+ * "errno is never set to zero by any system call or library function."
+ * This file makes use of this, by setting it to zero and checking if
+ * it was modified after calling an function (I'm guessing this is common
+ * practice, but I think it's worth explaining).
+ * Following the principle of least astonishment, if a function sets errno to
+ * zero, it will not return before setting it back either to its previous
+ * value or to a arbitrary nonzero value.
+ */
+
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on EOF,
+ * 1 on newline.
+ */
+static int reach_next_line_or_eof (FILE * const f)
+{
+ int prev_errno;
+ char c;
+
+ prev_errno = errno;
+
+ errno = 0;
+
+ c = (char) getc(f);
+
+ while ((c != '\n') && c != EOF)
+ {
+ c = (char) getc(f);
+ }
+
+ if (errno != 0)
+ {
+ RELABSD_FATAL
+ (
+ "[CONFIG] Error while attempting to reach EOF or next line: %s.",
+ strerror(errno)
+ );
+
+ errno = prev_errno;
+
+ return -1;
+ }
+
+ errno = prev_errno;
+
+ if (c == EOF)
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Returns -1 if the option was discarded (an error has been reported),
+ * 0 if the option was successfully parsed.
+ *
+ * ('length' - 1) is the number of relevant characters in 'name'.
+ * 'name' must support 'length' characters.
+ * name[length] will be set to \0, so it does not need to be when calling
+ * this function.
+ */
+static int parse_option
+(
+ struct relabsd_config * const conf,
+ enum relabsd_axis const axis,
+ char * const name,
+ int const length
+)
+{
+ name[length] = '\0';
+
+ if (strcmp(name, "direct") == 0)
+ {
+ conf->axis[axis].option[RELABSD_DIRECT_OPTION] = 1;
+
+ RELABSD_DEBUG
+ (
+ RELABSD_DEBUG_CONFIG,
+ "Axis '%s' enabled option 'direct'.",
+ relabsd_axis_to_name(axis)
+ );
+
+ if (conf->axis[axis].option[RELABSD_FRAMED_OPTION])
+ {
+ RELABSD_WARNING
+ (
+ "[CONFIG] Axis '%s': using option 'direct' discards option"
+ "'framed'.",
+ relabsd_axis_to_name(axis)
+ );
+ }
+ }
+ else if (strcmp(name, "real_fuzz") == 0)
+ {
+ conf->axis[axis].option[RELABSD_REAL_FUZZ_OPTION] = 1;
+
+ RELABSD_DEBUG
+ (
+ RELABSD_DEBUG_CONFIG,
+ "Axis '%s' enabled option 'real_fuzz'.",
+ relabsd_axis_to_name(axis)
+ );
+ }
+ else if (strcmp(name, "framed") == 0)
+ {
+ conf->axis[axis].option[RELABSD_FRAMED_OPTION] = 1;
+
+ RELABSD_DEBUG
+ (
+ RELABSD_DEBUG_CONFIG,
+ "Axis '%s' enabled option 'framed'.",
+ relabsd_axis_to_name(axis)
+ );
+
+ if (conf->axis[axis].option[RELABSD_DIRECT_OPTION])
+ {
+ RELABSD_WARNING
+ (
+ "[CONFIG] Axis '%s': using option 'direct' discards option"
+ "'framed'.",
+ relabsd_axis_to_name(axis)
+ );
+ }
+ }
+ else
+ {
+ RELABSD_ERROR
+ (
+ "[CONFIG] Unknown option '%s' for axis '%s'.",
+ name,
+ relabsd_axis_to_name(axis)
+ );
+
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Returns -1 on error,
+ * 0 on EOF,
+ * 1 on newline.
+ */
+static int read_axis_options
+(
+ struct relabsd_config * const conf,
+ FILE * const f,
+ enum relabsd_axis const axis
+)
+{
+ char option[(RELABSD_OPTION_MAX_SIZE + 1)];
+ int i, prev_errno;
+ char c;
+
+ option[RELABSD_OPTION_MAX_SIZE] = '\0';
+
+ prev_errno = errno;
+
+ errno = 0;
+
+ memset(conf->axis[axis].option, 0, RELABSD_OPTIONS_COUNT * sizeof(int));
+
+ i = 0;
+
+ while (i <= RELABSD_OPTION_MAX_SIZE)
+ {
+ c = (char) getc(f);
+
+ if ((errno != 0) && (c == EOF))
+ {
+ RELABSD_FATAL
+ (
+ "[CONFIG] Reading error while parsing option name (axis '%s'): %s.",
+ relabsd_axis_to_name(axis),
+ strerror(errno)
+ );
+
+ errno = prev_errno;
+
+ return -1;
+ }
+
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ break;
+
+ case ',':
+ /* We parsed a new option and there is a least another. */
+ parse_option(conf, axis, option, i);
+
+ i = 0;
+
+ break;
+
+ case '\n':
+ parse_option(conf, axis, option, i);
+ errno = prev_errno;
+
+ return 1;
+
+ case EOF:
+ parse_option(conf, axis, option, i);
+ errno = prev_errno;
+
+ return 0;
+
+ default:
+ option[i] = c;
+ i++;
+
+ break;
+ }
+ }
+
+ RELABSD_FATAL
+ (
+ "[CONFIG] Option name '%s[...]' (axis '%s') is too long (%d chars max).",
+ option,
+ relabsd_axis_to_name(axis),
+ RELABSD_OPTION_MAX_SIZE
+ );
+
+ return -1;
+}
+
+static int parse_timeout_option
+(
+ struct relabsd_config * const conf,
+ const char * const param
+)
+{
+ int timeout_msec;
+ const int prev_errno = errno;
+
+ conf->enable_timeout = 1;
+
+ errno = 0;
+
+ timeout_msec = atoi(param);
+
+ if (timeout_msec <= 0)
+ {
+ RELABSD_FATAL
+ (
+ "Illegal value for timeout \"%d\": accepted range is [1, %d].",
+ timeout_msec,
+ INT_MAX
+ );
+
+ return -1;
+ }
+
+ memset((void *) &(conf->timeout), 0, sizeof(struct timeval));
+
+ conf->timeout.tv_sec = (time_t) (timeout_msec / 1000);
+
+ conf->timeout.tv_usec =
+ (
+ ((suseconds_t) timeout_msec)
+ * ((suseconds_t) 1000)
+ );
+
+ return 0;
+}
+
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on succes.
+ */
+static int parse_axis_configuration_line
+(
+ struct relabsd_config * const conf,
+ FILE * const f,
+ const char * const buffer
+)
+{
+ int valc, prev_errno;
+ enum relabsd_axis axis;
+
+ axis = relabsd_axis_from_name(buffer);
+
+ if (axis == RELABSD_UNKNOWN)
+ {
+ RELABSD_FATAL
+ (
+ "[CONFIG] Unknown axis '%s'.",
+ buffer
+ );
+
+ return -1;
+ }
+
+ prev_errno = errno;
+ errno = 0;
+
+ valc =
+ fscanf
+ (
+ f,
+ "%d %d %d %d %d",
+ &(conf->axis[axis].min),
+ &(conf->axis[axis].max),
+ &(conf->axis[axis].fuzz),
+ &(conf->axis[axis].flat),
+ &(conf->axis[axis].resolution)
+ );
+
+ if (valc == EOF)
+ {
+ if (errno == 0)
+ {
+ RELABSD_FATAL
+ (
+ "[CONFIG] Unexpected end of file while reading axis '%s'.",
+ buffer
+ );
+ }
+ else
+ {
+ RELABSD_FATAL
+ (
+ "[CONFIG] An error occured while reading axis '%s': %s.",
+ buffer,
+ strerror(errno)
+ );
+ }
+
+ errno = prev_errno;
+
+ return -1;
+ }
+ else if (valc < 5)
+ {
+ RELABSD_FATAL
+ (
+ "[CONFIG] Invalid parameter count for axis '%s'.",
+ buffer
+ );
+
+ errno = prev_errno;
+
+ return -1;
+ }
+
+ RELABSD_DEBUG
+ (
+ RELABSD_DEBUG_CONFIG,
+ "Axis '%s': {min = %d; max = %d; fuzz = %d; flat = %d; resolution = %d}",
+ buffer,
+ conf->axis[axis].min,
+ conf->axis[axis].max,
+ conf->axis[axis].fuzz,
+ conf->axis[axis].flat,
+ conf->axis[axis].resolution
+ );
+
+ errno = prev_errno;
+
+ conf->axis[axis].enabled = 1;
+ conf->axis[axis].previous_value = 0;
+
+ return read_axis_options(conf, f, axis);
+}
+
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on EOF,
+ * 1 on newline.
+ */
+static int read_config_line
+(
+ struct relabsd_config * const conf,
+ FILE * const f,
+ const char * const prefix
+)
+{
+ if (!RELABSD_IS_PREFIX("#", prefix))
+ {
+ return parse_axis_configuration_line(conf, f, prefix);
+ }
+
+ return reach_next_line_or_eof(f);
+}
+
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on success.
+ */
+static int read_config_file
+(
+ struct relabsd_config * const conf,
+ char * const filename
+)
+{
+ FILE * f;
+ char buffer[(RELABSD_CONF_AXIS_CODE_SIZE + 1)];
+ int continue_reading, prev_errno;
+
+ buffer[RELABSD_CONF_AXIS_CODE_SIZE] = '\0';
+
+ f = fopen(filename, "r");
+
+ if (f == (FILE *) NULL)
+ {
+ RELABSD_FATAL
+ (
+ "[CONFIG] Could not open file: %s.",
+ strerror(errno)
+ );
+
+ return -1;
+ }
+
+
+ prev_errno = errno;
+ errno = 0;
+
+ continue_reading = 1;
+
+ while
+ (
+ (continue_reading == 1)
+ &&
+ (
+ fscanf
+ (
+ f,
+ "%" RELABSD_TO_STRING(RELABSD_CONF_AXIS_CODE_SIZE) "s",
+ buffer
+ )
+ != EOF
+ )
+ )
+ {
+ switch (read_config_line(conf, f, buffer))
+ {
+ case 1:
+ /* Everything is going well. */
+ break;
+
+ case 0:
+ /* EOF reached. */
+ continue_reading = 0;
+ break;
+
+ case -1:
+ /* A fatal error occured. */
+ errno = prev_errno;
+
+ fclose(f);
+ return -1;
+ }
+ }
+
+ if (errno != 0)
+ {
+ /* An error happened in the while loop condition. */
+ RELABSD_FATAL
+ (
+ "[CONFIG] Error while reading file: %s, last read '%s'.",
+ strerror(errno),
+ buffer
+ );
+
+ errno = prev_errno;
+
+ fclose(f);
+
+ return -1;
+ }
+
+ errno = prev_errno;
+
+ fclose(f);
+
+ return 0;
+}
+
+static void print_usage
+(
+ const char * const exec
+)
+{
+ RELABSD_FATAL
+ (
+ "USAGE: %s input_device config_file [<OPTION>+]\n"
+ "<OPTION>:\n"
+ "\t [-n | --name] <relabsd_device_name>: Names the virtual device.\n"
+ "\t [-t | --timeout] <timeout_in_ms>: Resets all enabled axes to zero"
+ " <timeout_in_ms> milliseconds after the last event. Range for"
+ " <timeout_in_ms>: [1, %d].\n"
+ "Alternatively, the previous usage is still supported:\n"
+ "\t%s input_device config_file [<relabsd_device_name>]\n"
+ "However, with that usage, <relabsd_device_name> cannot start with '-'.",
+ exec,
+ INT_MAX,
+ exec
+ );
+}
+/*
+ * Returns -1 on (fatal) error,
+ * 0 on valid usage.
+ */
+static int check_usage
+(
+ int const argc,
+ char * const * const argv
+)
+{
+ if (argc < 3)
+ {
+ print_usage(argv[0]);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+static void init_axes_config (struct relabsd_config * const conf)
+{
+ int i;
+
+ for (i = RELABSD_VALID_AXES_COUNT; i --> 0;)
+ {
+ conf->axis[i].enabled = 0;
+ }
+}
+
+static int parse_options
+(
+ struct relabsd_config * const conf,
+ int const argc,
+ char * const * const argv
+)
+{
+ int i;
+
+ if ((argc == 4) && !RELABSD_IS_PREFIX("-", argv[3]))
+ {
+ /* Old usage */
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_CONFIG, "Old usage detected.");
+
+ conf->device_name = argv[3];
+
+ RELABSD_DEBUG
+ (
+ RELABSD_DEBUG_CONFIG,
+ "Virtual device name param set to '%s'.",
+ conf->device_name
+ );
+
+ return 0;
+ }
+
+ conf->device_name = NULL;
+ conf->enable_timeout = 0;
+
+ for (i = 3; i < argc; ++i)
+ {
+ if
+ (
+ RELABSD_STRING_EQUALS("-n", argv[i])
+ || RELABSD_STRING_EQUALS("--name", argv[i])
+ )
+ {
+ i += 1;
+
+ if (i >= argc)
+ {
+ RELABSD_S_FATAL
+ (
+ "Missing value for parameter \"--name\"."
+ );
+
+ print_usage(argv[0]);
+
+ return -1;
+ }
+
+ conf->device_name = argv[i];
+ }
+ else if
+ (
+ RELABSD_STRING_EQUALS("-t", argv[i])
+ || RELABSD_STRING_EQUALS("--timeout", argv[i])
+ )
+ {
+ i += 1;
+
+ if (i >= argc)
+ {
+ RELABSD_S_FATAL
+ (
+ "Missing value for parameter \"--timeout\"."
+ );
+
+ print_usage(argv[0]);
+
+ return -1;
+ }
+
+ if (parse_timeout_option(conf, argv[i]) < 0)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ RELABSD_FATAL
+ (
+ "Unknown parameter \"%s\".",
+ argv[i]
+ );
+
+ print_usage(argv[0]);
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+int relabsd_config_parse
+(
+ struct relabsd_config * const conf,
+ int const argc,
+ char * const * const argv
+)
+{
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Parsing config & params...");
+
+ if (check_usage(argc, argv) < 0)
+ {
+ return -1;
+ }
+
+ if (parse_options(conf, argc, argv) < 0)
+ {
+ return -1;
+ }
+
+ conf->input_file = argv[1];
+
+ RELABSD_DEBUG
+ (
+ RELABSD_DEBUG_CONFIG,
+ "Using configuration file '%s'.",
+ conf->input_file
+ );
+
+ init_axes_config(conf);
+
+ if (read_config_file(conf, argv[2]) < 0)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int direct_filter
+(
+ struct relabsd_config_axis * const axis,
+ int * const value
+)
+{
+ if (abs(*value - axis->previous_value) <= axis->fuzz)
+ {
+ if (axis->option[RELABSD_REAL_FUZZ_OPTION])
+ {
+ axis->previous_value = *value;
+ }
+
+ return -1;
+ }
+
+ if (*value < axis->min)
+ {
+ *value = axis->min;
+ }
+ else if (*value > axis->max)
+ {
+ *value = axis->max;
+ }
+ else if (abs(*value) <= axis->flat)
+ {
+ *value = 0;
+ }
+
+ if (*value == axis->previous_value)
+ {
+ return -1;
+ }
+
+ axis->previous_value = *value;
+
+ return 1;
+}
+
+static int rel_to_abs_filter
+(
+ struct relabsd_config_axis * const axis,
+ int * const value
+)
+{
+ long int guard;
+
+ guard = (((long int) axis->previous_value) + ((long int) *value));
+
+ if (guard < ((long int) INT_MIN))
+ {
+ guard = ((long int) INT_MIN);
+ }
+ else if (guard > ((long int) INT_MAX))
+ {
+ guard = ((long int) INT_MAX);
+ }
+
+ *value = (int) guard;
+
+ if (axis->option[RELABSD_FRAMED_OPTION])
+ {
+ if (*value < axis->min)
+ {
+ *value = axis->min;
+ }
+ else if (*value > axis->max)
+ {
+ *value = axis->max;
+ }
+
+ if (*value == axis->previous_value)
+ {
+ return 0;
+ }
+
+ axis->previous_value = *value;
+
+ return 1;
+ }
+ else
+ {
+ if (*value == axis->previous_value)
+ {
+ return 0;
+ }
+
+ axis->previous_value = *value;
+
+ if ((*value < axis->min) || (*value > axis->max))
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+}
+
+int relabsd_config_filter
+(
+ struct relabsd_config * const conf,
+ enum relabsd_axis const axis,
+ int * const value
+)
+{
+ if ((axis == RELABSD_UNKNOWN) || !conf->axis[axis].enabled)
+ {
+ return 0;
+ }
+
+ /* TODO: handle conf->axis[axis].resolution */
+
+ if (conf->axis[axis].option[RELABSD_DIRECT_OPTION])
+ {
+ return direct_filter((conf->axis + axis), value);
+ }
+ else
+ {
+ return rel_to_abs_filter((conf->axis + axis), value);
+ }
+}
+
+void relabsd_config_get_absinfo
+(
+ const struct relabsd_config * const conf,
+ enum relabsd_axis const axis,
+ struct input_absinfo * const absinfo
+)
+{
+ absinfo->value = (__s32) 0;
+ absinfo->minimum = (__s32) conf->axis[axis].min;
+ absinfo->maximum = (__s32) conf->axis[axis].max;
+ absinfo->fuzz = (__s32) conf->axis[axis].fuzz;
+ absinfo->flat = (__s32) conf->axis[axis].flat;
+ absinfo->resolution = (__s32) conf->axis[axis].resolution;
+}
diff --git a/src/config/parameters.c b/src/config/parameters.c
new file mode 100644
index 0000000..308e5db
--- /dev/null
+++ b/src/config/parameters.c
@@ -0,0 +1,287 @@
+/**** POSIX *******************************************************************/
+#include <limits.h>
+
+/**** RELABSD *****************************************************************/
+#include <relabsd/config.h>
+#include <relabsd/debug.h>
+
+#include <relabsd/device/axis.h>
+
+#include <relabsd/util/string.h>
+
+#include <relabsd/config/parameters.h>
+
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
+static void print_usage (const char exec [const restrict static 1])
+{
+ printf
+ (
+ "USAGE: %s [<MODE>] [<OPTION>+]\n\n"
+
+ "<MODE>:\n"
+ "\t[-c | --client] <server_file>:\n"
+ "\t\tSends the commands to a given server instance.\n\n"
+
+ "\t[-s | --server] <server_file>:\n"
+ "\t\tCreates a named server instance.\n\n"
+
+ "\t[-1 | --self]:\n"
+ "\t\tCreates a unnamed server instance.\n\n"
+
+ "<OPTION>:\n"
+ "\t[-d | --daemon]:\n"
+ "\t\tRuns server instance in the background.\n\n"
+
+ "\t[-n | --name] <relabsd_device_name>:\n"
+ "\t\tNames the virtual device.\n\n"
+
+ "\t[-t | --timeout] <timeout_in_ms>:\n"
+ "\t\tSets a zeroing timeout (0 to disable).\n\n"
+
+ "\t[-a | --axis] <name> <min> <max> <fuzz> <flat> <resolution> "
+ "<options>:\n"
+ "\t\t(Re)defines an axis.\n\n"
+
+ "\t[-f | --config] <config_file>"
+ "<options>:\n"
+ "\t\t(Re)defines an axis.\n",
+ exec
+ );
+}
+
+static int parse_axis
+(
+ const int argc,
+ const char * argv [const restrict static argc],
+ struct relabsd_axis axes [const restrict static RELABSD_AXIS_AXES_COUNT]
+)
+{
+ enum relabsd_axis_name axis_name;
+ struct relabsd_axis *axis;
+
+ if (argc < 7)
+ {
+ RELABSD_S_FATAL("7 parameters must be provided for axis definition.");
+
+ return -1;
+ }
+
+ axis_index = relabsd_axis_from_name(argv[0]);
+
+ if (axis_index == RELABSD_UNKNOWN)
+ {
+ RELABSD_FATAL("Unknown axis \"%s\".", argv[0]);
+
+ return -1;
+ }
+
+ axis = (axes + axis_index);
+
+ axis->min = atoi(argv[1]);
+ axis->max = atoi(argv[2]);
+ axis->fuzz = atoi(argv[3]);
+ axis->flat = atoi(argv[4]);
+ axis->resolution = atoi(argv[5]);
+
+
+ return 0;
+}
+
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
+int relabsd_parameters_parse_execution_mode
+(
+ const int argc,
+ const char * argv [const restrict static argc],
+ struct relabsd_parameters params [const restrict static 1]
+)
+{
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Parsing exec mode...");
+
+ if (argc < 3)
+ {
+ print_usage(argv[0]);
+
+ return -1;
+ }
+
+ if
+ (
+ RELABSD_STRING_EQUALS("-c", argv[1])
+ || RELABSD_STRING_EQUALS("--client", argv[1])
+ )
+ {
+ params->mode = RELABSD_PARAMETERS_CLIENT_MODE;
+ params->node = argv[2];
+ params->read_argc = 2;
+ }
+ else if
+ (
+ RELABSD_STRING_EQUALS("-s", argv[1])
+ || RELABSD_STRING_EQUALS("--server", argv[1])
+ )
+ {
+ params->mode = RELABSD_PARAMETERS_CLIENT_MODE;
+ params->node = argv[2];
+ params->read_argc = 2;
+ }
+ else if
+ (
+ RELABSD_STRING_EQUALS("-1", argv[1])
+ || RELABSD_STRING_EQUALS("--self", argv[1])
+ )
+ {
+ params->mode = RELABSD_PARAMETERS_SERVER_MODE;
+ params->node = (char *) NULL;
+ params->read_argc = 1;
+ }
+ else
+ {
+ print_usage(argv[0]);
+
+ return -1;
+ }
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Parsed exec mode.");
+
+ return 0;
+}
+
+int relabsd_parameters_parse_options
+(
+ const int argc,
+ const char * argv [const restrict static argc],
+ struct relabsd_parameters params [const restrict static 1]
+)
+{
+ int i;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Parsing options...");
+
+ set_default_options(params);
+
+ for (i = params->read_argc; i < argc; ++i)
+ {
+ if
+ (
+ RELABSD_STRING_EQUALS("-d", argv[i])
+ || RELABSD_STRING_EQUALS("--daemon", argv[i])
+ )
+ {
+ params->run_as_daemon = 1;
+
+ if (params->node == ((char *) NULL))
+ {
+ RELABSD_S_WARNING
+ (
+ "Running as a daemon without any communication file."
+ );
+ }
+ }
+ else if
+ (
+ RELABSD_STRING_EQUALS("-n", argv[i])
+ || RELABSD_STRING_EQUALS("--name", argv[i])
+ )
+ {
+ if (argc == i)
+ {
+ RELABSD_FATAL("Missing value for \"%s\" <OPTION>.", argv[i]);
+
+ return -1;
+ }
+
+ ++i;
+ params->name = argv[i];
+ }
+ else if
+ (
+ RELABSD_STRING_EQUALS("-t", argv[i])
+ || RELABSD_STRING_EQUALS("--timeout", argv[i])
+ )
+ {
+ if (argc == i)
+ {
+ RELABSD_FATAL("Missing value for \"%s\" <OPTION>.", argv[i]);
+ print_usage(argv[0]);
+
+ return -1;
+ }
+
+ ++i;
+
+ if
+ (
+ relabsd_util_parse_int(argv[i], 0, INT_MAX, &(params->timeout))
+ < 0
+ )
+ {
+ RELABSD_FATAL
+ (
+ "Invalid value for \"%s\" <OPTION> (valid range is [%d, %d]).",
+ argv[i - 1],
+ 0,
+ INT_MAX
+ );
+
+ print_usage(argv[0]);
+
+ return -1;
+ }
+ }
+ else if
+ (
+ RELABSD_STRING_EQUALS("-a", argv[i])
+ || RELABSD_STRING_EQUALS("--axis", argv[i])
+ )
+ {
+ if (argc == i)
+ {
+ RELABSD_FATAL("Missing values for \"%s\" <OPTION>.", argv[i]);
+ print_usage(argv[0]);
+
+ return -1;
+ }
+
+ ++i;
+
+ if (parse_axis((argc - i), (argv + i), params->axes) < 0)
+ {
+ print_usage(argv[0]);
+
+ return -1;
+ }
+ }
+ else if
+ (
+ RELABSD_STRING_EQUALS("-f", argv[i])
+ || RELABSD_STRING_EQUALS("--config", argv[i])
+ )
+ {
+ if (argc == i)
+ {
+ RELABSD_FATAL("Missing value for \"%s\" <OPTION>.", argv[i]);
+ print_usage(argv[0]);
+
+ return -1;
+ }
+
+ ++i;
+ params->config_file = argv[i];
+ }
+ else
+ {
+ RELABSD_FATAL("Unknown <OPTION> \"%s\".", argv[i]);
+ print_usage(argv[0]);
+
+ return -1;
+ }
+ }
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Parsed options.");
+
+ return 0;
+}