31 #include <sys/types.h>
33 #include <sys/socket.h>
35 #include <sys/fcntl.h>
36 #include <netinet/in.h>
48 #if defined(DISABLE_SYSTEMD) || !defined(__linux__)
56 if (!(e = getenv(
"LISTEN_PID"))) {
62 l = strtoul(e, &p, 10);
69 if (!p || *p || l <= 0) {
75 if (getpid() != (pid_t)l) {
80 if (!(e = getenv(
"LISTEN_FDS"))) {
86 l = strtoul(e, &p, 10);
101 if ((flags = fcntl(fd, F_GETFD)) < 0) {
106 if (flags & FD_CLOEXEC)
109 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
118 if (unset_environment) {
119 unsetenv(
"LISTEN_PID");
120 unsetenv(
"LISTEN_FDS");
133 memset(&st_fd, 0,
sizeof(st_fd));
134 if (fstat(fd, &st_fd) < 0)
137 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)
151 return st_path.st_dev == st_fd.st_dev &&
152 st_path.st_ino == st_fd.st_ino;
161 if (fd < 0 || type < 0)
164 if (fstat(fd, &st_fd) < 0)
167 if (!S_ISSOCK(st_fd.st_mode))
172 socklen_t l =
sizeof(other_type);
174 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
177 if (l !=
sizeof(other_type))
180 if (other_type != type)
184 if (listening >= 0) {
186 socklen_t l =
sizeof(accepting);
188 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
191 if (l !=
sizeof(accepting))
194 if (!accepting != !listening)
205 struct sockaddr_un
un;
222 memset(&sockaddr, 0,
sizeof(sockaddr));
223 l =
sizeof(sockaddr);
225 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
228 if (l <
sizeof(sa_family_t))
231 return sockaddr.
sa.sa_family == family;
242 if (family != 0 && family != AF_INET && family != AF_INET6)
248 memset(&sockaddr, 0,
sizeof(sockaddr));
249 l =
sizeof(sockaddr);
251 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
254 if (l <
sizeof(sa_family_t))
257 if (sockaddr.
sa.sa_family != AF_INET &&
258 sockaddr.
sa.sa_family != AF_INET6)
262 if (sockaddr.
sa.sa_family != family)
266 if (sockaddr.
sa.sa_family == AF_INET) {
267 if (l <
sizeof(
struct sockaddr_in))
270 return htons(port) == sockaddr.
in4.sin_port;
272 if (l <
sizeof(
struct sockaddr_in6))
275 return htons(port) == sockaddr.
in6.sin6_port;
290 memset(&sockaddr, 0,
sizeof(sockaddr));
291 l =
sizeof(sockaddr);
293 if (getsockname(fd, &sockaddr.
sa, &l) < 0)
296 if (l <
sizeof(sa_family_t))
299 if (sockaddr.
sa.sa_family != AF_UNIX)
304 length = strlen(path);
308 return l == offsetof(
struct sockaddr_un, sun_path);
312 return (l >= offsetof(
struct sockaddr_un, sun_path) + length + 1) &&
313 memcmp(path, sockaddr.
un.sun_path, length + 1) == 0;
316 return (l == offsetof(
struct sockaddr_un, sun_path) + length) &&
317 memcmp(path, sockaddr.
un.sun_path, length) == 0;
324 #if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
328 struct msghdr msghdr;
338 if (!(e = getenv(
"NOTIFY_SOCKET")))
342 if ((e[0] !=
'@' && e[0] !=
'/') || e[1] == 0) {
347 if ((fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) {
352 memset(&sockaddr, 0,
sizeof(sockaddr));
353 sockaddr.
sa.sa_family = AF_UNIX;
354 strncpy(sockaddr.
un.sun_path, e,
sizeof(sockaddr.
un.sun_path));
356 if (sockaddr.
un.sun_path[0] ==
'@')
357 sockaddr.
un.sun_path[0] = 0;
359 memset(&iovec, 0,
sizeof(iovec));
360 iovec.iov_base = (
char *)state;
361 iovec.iov_len = strlen(state);
363 memset(&msghdr, 0,
sizeof(msghdr));
364 msghdr.msg_name = &sockaddr;
365 msghdr.msg_namelen = offsetof(
struct sockaddr_un, sun_path) + strlen(e);
367 if (msghdr.msg_namelen >
sizeof(
struct sockaddr_un))
368 msghdr.msg_namelen =
sizeof(
struct sockaddr_un);
370 msghdr.msg_iov = &iovec;
371 msghdr.msg_iovlen = 1;
373 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
381 if (unset_environment)
382 unsetenv(
"NOTIFY_SOCKET");
391 int sd_notifyf(
int unset_environment,
const char *format, ...) {
392 #if defined(DISABLE_SYSTEMD) || !defined(__linux__)
399 va_start(ap, format);
400 r = vasprintf(&p, format, ap);
414 #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;
#define SD_LISTEN_FDS_START
int sd_listen_fds(int unset_environment)
int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length)
int sd_notify(int unset_environment, const char *state)
static int sd_is_socket_internal(int fd, int type, int listening)
int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port)
struct sockaddr_storage storage
int sd_notifyf(int unset_environment, const char *format,...)
int sd_is_fifo(int fd, const char *path)
int sd_is_socket(int fd, int family, int type, int listening)