sd-daemon.c revision c463a6f1c4d375929a99ac258292ce5e1f64a835
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek This file is part of systemd.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek Copyright 2010 Lennart Poettering
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek (at your option) any later version.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic void unsetenv_all(bool unset_environment) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_listen_fds(int unset_environment) {
603938e0a9b5379984d7397e3cf81683c0037a53Lennart Poettering const char *e;
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt /* Is this for us? */
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) n; fd ++) {
fff40a51ccbb02e8dec4ff2ee505bc84f75e445cZbigniew Jędrzejewski-Szmek unsetenv_all(unset_environment);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **l = NULL;
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek n_names = strv_split_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek unsetenv_all(unset_environment);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering n_fds = sd_listen_fds(unset_environment);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = strv_extend_n(&l, "unknown", n_fds);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering_public_ int sd_is_fifo(int fd, const char *path) {
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek if (errno == ENOENT || errno == ENOTDIR)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek st_path.st_dev == st_fd.st_dev &&
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_is_special(int fd, const char *path) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (errno == ENOENT || errno == ENOTDIR)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek st_path.st_dev == st_fd.st_dev &&
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidtstatic int sd_is_socket_internal(int fd, int type, int listening) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(type >= 0, -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek socklen_t l = sizeof(other_type);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek socklen_t l = sizeof(accepting);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (l != sizeof(accepting))
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_is_socket(int fd, int family, int type, int listening) {
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering r = sd_is_socket_internal(fd, type, listening);
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek return sockaddr.sa.sa_family == family;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(IN_SET(family, 0, AF_INET, AF_INET6), -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_is_socket_internal(fd, type, listening);
892213bf1fd23e48d64a407ece6e10b07bef1926Zbigniew Jędrzejewski-Szmek if (getsockname(fd, &sockaddr.sa, &l) < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (sockaddr.sa.sa_family != AF_INET &&
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek sockaddr.sa.sa_family != AF_INET6)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (sockaddr.sa.sa_family != family)
892213bf1fd23e48d64a407ece6e10b07bef1926Zbigniew Jędrzejewski-Szmek if (sockaddr.sa.sa_family == AF_INET) {
892213bf1fd23e48d64a407ece6e10b07bef1926Zbigniew Jędrzejewski-Szmek if (l < sizeof(struct sockaddr_in))
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering return htons(port) == sockaddr.in.sin_port;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (l < sizeof(struct sockaddr_in6))
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return htons(port) == sockaddr.in6.sin6_port;
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek_public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek union sockaddr_union sockaddr = {};
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_is_socket_internal(fd, type, listening);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (getsockname(fd, &sockaddr.sa, &l) < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (sockaddr.sa.sa_family != AF_UNIX)
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek /* Unnamed socket */
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek return l == offsetof(struct sockaddr_un, sun_path);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek /* Normal path socket */
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek memcmp(path, sockaddr.un.sun_path, length+1) == 0;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek /* Abstract namespace socket */
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek (l == offsetof(struct sockaddr_un, sun_path) + length) &&
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek memcmp(path, sockaddr.un.sun_path, length) == 0;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_is_mq(int fd, const char *path) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek /* Check that the fd is valid */
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(fcntl(fd, F_GETFD) >= 0, -errno);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mq_getattr(fd, &attr) < 0) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek /* A non-mq fd (or an invalid one, but we ruled that out above) */
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(path_is_absolute(path), -EINVAL);
2c408cb6276e3b8d18fb4e2a81a1128d8bbaa70dLennart Poettering strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds) {
bool have_pid;
if (!state) {
r = -EINVAL;
goto finish;
r = -EINVAL;
goto finish;
r = -EINVAL;
goto finish;
if (fd < 0) {
r = -errno;
goto finish;
/* CMSG_SPACE(0) may return value different then zero, which results in miscalculated controllen. */
if (n_fds > 0) {
if (have_pid)
if (have_pid) {
goto finish;
if (have_pid) {
goto finish;
r = -errno;
if (unset_environment)
if (format) {
return -ENOMEM;
if (format) {
return -ENOMEM;
* created. This takes place in mount-setup.c, so is
uint64_t u;
goto finish;
r = safe_atou64(s, &u);
goto finish;
r = -EINVAL;
goto finish;
goto finish;
goto finish;
if (usec)
*usec = u;
if (unset_environment && s)
if (unset_environment && p)