summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct4
-rw-r--r--gpsd.c32
-rw-r--r--sd_socket.c33
3 files changed, 68 insertions, 1 deletions
diff --git a/SConstruct b/SConstruct
index 0d860f93..8bbcd1c7 100644
--- a/SConstruct
+++ b/SConstruct
@@ -83,6 +83,7 @@ boolopts = (
# Other daemon options
("timing", True, "latency timing support"),
("control_socket",True, "control socket for hotplug notifications"),
+ ("systemd", True, "systemd socket activation"),
# Client-side options
("clientdebug", True, "client debugging support"),
("oldstyle", True, "oldstyle (pre-JSON) protocol support"),
@@ -680,6 +681,9 @@ gpsdlibs = ["-lgpsd"] + usblibs + bluezlibs + gpslibs
gpsd_sources = ['gpsd.c','ntpshm.c','shmexport.c','dbusexport.c']
+if env['systemd']:
+ gpsd_sources.append("sd_socket.c")
+
gpsmon_sources = [
'gpsmon.c',
'monitor_italk.c',
diff --git a/gpsd.c b/gpsd.c
index bfaefd60..5041407a 100644
--- a/gpsd.c
+++ b/gpsd.c
@@ -52,6 +52,10 @@
#include "gps_json.h"
#include "revision.h"
+#if defined(SYSTEMD_ENABLE)
+#include "sd_socket.h"
+#endif
+
/*
* The name of a tty device from which to pick up whatever the local
* owning group for tty devices is. Used when we drop privileges.
@@ -145,6 +149,7 @@ static bool nowait = false;
#endif /* FORCE_NOWAIT */
static jmp_buf restartbuf;
static struct gps_context_t context;
+static int sd_socket_count = 0;
static volatile sig_atomic_t signalled;
@@ -465,6 +470,15 @@ static int passivesocks(char *service, char *tcp_or_udp,
for (i = 0; i < AFCOUNT; i++)
socks[i] = -1;
+#if defined(SYSTEMD_ENABLE)
+ if (sd_socket_count > 0) {
+ for (i = 0; i < AFCOUNT && i < sd_socket_count - 1; i++) {
+ socks[i] = SD_SOCKET_FDS_START + i + 1;
+ }
+ return sd_socket_count - 1;
+ }
+#endif
+
if (AF_UNSPEC == af || (AF_INET == af))
socks[0] = passivesock_af(AF_INET, service, tcp_or_udp, qlen);
@@ -1798,8 +1812,17 @@ int main(int argc, char *argv[])
}
}
+#ifdef SYSTEMD_ENABLE
+ sd_socket_count = sd_get_socket_count();
+ if (sd_socket_count > 0 && control_socket) {
+ gpsd_report(LOG_WARN,
+ "control socket passed on command line ignored\n");
+ control_socket = NULL;
+ }
+#endif
+
#ifdef CONTROL_SOCKET_ENABLE
- if (!control_socket && optind >= argc) {
+ if (!control_socket && optind >= argc && sd_socket_count <= 0) {
gpsd_report(LOG_ERROR,
"can't run with neither control socket nor devices\n");
exit(1);
@@ -1810,6 +1833,13 @@ int main(int argc, char *argv[])
* avoid a race condition in which hotplug scripts can try opening
* the socket before it's created.
*/
+#ifdef SYSTEMD_ENABLE
+ if (sd_socket_count > 0) {
+ csock = SD_SOCKET_FDS_START;
+ FD_SET(csock, &all_fds);
+ adjust_max_fd(csock, true);
+ }
+#endif
if (control_socket) {
(void)unlink(control_socket);
if ((csock = filesock(control_socket)) == -1) {
diff --git a/sd_socket.c b/sd_socket.c
new file mode 100644
index 00000000..8c8c7719
--- /dev/null
+++ b/sd_socket.c
@@ -0,0 +1,33 @@
+/*
+ * This file is Copyright (c) 2011 by Eckhart Wörner
+ * BSD terms apply: see the file COPYING in the distribution root for details.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "sd_socket.h"
+
+int sd_get_socket_count(void) {
+ unsigned long n;
+ const char* env;
+
+ env = getenv("LISTEN_PID");
+ if (!env)
+ return 0;
+
+ n = strtoul(env, NULL, 10);
+ if (n == ULONG_MAX || (pid_t)n != getpid())
+ return 0;
+
+ env = getenv("LISTEN_FDS");
+ if (!env)
+ return 0;
+
+ n = strtoul(env, NULL, 10);
+ if (n == ULONG_MAX)
+ return 0;
+
+ return (int)n;
+}