31 #include <sys/types.h>
33 #include <sys/socket.h>
35 #include <sys/fcntl.h>
36 #include <netinet/in.h>
49 #if defined(DISABLE_SYSTEMD) || !defined(__linux__)
57 if (!(e = getenv(
"LISTEN_PID"))) {
63 l = strtoul(e, &p, 10);
70 if (!p || *p || l <= 0) {
76 if (getpid() != (pid_t) l) {
81 if (!(e = getenv(
"LISTEN_FDS"))) {
87 l = strtoul(e, &p, 10);
102 if ((flags = fcntl(fd, F_GETFD)) < 0) {
107 if (flags & FD_CLOEXEC)
110 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
119 if (unset_environment) {
120 unsetenv(
"LISTEN_PID");
121 unsetenv(
"LISTEN_FDS");
134 memset(&st_fd, 0,
sizeof(st_fd));
135 if (fstat(fd, &st_fd) < 0)
138 if (!S_ISFIFO(st_fd.st_mode))
144 memset(&st_path, 0,
sizeof(st_path));
145 if (stat(path, &st_path) < 0) {
147 if (errno == ENOENT || errno == ENOTDIR)
154 st_path.st_dev == st_fd.st_dev &&
155 st_path.st_ino == st_fd.st_ino;
164 if (fd < 0 || type < 0)
167 if (fstat(fd, &st_fd) < 0)
170 if (!S_ISSOCK(st_fd.st_mode))
175 socklen_t l =
sizeof(other_type);
177 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
180 if (l !=
sizeof(other_type))
183 if (other_type != type)
187 if (listening >= 0) {
189 socklen_t l =
sizeof(accepting);
191 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
194 if (l !=
sizeof(accepting))
197 if (!accepting != !listening)
208 struct sockaddr_un
un;
225 memset(&sockaddr, 0,
sizeof(sockaddr));
226 l =
sizeof(sockaddr);
228 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
231 if (l <
sizeof(sa_family_t))
234 return sockaddr.
sa.sa_family == family;
245 if (family != 0 && family != AF_INET && family != AF_INET6)
251 memset(&sockaddr, 0,
sizeof(sockaddr));
252 l =
sizeof(sockaddr);
254 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
257 if (l <
sizeof(sa_family_t))
260 if (sockaddr.
sa.sa_family != AF_INET &&
261 sockaddr.
sa.sa_family != AF_INET6)
265 if (sockaddr.
sa.sa_family != family)
269 if (sockaddr.
sa.sa_family == AF_INET) {
270 if (l <
sizeof(
struct sockaddr_in))
273 return htons(port) == sockaddr.
in4.sin_port;
275 if (l <
sizeof(
struct sockaddr_in6))
278 return htons(port) == sockaddr.
in6.sin6_port;
293 memset(&sockaddr, 0,
sizeof(sockaddr));
294 l =
sizeof(sockaddr);
296 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
299 if (l <
sizeof(sa_family_t))
302 if (sockaddr.
sa.sa_family != AF_UNIX)
307 length = strlen(path);
311 return l == offsetof(
struct sockaddr_un, sun_path);
316 (l >= offsetof(
struct sockaddr_un, sun_path) + length + 1) &&
317 memcmp(path, sockaddr.
un.sun_path, length+1) == 0;
321 (l == offsetof(
struct sockaddr_un, sun_path) + length) &&
322 memcmp(path, sockaddr.
un.sun_path, length) == 0;
329 #if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
333 struct msghdr msghdr;
343 if (!(e = getenv(
"NOTIFY_SOCKET")))
347 if ((e[0] !=
'@' && e[0] !=
'/') || e[1] == 0) {
352 if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
357 memset(&sockaddr, 0,
sizeof(sockaddr));
358 sockaddr.
sa.sa_family = AF_UNIX;
359 strncpy(sockaddr.
un.sun_path, e,
sizeof(sockaddr.
un.sun_path));
361 if (sockaddr.
un.sun_path[0] ==
'@')
362 sockaddr.
un.sun_path[0] = 0;
364 memset(&iovec, 0,
sizeof(iovec));
365 iovec.iov_base = (
char*) state;
366 iovec.iov_len = strlen(state);
368 memset(&msghdr, 0,
sizeof(msghdr));
369 msghdr.msg_name = &sockaddr;
370 msghdr.msg_namelen = offsetof(
struct sockaddr_un, sun_path) + strlen(e);
372 if (msghdr.msg_namelen >
sizeof(
struct sockaddr_un))
373 msghdr.msg_namelen =
sizeof(
struct sockaddr_un);
375 msghdr.msg_iov = &iovec;
376 msghdr.msg_iovlen = 1;
378 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
386 if (unset_environment)
387 unsetenv(
"NOTIFY_SOCKET");
396 int sd_notifyf(
int unset_environment,
const char *format, ...) {
397 #if defined(DISABLE_SYSTEMD) || !defined(__linux__)
404 va_start(ap, format);
405 r = vasprintf(&p, format, ap);
419 #if defined(DISABLE_SYSTEMD) || !defined(__linux__)
428 if (lstat(
"/sys/fs/cgroup", &a) < 0)
431 if (lstat(
"/sys/fs/cgroup/systemd", &b) < 0)
434 return a.st_dev != b.st_dev;