From: Chuck Lever <chuck.lever@oracle.com>
To: Lennart Poettering <lennart@poettering.net>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [PATCH] rpcbind: add support for systemd socket activation
Date: Wed, 21 Jul 2010 13:56:44 -0400 [thread overview]
Message-ID: <4C4734DC.9010106@oracle.com> (raw)
In-Reply-To: <20100719021906.GA16939@tango.0pointer.de>
On 07/18/10 10:19 PM, Lennart Poettering wrote:
> Heya!
>
> (I sent this patch to Steve Dickson earlier, he asked me to post this
> here.)
>
> This patch allows us to spawn rpcbind automatically on first use in a
> systemd environment, the same way it is done on MacOS X with launchd.
>
> This makes use of socket-based activation as provided by systemd (in
> case you are wondering, systemd is a Fedora 14 feature, described in all
> detail here: http://0pointer.de/blog/projects/systemd.html). It uses the
> reference implementation of the fd passing code, as supplied by systemd
> upstream. I hope that's acceptable. It's liberally licensed, so I hope
> this is OK. If not, it isn't difficult to reimplement this without the
> reference implementation.
>
> The algorithms implemented are described here:
>
> http://0pointer.de/public/systemd-man/sd_listen_fds.html
> http://0pointer.de/public/systemd-man/sd-daemon.html
> http://0pointer.de/public/systemd-man/daemon.html
>
> Any comments welcome.
>
> If this patch is OK then I can provide systemd unit files as well.
>
> (This patch is generated with --ignore-space-change, to make it more
> readable. A version generated without this switch you find here under
> http://0pointer.de/public/0001-systemd-add-support-for-system-bus-activation.patch
> That's actually the patch you might want to merge. This patch here in
> the mail is the one you want to review. Since the rpcbind sources are a
> bit chaotic when it comes to indenting and whitespace, this patch
> ended up as messy as it is without the switch applied. Sorry for
> that. I'd recommend adopting a stricter whitespace regime for the
> package, following how they do it for the kernel. Would make it a lot
> ncier to prepare patches, and all the git warning madness about weird
> whitespace changes in your commits would go away. But anyway, this is
> just me nitpicking.)
>
> Lennart
>
> Signed-off-by: Lennart Poettering<lennart@poettering.net>
> ---
> src/Makefile.am | 6 +-
> src/rpcbind.c | 75 +++++++++-
> src/sd-daemon.c | 452 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> src/sd-daemon.h | 257 +++++++++++++++++++++++++++++++
> 4 files changed, 783 insertions(+), 7 deletions(-)
> create mode 100644 src/sd-daemon.c
> create mode 100644 src/sd-daemon.h
Why aren't sd-daemon.[ch] part of a systemd related library? They seem
pretty generic to me, and could be useful for other daemons.
Plus, the newly introduced update-systemd Makefile target seems to
suggest these won't be stable over time. Wouldn't it be better to have
a versioned library, external to rpcbind, with this code in it?
> diff --git a/src/Makefile.am b/src/Makefile.am
> index cc0a85b..6340fe9 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -20,7 +20,8 @@ rpcbind_SOURCES = check_bound.c rpcbind.c \
> rpcb_svc_4.c rpcb_svc_com.c \
> util.c pmap_svc.c rpcb_stat.c \
> rpcb_svc.c security.c warmstart.c \
> - rpcbind.h
> + rpcbind.h \
> + sd-daemon.c sd-daemon.h
>
> rpcinfo_SOURCES = rpcinfo.c
> rpcinfo_LDFLAGS = -lpthread -ltirpc
> @@ -32,3 +33,6 @@ rpcbind_LDADD = $(LIB_TIRPC)
> AM_CPPFLAGS = -I/usr/include/tirpc -DCHECK_LOCAL -DPORTMAP \
> -DFACILITY=LOG_MAIL -DSEVERITY=LOG_INFO
>
> +update-systemd:
> + curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c> sd-daemon.c
> + curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h> sd-daemon.h
> diff --git a/src/rpcbind.c b/src/rpcbind.c
> index 63023e1..0368eaf 100644
> --- a/src/rpcbind.c
> +++ b/src/rpcbind.c
> @@ -70,6 +70,7 @@
> #include<nss.h>
> #include "config.h"
> #include "rpcbind.h"
> +#include "sd-daemon.h"
>
> /*#define RPCBIND_DEBUG*/
>
> @@ -282,6 +283,7 @@ init_transport(struct netconfig *nconf)
> u_int32_t host_addr[4]; /* IPv4 or IPv6 */
> struct sockaddr_un sun;
> mode_t oldmask;
> + int n;
> res = NULL;
>
> if ((nconf->nc_semantics != NC_TPI_CLTS)&&
> @@ -301,6 +303,72 @@ init_transport(struct netconfig *nconf)
> }
> #endif
>
> + if (!__rpc_nconf2sockinfo(nconf,&si)) {
> + syslog(LOG_ERR, "cannot get information for %s",
> + nconf->nc_netid);
> + return (1);
> + }
> +
> + n = sd_listen_fds(0);
> + if (n< 0) {
> + syslog(LOG_ERR, "failed to acquire systemd scokets: %s", strerror(-n));
> + return 1;
> + }
> +
> + if (n> 0) {
> + int fd;
> +
> + /* We have systemd sockets, now find those that match
> + * our netconfig structure. */
> +
> + for (fd = SD_LISTEN_FDS_START; fd< SD_LISTEN_FDS_START + n; fd++) {
> + struct __rpc_sockinfo si_other;
> + union {
> + struct sockaddr sa;
> + struct sockaddr_un un;
> + struct sockaddr_in in4;
> + struct sockaddr_in6 in6;
> + struct sockaddr_storage storage;
> + } sa;
> + socklen_t addrlen = sizeof(sa);
> +
> + if (!__rpc_fd2sockinfo(fd,&si_other)) {
> + syslog(LOG_ERR, "cannog get information for fd %i", fd);
> + return 1;
> + }
> +
> + if (si.si_af != si_other.si_af ||
> + si.si_socktype != si_other.si_socktype ||
> + si.si_proto != si_other.si_proto)
> + continue;
> +
> + if (getsockname(fd,&sa.sa,&addrlen)< 0) {
> + syslog(LOG_ERR, "failed to query socket name: %s",
> + strerror(errno));
> + goto error;
> + }
> +
> + /* Copy the address */
> + taddr.addr.maxlen = taddr.addr.len = addrlen;
> + taddr.addr.buf = malloc(addrlen);
> + if (taddr.addr.buf == NULL) {
> + syslog(LOG_ERR,
> + "cannot allocate memory for %s address",
> + nconf->nc_netid);
> + goto error;
> + }
> + memcpy(taddr.addr.buf,&sa, addrlen);
> +
> + my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf,&taddr,
> + RPC_MAXDATASIZE, RPC_MAXDATASIZE);
> + if (my_xprt == (SVCXPRT *)NULL) {
> + syslog(LOG_ERR, "%s: could not create service",
> + nconf->nc_netid);
> + goto error;
> + }
> + }
> + } else {
> +
> /*
> * XXX - using RPC library internal functions. For NC_TPI_CLTS
> * we call this later, for each socket we like to bind.
> @@ -313,12 +381,6 @@ init_transport(struct netconfig *nconf)
> }
> }
>
> - if (!__rpc_nconf2sockinfo(nconf,&si)) {
> - syslog(LOG_ERR, "cannot get information for %s",
> - nconf->nc_netid);
> - return (1);
> - }
> -
> if ((strcmp(nconf->nc_netid, "local") == 0) ||
> (strcmp(nconf->nc_netid, "unix") == 0)) {
> memset(&sun, 0, sizeof sun);
> @@ -555,6 +617,7 @@ init_transport(struct netconfig *nconf)
> goto error;
> }
> }
> + }
>
> #ifdef PORTMAP
> /*
> diff --git a/src/sd-daemon.c b/src/sd-daemon.c
> new file mode 100644
> index 0000000..3bb258d
> --- /dev/null
> +++ b/src/sd-daemon.c
> @@ -0,0 +1,452 @@
> +/*-*- Mode: C; c-basic-offset: 8 -*-*/
> +
> +/***
> + Copyright 2010 Lennart Poettering
> +
> + Permission is hereby granted, free of charge, to any person
> + obtaining a copy of this software and associated documentation files
> + (the "Software"), to deal in the Software without restriction,
> + including without limitation the rights to use, copy, modify, merge,
> + publish, distribute, sublicense, and/or sell copies of the Software,
> + and to permit persons to whom the Software is furnished to do so,
> + subject to the following conditions:
> +
> + The above copyright notice and this permission notice shall be
> + included in all copies or substantial portions of the Software.
> +
> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + SOFTWARE.
> +***/
> +
> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif
> +
> +#include<sys/types.h>
> +#include<sys/stat.h>
> +#include<sys/socket.h>
> +#include<sys/un.h>
> +#include<sys/fcntl.h>
> +#include<netinet/in.h>
> +#include<stdlib.h>
> +#include<errno.h>
> +#include<unistd.h>
> +#include<string.h>
> +#include<stdarg.h>
> +#include<stdio.h>
> +
> +#include "sd-daemon.h"
> +
> +int sd_listen_fds(int unset_environment) {
> +
> +#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
> + return 0;
> +#else
> + int r, fd;
> + const char *e;
> + char *p = NULL;
> + unsigned long l;
> +
> + if (!(e = getenv("LISTEN_PID"))) {
> + r = 0;
> + goto finish;
> + }
> +
> + errno = 0;
> + l = strtoul(e,&p, 10);
> +
> + if (errno != 0) {
> + r = -errno;
> + goto finish;
> + }
> +
> + if (!p || *p || l<= 0) {
> + r = -EINVAL;
> + goto finish;
> + }
> +
> + /* Is this for us? */
> + if (getpid() != (pid_t) l) {
> + r = 0;
> + goto finish;
> + }
> +
> + if (!(e = getenv("LISTEN_FDS"))) {
> + r = 0;
> + goto finish;
> + }
> +
> + errno = 0;
> + l = strtoul(e,&p, 10);
> +
> + if (errno != 0) {
> + r = -errno;
> + goto finish;
> + }
> +
> + if (!p || *p) {
> + r = -EINVAL;
> + goto finish;
> + }
> +
> + for (fd = SD_LISTEN_FDS_START; fd< SD_LISTEN_FDS_START + (int) l; fd ++) {
> + int flags;
> +
> + if ((flags = fcntl(fd, F_GETFD))< 0) {
> + r = -errno;
> + goto finish;
> + }
> +
> + if (flags& FD_CLOEXEC)
> + continue;
> +
> + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC)< 0) {
> + r = -errno;
> + goto finish;
> + }
> + }
> +
> + r = (int) l;
> +
> +finish:
> + if (unset_environment) {
> + unsetenv("LISTEN_PID");
> + unsetenv("LISTEN_FDS");
> + }
> +
> + return r;
> +#endif
> +}
> +
> +int sd_is_fifo(int fd, const char *path) {
> + struct stat st_fd;
> +
> + if (fd< 0)
> + return -EINVAL;
> +
> + memset(&st_fd, 0, sizeof(st_fd));
> + if (fstat(fd,&st_fd)< 0)
> + return -errno;
> +
> + if (!S_ISFIFO(st_fd.st_mode))
> + return 0;
> +
> + if (path) {
> + struct stat st_path;
> +
> + memset(&st_path, 0, sizeof(st_path));
> + if (stat(path,&st_path)< 0) {
> +
> + if (errno == ENOENT || errno == ENOTDIR)
> + return 0;
> +
> + return -errno;
> + }
> +
> + return
> + st_path.st_dev == st_fd.st_dev&&
> + st_path.st_ino == st_fd.st_ino;
> + }
> +
> + return 1;
> +}
> +
> +static int sd_is_socket_internal(int fd, int type, int listening) {
> + struct stat st_fd;
> +
> + if (fd< 0 || type< 0)
> + return -EINVAL;
> +
> + if (fstat(fd,&st_fd)< 0)
> + return -errno;
> +
> + if (!S_ISSOCK(st_fd.st_mode))
> + return 0;
> +
> + if (type != 0) {
> + int other_type = 0;
> + socklen_t l = sizeof(other_type);
> +
> + if (getsockopt(fd, SOL_SOCKET, SO_TYPE,&other_type,&l)< 0)
> + return -errno;
> +
> + if (l != sizeof(other_type))
> + return -EINVAL;
> +
> + if (other_type != type)
> + return 0;
> + }
> +
> + if (listening>= 0) {
> + int accepting = 0;
> + socklen_t l = sizeof(accepting);
> +
> + if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN,&accepting,&l)< 0)
> + return -errno;
> +
> + if (l != sizeof(accepting))
> + return -EINVAL;
> +
> + if (!accepting != !listening)
> + return 0;
> + }
> +
> + return 1;
> +}
> +
> +union sockaddr_union {
> + struct sockaddr sa;
> + struct sockaddr_in in4;
> + struct sockaddr_in6 in6;
> + struct sockaddr_un un;
> + struct sockaddr_storage storage;
> +};
> +
> +int sd_is_socket(int fd, int family, int type, int listening) {
> + int r;
> +
> + if (family< 0)
> + return -EINVAL;
> +
> + if ((r = sd_is_socket_internal(fd, type, listening))<= 0)
> + return r;
> +
> + if (family> 0) {
> + union sockaddr_union sockaddr;
> + socklen_t l;
> +
> + memset(&sockaddr, 0, sizeof(sockaddr));
> + l = sizeof(sockaddr);
> +
> + if (getsockname(fd,&sockaddr.sa,&l)< 0)
> + return -errno;
> +
> + if (l< sizeof(sa_family_t))
> + return -EINVAL;
> +
> + return sockaddr.sa.sa_family == family;
> + }
> +
> + return 1;
> +}
> +
> +int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
> + union sockaddr_union sockaddr;
> + socklen_t l;
> + int r;
> +
> + if (family != 0&& family != AF_INET&& family != AF_INET6)
> + return -EINVAL;
> +
> + if ((r = sd_is_socket_internal(fd, type, listening))<= 0)
> + return r;
> +
> + memset(&sockaddr, 0, sizeof(sockaddr));
> + l = sizeof(sockaddr);
> +
> + if (getsockname(fd,&sockaddr.sa,&l)< 0)
> + return -errno;
> +
> + if (l< sizeof(sa_family_t))
> + return -EINVAL;
> +
> + if (sockaddr.sa.sa_family != AF_INET&&
> + sockaddr.sa.sa_family != AF_INET6)
> + return 0;
> +
> + if (family> 0)
> + if (sockaddr.sa.sa_family != family)
> + return 0;
> +
> + if (port> 0) {
> + if (sockaddr.sa.sa_family == AF_INET) {
> + if (l< sizeof(struct sockaddr_in))
> + return -EINVAL;
> +
> + return htons(port) == sockaddr.in4.sin_port;
> + } else {
> + if (l< sizeof(struct sockaddr_in6))
> + return -EINVAL;
> +
> + return htons(port) == sockaddr.in6.sin6_port;
> + }
> + }
> +
> + return 1;
> +}
> +
> +int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
> + union sockaddr_union sockaddr;
> + socklen_t l;
> + int r;
> +
> + if ((r = sd_is_socket_internal(fd, type, listening))<= 0)
> + return r;
> +
> + memset(&sockaddr, 0, sizeof(sockaddr));
> + l = sizeof(sockaddr);
> +
> + if (getsockname(fd,&sockaddr.sa,&l)< 0)
> + return -errno;
> +
> + if (l< sizeof(sa_family_t))
> + return -EINVAL;
> +
> + if (sockaddr.sa.sa_family != AF_UNIX)
> + return 0;
> +
> + if (path) {
> + if (length<= 0)
> + length = strlen(path);
> +
> + if (length<= 0)
> + /* Unnamed socket */
> + return l == sizeof(sa_family_t);
> +
> + if (path[0])
> + /* Normal path socket */
> + return
> + (l>= sizeof(sa_family_t) + length + 1)&&
> + memcmp(path, sockaddr.un.sun_path, length+1) == 0;
> + else
> + /* Abstract namespace socket */
> + return
> + (l == sizeof(sa_family_t) + length)&&
> + memcmp(path, sockaddr.un.sun_path, length) == 0;
> + }
> +
> + return 1;
> +}
> +
> +int sd_notify(int unset_environment, const char *state) {
> +#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
> + return 0;
> +#else
> + int fd = -1, r;
> + struct msghdr msghdr;
> + struct iovec iovec;
> + union sockaddr_union sockaddr;
> + struct ucred *ucred;
> + union {
> + struct cmsghdr cmsghdr;
> + uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
> + } control;
> + const char *e;
> +
> + if (!state) {
> + r = -EINVAL;
> + goto finish;
> + }
> +
> + if (!(e = getenv("NOTIFY_SOCKET")))
> + return 0;
> +
> + /* Must be an abstract socket, or an absolute path */
> + if ((e[0] != '@'&& e[0] != '/') || e[1] == 0) {
> + r = -EINVAL;
> + goto finish;
> + }
> +
> + if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0))< 0) {
> + r = -errno;
> + goto finish;
> + }
> +
> + memset(&sockaddr, 0, sizeof(sockaddr));
> + sockaddr.sa.sa_family = AF_UNIX;
> + strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
> +
> + if (sockaddr.un.sun_path[0] == '@')
> + sockaddr.un.sun_path[0] = 0;
> +
> + memset(&iovec, 0, sizeof(iovec));
> + iovec.iov_base = (char*) state;
> + iovec.iov_len = strlen(state);
> +
> + memset(&control, 0, sizeof(control));
> + control.cmsghdr.cmsg_level = SOL_SOCKET;
> + control.cmsghdr.cmsg_type = SCM_CREDENTIALS;
> + control.cmsghdr.cmsg_len = CMSG_LEN(sizeof(struct ucred));
> +
> + ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
> + ucred->pid = getpid();
> + ucred->uid = getuid();
> + ucred->gid = getgid();
> +
> + memset(&msghdr, 0, sizeof(msghdr));
> + msghdr.msg_name =&sockaddr;
> + msghdr.msg_namelen = sizeof(sa_family_t) + strlen(e);
> +
> + if (msghdr.msg_namelen> sizeof(struct sockaddr_un))
> + msghdr.msg_namelen = sizeof(struct sockaddr_un);
> +
> + msghdr.msg_iov =&iovec;
> + msghdr.msg_iovlen = 1;
> + msghdr.msg_control =&control;
> + msghdr.msg_controllen = control.cmsghdr.cmsg_len;
> +
> + if (sendmsg(fd,&msghdr, MSG_NOSIGNAL)< 0) {
> + r = -errno;
> + goto finish;
> + }
> +
> + r = 1;
> +
> +finish:
> + if (unset_environment)
> + unsetenv("NOTIFY_SOCKET");
> +
> + if (fd>= 0)
> + close(fd);
> +
> + return r;
> +#endif
> +}
> +
> +int sd_notifyf(int unset_environment, const char *format, ...) {
> +#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
> + return 0;
> +#else
> + va_list ap;
> + char *p = NULL;
> + int r;
> +
> + va_start(ap, format);
> + r = vasprintf(&p, format, ap);
> + va_end(ap);
> +
> + if (r< 0 || !p)
> + return -ENOMEM;
> +
> + r = sd_notify(unset_environment, p);
> + free(p);
> +
> + return r;
> +#endif
> +}
> +
> +int sd_booted(void) {
> +#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
> + return 0;
> +#else
> +
> + struct stat a, b;
> +
> + /* We simply test whether the systemd cgroup hierarchy is
> + * mounted */
> +
> + if (lstat("/cgroup",&a)< 0)
> + return 0;
> +
> + if (lstat("/cgroup/systemd",&b)< 0)
> + return 0;
> +
> + return a.st_dev != b.st_dev;
> +#endif
> +}
> diff --git a/src/sd-daemon.h b/src/sd-daemon.h
> new file mode 100644
> index 0000000..fd6221f
> --- /dev/null
> +++ b/src/sd-daemon.h
> @@ -0,0 +1,257 @@
> +/*-*- Mode: C; c-basic-offset: 8 -*-*/
> +
> +#ifndef foosddaemonhfoo
> +#define foosddaemonhfoo
> +
> +/***
> + Copyright 2010 Lennart Poettering
> +
> + Permission is hereby granted, free of charge, to any person
> + obtaining a copy of this software and associated documentation files
> + (the "Software"), to deal in the Software without restriction,
> + including without limitation the rights to use, copy, modify, merge,
> + publish, distribute, sublicense, and/or sell copies of the Software,
> + and to permit persons to whom the Software is furnished to do so,
> + subject to the following conditions:
> +
> + The above copyright notice and this permission notice shall be
> + included in all copies or substantial portions of the Software.
> +
> + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + SOFTWARE.
> +***/
> +
> +#include<sys/types.h>
> +#include<inttypes.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/*
> + Reference implementation of a few systemd related interfaces for
> + writing daemons. These interfaces are trivial to implement. To
> + simplify porting we provide this reference implementation.
> + Applications are welcome to reimplement the algorithms described
> + here if they do not want to include these two source files.
> +
> + The following functionality is provided:
> +
> + - Support for logging with log levels on stderr
> + - File descriptor passing for socket-based activation
> + - Daemon startup and status notification
> + - Detection of systemd boots
> +
> + You may compile this with -DDISABLE_SYSTEMD to disable systemd
> + support. This makes all those calls NOPs that are directly related to
> + systemd (i.e. only sd_is_xxx() will stay useful).
> +
> + Since this is drop-in code we don't want any of our symbols to be
> + exported in any case. Hence we declare hidden visibility for all of
> + them.
> +
> + You may find an up-to-date version of these source files online:
> +
> + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h
> + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
> +
> + This should compile on non-Linux systems, too, but with the
> + exception of the sd_is_xxx() calls all functions will become NOPs.
> +
> + See sd-daemon(7) for more information.
> +*/
> +
> +#if __GNUC__>= 4
> +#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
> +#define _sd_hidden_ __attribute__ ((visibility("hidden")))
> +#else
> +#define _sd_printf_attr_(a,b)
> +#define _sd_hidden_
> +#endif
> +
> +/*
> + Log levels for usage on stderr:
> +
> + fprintf(stderr, SD_NOTICE "Hello World!\n");
> +
> + This is similar to printk() usage in the kernel.
> +*/
> +#define SD_EMERG "<0>" /* system is unusable */
> +#define SD_ALERT "<1>" /* action must be taken immediately */
> +#define SD_CRIT "<2>" /* critical conditions */
> +#define SD_ERR "<3>" /* error conditions */
> +#define SD_WARNING "<4>" /* warning conditions */
> +#define SD_NOTICE "<5>" /* normal but significant condition */
> +#define SD_INFO "<6>" /* informational */
> +#define SD_DEBUG "<7>" /* debug-level messages */
> +
> +/* The first passed file descriptor is fd 3 */
> +#define SD_LISTEN_FDS_START 3
> +
> +/*
> + Returns how many file descriptors have been passed, or a negative
> + errno code on failure. Optionally, removes the $LISTEN_FDS and
> + $LISTEN_PID file descriptors from the environment (recommended, but
> + problematic in threaded environments). If r is the return value of
> + this function you'll find the file descriptors passed as fds
> + SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
> + errno style error code on failure. This function call ensures that
> + the FD_CLOEXEC flag is set for the passed file descriptors, to make
> + sure they are not passed on to child processes. If FD_CLOEXEC shall
> + not be set, the caller needs to unset it after this call for all file
> + descriptors that are used.
> +
> + See sd_listen_fds(3) for more information.
> +*/
> +int sd_listen_fds(int unset_environment) _sd_hidden_;
> +
> +/*
> + Helper call for identifying a passed file descriptor. Returns 1 if
> + the file descriptor is a FIFO in the file system stored under the
> + specified path, 0 otherwise. If path is NULL a path name check will
> + not be done and the call only verifies if the file descriptor
> + refers to a FIFO. Returns a negative errno style error code on
> + failure.
> +
> + See sd_is_fifo(3) for more information.
> +*/
> +int sd_is_fifo(int fd, const char *path) _sd_hidden_;
> +
> +/*
> + Helper call for identifying a passed file descriptor. Returns 1 if
> + the file descriptor is a socket of the specified family (AF_INET,
> + ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
> + family is 0 a socket family check will not be done. If type is 0 a
> + socket type check will not be done and the call only verifies if
> + the file descriptor refers to a socket. If listening is> 0 it is
> + verified that the socket is in listening mode. (i.e. listen() has
> + been called) If listening is == 0 it is verified that the socket is
> + not in listening mode. If listening is< 0 no listening mode check
> + is done. Returns a negative errno style error code on failure.
> +
> + See sd_is_socket(3) for more information.
> +*/
> +int sd_is_socket(int fd, int family, int type, int listening) _sd_hidden_;
> +
> +/*
> + Helper call for identifying a passed file descriptor. Returns 1 if
> + the file descriptor is an Internet socket, of the specified family
> + (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
> + SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
> + check is not done. If type is 0 a socket type check will not be
> + done. If port is 0 a socket port check will not be done. The
> + listening flag is used the same way as in sd_is_socket(). Returns a
> + negative errno style error code on failure.
> +
> + See sd_is_socket_inet(3) for more information.
> +*/
> +int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) _sd_hidden_;
> +
> +/*
> + Helper call for identifying a passed file descriptor. Returns 1 if
> + the file descriptor is an AF_UNIX socket of the specified type
> + (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
> + a socket type check will not be done. If path is NULL a socket path
> + check will not be done. For normal AF_UNIX sockets set length to
> + 0. For abstract namespace sockets set length to the length of the
> + socket name (including the initial 0 byte), and pass the full
> + socket path in path (including the initial 0 byte). The listening
> + flag is used the same way as in sd_is_socket(). Returns a negative
> + errno style error code on failure.
> +
> + See sd_is_socket_unix(3) for more information.
> +*/
> +int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) _sd_hidden_;
> +
> +/*
> + Informs systemd about changed daemon state. This takes a number of
> + newline seperated environment-style variable assignments in a
> + string. The following variables are known:
> +
> + READY=1 Tells systemd that daemon startup is finished (only
> + relevant for services of Type=notify). The passed
> + argument is a boolean "1" or "0". Since there is
> + little value in signalling non-readiness the only
> + value daemons should send is "READY=1".
> +
> + STATUS=... Passes a single-line status string back to systemd
> + that describes the daemon state. This is free-from
> + and can be used for various purposes: general state
> + feedback, fsck-like programs could pass completion
> + percentages and failing programs could pass a human
> + readable error message. Example: "STATUS=Completed
> + 66% of file system check..."
> +
> + ERRNO=... If a daemon fails, the errno-style error code,
> + formatted as string. Example: "ERRNO=2" for ENOENT.
> +
> + BUSERROR=... If a daemon fails, the D-Bus error-style error
> + code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
> +
> + MAINPID=... The main pid of a daemon, in case systemd did not
> + fork off the process itself. Example: "MAINPID=4711"
> +
> + Daemons can choose to send additional variables. However, it is
> + recommened to prefix variable names not listed above with X_.
> +
> + Returns a negative errno-style error code on failure. Returns> 0
> + if systemd could be notified, 0 if it couldn't possibly because
> + systemd is not running.
> +
> + Example: When a daemon finished starting up, it could issue this
> + call to notify systemd about it:
> +
> + sd_notify(0, "READY=1");
> +
> + See sd_notifyf() for more complete examples.
> +
> + See sd_notify(3) for more information.
> +*/
> +int sd_notify(int unset_environment, const char *state) _sd_hidden_;
> +
> +/*
> + Similar to sd_notify() but takes a format string.
> +
> + Example 1: A daemon could send the following after initialization:
> +
> + sd_notifyf(0, "READY=1\n"
> + "STATUS=Processing requests...\n"
> + "MAINPID=%lu",
> + (unsigned long) getpid());
> +
> + Example 2: A daemon could send the following shortly before
> + exiting, on failure:
> +
> + sd_notifyf(0, "STATUS=Failed to start up: %s\n"
> + "ERRNO=%i",
> + strerror(errno),
> + errno);
> +
> + See sd_notifyf(3) for more information.
> +*/
> +int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3) _sd_hidden_;
> +
> +/*
> + Returns> 0 if the system was booted with systemd. Returns< 0 on
> + error. Returns 0 if the system was not booted with systemd. Note
> + that all of the functions above handle non-systemd boots just
> + fine. You should NOT protect them with a call to this function. Also
> + note that this function checks whether the system, not the user
> + session is controlled by systemd. However the functions above work
> + for both session and system services.
> +
> + See sd_booted(3) for more information.
> +*/
> +int sd_booted(void) _sd_hidden_;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
next prev parent reply other threads:[~2010-07-21 17:57 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-19 2:19 [PATCH] rpcbind: add support for systemd socket activation Lennart Poettering
2010-07-21 17:56 ` Chuck Lever [this message]
2010-07-21 21:56 ` Lennart Poettering
2010-07-23 15:13 ` Chuck Lever
2010-07-23 16:27 ` Lennart Poettering
-- strict thread matches above, loose matches on Subject: below --
2011-12-19 23:42 [PATCH v2] " Cristian Rodriguez
2011-12-23 1:05 ` [PATCH] " Tom Gundersen
2011-12-23 1:34 ` Cristian Rodríguez
2011-12-23 2:40 ` Jim Rees
2012-02-01 11:47 ` Tom Gundersen
2012-02-01 15:32 ` Chuck Lever
2012-02-01 16:37 ` Tom Gundersen
2012-02-01 18:16 ` Chuck Lever
2012-02-01 19:48 ` Tom Gundersen
2012-02-01 21:45 ` Lennart Poettering
2012-02-01 22:03 ` Chuck Lever
2012-02-01 22:30 ` Lennart Poettering
2012-02-03 17:03 ` Chuck Lever
2012-02-01 19:59 ` Chuck Lever
2014-11-21 16:43 [PATCH] rpcbind: " Steve Dickson
2014-11-21 16:43 ` [PATCH] rpcbind: add support for " Steve Dickson
2014-11-25 17:05 [PATCH] rpcbind: systemd socket activation (v2) Steve Dickson
2014-11-25 17:05 ` [PATCH] rpcbind: add support for systemd socket activation Steve Dickson
2014-11-26 12:48 ` Steve Dickson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C4734DC.9010106@oracle.com \
--to=chuck.lever@oracle.com \
--cc=lennart@poettering.net \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).