1
0
libflex/rolexhound/main.c
2024-03-21 21:57:00 +02:00

191 lines
4.9 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <sys/inotify.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <libflex.h>
struct daemon_state {
bool running;
int inotify_fd;
int inotify_wd;
};
static struct daemon_state g_state = {
.running = true
};
void daemon_deinit(struct daemon_state *state) {
inotify_rm_watch(g_state.inotify_fd, g_state.inotify_wd);
}
void signal_handler(int signal) {
g_state.running = false;
printf("Stoping daemon\n");
daemon_deinit(&g_state);
exit(0);
}
#define PORT 12345
int main() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
return -1;
}
int on = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
return -1;
}
if (listen(server_fd, 1) == -1) {
perror("listen");
return -1;
}
printf("listening on 0.0.0.0:%d...\n", PORT);
struct sockaddr_storage client_addr;
socklen_t client_addrlen;
int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_addrlen);
if (client_fd == -1) {
perror("accept");
return -1;
}
printf("Accepted connection!\n");
struct flx_msg *read_msg = malloc(sizeof(struct flx_msg));
struct flx_msg *send_msg = malloc(sizeof(struct flx_msg));
struct flx_serialize_result result;
flx_msg_init(read_msg);
flx_msg_init(send_msg);
flx_serialize_result_init(&result);
uint8_t socket_buffer[FLX_PKT_MAXIMUM_SIZE];
while (true) {
int bytes_read = recv(client_fd, socket_buffer, sizeof(socket_buffer), 0);
if (bytes_read == 0 || bytes_read == -1) {
perror("recv");
return -1;
}
flx_deserialize(socket_buffer, read_msg, &result);
if (result.reply != FLX_REPLY_VALID) {
printf("Received error %x from client\n", result.reply);
send_msg->action = FLX_ACT_REPLY;
send_msg->option = result.reply;
send_msg = 0;
flx_serialize(socket_buffer, send_msg, &result);
write(client_fd, socket_buffer, result.size);
continue;
}
if (read_msg->action != FLX_ACT_WATCH) {
continue;
}
break;
}
char *path = strdup(read_msg->data[0]);
printf("Watching path: %s\n", path);
int inotify_fd = inotify_init();
if (inotify_fd == -1) {
perror("inotify_init");
return -1;
}
int inotify_wd = inotify_add_watch(inotify_fd, path, IN_CREATE | IN_DELETE | IN_ACCESS | IN_CLOSE_WRITE | IN_MODIFY | IN_MOVE_SELF);
if (inotify_fd == -1) {
perror("inotify_add_watch");
return -1;
}
char *base_path = strrchr(path, '/');
if (base_path == NULL) {
base_path = path;
} else {
base_path += 1;
}
signal(SIGABRT, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
uint8_t buffer[4096];
while (g_state.running) {
printf("Waiting for inotify event.\n");
int read_length = read(inotify_fd, buffer, sizeof(buffer));
if (read_length == -1) {
perror("read");
return -1;
}
int buffer_used = 0;
while (buffer_used < read_length) {
struct inotify_event *event = (struct inotify_event*)&buffer[buffer_used];
if (event->mask & IN_CREATE) {
send_msg->option = FLX_NOTIFY_CREATE;
}
if (event->mask & IN_DELETE) {
send_msg->option = FLX_NOTIFY_DELETE;
}
if (event->mask & IN_ACCESS) {
send_msg->option = FLX_NOTIFY_ACCESS;
}
if (event->mask & IN_CLOSE_WRITE) {
send_msg->option = FLX_NOTIFY_CLOSE;
}
if (event->mask & IN_MODIFY) {
send_msg->option = FLX_NOTIFY_MODIFY;
}
if (event->mask & IN_MOVE_SELF) {
send_msg->option = FLX_NOTIFY_MOVE;
}
buffer_used += sizeof(struct inotify_event) + event->len;
if (send_msg->option == FLX_UNSET_UNSET) {
continue;
}
send_msg->action = FLX_ACT_NOTIFY;
send_msg->data_len = FLX_DLEN_NOTIFY;
send_msg->data = malloc(sizeof(char*) * FLX_DLEN_NOTIFY);
send_msg->data[0] = base_path;
send_msg->data[1] = path;
flx_serialize(socket_buffer, send_msg, &result);
}
}
daemon_deinit(&g_state);
return 0;
}