2021-07-07 04:54:51 +02:00
|
|
|
#define _POSIX_C_SOURCE 200809L
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <poll.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "kanshi.h"
|
|
|
|
|
2021-07-07 05:00:51 +02:00
|
|
|
static int set_pipe_flags(int fd) {
|
|
|
|
int flags = fcntl(fd, F_GETFL);
|
|
|
|
if (flags == -1) {
|
|
|
|
perror("fnctl F_GETFL failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
flags |= O_NONBLOCK;
|
|
|
|
if (fcntl(fd, F_SETFL, flags) == -1) {
|
|
|
|
perror("fnctl F_SETFL failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
flags = fcntl(fd, F_GETFD);
|
|
|
|
if (flags == -1) {
|
|
|
|
perror("fnctl F_GETFD failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
flags |= O_CLOEXEC;
|
|
|
|
if (fcntl(fd, F_SETFD, flags) == -1) {
|
|
|
|
perror("fnctl F_SETFD failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int signal_pipefds[2];
|
|
|
|
|
|
|
|
static void signal_handler(int signum) {
|
|
|
|
if (write(signal_pipefds[1], &signum, sizeof(signum)) == -1) {
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-07 04:54:51 +02:00
|
|
|
enum readfds_type {
|
|
|
|
FD_WAYLAND,
|
2021-07-07 05:00:51 +02:00
|
|
|
FD_SIGNAL,
|
2021-07-07 04:54:51 +02:00
|
|
|
FD_COUNT,
|
|
|
|
};
|
|
|
|
|
|
|
|
int kanshi_main_loop(struct kanshi_state *state) {
|
2021-07-07 05:00:51 +02:00
|
|
|
if (pipe(signal_pipefds) == -1) {
|
|
|
|
perror("read from signalfd failed");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
if (set_pipe_flags(signal_pipefds[0]) == -1) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
if (set_pipe_flags(signal_pipefds[1]) == -1) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sigaction action;
|
|
|
|
sigfillset(&action.sa_mask);
|
|
|
|
action.sa_flags = 0;
|
|
|
|
action.sa_handler = signal_handler;
|
|
|
|
sigaction(SIGINT, &action, NULL);
|
|
|
|
sigaction(SIGQUIT, &action, NULL);
|
|
|
|
sigaction(SIGTERM, &action, NULL);
|
|
|
|
sigaction(SIGHUP, &action, NULL);
|
|
|
|
|
2021-07-07 04:54:51 +02:00
|
|
|
struct pollfd readfds[FD_COUNT] = {0};
|
|
|
|
readfds[FD_WAYLAND].fd = wl_display_get_fd(state->display);
|
|
|
|
readfds[FD_WAYLAND].events = POLLIN;
|
2021-07-07 05:00:51 +02:00
|
|
|
readfds[FD_SIGNAL].fd = signal_pipefds[0];
|
|
|
|
readfds[FD_SIGNAL].events = POLLIN;
|
2021-07-07 04:54:51 +02:00
|
|
|
|
|
|
|
while (state->running) {
|
|
|
|
while (wl_display_prepare_read(state->display) != 0) {
|
|
|
|
if (wl_display_dispatch_pending(state->display) == -1) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
ret = wl_display_flush(state->display);
|
|
|
|
if (ret != -1 || errno != EAGAIN) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret < 0 && errno != EPIPE) {
|
|
|
|
goto read_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
ret = poll(readfds, sizeof(readfds) / sizeof(readfds[0]), -1);
|
|
|
|
} while (ret == -1 && errno == EINTR);
|
|
|
|
/* will only be -1 if errno wasn't EINTR */
|
|
|
|
if (ret == -1) {
|
|
|
|
goto read_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wl_display_read_events(state->display) == -1) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2021-07-07 05:00:51 +02:00
|
|
|
if (readfds[FD_SIGNAL].revents & POLLIN) {
|
|
|
|
for (;;) {
|
|
|
|
int signum;
|
|
|
|
ssize_t s
|
|
|
|
= read(readfds[FD_SIGNAL].fd, &signum, sizeof(signum));
|
|
|
|
if (s == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (s < 0) {
|
|
|
|
if (errno == EAGAIN) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
perror("read from signal pipe failed");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
if (s < (ssize_t) sizeof(signum)) {
|
|
|
|
fprintf(stderr, "read too few bytes from signal pipe\n");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
switch (signum) {
|
|
|
|
case SIGHUP:
|
|
|
|
kanshi_reload_config(state);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* exiting after signal considered successful */
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-07 04:54:51 +02:00
|
|
|
if (wl_display_dispatch_pending(state->display) == -1) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
|
|
|
read_error:
|
|
|
|
wl_display_cancel_read(state->display);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|