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) {
107 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
116 if (unset_environment) {
117 unsetenv(
"LISTEN_PID");
118 unsetenv(
"LISTEN_FDS");
131 memset(&st_fd, 0,
sizeof(st_fd));
132 if (fstat(fd, &st_fd) < 0) {
136 if (!S_ISFIFO(st_fd.st_mode)) {
143 memset(&st_path, 0,
sizeof(st_path));
144 if (stat(path, &st_path) < 0) {
145 if (errno == ENOENT || errno == ENOTDIR) {
152 return st_path.st_dev == st_fd.st_dev &&
153 st_path.st_ino == st_fd.st_ino;
162 if (fd < 0 || type < 0) {
166 if (fstat(fd, &st_fd) < 0) {
170 if (!S_ISSOCK(st_fd.st_mode)) {
176 socklen_t l =
sizeof(other_type);
178 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) {
182 if (l !=
sizeof(other_type)) {
186 if (other_type != type) {
191 if (listening >= 0) {
193 socklen_t l =
sizeof(accepting);
195 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) {
199 if (l !=
sizeof(accepting)) {
203 if (!accepting != !listening) {
215 struct sockaddr_un
un;
234 memset(&sockaddr, 0,
sizeof(sockaddr));
235 l =
sizeof(sockaddr);
237 if (getsockname(fd, &sockaddr.
sa, &l) < 0) {
241 if (l <
sizeof(sa_family_t)) {
245 return sockaddr.
sa.sa_family == family;
256 if (family != 0 && family != AF_INET && family != AF_INET6) {
264 memset(&sockaddr, 0,
sizeof(sockaddr));
265 l =
sizeof(sockaddr);
267 if (getsockname(fd, &sockaddr.
sa, &l) < 0) {
271 if (l <
sizeof(sa_family_t)) {
275 if (sockaddr.
sa.sa_family != AF_INET &&
276 sockaddr.
sa.sa_family != AF_INET6) {
281 if (sockaddr.
sa.sa_family != family) {
287 if (sockaddr.
sa.sa_family == AF_INET) {
288 if (l <
sizeof(
struct sockaddr_in)) {
292 return htons(port) == sockaddr.
in4.sin_port;
294 if (l <
sizeof(
struct sockaddr_in6)) {
298 return htons(port) == sockaddr.
in6.sin6_port;
314 memset(&sockaddr, 0,
sizeof(sockaddr));
315 l =
sizeof(sockaddr);
317 if (getsockname(fd, &sockaddr.
sa, &l) < 0) {
321 if (l <
sizeof(sa_family_t)) {
325 if (sockaddr.
sa.sa_family != AF_UNIX) {
331 length = strlen(path);
336 return l == offsetof(
struct sockaddr_un, sun_path);
341 return (l >= offsetof(
struct sockaddr_un, sun_path) + length + 1) &&
342 memcmp(path, sockaddr.
un.sun_path, length + 1) == 0;
345 return (l == offsetof(
struct sockaddr_un, sun_path) + length) &&
346 memcmp(path, sockaddr.
un.sun_path, length) == 0;
354#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
358 struct msghdr msghdr;
368 if (!(e = getenv(
"NOTIFY_SOCKET"))) {
373 if ((e[0] !=
'@' && e[0] !=
'/') || e[1] == 0) {
378 if (strlen(e) >
sizeof(sockaddr.
un.sun_path)) {
383 if ((fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) {
388 memset(&sockaddr, 0,
sizeof(sockaddr));
389 sockaddr.
sa.sa_family = AF_UNIX;
390 strncpy(sockaddr.
un.sun_path, e,
sizeof(sockaddr.
un.sun_path) - 1);
392 if (sockaddr.
un.sun_path[0] ==
'@') {
393 sockaddr.
un.sun_path[0] = 0;
396 memset(&iovec, 0,
sizeof(iovec));
397 iovec.iov_base = (
char *)
state;
398 iovec.iov_len = strlen(
state);
400 memset(&msghdr, 0,
sizeof(msghdr));
401 msghdr.msg_name = &sockaddr;
402 msghdr.msg_namelen = offsetof(
struct sockaddr_un, sun_path) + strlen(e);
404 if (msghdr.msg_namelen >
sizeof(
struct sockaddr_un)) {
405 msghdr.msg_namelen =
sizeof(
struct sockaddr_un);
408 msghdr.msg_iov = &iovec;
409 msghdr.msg_iovlen = 1;
411 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
419 if (unset_environment) {
420 unsetenv(
"NOTIFY_SOCKET");
431int sd_notifyf(
int unset_environment,
const char *format, ...) {
432#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
439 va_start(ap, format);
440 r = vasprintf(&p, format, ap);
455#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
463 if (lstat(
"/sys/fs/cgroup", &a) < 0) {
467 if (lstat(
"/sys/fs/cgroup/systemd", &b) < 0) {
471 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