Compare commits

..

No commits in common. "089154cb170c54bf6c6af0fbb1333c293e4cc027" and "cd5f9f7a12f33c18db838a9978b8e4fd617c8eb5" have entirely different histories.

11 changed files with 170 additions and 373 deletions

View File

@ -34,14 +34,7 @@
"mpl-args.h": "c", "mpl-args.h": "c",
"*.in": "cpp", "*.in": "cpp",
"signal.h": "c", "signal.h": "c",
"stdio.h": "c", "stdio.h": "c"
"getopt.h": "c",
"mpl-common.h": "c",
"cerrno": "c",
"string": "c",
"string_view": "c",
"regex.h": "c",
"dirent.h": "c"
}, },
"cmake.configureOnOpen": false "cmake.configureOnOpen": false
} }

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.18.4) cmake_minimum_required(VERSION 3.18.4)
project(mportlink) project(mportlink)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Os") # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Os")
set(VERSION_MAJOR 0) set(VERSION_MAJOR 0)
set(VERSION_MINOR 1) set(VERSION_MINOR 1)

View File

@ -1,111 +0,0 @@
/*
* mpl-common.c
*
* by Alexander Zhirov (alexander@zhirov.kz)
* Telegram @alexanderzhirov
*/
#include "mpl-common.h"
#include <sys/stat.h>
#include <sys/file.h>
#define LOCKFILE "/run/lock/mportlink.lock"
static int mpl_create_dongle_dir()
{
struct stat st;
if (stat(MPL_DONGLE_PATH, &st) == 0)
{
if (!S_ISDIR(st.st_mode))
{
MPLOG(LOG_WARNING, "%s exists and is not a directory", MPL_DONGLE_PATH);
return 1;
}
}
else if (mkdir(MPL_DONGLE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
{
MPLOG(LOG_ERR, "unable to create a directory %s", MPL_DONGLE_PATH);
return 1;
}
return 0;
}
void static mpl_free(MPL *mpl)
{
if (mpl)
free(mpl);
}
MPL *mpl_init(MPL_PARAMETERS *parameters)
{
MPL *mpl = (MPL *)calloc(1, sizeof(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);
if (mpl->cancellable.exit)
{
flock(mpl->fd, LOCK_UN);
MPLOG(LOG_NOTICE, "stopping the %s daemon", MPL_NAME);
}
else
MPLOG(LOG_NOTICE, "successful completion of the process %d", getpid());
mpl_free(mpl);
closelog();
}
void mpl_loop(MPL *mpl)
{
if (mpl->parameters.check_device)
mpl_udev_check_devices(&mpl->udev);
mpl_udev_loop(&mpl->udev, &mpl->cancellable);
}

View File

@ -1,31 +0,0 @@
/*
* mpl-common.h
*
* by Alexander Zhirov (alexander@zhirov.kz)
* Telegram @alexanderzhirov
*/
#ifndef MPL_COMMON_H_
#define MPL_COMMON_H_
#include "mpl-lib.h"
#include "mpl-udev.h"
typedef struct
{
int check_device;
} MPL_PARAMETERS;
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

View File

@ -5,83 +5,108 @@
* Telegram @alexanderzhirov * Telegram @alexanderzhirov
*/ */
#include "mpl-lib.h"
#include "mpl-core.h" #include "mpl-core.h"
#include <regex.h> #include <sys/stat.h>
#include <dirent.h> #include <sys/file.h>
#include <fcntl.h> #include <unistd.h>
int device_path(const MPL_MODEM *modem) #define LOCKFILE "/run/lock/mportlink.lock"
{ #define DEV_PATH "/dev/"
DIR *dir; #define DONGLE_PATH (DEV_PATH "dongle/")
struct dirent *ent;
regex_t regex;
const char *pattern = "^ttyUSB[0-9]*$";
int ret = regcomp(&regex, pattern, REG_EXTENDED); static int mpl_create_dongle_dir()
if (ret != 0)
{ {
printf("Failed to compile regular expression\n"); 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);
return 1; return 1;
} }
}
dir = opendir(modem->path); else if (mkdir(DONGLE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
if (dir == NULL)
{ {
printf("Failed to open directory: %s\n", modem->path); MPLOG(LOG_ERR, "unable to create a directory %s", DONGLE_PATH);
regfree(&regex);
return 1; return 1;
} }
while ((ent = readdir(dir)) != NULL)
{
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
{
continue;
}
ret = regexec(&regex, ent->d_name, 0, NULL, 0);
if (ret == 0)
{
printf("Found a file matching the pattern: %s\n", ent->d_name);
char *path = (char *)calloc(strlen(MPL_DEV_PATH) + strlen(ent->d_name) + 1, sizeof(char));
strcpy(path, MPL_DEV_PATH);
strcat(path, ent->d_name);
int fd = open(path, O_RDWR);
if (fd < 0)
{
printf("Не удалось открыть USB устройство.\n");
free(path);
continue;
}
char *tty = ttyname(fd);
close(fd);
if (tty != NULL)
{
printf("%s устройство tty: %s\n", modem->action ? "Добавлено" : "Удалено", tty);
// if (!num)
// print_imei(tty);
}
else
{
printf("Устройство tty не найдено\n");
}
}
else if (ret != REG_NOMATCH)
{
printf("Failed to apply regular expression\n");
}
}
regfree(&regex);
closedir(dir);
return 0; return 0;
} }
void static mpl_free(MPL *mpl)
{
if (mpl)
free(mpl);
}
MPL *mpl_init(MPL_PARAMETERS *parameters)
{
MPL *mpl = (MPL *)calloc(1, sizeof(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();
}
void mpl_loop(MPL *mpl)
{
if (mpl->parameters.check_device)
mpl_udev_check_devices(&mpl->udev);
mpl_udev_loop(&mpl->udev, &mpl->cancellable);
}

View File

@ -8,13 +8,24 @@
#ifndef MPL_CORE_H_ #ifndef MPL_CORE_H_
#define MPL_CORE_H_ #define MPL_CORE_H_
#include "mpl-lib.h"
#include "mpl-udev.h"
typedef struct typedef struct
{ {
int port; int check_device;
char *path; } MPL_PARAMETERS;
int action;
} MPL_MODEM;
int device_path(const MPL_MODEM *modem); 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 #endif

View File

@ -6,20 +6,3 @@
*/ */
#include "mpl-lib.h" #include "mpl-lib.h"
char *mpl_get_copy_string(const char *str)
{
int size = strlen(str);
char *copy = (char *)calloc(size + 1, sizeof(char));
if (!copy)
{
MPLOG(LOG_ERR, "error getting the string");
return NULL;
}
strcpy(copy, str);
copy[size] = '\0';
return copy;
}

View File

@ -14,11 +14,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <syslog.h> #include <syslog.h>
#include <unistd.h>
#define MPL_NAME "mportlink" #define MPL_NAME "mportlink"
#define MPL_DEV_PATH "/dev/"
#define MPL_DONGLE_PATH (MPL_DEV_PATH "dongle/")
#define MPLOG(PRIORITY, fmt, ...) do { \ #define MPLOG(PRIORITY, fmt, ...) do { \
char buf[256]; \ char buf[256]; \
@ -34,6 +31,4 @@ typedef struct
int exit; int exit;
} MPL_CANCELLABLE; } MPL_CANCELLABLE;
char *mpl_get_copy_string(const char *str);
#endif #endif

View File

@ -6,48 +6,10 @@
*/ */
#include "mpl-udev.h" #include "mpl-udev.h"
#include "mpl-core.h"
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
void test(struct udev_device *dev)
{
const char *action = udev_device_get_action(dev);
// printf("action: %s\n", action);
// const char *devpath = udev_device_get_devpath(dev);
// printf("devpath: %s\n", devpath);
// const char *subsystem = udev_device_get_subsystem(dev);
// printf("subsystem: %s\n", subsystem);
const char *devtype = udev_device_get_devtype(dev);
// printf("devtype: %s\n", devtype);
const char *driver = udev_device_get_driver(dev);
// printf("driver: %s\n", driver);
// const char *sysattr_value = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
// printf("Номер порта: %s\n", sysattr_value);
const char *syspath = udev_device_get_syspath(dev);
// printf("syspath: %s\n", syspath);
// const char *sysname = udev_device_get_sysname(dev);
// printf("sysname: %s\n", sysname);
// const char *sysnum = udev_device_get_sysnum(dev);
// printf("sysnum: %s\n", sysnum);
const char *devnode = udev_device_get_devnode(dev);
// printf("devnode: %s\n", devnode);
// int is_initialized = udev_device_get_is_initialized(dev);
// printf("is_initialized: %d\n", is_initialized);
printf("action: %s\tdevtype: %s\tdriver: %s\tsyspath: %s\tdevnode: %s\n", action, devtype, driver, syspath, devnode);
}
int mpl_udev_init(MPL_UDEV *udev) int mpl_udev_init(MPL_UDEV *udev)
{ {
udev->context = udev_new(); udev->context = udev_new();
@ -79,71 +41,12 @@ int mpl_udev_init(MPL_UDEV *udev)
return 0; return 0;
} }
// action: bind devtype: usb_interface driver: option syspath: /sys/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.3/3-3.3:1.1
// action: unbind devtype: usb_interface driver: (null) syspath: /sys/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.3/3-3.3:1.1
static int mpl_device_is_interface(struct udev_device *dev)
{
return strcmp(udev_device_get_devtype(dev), "usb_interface") == 0;
}
static int mpl_device_is_modem(struct udev_device *dev)
{
const char *driver = udev_device_get_driver(dev);
const char *sysattr = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
if (!driver || !sysattr)
return 0;
return mpl_device_is_interface(dev) && strcmp(driver, "option") == 0 && sysattr;
}
static int mpl_connect_modem(struct udev_device *dev)
{
const char *action = udev_device_get_property_value(dev, "ACTION");
return strcmp(action, "bind") == 0 && mpl_device_is_modem(dev);
}
static int mpl_disconnect_modem(struct udev_device *dev)
{
const char *action = udev_device_get_property_value(dev, "ACTION");
return strcmp(action, "unbind") == 0 && mpl_device_is_interface(dev);
}
static MPL_MODEM *mpl_get_modem_info(struct udev_device *dev)
{
MPL_MODEM *modem = (MPL_MODEM *)calloc(1, sizeof(MPL_MODEM));
if (modem == NULL)
{
MPLOG(LOG_ERR, "error creating modem");
return NULL;
}
modem->port = atoi(udev_device_get_sysattr_value(dev, "bInterfaceNumber"));
modem->path = mpl_get_copy_string(udev_device_get_syspath(dev));
modem->action = strcmp(udev_device_get_property_value(dev, "ACTION"), "bind") == 0;
return modem;
}
static void mpl_free_modem(MPL_MODEM *modem)
{
if (modem->path)
free(modem->path);
free(modem);
}
int mpl_udev_check_devices(MPL_UDEV *udev) int mpl_udev_check_devices(MPL_UDEV *udev)
{ {
struct udev_device *dev; struct udev_device *dev;
struct udev_enumerate *enumerate; struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry; struct udev_list_entry *devices, *dev_list_entry;
MPL_MODEM *modem = NULL;
enumerate = udev_enumerate_new(udev->context); enumerate = udev_enumerate_new(udev->context);
if (enumerate == NULL) if (enumerate == NULL)
@ -168,14 +71,23 @@ int mpl_udev_check_devices(MPL_UDEV *udev)
const char *syspath = udev_list_entry_get_name(dev_list_entry); const char *syspath = udev_list_entry_get_name(dev_list_entry);
dev = udev_device_new_from_syspath(udev->context, syspath); dev = udev_device_new_from_syspath(udev->context, syspath);
if (!mpl_device_is_modem(dev)) const char *devtype = udev_device_get_devtype(dev);
if (!(strcmp(devtype, "usb_interface") == 0))
continue; continue;
modem = mpl_get_modem_info(dev); const char *driver = udev_device_get_driver(dev);
if (!(strcmp(driver, "option") == 0))
continue;
device_path(modem); const char *sysattr_value = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
printf("Номер порта: %s\n", sysattr_value);
// int num = atoi(sysattr_value);
const char *devsyspath = udev_device_get_syspath(dev);
printf("syspath: %s\n", devsyspath);
// device_path(syspaths, num);
mpl_free_modem(modem);
udev_device_unref(dev); udev_device_unref(dev);
} }
@ -200,13 +112,12 @@ void mpl_udev_free(MPL_UDEV *udev)
void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable) void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable)
{ {
MPL_MODEM *modem = NULL; const char *path_to_device = NULL;
int port_number = -1;
int status = -1; int status = -1;
pid_t pid = -1; pid_t pid = -1;
int stop = 0; while (1)
while (!stop)
{ {
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
@ -224,24 +135,45 @@ void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable)
struct udev_device *dev = udev_monitor_receive_device(udev->monitor); struct udev_device *dev = udev_monitor_receive_device(udev->monitor);
if (dev) if (dev)
{ {
// test(dev); const char *action = udev_device_get_property_value(dev, "ACTION");
if (!(strcmp(action, "bind") == 0))
if (mpl_connect_modem(dev))
{ {
modem = mpl_get_modem_info(dev); 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(); pid = fork();
if (pid == 0) if (pid == 0)
{ {
stop = 1; udev_device_unref(dev);
break;
} }
else else
wait(&status); wait(&status);
}
else if (mpl_disconnect_modem(dev))
{
// unmount ports
}
udev_device_unref(dev); udev_device_unref(dev);
} }
@ -252,8 +184,6 @@ void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable)
if (cancellable->exit) if (cancellable->exit)
return; return;
// printf("path: %s\t port: %d\t action: %d\n", modem->path, modem->port, modem->action); sleep(5);
printf("exit");
device_path(modem);
mpl_free_modem(modem);
} }

View File

@ -5,9 +5,10 @@
* Telegram @alexanderzhirov * Telegram @alexanderzhirov
*/ */
#include "mpl.h"
#include <getopt.h> #include <getopt.h>
#include "mpl.h"
static MPL *mpl; static MPL *mpl;
const char *const short_options = "hcv"; const char *const short_options = "hcv";

View File

@ -12,6 +12,7 @@
#define VERSION "unrelease" #define VERSION "unrelease"
#endif #endif
#include "mpl-common.h" #include "mpl-lib.h"
#include "mpl-core.h"
#endif #endif