From cd5f9f7a12f33c18db838a9978b8e4fd617c8eb5 Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Mon, 25 Dec 2023 00:06:56 +0300 Subject: [PATCH] - --- .vscode/settings.json | 11 +- CMakeLists.txt | 27 ++++ mportlink | Bin 0 -> 20848 bytes src/mpl-core.c | 354 ++++++++++-------------------------------- src/mpl-core.h | 20 ++- src/mpl-lib.h | 18 +-- src/mpl-udev.c | 167 +++++++++++++++----- src/mpl-udev.h | 19 ++- src/mpl.c | 65 +++++++- src/mpl.h | 5 +- 10 files changed, 344 insertions(+), 342 deletions(-) create mode 100755 mportlink diff --git a/.vscode/settings.json b/.vscode/settings.json index 48fe63b..cbe4c24 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -30,10 +30,11 @@ "mpl-lib.h": "c", "mpl-core.h": "c", "mpl.h": "c", - "mpl-udev.h": "c" + "mpl-udev.h": "c", + "mpl-args.h": "c", + "*.in": "cpp", + "signal.h": "c", + "stdio.h": "c" }, - "cmake.configureOnOpen": false, - "editor.rulers": [ - 80 - ] + "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 2188cc3..8b5b116 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,33 @@ cmake_minimum_required(VERSION 3.18.4) project(mportlink) +# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Os") + +set(VERSION_MAJOR 0) +set(VERSION_MINOR 1) +set(VERSION_PATCH 0) +string(TIMESTAMP CURRENT_YEAR "%y" UTC) +string(TIMESTAMP DAY_OF_YEAR "%j" UTC) + +string(CONCAT BASEVERSION "${VERSION_MAJOR}" "." "${VERSION_MINOR}" "." "${VERSION_PATCH}") +string(CONCAT BUILDVERSION "${BASEVERSION}" "." "${CURRENT_YEAR}" "${DAY_OF_YEAR}") + +execute_process( + COMMAND git describe HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +if(GIT_SHORT_HASH STREQUAL "") + set(VERSION "${BUILDVERSION}") +else() + set(VERSION "${GIT_VERSION}") +endif() + +add_definitions(-DVERSION="${VERSION}") + file(GLOB_RECURSE SRC_FILES_LIST src/*.c) find_package(PkgConfig REQUIRED) diff --git a/mportlink b/mportlink new file mode 100755 index 0000000000000000000000000000000000000000..34660c6b236d72a7f905dd1347bf7a676689b8f6 GIT binary patch literal 20848 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 Bu!jHu literal 0 HcmV?d00001 diff --git a/src/mpl-core.c b/src/mpl-core.c index 3f3e8c2..d60fc6a 100644 --- a/src/mpl-core.c +++ b/src/mpl-core.c @@ -5,304 +5,108 @@ * Telegram @alexanderzhirov */ +#include "mpl-core.h" + #include #include - -#include "mpl-core.h" +#include #define LOCKFILE "/run/lock/mportlink.lock" #define DEV_PATH "/dev/" #define DONGLE_PATH (DEV_PATH "dongle/") -static void mpl_create_dongle_dir() +static int mpl_create_dongle_dir() { struct stat st; - if (stat(DONGLE_PATH, &st) == 0) { - if (!S_ISDIR(st.st_mode)) { - MPLOG(LOG_WARNING, "%s exists and is not a directory", - DONGLE_PATH); - exit(EXIT_FAILURE); + if (stat(DONGLE_PATH, &st) == 0) + { + if (!S_ISDIR(st.st_mode)) + { + MPLOG(LOG_WARNING, "%s exists and is not a directory", DONGLE_PATH); + return 1; } - } else if (mkdir(DONGLE_PATH, - S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) { + } + else if (mkdir(DONGLE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) + { MPLOG(LOG_ERR, "unable to create a directory %s", DONGLE_PATH); - exit(EXIT_FAILURE); + return 1; } + + return 0; } -int mpl_init() +void static mpl_free(MPL *mpl) { - openlog(MPL, LOG_PID, LOG_SYSLOG); - - int lock_fd = open(LOCKFILE, O_CREAT | O_RDWR, 0644); - if (lock_fd < 0) { - MPLOG(LOG_ERR, "Unable to create a lockfile"); - exit(EXIT_FAILURE); - } - - int rc = flock(lock_fd, LOCK_EX | LOCK_NB); - if (rc || errno == EWOULDBLOCK) { - MPLOG(LOG_ERR, "Only one instance of %s is allowed", MPL); - exit(EXIT_FAILURE); - } - - mpl_create_dongle_dir(); - - MPLOG(LOG_NOTICE, "Starting the %s daemon", MPL); - - return lock_fd; + if (mpl) + free(mpl); } -void mpl_stop(const int lock_fd) +MPL *mpl_init(MPL_PARAMETERS *parameters) { - flock(lock_fd, LOCK_UN); + MPL *mpl = (MPL *)calloc(1, sizeof(MPL)); - MPLOG(LOG_NOTICE, "Stopping the %s daemon", MPL); + if (!mpl) + { + MPLOG(LOG_ERR, "error getting the MPL structure"); + exit(1); + } + + mpl->parameters.check_device = parameters->check_device; + mpl->cancellable.signal = 0; + mpl->cancellable.exit = 0; + + mpl->fd = open(LOCKFILE, O_CREAT | O_RDWR, 0644); + if (mpl->fd < 0) + { + MPLOG(LOG_ERR, "unable to create a lockfile"); + exit(1); + } + + int rc = flock(mpl->fd, LOCK_EX | LOCK_NB); + if (rc || errno == EWOULDBLOCK) + { + MPLOG(LOG_ERR, "only one instance of %s is allowed", MPL_NAME); + exit(1); + } + + if (mpl_create_dongle_dir()) + { + MPLOG(LOG_ERR, "%s will be stopped", MPL_NAME); + exit(1); + } + + if (mpl_udev_init(&mpl->udev)) + { + MPLOG(LOG_ERR, "%s will be stopped", MPL_NAME); + mpl_free(mpl); + exit(1); + } + + MPLOG(LOG_NOTICE, "starting the %s daemon", MPL_NAME); + + return mpl; +} + +void mpl_stop(MPL *mpl) +{ + mpl_udev_free(&mpl->udev); + + flock(mpl->fd, LOCK_UN); + + mpl_free(mpl); + + if (mpl->cancellable.exit) + MPLOG(LOG_NOTICE, "stopping the %s daemon", MPL_NAME); + else + MPLOG(LOG_NOTICE, "successful completion of the process %d", getpid()); closelog(); } -MPL_UDEV *mpl_new() +void mpl_loop(MPL *mpl) { - MPL_UDEV *mpl_udev = (MPL_UDEV *)calloc(1, sizeof(MPL_UDEV)); + if (mpl->parameters.check_device) + mpl_udev_check_devices(&mpl->udev); - if (mpl_udev == NULL) { - MPLOG(LOG_ERR, "Error getting the udev structure"); - exit(EXIT_FAILURE); - } - - return mpl_udev; + mpl_udev_loop(&mpl->udev, &mpl->cancellable); } - -void mpl_loop(MPL_UDEV *mpl_udev) -{ - -} - - -// typedef struct -// { -// const gchar *manufacturer; -// const gchar *model; -// const gchar *imei; -// const gchar *device_identifier; -// MMModemPortInfo *ports; -// guint n_ports; -// } MPLmodem; - - -// MPLmodem *mpl_get_new_modem() -// { -// MPLmodem *modem = (MPLmodem *)calloc(1, sizeof(MPLmodem)); - -// if (modem == NULL) -// { -// syslog(LOG_ERR, "mpl_get_new_modem, modem: memory allocation error"); -// raise(SIGINT); -// } - -// return modem; -// } - -// void mpl_free_modem(MPLmodem *modem) -// { -// if (modem->n_ports && modem->ports) -// mm_modem_port_info_array_free(modem->ports, modem->n_ports); -// free(modem); -// } - -// void mpl_print_modem_info(MPLmodem *modem, bool connected) -// { -// gchar *status; -// status = connected ? "Connected" : "Disconnected"; - -// g_print("%s %s %s (%s)\n", status, modem->manufacturer, modem->model, modem->device_identifier); -// g_print("`-- Count ports: %d\n", modem->n_ports); - -// for (guint i = 0; i < modem->n_ports; i++) -// { -// if (i + 1 < modem->n_ports) -// { -// g_print(" |-- Port %d:\n", i); -// g_print(" | |-- Name: %s\n", modem->ports[i].name); -// g_print(" | `-- Link: %s-%d\n", modem->imei, i); -// } -// else -// { -// g_print(" `-- Port %d:\n", i); -// g_print(" |-- Name: %s\n", modem->ports[i].name); -// g_print(" `-- Link: %s-%d\n", modem->imei, i); -// } -// } -// } - -// MPLmodem *mpl_get_new_modem_info(MMObject *obj) -// { -// MPLmodem *mpl_modem = NULL; -// MMModem *mm_modem = mm_object_get_modem(obj); - -// if (mm_modem == NULL) -// { -// syslog(LOG_ERR, "mpl_get_new_modem_info, mm_modem: modem does not implement the interface"); -// return NULL; -// } - -// mpl_modem = mpl_get_new_modem(); - -// mpl_modem->manufacturer = mm_modem_get_manufacturer(mm_modem); -// mpl_modem->model = mm_modem_get_model(mm_modem); -// mpl_modem->imei = mm_modem_get_equipment_identifier(mm_modem); -// mpl_modem->device_identifier = mm_modem_get_device_identifier(mm_modem); - -// gboolean success = mm_modem_get_ports(mm_modem, &mpl_modem->ports, &mpl_modem->n_ports); - -// g_object_unref(mm_modem); - -// if (success) -// return mpl_modem; -// else -// syslog(LOG_WARNING, "mpl_get_new_modem_info, success: error receiving modem ports"); - -// mpl_free_modem(mpl_modem); - -// return NULL; -// } - -// char *mpl_get_dst_path(guint index, const gchar *imei) -// { -// char *dst_path = NULL; - -// guint size_id = snprintf(NULL, 0, "-%d", index); -// char *id = (char *)calloc(size_id + 1, sizeof(char)); - -// if (id == NULL) -// { -// syslog(LOG_ERR, "mpl_get_dst_path, id: memory allocation error"); -// raise(SIGINT); -// } - -// sprintf(id, "-%d", index); - -// guint dst_path_size = strlen(DONGLE_PATH) + strlen(imei) + size_id; -// dst_path = (char *)calloc(dst_path_size + 1, sizeof(char)); - -// if (dst_path == NULL) -// { -// syslog(LOG_ERR, "mpl_get_dst_path, dst_path: memory allocation error"); -// raise(SIGINT); -// } - -// strcpy(dst_path, DONGLE_PATH); -// strcat(dst_path, imei); -// strcat(dst_path, id); - -// free(id); - -// return dst_path; -// } - -// char *mpl_get_src_path(const gchar *port_name) -// { -// char *src_path = NULL; - -// guint src_path_size = strlen(DEV_PATH) + strlen(port_name); -// src_path = (char *)calloc(src_path_size + 1, sizeof(char)); - -// if (src_path == NULL) -// { -// syslog(LOG_ERR, "mpl_get_src_path, src_path: memory allocation error"); -// raise(SIGINT); -// } - -// strcpy(src_path, DEV_PATH); -// strcat(src_path, port_name); - -// return src_path; -// } - -// void mpl_symlink_ports(MPLmodem *modem) -// { -// for (guint i = 0; i < modem->n_ports; i++) -// { -// char *src_path = mpl_get_src_path(modem->ports[i].name); -// char *dst_path = mpl_get_dst_path(i, modem->imei); -// struct stat st; - -// if (access(src_path, F_OK) == -1) -// { -// syslog(LOG_ERR, "mpl_symlink_ports, src_path: device file is not available [%s]", src_path); -// free(src_path); -// free(dst_path); -// continue; -// } - -// if (lstat(dst_path, &st) == 0) -// { -// syslog(LOG_WARNING, "mpl_symlink_ports, dst_path: a symbolic link to the device already exists [%s]", dst_path); -// if (unlink(dst_path) == -1) -// { -// syslog(LOG_ERR, "mpl_symlink_ports, dst_path: link could not be deleted [%s]", dst_path); -// free(src_path); -// free(dst_path); -// continue; -// } -// } - -// if (symlink(src_path, dst_path) == 0) -// syslog(LOG_NOTICE, "mpl_symlink_ports, dst_path: the symbolic link has been successfully created [%s -> %s]", dst_path, src_path); -// else -// syslog(LOG_ERR, "mpl_symlink_ports, dst_path: error creating a symbolic link [%s -> %s]", dst_path, src_path); - -// free(src_path); -// free(dst_path); -// } -// } - -// void mpl_unlink_ports(MPLmodem *modem) -// { -// for (guint i = 0; i < modem->n_ports; i++) -// { -// char *dst_path = mpl_get_dst_path(i, modem->imei); -// struct stat st; - -// if (lstat(dst_path, &st) == -1) -// { -// syslog(LOG_WARNING, "mpl_unlink_ports, dst_path: a symbolic link to the device not exists [%s]", dst_path); -// free(dst_path); -// continue; -// } - -// if (unlink(dst_path) == 0) -// syslog(LOG_NOTICE, "mpl_unlink_ports, dst_path: link was successfully deleted [%s]", dst_path); -// else -// syslog(LOG_ERR, "mpl_unlink_ports, dst_path: link could not be deleted [%s]", dst_path); - -// free(dst_path); -// } -// } - -// void mpl_device_added(MMManager *manager, MMObject *obj) -// { -// MPLmodem *modem = mpl_get_new_modem_info(obj); - -// if (modem == NULL) -// return; - -// // mpl_print_modem_info(modem, true); -// mpl_symlink_ports(modem); - -// mpl_free_modem(modem); -// } - -// void mpl_device_removed(MMManager *manager, MMObject *obj) -// { -// MPLmodem *modem = mpl_get_new_modem_info(obj); - -// if (modem == NULL) -// return; - -// // mpl_print_modem_info(modem, false); -// mpl_unlink_ports(modem); - -// mpl_free_modem(modem); -// } diff --git a/src/mpl-core.h b/src/mpl-core.h index 8872ac0..2047178 100644 --- a/src/mpl-core.h +++ b/src/mpl-core.h @@ -9,11 +9,23 @@ #define MPL_CORE_H_ #include "mpl-lib.h" +#include "mpl-udev.h" -int mpl_init(); -void mpl_stop(const int lock_fd); -void mpl_loop(MPL_UDEV *mpl_udev); +typedef struct +{ + int check_device; +} MPL_PARAMETERS; -MPL_UDEV *mpl_new(); +typedef struct +{ + int fd; + MPL_PARAMETERS parameters; + MPL_CANCELLABLE cancellable; + MPL_UDEV udev; +} MPL; + +MPL *mpl_init(MPL_PARAMETERS *parameters); +void mpl_stop(MPL *mpl); +void mpl_loop(MPL *mpl); #endif diff --git a/src/mpl-lib.h b/src/mpl-lib.h index 69fb474..4facc06 100644 --- a/src/mpl-lib.h +++ b/src/mpl-lib.h @@ -15,24 +15,20 @@ #include #include -#define MPL "mportlink" +#define MPL_NAME "mportlink" #define MPLOG(PRIORITY, fmt, ...) do { \ char buf[256]; \ snprintf(buf, sizeof(buf), fmt __VA_OPT__(,) __VA_ARGS__); \ - PRIORITY < LOG_WARNING ? \ - syslog(PRIORITY, "%s(): %s (%s)", __func__, buf, \ - strerror(errno)) : \ + PRIORITY < LOG_WARNING && errno ? \ + syslog(PRIORITY, "%s(): %s (%s)", __func__, buf, strerror(errno)) : \ syslog(PRIORITY, "%s(): %s", __func__, buf); \ } while(0) -typedef struct _MPL_UDEV MPL_UDEV; - -struct _MPL_UDEV +typedef struct { - struct udev *udev; - struct udev_monitor *monitor; - int udev_fd; -}; + int signal; + int exit; +} MPL_CANCELLABLE; #endif diff --git a/src/mpl-udev.c b/src/mpl-udev.c index 266502b..27ccaf2 100644 --- a/src/mpl-udev.c +++ b/src/mpl-udev.c @@ -5,48 +5,54 @@ * Telegram @alexanderzhirov */ -#include "mpl-lib.h" #include "mpl-udev.h" -#include -void mpl_udev_init(MPL_UDEV *mpl_udev) +#include +#include + +int mpl_udev_init(MPL_UDEV *udev) { - mpl_udev->udev = udev_new(); - if (mpl_udev->udev == NULL) { - MPLOG(LOG_ERR, "Error creating udev context"); - exit(EXIT_FAILURE); + udev->context = udev_new(); + if (udev->context == NULL) + { + MPLOG(LOG_ERR, "error creating udev context"); + return 1; } - mpl_udev->monitor = udev_monitor_new_from_netlink(mpl_udev->udev, "udev"); - if (mpl_udev->monitor == NULL) { - MPLOG(LOG_ERR, "Error creating udev monitor"); - udev_unref(mpl_udev->udev); - exit(EXIT_FAILURE); + udev->monitor = udev_monitor_new_from_netlink(udev->context, "udev"); + if (udev->monitor == NULL) + { + MPLOG(LOG_ERR, "error creating udev monitor"); + mpl_udev_free(udev); + return 1; } - udev_monitor_filter_add_match_subsystem_devtype(mpl_udev->monitor, - "usb", NULL); - udev_monitor_enable_receiving(mpl_udev->monitor); + udev_monitor_filter_add_match_subsystem_devtype(udev->monitor, "usb", NULL); + udev_monitor_enable_receiving(udev->monitor); - mpl_udev->udev_fd = udev_monitor_get_fd(mpl_udev->monitor); - if (mpl_udev->udev_fd < 0) { - MPLOG(LOG_ERR, "Error creating udev monitor descriptor"); - udev_unref(mpl_udev->udev); - exit(EXIT_FAILURE); + udev->fd = udev_monitor_get_fd(udev->monitor); + if (udev->fd < 0) + { + MPLOG(LOG_ERR, "error creating udev monitor descriptor"); + mpl_udev_free(udev); + return 1; } + + return 0; } -void mpl_udev_check_devices(MPL_UDEV *mpl_udev) +int mpl_udev_check_devices(MPL_UDEV *udev) { struct udev_device *dev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; - enumerate = udev_enumerate_new(mpl_udev->udev); + enumerate = udev_enumerate_new(udev->context); - if (enumerate == NULL) { - MPLOG(LOG_ERR, "Error creating udev enumerate"); - exit(EXIT_FAILURE); + if (enumerate == NULL) + { + MPLOG(LOG_ERR, "error creating udev enumerate"); + return 1; } udev_enumerate_add_match_subsystem(enumerate, "usb"); @@ -54,25 +60,26 @@ void mpl_udev_check_devices(MPL_UDEV *mpl_udev) devices = udev_enumerate_get_list_entry(enumerate); - if (devices == NULL) { - MPLOG(LOG_ERR, "Error get udev devices"); - exit(EXIT_FAILURE); + if (devices == NULL) + { + MPLOG(LOG_ERR, "error get udev devices"); + return 1; } - udev_list_entry_foreach(dev_list_entry, devices) { + udev_list_entry_foreach(dev_list_entry, devices) + { const char *syspath = udev_list_entry_get_name(dev_list_entry); - dev = udev_device_new_from_syspath(mpl_udev->udev, syspath); + dev = udev_device_new_from_syspath(udev->context, syspath); const char *devtype = udev_device_get_devtype(dev); if (!(strcmp(devtype, "usb_interface") == 0)) continue; - + const char *driver = udev_device_get_driver(dev); if (!(strcmp(driver, "option") == 0)) continue; - const char *sysattr_value = udev_device_get_sysattr_value(dev, - "bInterfaceNumber"); + const char *sysattr_value = udev_device_get_sysattr_value(dev, "bInterfaceNumber"); printf("Номер порта: %s\n", sysattr_value); // int num = atoi(sysattr_value); @@ -85,10 +92,98 @@ void mpl_udev_check_devices(MPL_UDEV *mpl_udev) } udev_enumerate_unref(enumerate); + + return 0; } -mpl_udev_free(MPL_UDEV *mpl_udev) +void mpl_udev_free(MPL_UDEV *udev) { - udev_monitor_unref(mpl_udev->monitor); - udev_unref(mpl_udev->udev); + if (udev->monitor) + { + udev_monitor_unref(udev->monitor); + udev->monitor = NULL; + } + if (udev->context) + { + udev_unref(udev->context); + udev->context = NULL; + } +} + +void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable) +{ + const char *path_to_device = NULL; + int port_number = -1; + int status = -1; + pid_t pid = -1; + + while (1) + { + fd_set fds; + FD_ZERO(&fds); + FD_SET(udev->fd, &fds); + + if (select(udev->fd + 1, &fds, NULL, NULL, NULL) <= 0) + { + if (cancellable->exit) + return; + + MPLOG(LOG_ERR, "file selection error"); + break; + } + + struct udev_device *dev = udev_monitor_receive_device(udev->monitor); + if (dev) + { + const char *action = udev_device_get_property_value(dev, "ACTION"); + if (!(strcmp(action, "bind") == 0)) + { + udev_device_unref(dev); + continue; + } + + const char *devtype = udev_device_get_devtype(dev); + if (!(strcmp(devtype, "usb_interface") == 0)) + { + udev_device_unref(dev); + continue; + } + + const char *driver = udev_device_get_driver(dev); + if (!(strcmp(driver, "option") == 0)) + { + udev_device_unref(dev); + continue; + } + + const char *sysattr_value = udev_device_get_sysattr_value(dev, "bInterfaceNumber"); + if (sysattr_value == NULL) + { + udev_device_unref(dev); + continue; + } + + port_number = atoi(sysattr_value); + path_to_device = udev_device_get_syspath(dev); + + pid = fork(); + if (pid == 0) + { + udev_device_unref(dev); + break; + } + else + wait(&status); + + udev_device_unref(dev); + } + } + + mpl_udev_free(udev); + + if (cancellable->exit) + return; + + sleep(5); + printf("exit"); } diff --git a/src/mpl-udev.h b/src/mpl-udev.h index b1ef2e7..9e0c7ce 100644 --- a/src/mpl-udev.h +++ b/src/mpl-udev.h @@ -5,7 +5,22 @@ * Telegram @alexanderzhirov */ +#ifndef MPL_UDEV_H_ +#define MPL_UDEV_H_ + +#include #include "mpl-lib.h" -void mpl_udev_init(MPL_UDEV *mpl_udev); -void mpl_udev_check_devices(MPL_UDEV *mpl_udev); +typedef struct +{ + struct udev *context; + struct udev_monitor *monitor; + int fd; +} MPL_UDEV; + +int mpl_udev_init(MPL_UDEV *udev); +void mpl_udev_free(MPL_UDEV *udev); +int mpl_udev_check_devices(MPL_UDEV *udev); +void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable); + +#endif diff --git a/src/mpl.c b/src/mpl.c index 4e24828..74e3a36 100644 --- a/src/mpl.c +++ b/src/mpl.c @@ -5,25 +5,74 @@ * Telegram @alexanderzhirov */ +#include + #include "mpl.h" +static MPL *mpl; + +const char *const short_options = "hcv"; + +const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"check-devices", 0, NULL, 'c'}, + {"version", 0, NULL, 'v'}, + {NULL, 0, NULL, 0}}; + +[[noreturn]] void static print_usage_and_exit(int code) +{ + printf("Usage: %s [OPTION]...\n\n", MPL_NAME); + puts(" -c, --check-devices checking connected devices at startup"); + puts(" -h, --help display this help text and exit"); + puts(" -v, --version display version information and exit\n"); + exit(code); +} + +[[noreturn]] void static print_version_and_exit() +{ + printf("%s version %s\n", MPL_NAME, VERSION); + exit(0); +} + static void signals_handler(int signum) { - MPLOG(LOG_WARNING, "cancelling the main loop (%d)", signum); + MPLOG(LOG_WARNING, "cancelling the mportlink loop (%d)", signum); + mpl->cancellable.signal = signum; + mpl->cancellable.exit = 1; } -int main() +int main(int argc, char *argv[]) { - int lock_fd = mpl_init(); + int c; - MPL_UDEV *mpl = mpl_new(); - mpl_udev_init(mpl); + MPL_PARAMETERS parameters = + { + .check_device = 0 + }; + + while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) + switch (c) + { + case 'c': + parameters.check_device = 1; + break; + case 'v': + print_version_and_exit(); + case 'h': + print_usage_and_exit(0); + case '?': + print_usage_and_exit(1); + } + + mpl = mpl_init(¶meters); - signal(SIGINT, signals_handler); signal(SIGHUP, signals_handler); + signal(SIGINT, signals_handler); signal(SIGTERM, signals_handler); - mpl_stop(lock_fd); + mpl_loop(mpl); - return EXIT_SUCCESS; + mpl_stop(mpl); + + return 0; } diff --git a/src/mpl.h b/src/mpl.h index 6eccea7..e5975dc 100644 --- a/src/mpl.h +++ b/src/mpl.h @@ -8,8 +8,11 @@ #ifndef MPL_H_ #define MPL_H_ +#ifndef VERSION +#define VERSION "unrelease" +#endif + #include "mpl-lib.h" #include "mpl-core.h" -#include "mpl-udev.h" #endif