diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/meson.build | 2 | ||||
-rw-r--r-- | lib/receiver.c | 83 |
2 files changed, 63 insertions, 22 deletions
diff --git a/lib/meson.build b/lib/meson.build index 787bc4f..c0ae401 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -28,7 +28,7 @@ install_headers(icipc_lib_headers, icipc_lib = library('icipc-' + icipc_api_version, icipc_lib_sources, install: true, - dependencies : [threads_dep], + dependencies : [threads_dep, libsystemd_dep], soversion: icipc_so_version, version: meson.project_version(), ) diff --git a/lib/receiver.c b/lib/receiver.c index 9b34494..e039ced 100644 --- a/lib/receiver.c +++ b/lib/receiver.c @@ -8,13 +8,20 @@ #include <stdlib.h> #include <stdio.h> -#include <unistd.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/epoll.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include <string.h> #include <errno.h> #include <assert.h> + +#ifdef HAVE_SYSTEMD +#include <systemd/sd-daemon.h> +#endif + #include "private.h" #include "receiver.h" #include "icipc.h" @@ -24,6 +31,7 @@ struct icipc_receiver { struct sockaddr_un addr; int socket_fd; + bool activated; uint8_t *buffer_read; size_t buffer_size; @@ -116,28 +124,60 @@ struct icipc_receiver *icipc_receiver_new( /* set address */ self->addr.sun_family = AF_LOCAL; - res = - icipc_construct_socket_path(path, self->addr.sun_path, - sizeof(self->addr.sun_path)); + res = icipc_construct_socket_path(path, self->addr.sun_path, + sizeof(self->addr.sun_path)); if (res < 0) goto error; - unlink(self->addr.sun_path); - - /* create socket */ - self->socket_fd = - socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (self->socket_fd < 0) - goto error; - - /* bind socket */ - if (bind(self->socket_fd, (struct sockaddr *)&self->addr, - sizeof(self->addr)) != 0) - goto error; - - /* listen socket */ - if (listen(self->socket_fd, MAX_SENDERS) != 0) - goto error; +#ifdef HAVE_SYSTEMD + { + int i, n = sd_listen_fds(0); + for (i = 0; i < n; ++i) { + if (sd_is_socket_unix(SD_LISTEN_FDS_START + i, + SOCK_STREAM, 1, + self->addr.sun_path, 0) > 0) { + self->socket_fd = SD_LISTEN_FDS_START + i; + self->activated = true; + icipc_log_info("receiver %p: Found socket " + "activation socket for '%s'", + self, self->addr.sun_path); + break; + } + } + } +#endif + + if (self->socket_fd < 0) { + struct stat socket_stat; + + /* create socket */ + self->socket_fd = + socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (self->socket_fd < 0) + goto error; + + if (stat(self->addr.sun_path, &socket_stat) < 0) { + if (errno != ENOENT) { + res = -errno; + icipc_log_error("receiver %p: stat %s failed " + "with error: %m", + self, self->addr.sun_path); + goto error; + } + } else if (socket_stat.st_mode & S_IWUSR || + socket_stat.st_mode & S_IWGRP) { + unlink(self->addr.sun_path); + } + + /* bind socket */ + if (bind(self->socket_fd, (struct sockaddr *)&self->addr, + sizeof(self->addr)) != 0) + goto error; + + /* listen socket */ + if (listen(self->socket_fd, MAX_SENDERS) != 0) + goto error; + } /* alloc buffer read */ self->buffer_size = buffer_size; @@ -174,7 +214,8 @@ void icipc_receiver_free(struct icipc_receiver *self) { icipc_epoll_thread_destroy(&self->epoll_thread); free(self->buffer_read); close(self->socket_fd); - unlink(self->addr.sun_path); + if (!self->activated) + unlink(self->addr.sun_path); free(self); } |