sd-daemon.c revision 31021ba0853d40ffdd8fdcd6611bddd4419a7357
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/***
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen This file is part of systemd.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright 2010 Lennart Poettering
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is free software; you can redistribute it and/or modify it
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen under the terms of the GNU Lesser General Public License as published by
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen (at your option) any later version.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is distributed in the hope that it will be useful, but
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Lesser General Public License for more details.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen You should have received a copy of the GNU Lesser General Public License
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen***/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <sys/stat.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <sys/socket.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <sys/un.h>
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen#include <netinet/in.h>
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen#include <stdlib.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <errno.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <unistd.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <string.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <stdarg.h>
d122f9ee3a0e3c02ff8100a3dcd1866e90a6537aTom Gundersen#include <stdio.h>
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen#include <stddef.h>
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen#include <limits.h>
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen#include <mqueue.h>
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "util.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "path-util.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "socket-util.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "sd-daemon.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen_public_ int sd_listen_fds(int unset_environment) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen const char *e;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen unsigned n;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r, fd;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen pid_t pid;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen e = getenv("LISTEN_PID");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (!e) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = 0;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen goto finish;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = parse_pid(e, &pid);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (r < 0)
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen goto finish;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen /* Is this for us? */
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen if (getpid() != pid) {
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen r = 0;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen goto finish;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen }
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen e = getenv("LISTEN_FDS");
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen if (!e) {
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen r = 0;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen goto finish;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen }
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen r = safe_atou(e, &n);
756775814cf69471f74ce853745bba69f2ba94efThomas Hindoe Paaboel Andersen if (r < 0)
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen goto finish;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) n; fd ++) {
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen r = fd_cloexec(fd, true);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (r < 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen goto finish;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = (int) n;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenfinish:
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (unset_environment) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen unsetenv("LISTEN_PID");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen unsetenv("LISTEN_FDS");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen_public_ int sd_is_fifo(int fd, const char *path) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen struct stat st_fd;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert_return(fd >= 0, -EBADF);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (fstat(fd, &st_fd) < 0)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return -errno;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (!S_ISFIFO(st_fd.st_mode))
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (path) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen struct stat st_path;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (stat(path, &st_path) < 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (errno == ENOENT || errno == ENOTDIR)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return -errno;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt return
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt st_path.st_dev == st_fd.st_dev &&
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt st_path.st_ino == st_fd.st_ino;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 1;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen_public_ int sd_is_special(int fd, const char *path) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen struct stat st_fd;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert_return(fd >= 0, -EBADF);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering if (fstat(fd, &st_fd) < 0)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return -errno;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 0;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering if (path) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen struct stat st_path;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (stat(path, &st_path) < 0) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (errno == ENOENT || errno == ENOTDIR)
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering return 0;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering return -errno;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering }
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering return
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering st_path.st_dev == st_fd.st_dev &&
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering st_path.st_ino == st_fd.st_ino;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return st_path.st_rdev == st_fd.st_rdev;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen else
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 1;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersenstatic int sd_is_socket_internal(int fd, int type, int listening) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen struct stat st_fd;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_return(fd >= 0, -EBADF);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_return(type >= 0, -EINVAL);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (fstat(fd, &st_fd) < 0)
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen return -errno;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen if (!S_ISSOCK(st_fd.st_mode))
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen return 0;
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt if (type != 0) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int other_type = 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen socklen_t l = sizeof(other_type);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return -errno;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (l != sizeof(other_type))
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return -EINVAL;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (other_type != type)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (listening >= 0) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int accepting = 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen socklen_t l = sizeof(accepting);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return -errno;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (l != sizeof(accepting))
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return -EINVAL;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (!accepting != !listening)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 1;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen_public_ int sd_is_socket(int fd, int family, int type, int listening) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_return(fd >= 0, -EBADF);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_return(family >= 0, -EINVAL);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = sd_is_socket_internal(fd, type, listening);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (r <= 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (family > 0) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen union sockaddr_union sockaddr = {};
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen socklen_t l = sizeof(sockaddr);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (getsockname(fd, &sockaddr.sa, &l) < 0)
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return -errno;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen if (l < sizeof(sa_family_t))
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return -EINVAL;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return sockaddr.sa.sa_family == family;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen }
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return 1;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen}
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen_public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen union sockaddr_union sockaddr = {};
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen socklen_t l = sizeof(sockaddr);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert_return(fd >= 0, -EBADF);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert_return(IN_SET(family, 0, AF_INET, AF_INET6), -EINVAL);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_is_socket_internal(fd, type, listening);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r <= 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (getsockname(fd, &sockaddr.sa, &l) < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -errno;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (l < sizeof(sa_family_t))
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -EINVAL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (sockaddr.sa.sa_family != AF_INET &&
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen sockaddr.sa.sa_family != AF_INET6)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (family != 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (sockaddr.sa.sa_family != family)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (port > 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (sockaddr.sa.sa_family == AF_INET) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (l < sizeof(struct sockaddr_in))
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -EINVAL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return htons(port) == sockaddr.in.sin_port;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen } else {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (l < sizeof(struct sockaddr_in6))
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -EINVAL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return htons(port) == sockaddr.in6.sin6_port;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen_public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen union sockaddr_union sockaddr = {};
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen socklen_t l = sizeof(sockaddr);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert_return(fd >= 0, -EBADF);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_is_socket_internal(fd, type, listening);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r <= 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (getsockname(fd, &sockaddr.sa, &l) < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -errno;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (l < sizeof(sa_family_t))
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -EINVAL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (sockaddr.sa.sa_family != AF_UNIX)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (path) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (length == 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen length = strlen(path);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (length == 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* Unnamed socket */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return l == offsetof(struct sockaddr_un, sun_path);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (path[0])
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* Normal path socket */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen memcmp(path, sockaddr.un.sun_path, length+1) == 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen else
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* Abstract namespace socket */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen (l == offsetof(struct sockaddr_un, sun_path) + length) &&
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen memcmp(path, sockaddr.un.sun_path, length) == 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen_public_ int sd_is_mq(int fd, const char *path) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen struct mq_attr attr;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert_return(fd >= 0, -EBADF);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (mq_getattr(fd, &attr) < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -errno;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (path) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen char fpath[PATH_MAX];
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen struct stat a, b;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert_return(path_is_absolute(path), -EINVAL);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (fstat(fd, &a) < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -errno;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen fpath[sizeof(fpath)-1] = 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (stat(fpath, &b) < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -errno;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (a.st_dev != b.st_dev ||
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen a.st_ino != b.st_ino)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen_public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen union sockaddr_union sockaddr = {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen .sa.sa_family = AF_UNIX,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen };
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen struct iovec iovec = {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen .iov_base = (char*) state,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen };
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen struct msghdr msghdr = {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen .msg_iov = &iovec,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen .msg_iovlen = 1,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen .msg_name = &sockaddr,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen };
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_close_ int fd = -1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen struct cmsghdr *cmsg = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen const char *e;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bool have_pid;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!state) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = -EINVAL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen goto finish;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen if (n_fds > 0 && !fds) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = -EINVAL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen goto finish;
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen e = getenv("NOTIFY_SOCKET");
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen if (!e)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen /* Must be an abstract socket, or an absolute path */
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = -EINVAL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen goto finish;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (fd < 0) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen r = -errno;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen goto finish;
1231c4d238844e77018caf5b5852f01d96373c47Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen iovec.iov_len = strlen(state);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (sockaddr.un.sun_path[0] == '@')
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen sockaddr.un.sun_path[0] = 0;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen msghdr.msg_namelen = sizeof(struct sockaddr_un);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen have_pid = pid != 0 && pid != getpid();
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (n_fds > 0 || have_pid) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen /* CMSG_SPACE(0) may return value different then zero, which results in miscalculated controllen. */
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen msghdr.msg_controllen = (n_fds ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen CMSG_SPACE(sizeof(struct ucred)) * have_pid;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen msghdr.msg_control = alloca(msghdr.msg_controllen);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen cmsg = CMSG_FIRSTHDR(&msghdr);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (n_fds > 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen cmsg->cmsg_level = SOL_SOCKET;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen cmsg->cmsg_type = SCM_RIGHTS;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (have_pid)
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen assert_se(cmsg = CMSG_NXTHDR(&msghdr, cmsg));
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (have_pid) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen struct ucred *ucred;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen cmsg->cmsg_level = SOL_SOCKET;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen cmsg->cmsg_type = SCM_CREDENTIALS;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen ucred = (struct ucred*) CMSG_DATA(cmsg);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen ucred->pid = pid;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen ucred->uid = getuid();
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen ucred->gid = getgid();
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen /* First try with fake ucred data, as requested */
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = 1;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen goto finish;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen }
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen /* If that failed, try with our own ucred instead */
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen if (have_pid) {
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred));
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen if (msghdr.msg_controllen == 0)
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen msghdr.msg_control = NULL;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = 1;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen goto finish;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = -errno;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersenfinish:
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (unset_environment)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen unsetenv("NOTIFY_SOCKET");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen_public_ int sd_pid_notify(pid_t pid, int unset_environment, const char *state) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return sd_pid_notify_with_fds(pid, unset_environment, state, NULL, 0);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen_public_ int sd_notify(int unset_environment, const char *state) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return sd_pid_notify_with_fds(0, unset_environment, state, NULL, 0);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen_public_ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen _cleanup_free_ char *p = NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen int r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (format) {
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen va_list ap;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen va_start(ap, format);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen r = vasprintf(&p, format, ap);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen va_end(ap);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen if (r < 0 || !p)
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen return -ENOMEM;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen }
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering return sd_pid_notify(pid, unset_environment, p);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering}
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering_public_ int sd_notifyf(int unset_environment, const char *format, ...) {
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering _cleanup_free_ char *p = NULL;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering int r;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering if (format) {
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering va_list ap;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen va_start(ap, format);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = vasprintf(&p, format, ap);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen va_end(ap);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0 || !p)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return -ENOMEM;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen }
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen return sd_pid_notify(0, unset_environment, p);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen}
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen_public_ int sd_booted(void) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen /* We test whether the runtime unit file directory has been
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen * created. This takes place in mount-setup.c, so is
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen * guaranteed to happen very early during boot. */
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen return laccess("/run/systemd/system/", F_OK) >= 0;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen}
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen_public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen const char *s, *p = ""; /* p is set to dummy value to do unsetting */
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen uint64_t u;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen int r = 0;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen s = getenv("WATCHDOG_USEC");
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (!s)
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen goto finish;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = safe_atou64(s, &u);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (r < 0)
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen goto finish;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (u <= 0) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = -EINVAL;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen goto finish;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen }
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen p = getenv("WATCHDOG_PID");
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (p) {
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams pid_t pid;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = parse_pid(p, &pid);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (r < 0)
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen goto finish;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen /* Is this for us? */
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (getpid() != pid) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = 0;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen goto finish;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen }
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen }
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
c15fb62a731f1a457af94e60ac6a4d23f219a8f6Thomas Hindoe Paaboel Andersen if (usec)
c15fb62a731f1a457af94e60ac6a4d23f219a8f6Thomas Hindoe Paaboel Andersen *usec = u;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = 1;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersenfinish:
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (unset_environment && s)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen unsetenv("WATCHDOG_USEC");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (unset_environment && p)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen unsetenv("WATCHDOG_PID");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return r;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen}
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen