Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 280643 Details for
Bug 376021
[patch] net-print/cups should provide systemd support
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
cups-1.4.6-systemd.patch
cups-1.4.6-systemd.patch (text/plain), 35.02 KB, created by
Alec Moskvin
on 2011-07-22 17:18:22 UTC
(
hide
)
Description:
cups-1.4.6-systemd.patch
Filename:
MIME Type:
Creator:
Alec Moskvin
Created:
2011-07-22 17:18:22 UTC
Size:
35.02 KB
patch
obsolete
>From 1db0a48375836c7e93ac30649007c2391be8b3b2 Mon Sep 17 00:00:00 2001 >From: Lennart Poettering <lennart@poettering.net> >Date: Mon, 4 Jul 2011 01:37:01 +0200 >Subject: [PATCH] systemd: add systemd socket activation and unit files > >On newer Linux machines systemd supports launchd-style socket >activation. This patch adds support for this mechanism and also adds >systemd unit files as appropriate to hook this up with systemd. > >This includes an MIT-licensed drop-in file that implements the most >basic interfaces needed to get the file descriptors from systemd. Most >of the systemd and Linux-specific code compiles to NOPs on other >systems. > >Three triggers to start CUPS are defined: a) if new printer hardware is >plugged in, b) when a client accesses the CUPS socket and c) when a >spool file resides in /var/spool/cups. >--- > Makedefs.in | 2 + > config-scripts/cups-systemd.m4 | 25 ++ > configure.in | 4 + > data/Makefile | 9 + > data/cups.path.in | 8 + > data/cups.service.in | 9 + > data/cups.socket.in | 9 + > scheduler/Makefile | 9 + > scheduler/main.c | 107 ++++++++ > scheduler/sd-daemon.c | 520 ++++++++++++++++++++++++++++++++++++++++ > scheduler/sd-daemon.h | 277 +++++++++++++++++++++ > 11 files changed, 979 insertions(+), 0 deletions(-) > create mode 100644 config-scripts/cups-systemd.m4 > create mode 100644 data/cups.path.in > create mode 100644 data/cups.service.in > create mode 100644 data/cups.socket.in > create mode 100644 scheduler/sd-daemon.c > create mode 100644 scheduler/sd-daemon.h > >diff --git a/Makedefs.in b/Makedefs.in >index 654eea4..02c43b6 100644 >--- a/Makedefs.in >+++ b/Makedefs.in >@@ -143,6 +143,7 @@ CXXFLAGS = @CPPFLAGS@ @CXXFLAGS@ > CXXLIBS = @CXXLIBS@ > DBUS_NOTIFIER = @DBUS_NOTIFIER@ > DBUS_NOTIFIERLIBS = @DBUS_NOTIFIERLIBS@ >+SYSTEMD_UNITS = @SYSTEMD_UNITS@ > DNSSD_BACKEND = @DNSSD_BACKEND@ > DSOFLAGS = -L../cups @DSOFLAGS@ > DSOLIBS = @DSOLIBS@ $(COMMONLIBS) >@@ -267,6 +268,7 @@ PAMFILE = @PAMFILE@ > > DEFAULT_LAUNCHD_CONF = @DEFAULT_LAUNCHD_CONF@ > DBUSDIR = @DBUSDIR@ >+SYSTEMDUNITDIR = $(BUILDROOT)@systemdsystemunitdir@ > > > # >diff --git a/config-scripts/cups-systemd.m4 b/config-scripts/cups-systemd.m4 >new file mode 100644 >index 0000000..fead8a9 >--- /dev/null >+++ b/config-scripts/cups-systemd.m4 >@@ -0,0 +1,25 @@ >+dnl >+dnl "$Id$" >+dnl >+dnl systemd stuff for CUPS. >+ >+dnl Find whether systemd is available >+ >+AC_ARG_WITH([systemdsystemunitdir], >+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), >+ [], [with_systemdsystemunitdir=$($PKGCONFIG --variable=systemdsystemunitdir systemd)]) >+if test "x$with_systemdsystemunitdir" != xno; then >+ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) >+fi >+ >+if test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ; then >+ SYSTEMD_UNITS="cups.service cups.socket cups.path" >+else >+ SYSTEMD_UNITS="" >+fi >+ >+AC_SUBST(SYSTEMD_UNITS) >+ >+dnl >+dnl "$Id$" >+dnl >diff --git a/configure.in b/configure.in >index 560f4f8..b0c19a9 100644 >--- a/configure.in >+++ b/configure.in >@@ -37,6 +37,7 @@ sinclude(config-scripts/cups-pam.m4) > sinclude(config-scripts/cups-largefile.m4) > sinclude(config-scripts/cups-dnssd.m4) > sinclude(config-scripts/cups-launchd.m4) >+sinclude(config-scripts/cups-systemd.m4) > sinclude(config-scripts/cups-defaults.m4) > sinclude(config-scripts/cups-pdf.m4) > sinclude(config-scripts/cups-scripting.m4) >@@ -71,6 +72,9 @@ AC_OUTPUT(Makedefs > conf/snmp.conf > cups-config > data/testprint >+ data/cups.service >+ data/cups.socket >+ data/cups.path > desktop/cups.desktop > doc/help/ref-cupsd-conf.html > doc/help/standard.html >diff --git a/data/Makefile b/data/Makefile >index b9de21a..cccab85 100644 >--- a/data/Makefile >+++ b/data/Makefile >@@ -112,6 +112,12 @@ install-data: > $(INSTALL_DATA) $$file $(DATADIR)/ppdc; \ > done > $(INSTALL_DIR) -m 755 $(DATADIR)/profiles >+ if test "x$(SYSTEMD_UNITS)" != "x" ; then \ >+ $(INSTALL_DIR) -m 755 $(SYSTEMDUNITDIR); \ >+ for file in $(SYSTEMD_UNITS); do \ >+ $(INSTALL_DATA) $$file $(SYSTEMDUNITDIR); \ >+ done; \ >+ fi > > > # >@@ -159,6 +165,9 @@ uninstall: > -$(RMDIR) $(DATADIR)/charsets > -$(RMDIR) $(DATADIR)/banners > -$(RMDIR) $(DATADIR) >+ for file in $(SYSTEMD_UNITS); do \ >+ $(RM) $(SYSTEMDUNITDIR)/$$file; \ >+ done > > > # >diff --git a/data/cups.path.in b/data/cups.path.in >new file mode 100644 >index 0000000..c99e39b >--- /dev/null >+++ b/data/cups.path.in >@@ -0,0 +1,8 @@ >+[Unit] >+Description=CUPS Printer Service Spool >+ >+[Path] >+DirectoryNotEmpty=@CUPS_REQUESTS@ >+ >+[Install] >+WantedBy=multi-user.target >diff --git a/data/cups.service.in b/data/cups.service.in >new file mode 100644 >index 0000000..007d0e6 >--- /dev/null >+++ b/data/cups.service.in >@@ -0,0 +1,9 @@ >+[Unit] >+Description=CUPS Printing Service >+ >+[Service] >+ExecStart=@sbindir@/cupsd -f >+ >+[Install] >+Also=cups.socket cups.path >+WantedBy=printer.target >diff --git a/data/cups.socket.in b/data/cups.socket.in >new file mode 100644 >index 0000000..b940096 >--- /dev/null >+++ b/data/cups.socket.in >@@ -0,0 +1,9 @@ >+[Unit] >+Description=CUPS Printing Service Sockets >+ >+[Socket] >+ListenStream=@CUPS_DEFAULT_DOMAINSOCKET@ >+ListenStream=631 >+ >+[Install] >+WantedBy=sockets.target >diff --git a/scheduler/Makefile b/scheduler/Makefile >index 3c7da8e..05152a6 100644 >--- a/scheduler/Makefile >+++ b/scheduler/Makefile >@@ -39,6 +39,7 @@ CUPSDOBJS = \ > server.o \ > statbuf.o \ > subscriptions.o \ >+ sd-daemon.o \ > sysman.o > LIBOBJS = \ > filter.o \ >@@ -568,6 +569,14 @@ sloc: > > > # >+# Update sd-daemon.[ch] drop-in file from upstream git >+# >+ >+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 >+ >+# > # Dependencies... > # > >diff --git a/scheduler/main.c b/scheduler/main.c >index baaa3a1..5a4b8e1 100644 >--- a/scheduler/main.c >+++ b/scheduler/main.c >@@ -26,6 +26,8 @@ > * launchd_checkin() - Check-in with launchd and collect the listening > * fds. > * launchd_checkout() - Update the launchd KeepAlive file as needed. >+ * systemd_checkin() - Check-in with systemd and collect the >+ * listening fds. > * parent_handler() - Catch USR1/CHLD signals... > * process_children() - Process all dead children... > * select_timeout() - Calculate the select timeout value. >@@ -62,6 +64,8 @@ > # endif /* !LAUNCH_JOBKEY_SERVICEIPC */ > #endif /* HAVE_LAUNCH_H */ > >+#include "sd-daemon.h" >+ > #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) > # include <malloc.h> > #endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ >@@ -78,6 +82,7 @@ > static void launchd_checkin(void); > static void launchd_checkout(void); > #endif /* HAVE_LAUNCHD */ >+static void systemd_checkin(void); > static void parent_handler(int sig); > static void process_children(void); > static void sigchld_handler(int sig); >@@ -520,6 +525,11 @@ main(int argc, /* I - Number of command-line args */ > #endif /* HAVE_LAUNCHD */ > > /* >+ * If we were started by systemd get the listen sockets file descriptors... >+ */ >+ systemd_checkin(); >+ >+ /* > * Startup the server... > */ > >@@ -731,6 +741,12 @@ main(int argc, /* I - Number of command-line args */ > #endif /* HAVE_LAUNCHD */ > > /* >+ * If we were started by systemd get the listen sockets file descriptors... >+ */ >+ >+ systemd_checkin(); >+ >+ /* > * Startup the server... > */ > >@@ -1535,6 +1551,97 @@ launchd_checkout(void) > } > #endif /* HAVE_LAUNCHD */ > >+static void >+systemd_checkin(void) >+{ >+ int n, fd; >+ >+ n = sd_listen_fds(1); >+ if (n < 0) >+ { >+ cupsdLogMessage(CUPSD_LOG_ERROR, >+ "systemd_checkin: Failed to acquire sockets from systemd - %s", >+ strerror(-n)); >+ exit(EXIT_FAILURE); >+ return; >+ } >+ >+ if (n == 0) >+ return; >+ >+ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) >+ { >+ http_addr_t addr; >+ socklen_t addrlen; >+ int r; >+ cupsd_listener_t *lis; >+ char s[256]; >+ >+ r = sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1); >+ if (r < 0) { >+ cupsdLogMessage(CUPSD_LOG_ERROR, >+ "systemd_checkin: Unable to verify socket type - %s", >+ strerror(-r)); >+ continue; >+ } >+ >+ if (!r) { >+ cupsdLogMessage(CUPSD_LOG_ERROR, >+ "systemd_checkin: Socket not of the right type"); >+ continue; >+ } >+ >+ if (getsockname(fd, (struct sockaddr*) &addr, &addrlen)) >+ { >+ cupsdLogMessage(CUPSD_LOG_ERROR, >+ "systemd_checkin: Unable to get local address - %s", >+ strerror(errno)); >+ continue; >+ } >+ >+ /* >+ * Try to match the systemd socket address to one of the listeners... >+ */ >+ >+ for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); >+ lis; >+ lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) >+ if (httpAddrEqual(&lis->address, &addr)) >+ break; >+ >+ if (lis) >+ { >+ cupsdLogMessage(CUPSD_LOG_DEBUG, >+ "systemd_checkin: Matched existing listener %s with fd %d...", >+ httpAddrString(&(lis->address), s, sizeof(s)), fd); >+ } >+ else >+ { >+ cupsdLogMessage(CUPSD_LOG_DEBUG, >+ "systemd_checkin: Adding new listener %s with fd %d...", >+ httpAddrString(&addr, s, sizeof(s)), fd); >+ >+ if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) >+ { >+ cupsdLogMessage(CUPSD_LOG_ERROR, >+ "systemd_checkin: Unable to allocate listener - " >+ "%s.", strerror(errno)); >+ exit(EXIT_FAILURE); >+ } >+ >+ cupsArrayAdd(Listeners, lis); >+ >+ memcpy(&lis->address, &addr, sizeof(lis->address)); >+ } >+ >+ lis->fd = fd; >+ >+# ifdef HAVE_SSL >+ if (_httpAddrPort(&(lis->address)) == 443) >+ lis->encryption = HTTP_ENCRYPT_ALWAYS; >+# endif /* HAVE_SSL */ >+ } >+} > > /* > * 'parent_handler()' - Catch USR1/CHLD signals... >diff --git a/scheduler/sd-daemon.c b/scheduler/sd-daemon.c >new file mode 100644 >index 0000000..a2ec74c >--- /dev/null >+++ b/scheduler/sd-daemon.c >@@ -0,0 +1,520 @@ >+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ >+ >+/*** >+ 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 <stddef.h> >+#include <limits.h> >+ >+#if defined(__linux__) >+#include <mqueue.h> >+#endif >+ >+#include "sd-daemon.h" >+ >+#if (__GNUC__ >= 4) && !defined(SD_EXPORT_SYMBOLS) >+#define _sd_hidden_ __attribute__ ((visibility("hidden"))) >+#else >+#define _sd_hidden_ >+#endif >+ >+_sd_hidden_ 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 >+} >+ >+_sd_hidden_ 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; >+} >+ >+_sd_hidden_ int sd_is_special(int fd, const char *path) { >+ struct stat st_fd; >+ >+ if (fd < 0) >+ return -EINVAL; >+ >+ if (fstat(fd, &st_fd) < 0) >+ return -errno; >+ >+ if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) >+ return 0; >+ >+ if (path) { >+ struct stat st_path; >+ >+ if (stat(path, &st_path) < 0) { >+ >+ if (errno == ENOENT || errno == ENOTDIR) >+ return 0; >+ >+ return -errno; >+ } >+ >+ if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) >+ return >+ st_path.st_dev == st_fd.st_dev && >+ st_path.st_ino == st_fd.st_ino; >+ else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) >+ return st_path.st_rdev == st_fd.st_rdev; >+ else >+ return 0; >+ } >+ >+ 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; >+}; >+ >+_sd_hidden_ 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; >+} >+ >+_sd_hidden_ 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; >+} >+ >+_sd_hidden_ 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 == offsetof(struct sockaddr_un, sun_path); >+ >+ if (path[0]) >+ /* Normal path socket */ >+ return >+ (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && >+ memcmp(path, sockaddr.un.sun_path, length+1) == 0; >+ else >+ /* Abstract namespace socket */ >+ return >+ (l == offsetof(struct sockaddr_un, sun_path) + length) && >+ memcmp(path, sockaddr.un.sun_path, length) == 0; >+ } >+ >+ return 1; >+} >+ >+_sd_hidden_ int sd_is_mq(int fd, const char *path) { >+#if !defined(__linux__) >+ return 0; >+#else >+ struct mq_attr attr; >+ >+ if (fd < 0) >+ return -EINVAL; >+ >+ if (mq_getattr(fd, &attr) < 0) >+ return -errno; >+ >+ if (path) { >+ char fpath[PATH_MAX]; >+ struct stat a, b; >+ >+ if (path[0] != '/') >+ return -EINVAL; >+ >+ if (fstat(fd, &a) < 0) >+ return -errno; >+ >+ strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); >+ fpath[sizeof(fpath)-1] = 0; >+ >+ if (stat(fpath, &b) < 0) >+ return -errno; >+ >+ if (a.st_dev != b.st_dev || >+ a.st_ino != b.st_ino) >+ return 0; >+ } >+ >+ return 1; >+#endif >+} >+ >+_sd_hidden_ int sd_notify(int unset_environment, const char *state) { >+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) >+ return 0; >+#else >+ int fd = -1, r; >+ struct msghdr msghdr; >+ struct iovec iovec; >+ union sockaddr_union sockaddr; >+ 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(&msghdr, 0, sizeof(msghdr)); >+ msghdr.msg_name = &sockaddr; >+ msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + 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; >+ >+ 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 >+} >+ >+_sd_hidden_ 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 >+} >+ >+_sd_hidden_ 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("/sys/fs/cgroup", &a) < 0) >+ return 0; >+ >+ if (lstat("/sys/fs/cgroup/systemd", &b) < 0) >+ return 0; >+ >+ return a.st_dev != b.st_dev; >+#endif >+} >diff --git a/scheduler/sd-daemon.h b/scheduler/sd-daemon.h >new file mode 100644 >index 0000000..46dc7fd >--- /dev/null >+++ b/scheduler/sd-daemon.h >@@ -0,0 +1,277 @@ >+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ >+ >+#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. >+*/ >+ >+#ifndef _sd_printf_attr_ >+#if __GNUC__ >= 4 >+#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) >+#else >+#define _sd_printf_attr_(a,b) >+#endif >+#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); >+ >+/* >+ 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); >+ >+/* >+ Helper call for identifying a passed file descriptor. Returns 1 if >+ the file descriptor is a special character device on 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 special character. >+ Returns a negative errno style error code on failure. >+ >+ See sd_is_special(3) for more information. >+*/ >+int sd_is_special(int fd, const char *path); >+ >+/* >+ 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); >+ >+/* >+ 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); >+ >+/* >+ 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); >+ >+/* >+ Helper call for identifying a passed file descriptor. Returns 1 if >+ the file descriptor is a POSIX Message Queue of the specified name, >+ 0 otherwise. If path is NULL a message queue name check is not >+ done. Returns a negative errno style error code on failure. >+*/ >+int sd_is_mq(int fd, const char *path); >+ >+/* >+ Informs systemd about changed daemon state. This takes a number of >+ newline separated 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 signaling 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 >+ recommended 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); >+ >+/* >+ 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); >+ >+/* >+ 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 user and system services. >+ >+ See sd_booted(3) for more information. >+*/ >+int sd_booted(void); >+ >+#ifdef __cplusplus >+} >+#endif >+ >+#endif >-- >1.7.6 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 376021
:
280643
|
280645
|
280647
|
300199