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 #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...