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
parent4355548f79375a62bb5e3bb5695190d48e4c0bc3 (diff)
Starting to turn relabsd into a proper daemon...
-rw-r--r--CMakeLists.txt4
-rw-r--r--include/relabsd/client.h0
-rw-r--r--include/relabsd/config.h0
-rw-r--r--include/relabsd/config/config_file.h (renamed from src/config.h)0
-rw-r--r--include/relabsd/config/parameters.h0
-rw-r--r--include/relabsd/debug.h (renamed from src/error.h)16
-rw-r--r--include/relabsd/device/axis.h (renamed from src/axis.h)45
-rw-r--r--include/relabsd/device/physical_device.h (renamed from src/input.h)5
-rw-r--r--include/relabsd/device/virtual_device.h (renamed from src/relabsd_device.h)21
-rw-r--r--include/relabsd/server.h0
-rw-r--r--include/relabsd/util/macro.h6
-rw-r--r--include/relabsd/util/string.h (renamed from src/pervasive.h)16
-rw-r--r--src/CMakeLists.txt10
-rw-r--r--src/client.c189
-rw-r--r--src/config/config_file.c (renamed from src/config.c)0
-rw-r--r--src/config/parameters.c287
-rw-r--r--src/device/axis/axis_name.c (renamed from src/axis.c)45
-rw-r--r--src/device/physical_device.c (renamed from src/input.c)14
-rw-r--r--src/device/virtual_device.c (renamed from src/relabsd_device.c)46
-rw-r--r--src/main.c171
-rw-r--r--src/server/daemon.c126
-rw-r--r--src/server/main_loop.c165
-rw-r--r--src/server/server.c113
-rw-r--r--src/util/string.c36
24 files changed, 1064 insertions, 251 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0697bcb..f5da0f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,9 +7,11 @@ include(FindPkgConfig)
# ${SRC_FILES} is recursively defined in the subdirectories.
# Each subdirectory adds only the source files that are present at its level.
-add_subdirectory(src)
+file(GLOB_RECURSE SRC_FILES src/ true *.c)
add_executable(relabsd ${SRC_FILES})
+include_directories(include/)
+
# Language parameters.
enable_language(C)
target_compile_features(relabsd PUBLIC c_variadic_macros)
diff --git a/include/relabsd/client.h b/include/relabsd/client.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/relabsd/client.h
diff --git a/include/relabsd/config.h b/include/relabsd/config.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/relabsd/config.h
diff --git a/src/config.h b/include/relabsd/config/config_file.h
index 3aa1a13..3aa1a13 100644
--- a/src/config.h
+++ b/include/relabsd/config/config_file.h
diff --git a/include/relabsd/config/parameters.h b/include/relabsd/config/parameters.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/relabsd/config/parameters.h
diff --git a/src/error.h b/include/relabsd/debug.h
index 863a1bb..025c312 100644
--- a/src/error.h
+++ b/include/relabsd/debug.h
@@ -1,10 +1,8 @@
-#ifndef RELABSD_ERROR_H
-#define RELABSD_ERROR_H
+#pragma once
#include <stdio.h>
-#include "config.h"
-#include "pervasive.h"
+#include <relabsd/util/macro.h>
#ifndef RELABSD_DEBUG_PROGRAM_FLOW
#define RELABSD_DEBUG_PROGRAM_FLOW 0
@@ -22,10 +20,18 @@
#define RELABSD_DEBUG_VIRTUAL_EVENTS 0
#endif
+#ifndef RELABSD_ENABLE_WARNINGS_OUTPUT
#define RELABSD_ENABLE_WARNINGS_OUTPUT 1
+#endif
+#ifndef RELABSD_ENABLE_RUNTIME_ERRORS_OUTPUT
#define RELABSD_ENABLE_RUNTIME_ERRORS_OUTPUT 1
+#endif
+#ifndef RELABSD_ENABLE_PROGRAMMING_ERRORS_OUTPUT
#define RELABSD_ENABLE_PROGRAMMING_ERRORS_OUTPUT 1
+#endif
+#ifndef RELABSD_ENABLE_FATAL_ERROR_OUTPUT
#define RELABSD_ENABLE_FATAL_ERROR_OUTPUT 1
+#endif
#ifdef RELABSD_ENABLE_ERROR_LOCATION
#define RELABSD_LOCATION "[" __FILE__ "][" RELABSD_TO_STRING(__LINE__) "]"
@@ -137,5 +143,3 @@
RELABSD_PRINT_S_STDERR("F", str);\
}\
)
-
-#endif
diff --git a/src/axis.h b/include/relabsd/device/axis.h
index 2c4ea72..3829b51 100644
--- a/src/axis.h
+++ b/include/relabsd/device/axis.h
@@ -1,10 +1,9 @@
-#ifndef RELABSD_AXIS_H
-#define RELABSD_AXIS_H
+#pragma once
/* Number of axes that can be configured. */
-#define RELABSD_VALID_AXES_COUNT 8
+#define RELABSD_AXIS_AXES_COUNT 8
-enum relabsd_axis
+enum relabsd_axis_name
{
RELABSD_X,
RELABSD_Y,
@@ -17,6 +16,15 @@ enum relabsd_axis
RELABSD_UNKNOWN
};
+struct relabsd_axis
+{
+ int min;
+ int max;
+ int fuzz;
+ int flat;
+ int resolution;
+ int flags;
+};
/*
* Gives the relabsd_axis and EV_ABS event code equivalent to an EV_REL event
@@ -24,10 +32,10 @@ enum relabsd_axis
* If the returned relabsd_axis is RELABSD_UNKNOWN, no value is inserted into
* 'abs_code'.
*/
-enum relabsd_axis relabsd_axis_convert_evdev_rel
+enum relabsd_axis_name relabsd_axis_name_and_evdev_abs_from_evdev_rel
(
- unsigned int const rel_code,
- unsigned int * const abs_code
+ const unsigned int rel_code,
+ unsigned int abs_code [const restrict static 1]
);
/*
@@ -35,14 +43,21 @@ enum relabsd_axis relabsd_axis_convert_evdev_rel
* There is no equivalent for RELABSD_UNKNOWN, so 'e' is forbidden from
* taking this value.
*/
-unsigned int relabsd_axis_to_rel (enum relabsd_axis const e);
-unsigned int relabsd_axis_to_abs (enum relabsd_axis const e);
+unsigned int relabsd_axis_name_to_evdev_rel (const enum relabsd_axis_name e);
+unsigned int relabsd_axis_name_to_evdev_abs (const enum relabsd_axis_name e);
/*
* Returns the relabsd_axis equivalent of a EV_REL/EV_ABS code.
*/
-enum relabsd_axis relabsd_axis_from_rel (unsigned int const rel);
-enum relabsd_axis relabsd_axis_from_abs (unsigned int const abs);
+enum relabsd_axis_name relabsd_axis_name_from_evdev_rel
+(
+ const unsigned int rel
+);
+
+enum relabsd_axis_name relabsd_axis_name_from_evdev_abs
+(
+ const unsigned int abs
+);
/*
* Returns the relabsd_axis whose name is 'name', according to the configuration
@@ -50,12 +65,14 @@ enum relabsd_axis relabsd_axis_from_abs (unsigned int const abs);
* RELABSD_UNKNOWN is returned for any name that didn't match any other
* possibility.
*/
-enum relabsd_axis relabsd_axis_from_name (const char * const name);
+enum relabsd_axis_name relabsd_axis_parse_name
+(
+ const char name [const restrict static 1]
+);
/*
* Gives an string representation of an relabsd_axis.
* "??" is returned for RELABSD_UNKNOWN.
* Returned values should be coherent with the configuration file syntax.
*/
-char * relabsd_axis_to_name (enum relabsd_axis const e);
-#endif
+const char * relabsd_axis_name_to_string (const enum relabsd_axis_name e);
diff --git a/src/input.h b/include/relabsd/device/physical_device.h
index 2e1b502..17866f7 100644
--- a/src/input.h
+++ b/include/relabsd/device/physical_device.h
@@ -1,10 +1,7 @@
-#ifndef RELABSD_INPUT_H
-#define RELABSD_INPUT_H
+#pragma once
#include <libevdev/libevdev.h>
-#include "config.h"
-
struct relabsd_input
{
struct libevdev * dev;
diff --git a/src/relabsd_device.h b/include/relabsd/device/virtual_device.h
index 4aa181d..d398c7f 100644
--- a/src/relabsd_device.h
+++ b/include/relabsd/device/virtual_device.h
@@ -1,10 +1,20 @@
-#ifndef RELABSD_RELABSD_DEVICE_H
-#define RELABSD_RELABSD_DEVICE_H
+#pragma once
#include <libevdev/libevdev.h>
+#include <libevdev/libevdev-uinput.h>
-#include "config.h"
-#include "input.h"
+/*
+ LIBEVDEV_UINPUT_OPEN_MANAGED is not defined on my machines.
+ It is not my place to define it, so I'll avoid the issue by defining my own
+ constant.
+*/
+#ifndef LIBEVDEV_UINPUT_OPEN_MANAGED
+ #pragma message "[WARNING] libevdev did not define " \
+ "LIBEVDEV_UINPUT_OPEN_MANAGED, using value '-2' instead."
+ #define RELABSD_UINPUT_OPEN_MANAGED -2
+#else
+ #define RELABSD_UINPUT_OPEN_MANAGED LIBEVDEV_UINPUT_OPEN_MANAGED
+#endif
struct relabsd_device
{
@@ -59,6 +69,3 @@ void relabsd_device_set_axes_to_zero
const struct relabsd_device * const dev,
const struct relabsd_config * const config
);
-
-
-#endif
diff --git a/include/relabsd/server.h b/include/relabsd/server.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/relabsd/server.h
diff --git a/include/relabsd/util/macro.h b/include/relabsd/util/macro.h
new file mode 100644
index 0000000..b9adb5e
--- /dev/null
+++ b/include/relabsd/util/macro.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#define RELABSD_ISOLATE(a) do {a} while (0)
+
+#define RELABSD__TO_STRING(x) #x
+#define RELABSD_TO_STRING(x) RELABSD__TO_STRING(x)
diff --git a/src/pervasive.h b/include/relabsd/util/string.h
index 6c08305..d632720 100644
--- a/src/pervasive.h
+++ b/include/relabsd/util/string.h
@@ -1,16 +1,18 @@
-#ifndef RELABSD_PERVASIVE_H
-#define RELABSD_PERVASIVE_H
+#pragma once
#include <string.h>
-#define RELABSD__TO_STRING(x) #x
-#define RELABSD_TO_STRING(x) RELABSD__TO_STRING(x)
-
-#define RELABSD_ISOLATE(a) do {a} while (0)
+#include <relabsd/util/macro.h>
/* strncmp stops at '\0' and strlen does not count '\0'. */
#define RELABSD_IS_PREFIX(a, b) (strncmp(a, b, strlen(a)) == 0)
#define RELABSD_STRING_EQUALS(a, b) (strcmp(a, b) == 0)
-#endif
+int relabsd_util_parse_int
+(
+ const char string [const restrict static 1],
+ const int min,
+ const int max,
+ int output [const restrict static 1]
+);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
deleted file mode 100644
index 98af72c..0000000
--- a/src/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-set(
- SRC_FILES ${SRC_FILES}
- ${CMAKE_CURRENT_SOURCE_DIR}/main.c
- ${CMAKE_CURRENT_SOURCE_DIR}/config.c
- ${CMAKE_CURRENT_SOURCE_DIR}/input.c
- ${CMAKE_CURRENT_SOURCE_DIR}/axis.c
- ${CMAKE_CURRENT_SOURCE_DIR}/relabsd_device.c
-)
-
-set(SRC_FILES ${SRC_FILES} PARENT_SCOPE)
diff --git a/src/client.c b/src/client.c
new file mode 100644
index 0000000..d03a768
--- /dev/null
+++ b/src/client.c
@@ -0,0 +1,189 @@
+/**** POSIX *******************************************************************/
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+/**** RELABSD *****************************************************************/
+#include <relabsd/client.h>
+#include <relabsd/config.h>
+#include <relabsd/debug.h>
+
+#include <relabsd/config/parameters.h>
+
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
+static int open_socket
+(
+ FILE * s [const restrict static 1],
+ const char socket_name [const restrict static 1]
+)
+{
+ const int old_errno = errno;
+ int fd;
+ struct sockaddr_un addr;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Opening socket to server...");
+
+ errno = 0;
+
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ {
+ RELABSD_FATAL
+ (
+ "Unable to create socket: %s.",
+ strerror(errno)
+ );
+
+ errno = old_errno;
+
+ return -1;
+ }
+
+ errno = old_errno;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, socket_name, (sizeof(addr.sun_path) - 1));
+
+ errno = 0;
+
+ if (connect(fd, ((struct sockaddr*) &addr), sizeof(addr)) == -1)
+ {
+ RELABSD_FATAL
+ (
+ "Unable to connect to address: %s.",
+ strerror(errno)
+ );
+
+ errno = old_errno;
+
+ close(fd);
+
+ return -1;
+ }
+
+ errno = 0;
+
+ *s = fdopen(fd, "w+");
+
+ if (*s == ((FILE *) NULL))
+ {
+ RELABSD_FATAL
+ (
+ "Unable to open socket as a file: %s.",
+ strerror(errno)
+ );
+
+ errno = old_errno;
+
+ close(fd);
+
+ return -1;
+ }
+
+ errno = old_errno;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Opened socket to server.");
+
+ return 0;
+}
+
+static int send_commands
+(
+ const int argc,
+ const char * argv [const restrict static argc],
+ FILE socket [const restrict static 1]
+)
+{
+ int i, j;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Sending commands to server...");
+
+ for (i = 3; i < argc;)
+ {
+
+ if (fputs(argv[i], socket) == EOF)
+ {
+ // TODO: error
+ }
+
+ for
+ (
+ j = relabsd_parameters_argument_count_for(argv[i]),
+ i++;
+ ((j > 0) && (i < argc));
+ j++, i--
+ )
+ {
+ if (fputc(' ', socket) == EOF)
+ {
+ // TODO: error
+ }
+ if (fputs(argv[i], socket) == EOF)
+ {
+ // TODO: error
+ }
+ }
+
+ if (fputc('\0', socket) == EOF)
+ {
+ // TODO: error
+ }
+ }
+
+ if (fputc('\0', socket) == EOF)
+ {
+ }
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Sent commands to server.");
+
+ return 0;
+}
+
+static int receive_reply
+(
+ FILE socket [const restrict static 1]
+)
+{
+ return 0;
+}
+
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
+int relabsd_client
+(
+ const int argc,
+ const char * argv [const restrict static argc],
+ struct relabsd_parameters params [const restrict static 1]
+)
+{
+ FILE * socket;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Started client mode.");
+
+ if (open_socket(&socket, relabsd_parameters_get_node(params)) < 0)
+ {
+ return -1;
+ }
+
+ if (send_commands(argc, argv, socket) < 0)
+ {
+ return -2;
+ }
+
+ if (receive_reply(socket) < 0)
+ {
+ return -3;
+ }
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Completed client mode.");
+
+ return 0;
+}
diff --git a/src/config.c b/src/config/config_file.c
index ad060a5..ad060a5 100644
--- a/src/config.c
+++ b/src/config/config_file.c
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;
+}
diff --git a/src/axis.c b/src/device/axis/axis_name.c
index c4729ba..c18a28f 100644
--- a/src/axis.c
+++ b/src/device/axis/axis_name.c
@@ -1,11 +1,24 @@
+/**** LIBEVDEV ****************************************************************/
#include <libevdev/libevdev.h>
-#include "pervasive.h"
+/**** RELABSD *****************************************************************/
+#include <relabsd/debug.h>
-#include "axis.h"
-#include "error.h"
+#include <relabsd/util/string.h>
-enum relabsd_axis relabsd_axis_from_name (const char * const name)
+#include <relabsd/device/axis.h>
+
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
+enum relabsd_axis_name relabsd_axis_parse_name
+(
+ const char name [const restrict static 1]
+)
{
if (RELABSD_STRING_EQUALS("X", name))
{
@@ -43,7 +56,7 @@ enum relabsd_axis relabsd_axis_from_name (const char * const name)
return RELABSD_UNKNOWN;
}
-char * relabsd_axis_to_name (enum relabsd_axis const e)
+const char * relabsd_axis_name_to_string (const enum relabsd_axis_name e)
{
switch (e)
{
@@ -83,10 +96,10 @@ char * relabsd_axis_to_name (enum relabsd_axis const e)
return "..";
}
-enum relabsd_axis relabsd_axis_convert_evdev_rel
+enum relabsd_axis_name relabsd_axis_name_and_evdev_abs_from_evdev_rel
(
- unsigned int const rel_code,
- unsigned int * const abs_code
+ const unsigned int rel_code,
+ unsigned int abs_code [const restrict static 1]
)
{
switch (rel_code)
@@ -128,7 +141,7 @@ enum relabsd_axis relabsd_axis_convert_evdev_rel
}
}
-unsigned int relabsd_axis_to_rel (enum relabsd_axis const e)
+unsigned int relabsd_axis_name_to_evdev_rel (const enum relabsd_axis_name e)
{
switch (e)
{
@@ -159,7 +172,7 @@ unsigned int relabsd_axis_to_rel (enum relabsd_axis const e)
case RELABSD_UNKNOWN:
RELABSD_S_PROG_ERROR
(
- "relabsd_axis_to_rel(RELABSD_UNKNOWN) is forbidden."
+ "relabsd_axis_name_to_evdev_rel(RELABSD_UNKNOWN) is forbidden."
);
return REL_MAX;
@@ -167,12 +180,15 @@ unsigned int relabsd_axis_to_rel (enum relabsd_axis const e)
break;
}
- RELABSD_S_PROG_ERROR("relabsd_axis_to_rel is missing at least 1 case.");
+ RELABSD_S_PROG_ERROR
+ (
+ "relabsd_axis_name_to_evdev_rel is missing at least 1 case."
+ );
return REL_MAX;
}
-unsigned int relabsd_axis_to_abs (enum relabsd_axis const e)
+unsigned int relabsd_axis_name_to_evdev_abs (const enum relabsd_axis_name e)
{
switch (e)
{
@@ -219,7 +235,7 @@ unsigned int relabsd_axis_to_abs (enum relabsd_axis const e)
/*
* Returns the relabsd_axis equivalent of a EV_REL/EV_ABS code.
*/
-enum relabsd_axis relabsd_axis_from_rel (unsigned int const rel)
+enum relabsd_axis_name relabsd_axis_name_from_evdev_rel (const unsigned int rel)
{
switch (rel)
{
@@ -251,7 +267,8 @@ enum relabsd_axis relabsd_axis_from_rel (unsigned int const rel)
return RELABSD_UNKNOWN;
}
}
-enum relabsd_axis relabsd_axis_from_abs (unsigned int const abs)
+
+enum relabsd_axis_name relabsd_axis_name_from_evdev_abs (const unsigned int abs)
{
switch (abs)
{
diff --git a/src/input.c b/src/device/physical_device.c
index e8e1bab..a518750 100644
--- a/src/input.c
+++ b/src/device/physical_device.c
@@ -79,9 +79,9 @@ static int device_is_compatible
return 0;
}
-int relabsd_input_open
+int relabsd_physical_device_open
(
- struct relabsd_input * const input,
+ struct relabsd_physical_device * const input,
const struct relabsd_config * const conf
)
{
@@ -126,7 +126,7 @@ int relabsd_input_open
return 0;
}
-void relabsd_input_close (const struct relabsd_input * const input)
+void relabsd_physical_device_close (const struct relabsd_physical_device * const input)
{
RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Closing input device...");
@@ -134,9 +134,9 @@ void relabsd_input_close (const struct relabsd_input * const input)
close(input->fd);
}
-int relabsd_input_read
+int relabsd_physical_device_read
(
- const struct relabsd_input * const input,
+ const struct relabsd_physical_device * const input,
unsigned int * const input_type,
unsigned int * const input_code,
int * const input_value
@@ -190,9 +190,9 @@ int relabsd_input_read
return 0;
}
-int relabsd_input_wait_for_next_event
+int relabsd_physical_device_wait_for_next_event
(
- const struct relabsd_input * const input,
+ const struct relabsd_physical_device * const input,
const struct relabsd_config * const config
)
{
diff --git a/src/relabsd_device.c b/src/device/virtual_device.c
index 51dd6c0..19d1097 100644
--- a/src/relabsd_device.c
+++ b/src/device/virtual_device.c
@@ -1,34 +1,8 @@
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <libevdev/libevdev-uinput.h>
-
-#include "error.h"
-#include "axis.h"
-#include "config.h"
-
-#include "relabsd_device.h"
-
-/*
- LIBEVDEV_UINPUT_OPEN_MANAGED is not defined on my machines.
- It is not my place to define it, so I'll avoid the issue by defining my own
- constant.
-*/
-#ifndef LIBEVDEV_UINPUT_OPEN_MANAGED
- #pragma message "[WARNING] libevdev did not define "\
- "LIBEVDEV_UINPUT_OPEN_MANAGED, using value '-2' instead."
- #define RELABSD_UINPUT_OPEN_MANAGED -2
-#else
- #define RELABSD_UINPUT_OPEN_MANAGED LIBEVDEV_UINPUT_OPEN_MANAGED
-#endif
+
static void replace_rel_axes
(
- struct relabsd_device * const dev,
+ struct relabsd_virtual_device * const dev,
const struct relabsd_config * const config
)
{
@@ -132,9 +106,9 @@ static int rename_device
return 0;
}
-int relabsd_device_create
+int relabsd_virtual_device_create
(
- struct relabsd_device * const dev,
+ struct relabsd_virtual_device * const dev,
const struct relabsd_config * const config
)
{
@@ -208,7 +182,7 @@ int relabsd_device_create
return 0;
}
-void relabsd_device_destroy (const struct relabsd_device * const dev)
+void relabsd_virtual_device_destroy (const struct relabsd_virtual_device * const dev)
{
RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Destroying virtual device...");
@@ -216,9 +190,9 @@ void relabsd_device_destroy (const struct relabsd_device * const dev)
libevdev_free(dev->dev);
}
-int relabsd_device_write_evdev_event
+int relabsd_virtual_device_write_evdev_event
(
- const struct relabsd_device * const dev,
+ const struct relabsd_virtual_device * const dev,
unsigned int const type,
unsigned int const code,
int const value
@@ -262,9 +236,9 @@ int relabsd_device_write_evdev_event
return -1;
}
-void relabsd_device_set_axes_to_zero
+void relabsd_virtual_device_set_axes_to_zero
(
- const struct relabsd_device * const dev,
+ const struct relabsd_virtual_device * const dev,
const struct relabsd_config * const config
)
{
@@ -274,7 +248,7 @@ void relabsd_device_set_axes_to_zero
{
if (config->axis[i].enabled)
{
- relabsd_device_write_evdev_event
+ relabsd_virtual_device_write_evdev_event
(
dev,
EV_ABS,
diff --git a/src/main.c b/src/main.c
index bd5375c..d4089b9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,163 +1,44 @@
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h>
+/**** RELABSD *****************************************************************/
+#include <relabsd/client.h>
+#include <relabsd/config.h>
+#include <relabsd/debug.h>
+#include <relabsd/server.h>
-#include "pervasive.h"
-#include "error.h"
-#include "config.h"
-#include "input.h"
-#include "relabsd_device.h"
+#include <relabsd/config/parameters.h>
-static int RELABSD_RUN = 1;
-
-static void interrupt (int unused_mandatory_parameter)
-{
- RELABSD_RUN = 0;
-
- RELABSD_S_WARNING("Interrupted, will exit at the next input device event.");
-}
-
-static void handle_relative_axis_event
-(
- struct relabsd_config * const conf,
- const struct relabsd_device * const dev,
- unsigned int const input_type,
- unsigned int const input_code,
- int value
-)
-{
- unsigned int abs_code;
- enum relabsd_axis rad_code;
-
- rad_code = relabsd_axis_convert_evdev_rel(input_code, &abs_code);
-
- switch (relabsd_config_filter(conf, rad_code, &value))
- {
- case -1:
- /* 'conf' doesn't want the event to be transmitted. */
- break;
-
- case 0:
- /* 'conf' wants the event to be transmitted as is. */
- relabsd_device_write_evdev_event(dev, input_type, input_code, value);
- break;
-
- case 1:
- /* 'conf' allows the value to be emitted */
- relabsd_device_write_evdev_event(dev, EV_ABS, abs_code, value);
- break;
- }
-}
-
-static void convert_input
-(
- struct relabsd_config * const conf,
- struct relabsd_input * const input,
- const struct relabsd_device * const dev
-)
-{
- unsigned int input_type, input_code;
- int value;
-
- RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Handling input events...");
-
- input->timed_out = 1;
-
- while (RELABSD_RUN == 1)
- {
- if (conf->enable_timeout)
- {
- switch (relabsd_input_wait_for_next_event(input, conf))
- {
- case 1:
- input->timed_out = 0;
- break;
-
- case 0:
- relabsd_device_set_axes_to_zero(dev, conf);
- input->timed_out = 1;
- break;
-
- case -1:
- continue;
- }
- }
-
- if (relabsd_input_read(input, &input_type, &input_code, &value) < 0)
- {
- /*
- * The next event should not be retransmitted, or some kind of error
- * happened.
- */
- /* TODO: error handling. */
- continue;
- }
-
- if (input_type == EV_REL)
- {
- /* We might have to convert the event. */
- handle_relative_axis_event(conf, dev, input_type, input_code, value);
- }
- else
- {
- /* Any other event is retransmitted as is. */
- relabsd_device_write_evdev_event(dev, input_type, input_code, value);
- }
- }
-}
-
-static int set_signal_handlers ()
-{
- RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Setting signal handlers.");
-
- if (signal(SIGINT, interrupt) == SIG_ERR)
- {
- RELABSD_S_FATAL("Unable to set the SIGINT signal handler.");
-
- return -1;
- }
-
- return 0;
-}
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
int main (int argc, char ** argv)
{
- struct relabsd_config conf;
- struct relabsd_input input;
- struct relabsd_device dev;
+ int retval;
+ struct relabsd_parameters params;
RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "relabsd started.");
- if (set_signal_handlers() < 0)
+ if (relabsd_parameters_parse_execution_mode(argc, argv, &params) < 0)
{
- return -1;
- }
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "relabsd crashing");
- if (relabsd_config_parse(&conf, argc, argv) < 0)
- {
- return -2;
+ return -1;
}
- if (relabsd_input_open(&input, &conf) < 0)
+ switch (relabsd_parameters_get_execution_mode(&params))
{
- return -3;
- }
+ case RELABSD_PARAMETERS_CLIENT_MODE:
+ retval = relabsd_client_main(argc, argv, &params);
+ break;
- if (relabsd_device_create(&dev, &conf) < 0)
- {
- return -4;
+ case RELABSD_PARAMETERS_RUN_SERVER_MODE:
+ retval = relabsd_server_main(argc, argv, &params);
+ break;
}
- convert_input(&conf, &input, &dev);
-
- RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Terminating...");
-
- relabsd_device_destroy(&dev);
- relabsd_input_close(&input);
-
- RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Done.");
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "relabsd terminating.");
- return 0;
+ return retval;
}
diff --git a/src/server/daemon.c b/src/server/daemon.c
new file mode 100644
index 0000000..7b8e736
--- /dev/null
+++ b/src/server/daemon.c
@@ -0,0 +1,126 @@
+/**** POSIX *******************************************************************/
+#include <sys/types.h>
+
+#include <unistd.h>
+
+/**** RELABSD *****************************************************************/
+#include <relabsd/config.h>
+#include <relabsd/debug.h>
+#include <relabsd/server.h>
+
+#include <relabsd/config/parameters.h>
+
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
+/*
+ * Daemon creation function made using the instructions for old-school daemons
+ * at https://www.freedesktop.org/software/systemd/man/daemon.html
+ * Only meant to be used before things really start. This won't properly create
+ * a daemon on an already running server instance with a virtual device and so
+ * on...
+ */
+int relabsd_server_create_daemon (void)
+{
+ pid_t proc_id;
+
+ /* 1/ Close all open file descriptors ... **********************************/
+ /* None were opened at this point. */
+
+ /* 2/ Reset all signal handlers ... ****************************************/
+ /* Those were not modified at this point. */
+
+ /* 3/ Reset the signal mask using sigprocmask() ****************************/
+ /* Not modified at this point. */
+
+ /* 4/ Sanitize the environment block ... ***********************************/
+ /* What? */
+
+ /* 5/ fork() ***************************************************************/
+ errno = 0;
+ proc_id = fork();
+
+ if (proc_id == ((pid_t) -1))
+ {
+ RELABSD_FATAL
+ (
+ "Step 5 of the daemon creation process, fork(), failed: %s.",
+ strerror(errno)
+ );
+
+ return -1;
+ }
+
+ if (proc_id != ((pid_t) 0))
+ {
+ /* Awaiting step 14...*/
+ /* TODO: insert unnamed pipe */
+ /* 15/ Original process exits *******************************************/
+ exit();
+ }
+
+ /* 6/ setsid() *************************************************************/
+ errno = 0;
+
+ proc_id = setsid();
+
+ if (proc_id == ((pid_t) -1))
+ {
+ RELABSD_FATAL
+ (
+ "Step 6 of the daemon creation process, setsid(), failed: %s.",
+ strerror(errno)
+ );
+
+ return -1;
+ }
+
+ /* 7/ fork() again *********************************************************/
+ errno = 0;
+ proc_id = fork();
+
+ if (proc_id == ((pid_t) -1))
+ {
+ RELABSD_FATAL
+ (
+ "Step 5 of the daemon creation process, fork(), failed: %s.",
+ strerror(errno)
+ );
+
+ return -1;
+ }
+
+ if (proc_id != ((pid_t) 0))
+ {
+ /* 8/ First child process exits *****************************************/
+ exit();
+ }
+
+ /* 9/ /dev/null for standard input/outputs *********************************/
+
+ /* 10/ reset umask to 0 ****************************************************/
+
+ /* 11/ Set current directory to / ******************************************/
+ errno = 0;
+
+ if (chdir("/") == -1)
+ {
+ // Can't print an error message at that point though...
+ return -1;
+ }
+
+ /* 12/ lock file using PID to assert single instance ***********************/
+ /* Don't want to limit to a single instance. */
+
+ /* 13/ Drop privileges *****************************************************/
+
+ /* 14/ Signal completion ***************************************************/
+
+ /* Step 15 is done on the very first process. */
+
+ return 0;
+}
diff --git a/src/server/main_loop.c b/src/server/main_loop.c
new file mode 100644
index 0000000..7db1423
--- /dev/null
+++ b/src/server/main_loop.c
@@ -0,0 +1,165 @@
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "pervasive.h"
+#include "error.h"
+#include "config.h"
+#include "input.h"
+#include "relabsd_device.h"
+
+static int RELABSD_RUN = 1;
+
+static void interrupt (int unused_mandatory_parameter)
+{
+ RELABSD_RUN = 0;
+
+ RELABSD_S_WARNING("Interrupted, will exit at the next input device event.");
+}
+
+static void handle_relative_axis_event
+(
+ struct relabsd_config * const conf,
+ const struct relabsd_device * const dev,
+ unsigned int const input_type,
+ unsigned int const input_code,
+ int value
+)
+{
+ unsigned int abs_code;
+ enum relabsd_axis rad_code;
+
+ rad_code = relabsd_axis_convert_evdev_rel(input_code, &abs_code);
+
+ switch (relabsd_config_filter(conf, rad_code, &value))
+ {
+ case -1:
+ /* 'conf' doesn't want the event to be transmitted. */
+ break;
+
+ case 0:
+ /* 'conf' wants the event to be transmitted as is. */
+ relabsd_device_write_evdev_event(dev, input_type, input_code, value);
+ break;
+
+ case 1:
+ /* 'conf' allows the value to be emitted */
+ relabsd_device_write_evdev_event(dev, EV_ABS, abs_code, value);
+ break;
+ }
+}
+
+static void convert_input
+(
+ struct relabsd_config * const conf,
+ struct relabsd_input * const input,
+ const struct relabsd_device * const dev
+)
+{
+ unsigned int input_type, input_code;
+ int value;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Handling input events...");
+
+ input->timed_out = 1;
+
+ while (RELABSD_RUN == 1)
+ {
+ if (conf->enable_timeout)
+ {
+ switch (relabsd_input_wait_for_next_event(input, conf))
+ {
+ case 1:
+ input->timed_out = 0;
+ break;
+
+ case 0:
+ relabsd_device_set_axes_to_zero(dev, conf);
+ input->timed_out = 1;
+ break;
+
+ case -1:
+ continue;
+ }
+ }
+
+ if (relabsd_input_read(input, &input_type, &input_code, &value) < 0)
+ {
+ /*
+ * The next event should not be retransmitted, or some kind of error
+ * happened.
+ */
+ /* TODO: error handling. */
+ continue;
+ }
+
+ if (input_type == EV_REL)
+ {
+ /* We might have to convert the event. */
+ handle_relative_axis_event(conf, dev, input_type, input_code, value);
+ }
+ else
+ {
+ /* Any other event is retransmitted as is. */
+ relabsd_device_write_evdev_event(dev, input_type, input_code, value);
+ }
+ }
+}
+
+static int set_signal_handlers ()
+{
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Setting signal handlers.");
+
+ if (signal(SIGINT, interrupt) == SIG_ERR)
+ {
+ RELABSD_S_FATAL("Unable to set the SIGINT signal handler.");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+int main (int argc, char ** argv)
+{
+ struct relabsd_config conf;
+ struct relabsd_input input;
+ struct relabsd_device dev;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "relabsd started.");
+
+ if (set_signal_handlers() < 0)
+ {
+ return -1;
+ }
+
+ if (relabsd_config_parse(&conf, argc, argv) < 0)
+ {
+ return -2;
+ }
+
+ if (relabsd_input_open(&input, &conf) < 0)
+ {
+ return -3;
+ }
+
+ if (relabsd_device_create(&dev, &conf) < 0)
+ {
+ return -4;
+ }
+
+ convert_input(&conf, &input, &dev);
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Terminating...");
+
+ relabsd_device_destroy(&dev);
+ relabsd_input_close(&input);
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Done.");
+
+ return 0;
+}
+*/
diff --git a/src/server/server.c b/src/server/server.c
new file mode 100644
index 0000000..debeb91
--- /dev/null
+++ b/src/server/server.c
@@ -0,0 +1,113 @@
+/**** RELABSD *****************************************************************/
+#include <relabsd/config.h>
+#include <relabsd/debug.h>
+#include <relabsd/server.h>
+
+#include <relabsd/config/parameters.h>
+
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
+int initialize
+(
+ struct relabsd_server server [const restrict static 1],
+ struct relabsd_parameters params [const static 1]
+)
+{
+ server->parameters = params;
+
+ if
+ (
+ relabsd_physical_device_open
+ (
+ relabsd_parameters_get_physical_device_name(params),
+ &(server->physical_device)
+ )
+ < 0
+ )
+ {
+ return -1;
+ }
+
+ if
+ (
+ relabsd_virtual_device_create
+ (
+
+ &(server->virtual_device)
+ )
+ < 0
+ )
+ {
+ relabsd_physical_device_close(&(server->physical_device));
+
+ return -2;
+ }
+
+ if
+ (
+ (relabsd_parameters_get_communication_node(params) != ((...) NULL))
+ && (relabsd_server_spawn_communication_node(server) < 0)
+ )
+ {
+ relabsd_virtual_device_destroy(&(server->virtual_device));
+ relabsd_physical_device_close(&(server->physical_device));
+
+ return -3;
+ }
+
+ return 0;
+}
+
+void finalize (struct relabsd_server server [const static 1])
+{
+ if (relabsd_parameters_get_communication_node(params) != ((...) NULL))
+ {
+ relabsd_server_join_communication_node(&server);
+ }
+
+ relabsd_virtual_device_destroy(&(server->virtual_device));
+ relabsd_physical_device_close(&(server->physical_device));
+
+ return 0;
+}
+
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
+int relabsd_server
+(
+ const int argc,
+ const char * const argv [const restrict static argc],
+ struct relabsd_parameters params [const static 1]
+)
+{
+ struct relabsd_server server;
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Started server mode.");
+
+ if (relabsd_parameters_parse_options(argc, argv, params) < 0)
+ {
+ return -1;
+ }
+
+ if
+ (
+ (relabsd_parameters_run_as_daemon(params))
+ && (relabsd_server_create_daemon() < 0)
+ )
+ {
+ return -2;
+ }
+
+ (void) initialize(&server, params);
+
+ (void) relabsd_server_conversion_loop(&server);
+
+ finalize(&server);
+
+
+ RELABSD_S_DEBUG(RELABSD_DEBUG_PROGRAM_FLOW, "Completed server mode.");
+
+ return 0;
+}
diff --git a/src/util/string.c b/src/util/string.c
new file mode 100644
index 0000000..edb5eb6
--- /dev/null
+++ b/src/util/string.c
@@ -0,0 +1,36 @@
+/**** POSIX *******************************************************************/
+#include <stdlib.h>
+
+/******************************************************************************/
+/**** LOCAL FUNCTIONS *********************************************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/**** EXPORTED FUNCTIONS ******************************************************/
+/******************************************************************************/
+int relabsd_util_parse_int
+(
+ const char string [const restrict static 1],
+ const int min,
+ const int max,
+ int output [const restrict static 1]
+)
+{
+ char * invalid_char; /* may become an alias of string. */
+ long int buffer;
+
+ buffer = strtol(string, &invalid_char, 10);
+
+ if ((invalid_char[0] != '\0') || (string[0] == '\0'))
+ {
+ return -1;
+ }
+
+ if ((buffer < ((long int) min)) || (buffer > ((long int) max)))
+ {
+ return -2;
+ }
+
+ *output = ((int) buffer);
+ return 0;
+}