Description: systemd socket activation support. This variation of the patch is Gentoo's and features the runtime detection of systemd, to have cups continue to work without systemd enabled. It has been slightly amended (mostly whitespace fixes) to bring it as close as possible to Fedora's. . Original description: 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. Origin: http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/net-print/cups/files/cups-1.5.0-systemd-socket-2.patch?view=markup Origin: http://pkgs.fedoraproject.org/cgit/cups.git/tree/cups-systemd-socket.patch?id=7048cf473bca56b13d3c2f140fd749d561490784 From: Lennart Poettering Author: Lennart Poettering Last-Update: 2014-10-23 --- a/config.h.in +++ b/config.h.in @@ -451,6 +451,13 @@ /* + * Do we have systemd support? + */ + +#undef HAVE_SYSTEMD + + +/* * Various scripting languages... */ --- /dev/null +++ b/config-scripts/cups-systemd.m4 @@ -0,0 +1,36 @@ +dnl +dnl "$Id$" +dnl +dnl systemd stuff for CUPS. + +dnl Find whether systemd is available + +SDLIBS="" +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_MSG_CHECKING(for libsystemd-daemon) + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) + if $PKGCONFIG --exists libsystemd-daemon; then + AC_MSG_RESULT(yes) + SDCFLAGS=`$PKGCONFIG --cflags libsystemd-daemon` + SDLIBS=`$PKGCONFIG --libs libsystemd-daemon` + AC_DEFINE(HAVE_SYSTEMD) + else + AC_MSG_RESULT(no) + fi +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) +AC_SUBST(SDLIBS) + +dnl +dnl "$Id$" +dnl --- a/configure.in +++ b/configure.in @@ -33,6 +33,7 @@ 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-scripting.m4) @@ -67,6 +68,9 @@ conf/snmp.conf cups-config data/testprint + data/cups.service + data/cups.socket + data/cups.path desktop/cups.desktop doc/help/ref-cups-files-conf.html doc/help/ref-cupsd-conf.html --- a/cups/usersys.c +++ b/cups/usersys.c @@ -1028,7 +1028,7 @@ struct stat sockinfo; /* Domain socket information */ if (!stat(CUPS_DEFAULT_DOMAINSOCKET, &sockinfo) && - (sockinfo.st_mode & S_IRWXO) == S_IRWXO) + (sockinfo.st_mode & (S_IROTH | S_IWOTH)) == (S_IROTH | S_IWOTH)) cups_server = CUPS_DEFAULT_DOMAINSOCKET; else #endif /* CUPS_DEFAULT_DOMAINSOCKET */ --- /dev/null +++ b/data/cups.path.in @@ -0,0 +1,8 @@ +[Unit] +Description=CUPS Printer Service Spool + +[Path] +PathExistsGlob=@CUPS_REQUESTS@/d* + +[Install] +WantedBy=paths.target --- /dev/null +++ b/data/cups.service.in @@ -0,0 +1,12 @@ +[Unit] +Description=CUPS Printing Service +Documentation=man:cupsd(8) man:cupsd.conf(5) +Requires=cups.socket + +[Service] +ExecStart=@sbindir@/cupsd -f +PrivateTmp=true + +[Install] +Also=cups.socket cups.path +WantedBy=printer.target --- /dev/null +++ b/data/cups.socket.in @@ -0,0 +1,10 @@ +[Unit] +Description=CUPS Printing Service Sockets + +[Socket] +ListenStream=@CUPS_DEFAULT_DOMAINSOCKET@ +BindIPv6Only=ipv6-only +PassCredentials=true + +[Install] +WantedBy=sockets.target --- a/data/Makefile +++ b/data/Makefile @@ -100,6 +100,12 @@ $(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 # @@ -143,6 +149,9 @@ -$(RMDIR) $(DATADIR)/data -$(RMDIR) $(DATADIR)/banners -$(RMDIR) $(DATADIR) + for file in $(SYSTEMD_UNITS); do \ + $(RM) $(SYSTEMDUNITDIR)/$$file; \ + done # --- a/Makedefs.in +++ b/Makedefs.in @@ -134,6 +134,7 @@ 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) @@ -141,6 +142,7 @@ IPPFIND_BIN = @IPPFIND_BIN@ IPPFIND_MAN = @IPPFIND_MAN@ LAUNCHDLIBS = @LAUNCHDLIBS@ +SDLIBS = @SDLIBS@ LDFLAGS = -L../cgi-bin -L../cups -L../filter -L../ppdc \ -L../scheduler @LDARCHFLAGS@ \ @LDFLAGS@ @RELROFLAGS@ @PIEFLAGS@ $(OPTIM) @@ -232,6 +234,7 @@ DEFAULT_LAUNCHD_CONF = @DEFAULT_LAUNCHD_CONF@ DBUSDIR = @DBUSDIR@ +SYSTEMDUNITDIR = $(BUILDROOT)@systemdsystemunitdir@ # --- a/scheduler/client.h +++ b/scheduler/client.h @@ -79,6 +79,9 @@ int fd; /* File descriptor for this server */ http_addr_t address; /* Bind address of socket */ http_encryption_t encryption; /* To encrypt or not to encrypt... */ +#ifdef HAVE_SYSTEMD + int is_systemd; /* Is this a systemd socket? */ +#endif /* HAVE_SYSTEMD */ } cupsd_listener_t; --- a/scheduler/listen.c +++ b/scheduler/listen.c @@ -401,7 +401,11 @@ lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) { - if (lis->fd != -1) + if (lis->fd != -1 +#ifdef HAVE_SYSTEMD + && !lis->is_systemd +#endif /* HAVE_SYSTEMD */ + ) { #ifdef WIN32 closesocket(lis->fd); --- a/scheduler/main.c +++ b/scheduler/main.c @@ -39,6 +39,10 @@ # endif /* !LAUNCH_JOBKEY_SERVICEIPC */ #endif /* HAVE_LAUNCH_H */ +#ifdef HAVE_SYSTEMD +#include +#endif /* HAVE_SYSTEMD */ + #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) # include #endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ @@ -64,6 +68,9 @@ static void launchd_checkin(void); static void launchd_checkout(void); #endif /* HAVE_LAUNCHD */ +#ifdef HAVE_SYSTEMD +static int systemd_checkin(void); +#endif /* HAVE_SYSTEMD */ static void parent_handler(int sig); static void process_children(void); static void sigchld_handler(int sig); @@ -586,6 +593,14 @@ } #endif /* HAVE_LAUNCHD */ +#ifdef HAVE_SYSTEMD + /* + * If we were started by systemd get the listen sockets file descriptors... + */ + if (systemd_checkin() < 0) + exit(EXIT_FAILURE); +#endif /* HAVE_SYSTEMD */ + /* * Startup the server... */ @@ -774,6 +789,16 @@ } #endif /* HAVE_LAUNCHD */ +#ifdef HAVE_SYSTEMD + /* + * If we were started by systemd get the listen sockets file + * descriptors... + */ + + if (systemd_checkin() < 0) + exit(EXIT_FAILURE); +#endif /* HAVE_SYSTEMD */ + /* * Startup the server... */ @@ -1557,6 +1582,104 @@ } #endif /* HAVE_LAUNCHD */ +#ifdef HAVE_SYSTEMD +static int +systemd_checkin(void) +{ + int n, fd; + + n = sd_listen_fds(0); + if (n < 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "systemd_checkin: Failed to acquire sockets from systemd - %s" + " -- skipping systemd activation", + strerror(-n)); + return (1); + } + + if (n == 0) + return (0); + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) + { + http_addr_t addr; + socklen_t addrlen = sizeof (addr); + 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)); + return (-ENOMEM); + } + + cupsArrayAdd(Listeners, lis); + + memcpy(&lis->address, &addr, sizeof(lis->address)); + } + + lis->fd = fd; + lis->is_systemd = 1; + +# ifdef HAVE_SSL + if (_httpAddrPort(&(lis->address)) == 443) + lis->encryption = HTTP_ENCRYPT_ALWAYS; +# endif /* HAVE_SSL */ + } + + return (0); +} +#endif /* HAVE_SYSTEMD */ /* * 'parent_handler()' - Catch USR1/CHLD signals... --- a/scheduler/Makefile +++ b/scheduler/Makefile @@ -381,7 +381,7 @@ $(CC) $(LDFLAGS) -o cupsd $(CUPSDOBJS) -L. -lcupsmime \ $(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \ $(LIBPAPER) $(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBS) \ - $(LIBGSSAPI) $(LIBWRAP) + $(LIBGSSAPI) $(LIBWRAP) $(SDLIBS) cupsd-static: $(CUPSDOBJS) libcupsmime.a ../cups/$(LIBCUPSSTATIC) echo Linking $@... @@ -389,7 +389,7 @@ $(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \ ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(LIBZ) $(LIBPAPER) \ $(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBGSSAPI) \ - $(LIBWRAP) + $(LIBWRAP) $(SDLIBS) tls.o: tls-darwin.c tls-gnutls.c tls-openssl.c