34#include <netinet/in.h>
41#include <sys/socket.h>
53 if (!(e = getenv(
"LISTEN_PID"))) {
59 l = strtoul(e, &p, 10);
66 if (!p || *p || l <= 0) {
72 if (getpid() != (pid_t)l) {
77 if (!(e = getenv(
"LISTEN_FDS"))) {
83 l = strtoul(e, &p, 10);
98 if ((flags = fcntl(fd, F_GETFD)) < 0) {
103 if (flags & FD_CLOEXEC)
106 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
115 if (unset_environment) {
116 unsetenv(
"LISTEN_PID");
117 unsetenv(
"LISTEN_FDS");
129 memset(&st_fd, 0,
sizeof(st_fd));
130 if (fstat(fd, &st_fd) < 0)
133 if (!S_ISFIFO(st_fd.st_mode))
139 memset(&st_path, 0,
sizeof(st_path));
140 if (stat(path, &st_path) < 0) {
141 if (errno == ENOENT || errno == ENOTDIR)
147 return st_path.st_dev == st_fd.st_dev &&
148 st_path.st_ino == st_fd.st_ino;
157 if (fd < 0 || type < 0)
160 if (fstat(fd, &st_fd) < 0)
163 if (!S_ISSOCK(st_fd.st_mode))
168 socklen_t l =
sizeof(other_type);
170 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
173 if (l !=
sizeof(other_type))
176 if (other_type != type)
180 if (listening >= 0) {
182 socklen_t l =
sizeof(accepting);
184 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
187 if (l !=
sizeof(accepting))
190 if (!accepting != !listening)
201 struct sockaddr_un
un;
218 memset(&sockaddr, 0,
sizeof(sockaddr));
219 l =
sizeof(sockaddr);
221 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
224 if (l <
sizeof(sa_family_t))
227 return sockaddr.
sa.sa_family == family;
238 if (family != 0 && family != AF_INET && family != AF_INET6)
244 memset(&sockaddr, 0,
sizeof(sockaddr));
245 l =
sizeof(sockaddr);
247 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
250 if (l <
sizeof(sa_family_t))
253 if (sockaddr.
sa.sa_family != AF_INET &&
254 sockaddr.
sa.sa_family != AF_INET6)
258 if (sockaddr.
sa.sa_family != family)
262 if (sockaddr.
sa.sa_family == AF_INET) {
263 if (l <
sizeof(
struct sockaddr_in))
266 return htons(port) == sockaddr.
in4.sin_port;
268 if (l <
sizeof(
struct sockaddr_in6))
271 return htons(port) == sockaddr.
in6.sin6_port;
286 memset(&sockaddr, 0,
sizeof(sockaddr));
287 l =
sizeof(sockaddr);
289 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
292 if (l <
sizeof(sa_family_t))
295 if (sockaddr.
sa.sa_family != AF_UNIX)
300 length = strlen(path);
304 return l == offsetof(
struct sockaddr_un, sun_path);
308 return (l >= offsetof(
struct sockaddr_un, sun_path) + length + 1) &&
309 memcmp(path, sockaddr.
un.sun_path, length + 1) == 0;
312 return (l == offsetof(
struct sockaddr_un, sun_path) + length) &&
313 memcmp(path, sockaddr.
un.sun_path, length) == 0;
320#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
324 struct msghdr msghdr;
334 if (!(e = getenv(
"NOTIFY_SOCKET")))
338 if ((e[0] !=
'@' && e[0] !=
'/') || e[1] == 0) {
343 if (strlen(e) >
sizeof(sockaddr.
un.sun_path)) {
348 if ((fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) {
353 memset(&sockaddr, 0,
sizeof(sockaddr));
354 sockaddr.
sa.sa_family = AF_UNIX;
355 strncpy(sockaddr.
un.sun_path, e,
sizeof(sockaddr.
un.sun_path) - 1);
357 if (sockaddr.
un.sun_path[0] ==
'@')
358 sockaddr.
un.sun_path[0] = 0;
360 memset(&iovec, 0,
sizeof(iovec));
361 iovec.iov_base = (
char *)
state;
362 iovec.iov_len = strlen(
state);
364 memset(&msghdr, 0,
sizeof(msghdr));
365 msghdr.msg_name = &sockaddr;
366 msghdr.msg_namelen = offsetof(
struct sockaddr_un, sun_path) + strlen(e);
368 if (msghdr.msg_namelen >
sizeof(
struct sockaddr_un))
369 msghdr.msg_namelen =
sizeof(
struct sockaddr_un);
371 msghdr.msg_iov = &iovec;
372 msghdr.msg_iovlen = 1;
374 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
382 if (unset_environment)
383 unsetenv(
"NOTIFY_SOCKET");
392int sd_notifyf(
int unset_environment,
const char *format, ...) {
393#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
400 va_start(ap, format);
401 r = vasprintf(&p, format, ap);
415#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
423 if (lstat(
"/sys/fs/cgroup", &a) < 0)
426 if (lstat(
"/sys/fs/cgroup/systemd", &b) < 0)
429 return a.st_dev != b.st_dev;
static int sd_is_socket_internal(int fd, int type, int listening)
int sd_notify(int unset_environment, const char *state)
int sd_is_fifo(int fd, const char *path)
int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port)
int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length)
int sd_notifyf(int unset_environment, const char *format,...)
int sd_listen_fds(int unset_environment)
int sd_is_socket(int fd, int family, int type, int listening)
#define SD_LISTEN_FDS_START
struct sockaddr_storage storage