tomh / rpms / lirc

Forked from rpms/lirc 6 years ago
Clone
Blob Blame History Raw
From 171ac321f1e97a60fbda3858c4c84d60d0b7dacb Mon Sep 17 00:00:00 2001
From: Alec Leamas <alec@tests.notat.diaspora.com>
Date: Wed, 9 Oct 2013 20:57:12 +0200
Subject: [PATCH 104/105] Add systemd socket activation support.

Since systemd was introduced lirc clients have had problems at
startup when trying to connect to the lircd socket before it's
created. The root cause is the aggressive parallell boot performed
by systemd.

The solution is to add socket activation. In this mode, the socket
is created by systemd and handed over to lircd at startup. The patch
implements this. It should be reasonably transparent.

At configure time it enables systemd support if it's available,
otherwise it's silently ignored.

In runtime lircd looks for and uses a socket handed over by systemd.
If there is no such socket it proceeds as normal.

Adds a dependency on pkg-config for the PKG_CHECK_MODULES macro.
---
 configure.ac    |  7 +++++
 daemons/lircd.c | 94 ++++++++++++++++++++++++++++++++++-----------------------
 2 files changed, 63 insertions(+), 38 deletions(-)

diff --git a/configure.ac b/configure.ac
index af28e4f..7df186a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -232,6 +232,9 @@ AH_TEMPLATE([HAVE_SCSI],
 AH_TEMPLATE([HAVE_SOUNDCARD],
 	[defined if soundcard API is available])
 
+AH_TEMPLATE([HAVE_SYSTEMD],
+	[defined if systemd API is available])
+
 AH_TEMPLATE([HAVE_VSYSLOG],
 	[define if you have vsyslog( prio, fmt, va_arg )])
 
@@ -414,6 +417,10 @@ AC_CHECK_HEADERS(linux/i2c-dev.h,[
   ]
 )
 
+PKG_CHECK_MODULES([SYSTEMD],[libsystemd-daemon],[AC_DEFINE(HAVE_SYSTEMD)],[true])
+CFLAGS="$CFLAGS $SYSTEMD_CFLAGS"
+LIBS="$LIBS $SYSTEMD_LIBS"
+
 dnl here we see what driver the user wants.
 
 AC_ARG_WITH(driver,
diff --git a/daemons/lircd.c b/daemons/lircd.c
index 8ace7af..9cde69b 100644
--- a/daemons/lircd.c
+++ b/daemons/lircd.c
@@ -63,6 +63,10 @@
 #include "input_map.h"
 #endif
 
+#ifdef HAVE_SYSTEMD
+#include "systemd/sd-daemon.h"
+#endif
+
 #if defined __APPLE__  || defined __FreeBSD__
 #include <sys/ioctl.h>
 #endif
@@ -855,6 +859,7 @@ void start_server(mode_t permission, int nodaemon)
 	int ret;
 	int new = 1;
 	int fd;
+	int n;
 
 	/* create pid lockfile in /var/run */
 	if ((fd = open(pidfile, O_RDWR | O_CREAT, 0644)) == -1 || (pidf = fdopen(fd, "r+")) == NULL) {
@@ -881,51 +886,64 @@ void start_server(mode_t permission, int nodaemon)
 	(void)ftruncate(fileno(pidf), ftell(pidf));
 
 	/* create socket */
-	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (sockfd == -1) {
-		fprintf(stderr, "%s: could not create socket\n", progname);
-		perror(progname);
+	sockfd = -1;
+#ifdef HAVE_SYSTEMD
+        n = sd_listen_fds(0);
+        if (n > 1) {
+                fprintf(stderr, "Too many file descriptors received.\n");
 		goto start_server_failed0;
-	}
+                exit(1);
+        }
+        else if (n == 1)
+                sockfd  = SD_LISTEN_FDS_START + 0;
+#endif
+        if (sockfd == -1) {
+		sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+		if (sockfd == -1) {
+			fprintf(stderr, "%s: could not create socket\n", progname);
+			perror(progname);
+			goto start_server_failed0;
+		}
 
-	/* 
-	   get owner, permissions, etc.
-	   so new socket can be the same since we
-	   have to delete the old socket.  
-	 */
-	ret = stat(lircdfile, &s);
-	if (ret == -1 && errno != ENOENT) {
-		fprintf(stderr, "%s: could not get file information for %s\n", progname, lircdfile);
-		perror(progname);
-		goto start_server_failed1;
-	}
-	if (ret != -1) {
-		new = 0;
-		ret = unlink(lircdfile);
-		if (ret == -1) {
-			fprintf(stderr, "%s: could not delete %s\n", progname, lircdfile);
-			perror(NULL);
+		/*
+		   get owner, permissions, etc.
+		   so new socket can be the same since we
+		   have to delete the old socket.
+		 */
+		ret = stat(lircdfile, &s);
+		if (ret == -1 && errno != ENOENT) {
+			fprintf(stderr, "%s: could not get file information for %s\n", progname, lircdfile);
+			perror(progname);
 			goto start_server_failed1;
 		}
-	}
+		if (ret != -1) {
+			new = 0;
+			ret = unlink(lircdfile);
+			if (ret == -1) {
+				fprintf(stderr, "%s: could not delete %s\n", progname, lircdfile);
+				perror(NULL);
+				goto start_server_failed1;
+			}
+		}
 
-	serv_addr.sun_family = AF_UNIX;
-	strcpy(serv_addr.sun_path, lircdfile);
-	if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
-		fprintf(stderr, "%s: could not assign address to socket\n", progname);
-		perror(progname);
-		goto start_server_failed1;
-	}
+		serv_addr.sun_family = AF_UNIX;
+		strcpy(serv_addr.sun_path, lircdfile);
+		if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
+			fprintf(stderr, "%s: could not assign address to socket\n", progname);
+			perror(progname);
+			goto start_server_failed1;
+		}
 
-	if (new ? chmod(lircdfile, permission)
-	    : (chmod(lircdfile, s.st_mode) == -1 || chown(lircdfile, s.st_uid, s.st_gid) == -1)
-	    ) {
-		fprintf(stderr, "%s: could not set file permissions\n", progname);
-		perror(progname);
-		goto start_server_failed1;
-	}
+		if (new ? chmod(lircdfile, permission)
+		    : (chmod(lircdfile, s.st_mode) == -1 || chown(lircdfile, s.st_uid, s.st_gid) == -1)
+		    ) {
+			fprintf(stderr, "%s: could not set file permissions\n", progname);
+			perror(progname);
+			goto start_server_failed1;
+		}
 
-	listen(sockfd, 3);
+		listen(sockfd, 3);
+        }
 	nolinger(sockfd);
 
 	if (useuinput) {
-- 
1.8.3.1