diff options
author | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2014-03-21 16:42:53 +0000 |
---|---|---|
committer | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2014-03-21 16:42:53 +0000 |
commit | 1720786e61396c74c14b561e11b22c9c045898c6 (patch) | |
tree | f65d9faacf8650c3f395e60a141cc0b579d1e5ec | |
parent | f2b8078bd6129eb05e81a9bb07a2d7a295d5422e (diff) | |
download | cups-1720786e61396c74c14b561e11b22c9c045898c6.tar.gz |
Add systemd support to cupsd (STR #3282)
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11717 a1ca3aef-8c08-0410-bb20-df032aa958be
-rw-r--r-- | CHANGES.txt | 3 | ||||
-rw-r--r-- | config-scripts/cups-directories.m4 | 96 | ||||
-rw-r--r-- | config-scripts/cups-ondemand.m4 | 76 | ||||
-rw-r--r-- | config-scripts/cups-startup.m4 | 176 | ||||
-rw-r--r-- | config.h.in | 7 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | scheduler/Makefile | 40 | ||||
-rw-r--r-- | scheduler/client.c | 2 | ||||
-rw-r--r-- | scheduler/client.h | 5 | ||||
-rw-r--r-- | scheduler/conf.c | 11 | ||||
-rw-r--r-- | scheduler/conf.h | 6 | ||||
-rw-r--r-- | scheduler/cupsd.h | 8 | ||||
-rw-r--r-- | scheduler/listen.c | 21 | ||||
-rw-r--r-- | scheduler/main.c | 746 | ||||
-rw-r--r-- | scheduler/org.cups.cupsd.socket.in | 1 | ||||
-rw-r--r-- | xcode/CUPS.xcodeproj/project.pbxproj | 18 |
16 files changed, 668 insertions, 550 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 7d9cdeeca..98730973d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -CHANGES.txt - 2.0b1 - 2014-03-04 +CHANGES.txt - 2.0b1 - 2014-03-21 -------------------------------- CHANGES IN CUPS V2.0b1 @@ -11,6 +11,7 @@ CHANGES IN CUPS V2.0b1 - Dropped support for AIX, HP-UX, and OSF/1 (aka Digital UNIX) - Adopted Linux man page conventions and updated all man pages (STR #4372) + - Added systemd support (STR #3282) - Added support for re-sending a job as a raster file if a higher-level format such as PDF fails (<rdar://problem/15583721>) - Added support for regular expression matching in the MIME type rules diff --git a/config-scripts/cups-directories.m4 b/config-scripts/cups-directories.m4 index f4227506f..40a17038a 100644 --- a/config-scripts/cups-directories.m4 +++ b/config-scripts/cups-directories.m4 @@ -121,102 +121,6 @@ fi AC_SUBST(privateinclude) AC_SUBST(PRIVATEINCLUDE) -dnl Setup init.d locations... -AC_ARG_WITH(rcdir, [ --with-rcdir set path for rc scripts],rcdir="$withval",rcdir="") -AC_ARG_WITH(rclevels, [ --with-rclevels set run levels for rc scripts],rclevels="$withval",rclevels="2 3 5") -AC_ARG_WITH(rcstart, [ --with-rcstart set start number for rc scripts],rcstart="$withval",rcstart="99") -AC_ARG_WITH(rcstop, [ --with-rcstop set stop number for rc scripts],rcstop="$withval",rcstop="00") -AC_ARG_WITH(smfmanifestdir, [ --with-smfmanifestdir set path for Solaris SMF manifest],smfmanifestdir="$withval",smfmanifestdir="") - -INITDIR="" -INITDDIR="" -RCLEVELS="$rclevels" -RCSTART="$rcstart" -RCSTOP="$rcstop" -SMFMANIFESTDIR="" - -if test x$rcdir = x; then - case "$uname" in - Darwin*) - # Darwin and MacOS X... - if test ! -x /sbin/launchd; then - INITDDIR="/System/Library/StartupItems/PrintingServices" - fi - ;; - - FreeBSD* | OpenBSD* | MirBSD* | ekkoBSD*) - # FreeBSD and OpenBSD - ;; - - Linux | GNU | GNU/k*BSD*) - # Linux/HURD seems to choose an init.d directory at random... - if test -d /sbin/init.d; then - # SuSE - INITDIR="/sbin/init.d" - else - if test -d /etc/init.d; then - # Others - INITDIR="/etc" - else - # RedHat - INITDIR="/etc/rc.d" - fi - fi - RCSTART="81" - RCSTOP="36" - ;; - - NetBSD*) - # NetBSD - INITDDIR="/etc/rc.d" - ;; - - SunOS*) - # Solaris - if test "x$smfmanifestdir" != x; then - SMFMANIFESTDIR=$smfmanifestdir - else - INITDIR="/etc" - RCSTART="81" - fi - ;; - - *) - INITDIR="/etc" - ;; - - esac -elif test "x$rcdir" != xno; then - if test "x$rclevels" = x; then - INITDDIR="$rcdir" - else - INITDIR="$rcdir" - fi -fi - -AC_SUBST(INITDIR) -AC_SUBST(INITDDIR) -AC_SUBST(RCLEVELS) -AC_SUBST(RCSTART) -AC_SUBST(RCSTOP) -AC_SUBST(SMFMANIFESTDIR) - -dnl Xinetd support... -AC_ARG_WITH(xinetd, [ --with-xinetd set path for xinetd config files],XINETD="$withval",XINETD="") - -if test "x$XINETD" = x -a ! -x /sbin/launchd; then - for dir in /private/etc/xinetd.d /etc/xinetd.d /usr/local/etc/xinetd.d; do - if test -d $dir; then - XINETD="$dir" - break - fi - done -elif test "x$XINETD" = xno; then - XINETD="" -fi - -AC_SUBST(XINETD) - dnl LPD sharing support... AC_ARG_WITH(lpdconfig, [ --with-lpdconfig set URI for LPD config file], LPDCONFIG="$withval", LPDCONFIG="") diff --git a/config-scripts/cups-ondemand.m4 b/config-scripts/cups-ondemand.m4 deleted file mode 100644 index b1ea1a3ff..000000000 --- a/config-scripts/cups-ondemand.m4 +++ /dev/null @@ -1,76 +0,0 @@ -dnl -dnl "$Id$" -dnl -dnl Launch-on-demand stuff for CUPS. -dnl -dnl Copyright 2007-2014 by Apple Inc. -dnl Copyright 1997-2005 by Easy Software Products, all rights reserved. -dnl -dnl These coded instructions, statements, and computer programs are the -dnl property of Apple Inc. and are protected by Federal copyright -dnl law. Distribution and use rights are outlined in the file "LICENSE.txt" -dnl which should have been included with this file. If this file is -dnl file is missing or damaged, see the license at "http://www.cups.org/". -dnl - -ONDEMANDFLAGS="" -ONDEMANDLIBS="" -AC_SUBST(ONDEMANDFLAGS) -AC_SUBST(ONDEMANDLIBS) - -dnl Launchd is used on OS X/Darwin... -AC_ARG_ENABLE(launchd, [ --disable-launchd disable launchd support]) -LAUNCHD_DIR="" -AC_SUBST(LAUNCHD_DIR) - -if test x$enable_launchd != xno; then - AC_CHECK_FUNC(launch_msg, AC_DEFINE(HAVE_LAUNCHD)) - if test $uversion -ge 140; then - AC_CHECK_FUNC(launch_activate_socket, [ - AC_DEFINE(HAVE_LAUNCHD) - AC_DEFINE(HAVE_LAUNCH_ACTIVATE_SOCKET)]) - fi - AC_CHECK_HEADER(launch.h, AC_DEFINE(HAVE_LAUNCH_H)) - - case "$uname" in - Darwin*) - # Darwin, MacOS X - LAUNCHD_DIR="/System/Library/LaunchDaemons/org.cups.cupsd.plist" - # liblaunch is already part of libSystem - ;; - *) - # All others; this test will need to be updated - ;; - esac -fi - -dnl Systemd is used on Linux... -AC_ARG_ENABLE(systemd, [ --disable-systemd disable systemd support]) -AC_ARG_WITH(systemd, [ --with-systemd set directory for systemd service files], - SYSTEMD_DIR="$withval", SYSTEMD_DIR="") -AC_SUBST(SYSTEMD_DIR) - -if test x$enable_systemd != xno; then - if test "x$PKGCONFIG" = x; then - if test x$enable_systemd = xyes; then - AC_MSG_ERROR(Need pkg-config to enable systemd support.) - fi - else - AC_MSG_CHECKING(for libsystemd-daemon) - if $PKGCONFIG --exists libsystemd-daemon; then - AC_MSG_RESULT(yes) - ONDEMANDFLAGS=`$PKGCONFIG --cflags libsystemd-daemon` - ONDEMANDLIBS=`$PKGCONFIG --libs libsystemd-daemon` - AC_DEFINE(HAVE_SYSTEMD) - if test "x$SYSTEMD_DIR" = x; then - SYSTEMD_DIR="`$PKGCONFIG --variable=systemdsystemunitdir systemd`" - fi - else - AC_MSG_RESULT(no) - fi - fi -fi - -dnl -dnl End of "$Id$". -dnl diff --git a/config-scripts/cups-startup.m4 b/config-scripts/cups-startup.m4 new file mode 100644 index 000000000..dcb13d2dd --- /dev/null +++ b/config-scripts/cups-startup.m4 @@ -0,0 +1,176 @@ +dnl +dnl "$Id$" +dnl +dnl Launch-on-demand/startup stuff for CUPS. +dnl +dnl Copyright 2007-2014 by Apple Inc. +dnl Copyright 1997-2005 by Easy Software Products, all rights reserved. +dnl +dnl These coded instructions, statements, and computer programs are the +dnl property of Apple Inc. and are protected by Federal copyright +dnl law. Distribution and use rights are outlined in the file "LICENSE.txt" +dnl which should have been included with this file. If this file is +dnl file is missing or damaged, see the license at "http://www.cups.org/". +dnl + +ONDEMANDFLAGS="" +ONDEMANDLIBS="" +AC_SUBST(ONDEMANDFLAGS) +AC_SUBST(ONDEMANDLIBS) + +dnl Launchd is used on OS X/Darwin... +AC_ARG_ENABLE(launchd, [ --disable-launchd disable launchd support]) +LAUNCHD_DIR="" +AC_SUBST(LAUNCHD_DIR) + +if test x$enable_launchd != xno; then + AC_CHECK_FUNC(launch_msg, AC_DEFINE(HAVE_LAUNCHD)) + if test $uversion -ge 140; then + AC_CHECK_FUNC(launch_activate_socket, [ + AC_DEFINE(HAVE_LAUNCHD) + AC_DEFINE(HAVE_LAUNCH_ACTIVATE_SOCKET)]) + fi + AC_CHECK_HEADER(launch.h, AC_DEFINE(HAVE_LAUNCH_H)) + + case "$uname" in + Darwin*) + # Darwin, MacOS X + LAUNCHD_DIR="/System/Library/LaunchDaemons/org.cups.cupsd.plist" + # liblaunch is already part of libSystem + ;; + *) + # All others; this test will need to be updated + ;; + esac +fi + +dnl Systemd is used on Linux... +AC_ARG_ENABLE(systemd, [ --disable-systemd disable systemd support]) +AC_ARG_WITH(systemd, [ --with-systemd set directory for systemd service files], + SYSTEMD_DIR="$withval", SYSTEMD_DIR="") +AC_SUBST(SYSTEMD_DIR) + +if test x$enable_systemd != xno; then + if test "x$PKGCONFIG" = x; then + if test x$enable_systemd = xyes; then + AC_MSG_ERROR(Need pkg-config to enable systemd support.) + fi + else + AC_MSG_CHECKING(for libsystemd-daemon) + if $PKGCONFIG --exists libsystemd-daemon; then + AC_MSG_RESULT(yes) + ONDEMANDFLAGS=`$PKGCONFIG --cflags libsystemd-daemon` + ONDEMANDLIBS=`$PKGCONFIG --libs libsystemd-daemon` + AC_DEFINE(HAVE_SYSTEMD) + if test "x$SYSTEMD_DIR" = x; then + SYSTEMD_DIR="`$PKGCONFIG --variable=systemdsystemunitdir systemd`" + fi + else + AC_MSG_RESULT(no) + fi + fi +fi + +dnl Solaris uses smf +SMFMANIFESTDIR="" +AC_SUBST(SMFMANIFESTDIR) +AC_ARG_WITH(smfmanifestdir, [ --with-smfmanifestdir set path for Solaris SMF manifest],SMFMANIFESTDIR="$withval") + +dnl Use init on other platforms... +AC_ARG_WITH(rcdir, [ --with-rcdir set path for rc scripts],rcdir="$withval",rcdir="") +AC_ARG_WITH(rclevels, [ --with-rclevels set run levels for rc scripts],rclevels="$withval",rclevels="2 3 5") +AC_ARG_WITH(rcstart, [ --with-rcstart set start number for rc scripts],rcstart="$withval",rcstart="") +AC_ARG_WITH(rcstop, [ --with-rcstop set stop number for rc scripts],rcstop="$withval",rcstop="") + +if test x$rcdir = x; then + if test x$LAUNCHD_DIR = x -a x$SYSTEMD_DIR = x -a x$SMFMANIFESTDIR = x; then + # Fall back on "init", the original service startup interface... + if test -d /sbin/init.d; then + # SuSE + rcdir="/sbin/init.d" + elif test -d /etc/init.d; then + # Others + rcdir="/etc" + else + # RedHat, NetBSD + rcdir="/etc/rc.d" + fi + else + rcdir="no" + fi +fi + +if test "x$rcstart" = x; then + case "$uname" in + Linux | GNU | GNU/k*BSD*) + # Linux + rcstart="81" + ;; + + SunOS*) + # Solaris + rcstart="81" + ;; + + *) + # Others + rcstart="99" + ;; + esac +fi + +if test "x$rcstop" = x; then + case "$uname" in + Linux | GNU | GNU/k*BSD*) + # Linux + rcstop="36" + ;; + + *) + # Others + rcstop="00" + ;; + esac +fi + +INITDIR="" +INITDDIR="" +RCLEVELS="$rclevels" +RCSTART="$rcstart" +RCSTOP="$rcstop" +AC_SUBST(INITDIR) +AC_SUBST(INITDDIR) +AC_SUBST(RCLEVELS) +AC_SUBST(RCSTART) +AC_SUBST(RCSTOP) + +if test "x$rcdir" != xno; then + if test "x$rclevels" = x; then + INITDDIR="$rcdir" + else + INITDIR="$rcdir" + fi +fi + +dnl Xinetd support... +AC_ARG_WITH(xinetd, [ --with-xinetd set path for xinetd config files],xinetd="$withval",xinetd="") +XINETD="" +AC_SUBST(XINETD) + +if test "x$xinetd" = x; then + if test ! -x /sbin/launchd; then + for dir in /etc/xinetd.d /usr/local/etc/xinetd.d; do + if test -d $dir; then + XINETD="$dir" + break + fi + done + fi +elif test "x$xinet" != xno; then + XINETD="$xinetd" +fi + + +dnl +dnl End of "$Id$". +dnl diff --git a/config.h.in b/config.h.in index 1b2df157e..f673a395b 100644 --- a/config.h.in +++ b/config.h.in @@ -458,6 +458,13 @@ /* + * Do we have systemd support? + */ + +#undef HAVE_SYSTEMD + + +/* * Various scripting languages... */ diff --git a/configure.ac b/configure.ac index cf97de7ff..5ee8e8ba7 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ sinclude(config-scripts/cups-ssl.m4) sinclude(config-scripts/cups-pam.m4) sinclude(config-scripts/cups-largefile.m4) sinclude(config-scripts/cups-dnssd.m4) -sinclude(config-scripts/cups-ondemand.m4) +sinclude(config-scripts/cups-startup.m4) sinclude(config-scripts/cups-defaults.m4) sinclude(config-scripts/cups-scripting.m4) diff --git a/scheduler/Makefile b/scheduler/Makefile index 4d8393d63..9fb318a84 100644 --- a/scheduler/Makefile +++ b/scheduler/Makefile @@ -289,7 +289,6 @@ uninstall: $(RM) $(SERVERBIN)/daemon/cups-driverd $(RM) $(SERVERBIN)/daemon/cups-exec $(RM) $(SERVERBIN)/daemon/cups-lpd - $(RM) $(BUILDROOT)/System/Library/Printers/Libraries/convert -$(RMDIR) $(STATEDIR)/certs -$(RMDIR) $(STATEDIR) -$(RMDIR) $(SERVERROOT)/ppd @@ -311,8 +310,8 @@ uninstall: -$(RMDIR) $(LIBDIR) $(RM) $(INCLUDEDIR)/cups/mime.h -$(RMDIR) $(INCLUDEDIR)/cups - echo Uninstalling startup script... if test "x$(INITDIR)" != x; then \ + echo Uninstalling init scripts...; \ $(RM) $(BUILDROOT)$(INITDIR)/init.d/cups; \ $(RMDIR) $(BUILDROOT)$(INITDIR)/init.d; \ $(RM) $(BUILDROOT)$(INITDIR)/rc0.d/K00cups; \ @@ -324,23 +323,24 @@ uninstall: $(RM) $(BUILDROOT)$(INITDIR)/rc5.d/S99cups; \ $(RMDIR) $(BUILDROOT)$(INITDIR)/rc5.d; \ fi - if test "x$(INITDIR)" = x -a "x$(INITDDIR)" != x; then \ - if test "$(INITDDIR)" = "/System/Library/StartupItems/PrintingServices"; then \ - $(RM) $(BUILDROOT)$(INITDDIR)/PrintingServices; \ - $(RM) $(BUILDROOT)$(INITDDIR)/StartupParameters.plist; \ - $(RM) $(BUILDROOT)$(INITDDIR)/Resources/English.lproj/Localizable.strings; \ - $(RMDIR) $(BUILDROOT)$(INITDDIR)/Resources/English.lproj; \ - elif test "$(INITDDIR)" = "/System/Library/LaunchDaemons"; then \ - $(RM) $(BUILDROOT)$(INITDDIR)/org.cups.cupsd.plist; \ - $(RM) $(BUILDROOT)$(INITDDIR)/org.cups.cups-lpd.plist; \ - $(RMDIR) $(BUILDROOT)/System/Library/StartupItems/PrintingServices; \ - else \ - $(INSTALL_SCRIPT) init/cups.sh $(BUILDROOT)$(INITDDIR)/cups; \ - fi \ + if test "x$(INITDDIR)" != x; then \ + echo Uninstalling startup script...; \ + $(RM) $(BUILDROOT)$(INITDDIR)/cups.sh; \ $(RMDIR) $(BUILDROOT)$(INITDDIR); \ fi + if test "x$LAUNCHD_DIR" != x; then \ + echo Uninstalling launchd files...; \ + $(RM) $(BUILDROOT)$(LAUNCHD_DIR)/org.cups.cupsd.plist; \ + $(RM) $(BUILDROOT)$(LAUNCHD_DIR)/org.cups.cups-lpd.plist; \ + fi + if test "x$SYSTEMD_DIR" != x; then \ + echo Uninstalling systemd files...; \ + $(RM) $(BUILDROOT)$(SYSTEMD_DIR)/org.cups.cupsd.path; \ + $(RM) $(BUILDROOT)$(SYSTEMD_DIR)/org.cups.cupsd.service; \ + $(RM) $(BUILDROOT)$(SYSTEMD_DIR)/org.cups.cupsd.socket; \ + fi if test "x$(SMFMANIFESTDIR)" != x; then \ - echo Uninstalling SMF manifest in $(SMFMANIFESTDIR)...;\ + echo Uninstalling SMF manifest file...;\ $(RM) $(BUILDROOT)$(SMFMANIFESTDIR)/cups.xml; \ fi if test "x$(XINETD)" != x; then \ @@ -379,16 +379,16 @@ cupsd: $(CUPSDOBJS) $(LIBCUPSMIME) ../cups/$(LIBCUPS) echo Linking $@... $(CC) $(LDFLAGS) -o cupsd $(CUPSDOBJS) -L. -lcupsmime \ $(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \ - $(LIBPAPER) $(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBS) \ - $(LIBGSSAPI) $(LIBWRAP) + $(LIBPAPER) $(LIBMALLOC) $(SERVERLIBS) $(ONDEMANDLIBS) \ + $(DNSSDLIBS) $(LIBS) $(LIBGSSAPI) $(LIBWRAP) cupsd-static: $(CUPSDOBJS) libcupsmime.a ../cups/$(LIBCUPSSTATIC) echo Linking $@... $(CC) $(LDFLAGS) -o cupsd-static $(CUPSDOBJS) libcupsmime.a \ $(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \ ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(LIBZ) $(LIBPAPER) \ - $(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBGSSAPI) \ - $(LIBWRAP) + $(LIBMALLOC) $(SERVERLIBS) $(ONDEMANDLIBS) $(DNSSDLIBS) \ + $(LIBGSSAPI) $(LIBWRAP) # diff --git a/scheduler/client.c b/scheduler/client.c index b7a3c798d..b6a93082e 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -2516,7 +2516,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ bytes = (ssize_t)(sizeof(con->header) - (size_t)con->header_used); - if (!con->pipe_pid && bytes > httpGetRemaining(con->http)) + if (!con->pipe_pid && bytes > (ssize_t)httpGetRemaining(con->http)) { /* * Limit GET bytes to original size of file (STR #3265)... diff --git a/scheduler/client.h b/scheduler/client.h index 6217eac9c..afe8d3ac3 100644 --- a/scheduler/client.h +++ b/scheduler/client.h @@ -3,7 +3,7 @@ * * Client definitions for the CUPS scheduler. * - * Copyright 2007-2013 by Apple Inc. + * Copyright 2007-2014 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -81,6 +81,9 @@ typedef struct 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... */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + int on_demand; /* Is this a socket from launchd/systemd? */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ } cupsd_listener_t; diff --git a/scheduler/conf.c b/scheduler/conf.c index 1e82b2295..97eedc768 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -85,13 +85,16 @@ static const cupsd_var_t cupsd_vars[] = #ifdef HAVE_GSSAPI { "GSSServiceName", &GSSServiceName, CUPSD_VARTYPE_STRING }, #endif /* HAVE_GSSAPI */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + { "IdleExitTimeout", &IdleExitTimeout, CUPSD_VARTYPE_TIME }, +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ { "JobKillDelay", &JobKillDelay, CUPSD_VARTYPE_TIME }, { "JobRetryLimit", &JobRetryLimit, CUPSD_VARTYPE_INTEGER }, { "JobRetryInterval", &JobRetryInterval, CUPSD_VARTYPE_TIME }, { "KeepAliveTimeout", &KeepAliveTimeout, CUPSD_VARTYPE_TIME }, { "KeepAlive", &KeepAlive, CUPSD_VARTYPE_BOOLEAN }, #ifdef HAVE_LAUNCHD - { "LaunchdTimeout", &LaunchdTimeout, CUPSD_VARTYPE_TIME }, + { "LaunchdTimeout", &IdleExitTimeout, CUPSD_VARTYPE_TIME }, #endif /* HAVE_LAUNCHD */ { "LimitRequestBody", &MaxRequestSize, CUPSD_VARTYPE_INTEGER }, { "ListenBackLog", &ListenBackLog, CUPSD_VARTYPE_INTEGER }, @@ -752,9 +755,9 @@ cupsdReadConfiguration(void) DefaultLeaseDuration = 86400; MaxLeaseDuration = 0; -#ifdef HAVE_LAUNCHD - LaunchdTimeout = 60; -#endif /* HAVE_LAUNCHD */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + IdleExitTimeout = 60; +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Setup environment variables... diff --git a/scheduler/conf.h b/scheduler/conf.h index 6b43d66c5..3cc8acb5e 100644 --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -243,10 +243,10 @@ VAR char *ServerKeychain VALUE(NULL); /* Keychain holding cert + key */ #endif /* HAVE_SSL */ -#ifdef HAVE_LAUNCHD -VAR int LaunchdTimeout VALUE(60); +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) +VAR int IdleExitTimeout VALUE(60); /* Time after which an idle cupsd will exit */ -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ #ifdef HAVE_AUTHORIZATION_H VAR char *SystemGroupAuthKey VALUE(NULL); diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h index d0f8fb5c4..3885305a7 100644 --- a/scheduler/cupsd.h +++ b/scheduler/cupsd.h @@ -158,10 +158,10 @@ VAR int NeedReload VALUE(RELOAD_ALL), VAR void *DefaultProfile VALUE(0); /* Default security profile */ -#ifdef HAVE_LAUNCH_H -VAR int Launchd VALUE(0); - /* Running from launchd */ -#endif /* HAVE_LAUNCH_H */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) +VAR int OnDemand VALUE(0); + /* Launched on demand */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* diff --git a/scheduler/listen.c b/scheduler/listen.c index 7ef4a3c92..6fe34c90e 100644 --- a/scheduler/listen.c +++ b/scheduler/listen.c @@ -3,7 +3,7 @@ * * Server listening routines for the CUPS scheduler. * - * Copyright 2007-2013 by Apple Inc. + * Copyright 2007-2014 by Apple Inc. * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -274,16 +274,25 @@ cupsdStopListening(void) lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) { +#ifdef HAVE_SYSTEMD + if (lis->fd != -1 && !lis->on_demand) + httpAddrClose(&(lis->address), lis->fd); + +#elif defined(HAVE_LAUNCHD) if (lis->fd != -1) { -#ifdef HAVE_LAUNCH_H - httpAddrClose(NULL, lis->fd); + if (lis->on_demand) + httpAddrClose(NULL, lis->fd); + else + httpAddrClose(&(lis->address), lis->fd); + } + #else + if (lis->fd != -1) httpAddrClose(&(lis->address), lis->fd); -#endif /* HAVE_LAUNCH */ +#endif /* HAVE_SYSTEMD */ - lis->fd = -1; - } + lis->fd = -1; } } diff --git a/scheduler/main.c b/scheduler/main.c index f847e275c..555b6d6d8 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -34,6 +34,11 @@ extern int launch_activate_socket(const char *name, int **fds, size_t *cnt); # endif /* HAVE_LAUNCH_ACTIVATE_SOCKET */ #endif /* HAVE_LAUNCH_H */ +#ifdef HAVE_SYSTEMD +# define CUPS_KEEPALIVE CUPS_CACHEDIR "/org.cups.cupsd" + /* Name of the systemd path file */ +#endif /* HAVE_SYSTEMD */ + #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) # include <malloc.h> #endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ @@ -51,16 +56,16 @@ extern int launch_activate_socket(const char *name, int **fds, size_t *cnt); * Local functions... */ -#ifdef HAVE_LAUNCHD -static void launchd_checkin(void); -static void launchd_checkout(void); -#endif /* HAVE_LAUNCHD */ static void parent_handler(int sig); static void process_children(void); static void sigchld_handler(int sig); static void sighup_handler(int sig); static void sigterm_handler(int sig); static long select_timeout(int fds); +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) +static void service_checkin(void); +static void service_checkout(void); +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ static void usage(int status) __attribute__((noreturn)); @@ -114,10 +119,10 @@ main(int argc, /* I - Number of command-line args */ #else time_t netif_time = 0; /* Time since last network update */ #endif /* __APPLE__ */ -#if HAVE_LAUNCHD - int launchd_idle_exit; +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + int service_idle_exit; /* Idle exit on select timeout? */ -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ #ifdef HAVE_GETEUID @@ -141,8 +146,8 @@ main(int argc, /* I - Number of command-line args */ #ifdef HAVE_LAUNCHD if (getenv("CUPSD_LAUNCHD")) { - Launchd = 1; - fg = 1; + OnDemand = 1; + fg = 1; } #endif /* HAVE_LAUNCHD */ @@ -219,15 +224,15 @@ main(int argc, /* I - Number of command-line args */ usage(0); break; - case 'l' : /* Started by launchd... */ -#ifdef HAVE_LAUNCHD - Launchd = 1; - fg = 1; + case 'l' : /* Started by launchd/systemd... */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + OnDemand = 1; + fg = 1; #else - _cupsLangPuts(stderr, _("cupsd: launchd(8) support not compiled " + _cupsLangPuts(stderr, _("cupsd: On-demand support not compiled " "in, running in normal mode.")); fg = 0; -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ break; case 'p' : /* Stop immediately for profiling */ @@ -531,17 +536,18 @@ main(int argc, /* I - Number of command-line args */ cupsdCleanFiles(CacheDir, "*.ipp"); -#if HAVE_LAUNCHD - if (Launchd) +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + if (OnDemand) { /* - * If we were started by launchd get the listen sockets file descriptors... + * If we were started on demand by launchd or systemd get the listen sockets + * file descriptors... */ - launchd_checkin(); - launchd_checkout(); + service_checkin(); + service_checkout(); } -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Startup the server... @@ -628,18 +634,15 @@ main(int argc, /* I - Number of command-line args */ * Send server-started event... */ -#ifdef HAVE_LAUNCHD - if (Launchd) - cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, - "Scheduler started via launchd."); +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + if (OnDemand) + cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started on demand."); else -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ if (fg) - cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, - "Scheduler started in foreground."); + cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in foreground."); else - cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, - "Scheduler started in background."); + cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in background."); /* * Start any pending print jobs... @@ -718,18 +721,18 @@ main(int argc, /* I - Number of command-line args */ break; } -#if HAVE_LAUNCHD - if (Launchd) +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + if (OnDemand) { /* - * If we were started by launchd, get the listen socket file + * If we were started by launchd or systemd, get the listen socket file * descriptors... */ - launchd_checkin(); - launchd_checkout(); + service_checkin(); + service_checkout(); } -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Startup the server... @@ -760,23 +763,23 @@ main(int argc, /* I - Number of command-line args */ if ((timeout = select_timeout(fds)) > 1 && LastEvent) timeout = 1; -#if HAVE_LAUNCHD +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) /* * If no other work is scheduled and we're being controlled by * launchd then timeout after 'LaunchdTimeout' seconds of * inactivity... */ - if (timeout == 86400 && Launchd && LaunchdTimeout && + if (timeout == 86400 && OnDemand && IdleExitTimeout && !cupsArrayCount(ActiveJobs) && (!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers))) { - timeout = LaunchdTimeout; - launchd_idle_exit = 1; + timeout = IdleExitTimeout; + service_idle_exit = 1; } else - launchd_idle_exit = 0; -#endif /* HAVE_LAUNCHD */ + service_idle_exit = 0; +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ if ((fds = cupsdDoSelect(timeout)) < 0) { @@ -873,13 +876,13 @@ main(int argc, /* I - Number of command-line args */ } #endif /* !__APPLE__ */ -#if HAVE_LAUNCHD +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) /* * If no other work was scheduled and we're being controlled by launchd * then timeout after 'LaunchdTimeout' seconds of inactivity... */ - if (!fds && launchd_idle_exit) + if (!fds && service_idle_exit) { cupsdLogMessage(CUPSD_LOG_INFO, "Printer sharing is off and there are no jobs pending, " @@ -887,7 +890,7 @@ main(int argc, /* I - Number of command-line args */ stop_scheduler = 1; break; } -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Resume listening for new connections as needed... @@ -941,8 +944,7 @@ main(int argc, /* I - Number of command-line args */ * Process pending data in the input buffer... */ - // TODO: Use httpGetReady() - if (con->http->used) + if (httpGetReady(con->http)) { cupsdReadClient(con); continue; @@ -952,13 +954,10 @@ main(int argc, /* I - Number of command-line args */ * Check the activity and close old clients... */ - // TODO: Use httpGetActivity() activity = current_time - Timeout; - if (con->http->activity < activity && !con->pipe_pid) + if (httpGetActivity(con->http) < activity && !con->pipe_pid) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Closing client %d after %d seconds of inactivity...", - con->number, Timeout); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Closing client %d after %d seconds of inactivity.", con->number, Timeout); cupsdCloseClient(con); continue; @@ -1095,14 +1094,14 @@ main(int argc, /* I - Number of command-line args */ cupsdStopServer(); -#ifdef HAVE_LAUNCHD +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) /* - * Update the launchd KeepAlive file as needed... + * Update the keep-alive file as needed... */ - if (Launchd) - launchd_checkout(); -#endif /* HAVE_LAUNCHD */ + if (OnDemand) + service_checkout(); +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Stop all jobs... @@ -1292,278 +1291,6 @@ cupsdSetStringf(char **s, /* O - New string */ } -#ifdef HAVE_LAUNCHD -/* - * 'launchd_checkin()' - Check-in with launchd and collect the listening fds. - */ - -static void -launchd_checkin(void) -{ -# ifdef HAVE_LAUNCH_ACTIVATE_SOCKET - int error; /* Check-in error, if any */ - size_t i, /* Looping var */ - count; /* Number of listeners */ - int *ld_sockets; /* Listener sockets */ - cupsd_listener_t *lis; /* Listeners array */ - http_addr_t addr; /* Address variable */ - socklen_t addrlen; /* Length of address */ - char s[256]; /* String addresss */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: pid=%d", (int)getpid()); - - /* - * Check-in with launchd... - */ - - if ((error = launch_activate_socket("Listeners", &ld_sockets, &count)) != 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Unable to get listener sockets: %s", strerror(error)); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - /* - * Try to match the launchd sockets to the cupsd listeners... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: %d listeners.", (int)count); - - for (i = 0; i < count; i ++) - { - /* - * Get the launchd socket address... - */ - - addrlen = sizeof(addr); - - if (getsockname(ld_sockets[i], (struct sockaddr *)&addr, &addrlen)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Unable to get local address for listener #%d: %s", (int)i + 1, strerror(errno)); - continue; - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Listener #%d at fd %d, \"%s\".", (int)i + 1, ld_sockets[i], httpAddrString(&addr, s, sizeof(s))); - - for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); - lis; - lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) - if (httpAddrEqual(&lis->address, &addr)) - break; - - /* - * Add a new listener if there's no match... - */ - - if (lis) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Matched existing listener #%d to %s.", (int)i + 1, httpAddrString(&(lis->address), s, sizeof(s))); - } - else - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Adding new listener #%d for %s.", (int)i + 1, httpAddrString(&addr, s, sizeof(s))); - - if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Unable to allocate listener: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - - cupsArrayAdd(Listeners, lis); - - memcpy(&lis->address, &addr, sizeof(lis->address)); - } - - lis->fd = ld_sockets[i]; - -# ifdef HAVE_SSL - if (httpAddrPort(&(lis->address)) == 443) - lis->encryption = HTTP_ENCRYPT_ALWAYS; -# endif /* HAVE_SSL */ - } - -# else - size_t i, /* Looping var */ - count; /* Number of listeners */ - launch_data_t ld_msg, /* Launch data message */ - ld_resp, /* Launch data response */ - ld_array, /* Launch data array */ - ld_sockets, /* Launch data sockets dictionary */ - tmp; /* Launch data */ - cupsd_listener_t *lis; /* Listeners array */ - http_addr_t addr; /* Address variable */ - socklen_t addrlen; /* Length of address */ - int fd; /* File descriptor */ - char s[256]; /* String addresss */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: pid=%d", (int)getpid()); - - /* - * Check-in with launchd... - */ - - ld_msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); - if ((ld_resp = launch_msg(ld_msg)) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "launchd_checkin: launch_msg(\"" LAUNCH_KEY_CHECKIN - "\") IPC failure"); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - if (launch_data_get_type(ld_resp) == LAUNCH_DATA_ERRNO) - { - errno = launch_data_get_errno(ld_resp); - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Check-in failed: %s", - strerror(errno)); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - /* - * Get the sockets dictionary... - */ - - if ((ld_sockets = launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_SOCKETS)) - == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "launchd_checkin: No sockets found to answer requests on."); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - /* - * Get the array of listener sockets... - */ - - if ((ld_array = launch_data_dict_lookup(ld_sockets, "Listeners")) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "launchd_checkin: No sockets found to answer requests on."); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - /* - * Add listening fd(s) to the Listener array... - */ - - if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY) - { - count = launch_data_array_get_count(ld_array); - - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: %d listeners.", (int)count); - - for (i = 0; i < count; i ++) - { - /* - * Get the launchd file descriptor and address... - */ - - if ((tmp = launch_data_array_get_index(ld_array, i)) != NULL) - { - fd = launch_data_get_fd(tmp); - addrlen = sizeof(addr); - - if (getsockname(fd, (struct sockaddr *)&addr, &addrlen)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Unable to get local address for listener #%d: %s", (int)i + 1, strerror(errno)); - continue; - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Listener #%d at fd %d, \"%s\".", (int)i + 1, fd, httpAddrString(&addr, s, sizeof(s))); - - /* - * Try to match the launchd 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; - - /* - * Add a new listener If there's no match... - */ - - if (lis) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Matched existing listener #%d to %s.", (int)i + 1, httpAddrString(&(lis->address), s, sizeof(s))); - } - else - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: Adding new listener #%d for %s.", (int)i + 1, httpAddrString(&addr, s, sizeof(s))); - - if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_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 */ - } - } - } - - launch_data_free(ld_msg); - launch_data_free(ld_resp); -# endif /* HAVE_LAUNCH_ACTIVATE_SOCKET */ -} - - -/* - * 'launchd_checkout()' - Update the launchd KeepAlive file as needed. - */ - -static void -launchd_checkout(void) -{ - int fd; /* File descriptor */ - - - /* - * Create or remove the launchd KeepAlive file based on whether - * there are active jobs, polling, browsing for remote printers or - * shared printers to advertise... - */ - - if (cupsArrayCount(ActiveJobs) || - (Browsing && BrowseLocalProtocols && cupsArrayCount(Printers))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Creating launchd keepalive file \"" CUPS_KEEPALIVE - "\"..."); - - if ((fd = open(CUPS_KEEPALIVE, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR)) >= 0) - close(fd); - } - else - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Removing launchd keepalive file \"" CUPS_KEEPALIVE - "\"..."); - - unlink(CUPS_KEEPALIVE); - } -} -#endif /* HAVE_LAUNCHD */ - - /* * 'parent_handler()' - Catch USR1/CHLD signals... */ @@ -1838,11 +1565,10 @@ select_timeout(int fds) /* I - Number of descriptors returned */ * processed; if so, the timeout should be 0... */ - // TODO: Use httpGetReady() for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) - if (con->http->used > 0) + if (httpGetReady(con->http)) return (0); /* @@ -1893,13 +1619,12 @@ select_timeout(int fds) /* I - Number of descriptors returned */ * Check the activity and close old clients... */ - // TODO: Use httpGetActivity() for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) - if ((con->http->activity + Timeout) < timeout) + if ((httpGetActivity(con->http) + Timeout) < timeout) { - timeout = con->http->activity + Timeout; + timeout = httpGetActivity(con->http) + Timeout; why = "timeout a client connection"; } @@ -2063,6 +1788,357 @@ sigterm_handler(int sig) /* I - Signal number */ } +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) +/* + * 'service_checkin()' - Check-in with launchd and collect the listening fds. + */ + +static void +service_checkin(void) +{ +# ifdef HAVE_LAUNCH_ACTIVATE_SOCKET + int error; /* Check-in error, if any */ + size_t i, /* Looping var */ + count; /* Number of listeners */ + int *ld_sockets; /* Listener sockets */ + cupsd_listener_t *lis; /* Listeners array */ + http_addr_t addr; /* Address variable */ + socklen_t addrlen; /* Length of address */ + char s[256]; /* String addresss */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: pid=%d", (int)getpid()); + + /* + * Check-in with launchd... + */ + + if ((error = launch_activate_socket("Listeners", &ld_sockets, &count)) != 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get listener sockets: %s", strerror(error)); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Try to match the launchd sockets to the cupsd listeners... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: %d listeners.", (int)count); + + for (i = 0; i < count; i ++) + { + /* + * Get the launchd socket address... + */ + + addrlen = sizeof(addr); + + if (getsockname(ld_sockets[i], (struct sockaddr *)&addr, &addrlen)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get local address for listener #%d: %s", (int)i + 1, strerror(errno)); + continue; + } + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Listener #%d at fd %d, \"%s\".", (int)i + 1, ld_sockets[i], httpAddrString(&addr, s, sizeof(s))); + + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + if (httpAddrEqual(&lis->address, &addr)) + break; + + /* + * Add a new listener if there's no match... + */ + + if (lis) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Matched existing listener #%d to %s.", (int)i + 1, httpAddrString(&(lis->address), s, sizeof(s))); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Adding new listener #%d for %s.", (int)i + 1, httpAddrString(&addr, s, sizeof(s))); + + if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to allocate listener: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + cupsArrayAdd(Listeners, lis); + + memcpy(&lis->address, &addr, sizeof(lis->address)); + } + + lis->fd = ld_sockets[i]; + lis->on_demand = 1; + +# ifdef HAVE_SSL + if (httpAddrPort(&(lis->address)) == 443) + lis->encryption = HTTP_ENCRYPT_ALWAYS; +# endif /* HAVE_SSL */ + } + +# elif defined(HAVE_LAUNCHD) + size_t i, /* Looping var */ + count; /* Number of listeners */ + launch_data_t ld_msg, /* Launch data message */ + ld_resp, /* Launch data response */ + ld_array, /* Launch data array */ + ld_sockets, /* Launch data sockets dictionary */ + tmp; /* Launch data */ + cupsd_listener_t *lis; /* Listeners array */ + http_addr_t addr; /* Address variable */ + socklen_t addrlen; /* Length of address */ + int fd; /* File descriptor */ + char s[256]; /* String addresss */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: pid=%d", (int)getpid()); + + /* + * Check-in with launchd... + */ + + ld_msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); + if ((ld_resp = launch_msg(ld_msg)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "service_checkin: launch_msg(\"" LAUNCH_KEY_CHECKIN + "\") IPC failure"); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + if (launch_data_get_type(ld_resp) == LAUNCH_DATA_ERRNO) + { + errno = launch_data_get_errno(ld_resp); + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Check-in failed: %s", + strerror(errno)); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Get the sockets dictionary... + */ + + if ((ld_sockets = launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_SOCKETS)) + == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "service_checkin: No sockets found to answer requests on."); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Get the array of listener sockets... + */ + + if ((ld_array = launch_data_dict_lookup(ld_sockets, "Listeners")) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "service_checkin: No sockets found to answer requests on."); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Add listening fd(s) to the Listener array... + */ + + if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY) + { + count = launch_data_array_get_count(ld_array); + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: %d listeners.", (int)count); + + for (i = 0; i < count; i ++) + { + /* + * Get the launchd file descriptor and address... + */ + + if ((tmp = launch_data_array_get_index(ld_array, i)) != NULL) + { + fd = launch_data_get_fd(tmp); + addrlen = sizeof(addr); + + if (getsockname(fd, (struct sockaddr *)&addr, &addrlen)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get local address for listener #%d: %s", (int)i + 1, strerror(errno)); + continue; + } + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Listener #%d at fd %d, \"%s\".", (int)i + 1, fd, httpAddrString(&addr, s, sizeof(s))); + + /* + * Try to match the launchd 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; + + /* + * Add a new listener If there's no match... + */ + + if (lis) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Matched existing listener #%d to %s.", (int)i + 1, httpAddrString(&(lis->address), s, sizeof(s))); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Adding new listener #%d for %s.", (int)i + 1, httpAddrString(&addr, s, sizeof(s))); + + if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to allocate listener: %s.", strerror(errno)); + exit(EXIT_FAILURE); + } + + cupsArrayAdd(Listeners, lis); + + memcpy(&lis->address, &addr, sizeof(lis->address)); + } + + lis->fd = fd; + lis->on_demand = 1; + +# ifdef HAVE_SSL + if (httpAddrPort(&(lis->address)) == 443) + lis->encryption = HTTP_ENCRYPT_ALWAYS; +# endif /* HAVE_SSL */ + } + } + } + + launch_data_free(ld_msg); + launch_data_free(ld_resp); + +# else /* HAVE_SYSTEMD */ + int i, /* Looping var */ + count; /* Number of listeners */ + cupsd_listener_t *lis; /* Listeners array */ + http_addr_t addr; /* Address variable */ + socklen_t addrlen; /* Length of address */ + char s[256]; /* String addresss */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: pid=%d", (int)getpid()); + + /* + * Check-in with systemd... + */ + + if ((count = sd_listen_fds(0)) < 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get listener sockets: %s", strerror(error)); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Try to match the systemd sockets to the cupsd listeners... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: %d listeners.", count); + + for (i = 0; i < count; i ++) + { + /* + * Get the launchd socket address... + */ + + addrlen = sizeof(addr); + + if (getsockname(SD_LISTEN_FDS_START + i, (struct sockaddr *)&addr, &addrlen)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get local address for listener #%d: %s", (int)i + 1, strerror(errno)); + continue; + } + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Listener #%d at fd %d, \"%s\".", (int)i + 1, SD_LISTEN_FDS_START + i, httpAddrString(&addr, s, sizeof(s))); + + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + if (httpAddrEqual(&lis->address, &addr)) + break; + + /* + * Add a new listener if there's no match... + */ + + if (lis) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Matched existing listener #%d to %s.", (int)i + 1, httpAddrString(&(lis->address), s, sizeof(s))); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Adding new listener #%d for %s.", (int)i + 1, httpAddrString(&addr, s, sizeof(s))); + + if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to allocate listener: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + cupsArrayAdd(Listeners, lis); + + memcpy(&lis->address, &addr, sizeof(lis->address)); + } + + lis->fd = SD_LISTEN_FDS_START + i; + lis->on_demand = 1; + +# ifdef HAVE_SSL + if (httpAddrPort(&(lis->address)) == 443) + lis->encryption = HTTP_ENCRYPT_ALWAYS; +# endif /* HAVE_SSL */ + } +# endif /* HAVE_LAUNCH_ACTIVATE_SOCKET */ +} + + +/* + * 'service_checkout()' - Update the CUPS_KEEPALIVE file as needed. + */ + +static void +service_checkout(void) +{ + int fd; /* File descriptor */ + + + /* + * Create or remove the systemd path file based on whether there are active + * jobs or shared printers to advertise... + */ + + if (cupsArrayCount(ActiveJobs) || + (Browsing && BrowseLocalProtocols && cupsArrayCount(Printers))) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating keep-alive file \"" CUPS_KEEPALIVE "\"."); + + if ((fd = open(CUPS_KEEPALIVE, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR)) >= 0) + close(fd); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Removing keep-alive file \"" CUPS_KEEPALIVE "\"."); + + unlink(CUPS_KEEPALIVE); + } +} +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ + + /* * 'usage()' - Show scheduler usage. */ @@ -2080,7 +2156,7 @@ usage(int status) /* O - Exit status */ _cupsLangPuts(fp, _(" -F Run in the foreground but " "detach from console.")); _cupsLangPuts(fp, _(" -h Show this usage message.")); - _cupsLangPuts(fp, _(" -l Run cupsd from launchd(8).")); + _cupsLangPuts(fp, _(" -l Run cupsd on demand.")); _cupsLangPuts(fp, _(" -t Test the configuration " "file.")); diff --git a/scheduler/org.cups.cupsd.socket.in b/scheduler/org.cups.cupsd.socket.in index c705c3762..cd98aa56e 100644 --- a/scheduler/org.cups.cupsd.socket.in +++ b/scheduler/org.cups.cupsd.socket.in @@ -6,6 +6,7 @@ ListenStream=@CUPS_DEFAULT_DOMAINSOCKET@ ListenStream=[::1]:631 ListenStream=127.0.0.1:631 BindIPv6Only=ipv6-only +ReusePort=true [Install] WantedBy=sockets.target diff --git a/xcode/CUPS.xcodeproj/project.pbxproj b/xcode/CUPS.xcodeproj/project.pbxproj index 7e099b4a8..b417bd855 100644 --- a/xcode/CUPS.xcodeproj/project.pbxproj +++ b/xcode/CUPS.xcodeproj/project.pbxproj @@ -1359,7 +1359,7 @@ 72E65BA818DC799B00097E89 /* cups-dnssd.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-dnssd.m4"; path = "../config-scripts/cups-dnssd.m4"; sourceTree = "<group>"; }; 72E65BA918DC799B00097E89 /* cups-gssapi.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-gssapi.m4"; path = "../config-scripts/cups-gssapi.m4"; sourceTree = "<group>"; }; 72E65BAA18DC799B00097E89 /* cups-largefile.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-largefile.m4"; path = "../config-scripts/cups-largefile.m4"; sourceTree = "<group>"; }; - 72E65BAB18DC799B00097E89 /* cups-ondemand.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-ondemand.m4"; path = "../config-scripts/cups-ondemand.m4"; sourceTree = "<group>"; }; + 72E65BAB18DC799B00097E89 /* cups-startup.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-startup.m4"; path = "../config-scripts/cups-startup.m4"; sourceTree = "<group>"; }; 72E65BAC18DC799B00097E89 /* cups-libtool.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-libtool.m4"; path = "../config-scripts/cups-libtool.m4"; sourceTree = "<group>"; }; 72E65BAD18DC799B00097E89 /* cups-manpages.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-manpages.m4"; path = "../config-scripts/cups-manpages.m4"; sourceTree = "<group>"; }; 72E65BAE18DC799B00097E89 /* cups-network.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; name = "cups-network.m4"; path = "../config-scripts/cups-network.m4"; sourceTree = "<group>"; }; @@ -1408,6 +1408,13 @@ 72E65BDA18DC852700097E89 /* api-mime.header */ = {isa = PBXFileReference; lastKnownFileType = text; name = "api-mime.header"; path = "../scheduler/api-mime.header"; sourceTree = SOURCE_ROOT; }; 72E65BDB18DC852700097E89 /* api-mime.shtml */ = {isa = PBXFileReference; lastKnownFileType = text.html.other; name = "api-mime.shtml"; path = "../scheduler/api-mime.shtml"; sourceTree = SOURCE_ROOT; }; 72E65BDC18DC852700097E89 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; name = Makefile; path = ../scheduler/Makefile; sourceTree = SOURCE_ROOT; }; + 72E65BDD18DCA35700097E89 /* CHANGES-1.7.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "CHANGES-1.7.txt"; path = "../CHANGES-1.7.txt"; sourceTree = "<group>"; }; + 72E65BDE18DCA35700097E89 /* CHANGES.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = CHANGES.txt; path = ../CHANGES.txt; sourceTree = "<group>"; }; + 72E65BDF18DCA35700097E89 /* CREDITS.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = CREDITS.txt; path = ../CREDITS.txt; sourceTree = "<group>"; }; + 72E65BE018DCA35700097E89 /* INSTALL.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = INSTALL.txt; path = ../INSTALL.txt; sourceTree = "<group>"; }; + 72E65BE118DCA35700097E89 /* IPPTOOL.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = IPPTOOL.txt; path = ../IPPTOOL.txt; sourceTree = "<group>"; }; + 72E65BE218DCA35700097E89 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = LICENSE.txt; path = ../LICENSE.txt; sourceTree = "<group>"; }; + 72E65BE318DCA35700097E89 /* README.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = README.txt; path = ../README.txt; sourceTree = "<group>"; }; 72F75A521336F950004BB496 /* cupstestppd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cupstestppd; sourceTree = BUILT_PRODUCTS_DIR; }; 72F75A5B1336F988004BB496 /* cupstestppd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cupstestppd.c; path = ../systemv/cupstestppd.c; sourceTree = "<group>"; }; 72F75A611336F9A3004BB496 /* libcupsimage.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libcupsimage.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2110,7 +2117,7 @@ 72E65BA818DC799B00097E89 /* cups-dnssd.m4 */, 72E65BA918DC799B00097E89 /* cups-gssapi.m4 */, 72E65BAA18DC799B00097E89 /* cups-largefile.m4 */, - 72E65BAB18DC799B00097E89 /* cups-ondemand.m4 */, + 72E65BAB18DC799B00097E89 /* cups-startup.m4 */, 72E65BAC18DC799B00097E89 /* cups-libtool.m4 */, 72E65BAD18DC799B00097E89 /* cups-manpages.m4 */, 72E65BAE18DC799B00097E89 /* cups-network.m4 */, @@ -2128,6 +2135,13 @@ 72E65BB818DC79F800097E89 /* Documentation */ = { isa = PBXGroup; children = ( + 72E65BDE18DCA35700097E89 /* CHANGES.txt */, + 72E65BDD18DCA35700097E89 /* CHANGES-1.7.txt */, + 72E65BDF18DCA35700097E89 /* CREDITS.txt */, + 72E65BE018DCA35700097E89 /* INSTALL.txt */, + 72E65BE118DCA35700097E89 /* IPPTOOL.txt */, + 72E65BE218DCA35700097E89 /* LICENSE.txt */, + 72E65BE318DCA35700097E89 /* README.txt */, 72E65BB918DC7A3600097E89 /* doc */, 72E65BBA18DC7A3600097E89 /* man */, 72E65BBB18DC7A6B00097E89 /* api-array.header */, |