Support systemd socket activation

Check if systemd passed us a socket when starting obmc-console before
creating the socket ourselves. This will support use cases where we
don't need obmc-console until a SoL is activated by the user.

Tested: Verified that existing unit file installation is unchanged -
statically enabled obmc-console@.service instances will be started.

Then disabled obmc-console@ttyS2.service and enabled
obmc-console@ttyS2.socket (with a drop-in change to override
ListenStream to "obmc-console") and verifed that activating Redfish and
SSH SoL would start obmc-console@ttyS2.service and console redirection
worked.

Change-Id: I42e96af46a5893145abf27761e97fd4f1b73719d
Signed-off-by: Jonathan Doman <jonathan.doman@intel.com>
diff --git a/Makefile.am b/Makefile.am
index 2ee97a2..696fec9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,6 +11,7 @@
 
 if WITH_SYSTEMD
 systemdsystemunit_DATA = conf/obmc-console@.service \
+			 conf/obmc-console@.socket \
 			 conf/obmc-console-ssh@.service
 
 if ENABLE_CONCURRENT_SERVERS
diff --git a/conf/obmc-console@.socket.in b/conf/obmc-console@.socket.in
new file mode 100644
index 0000000..6f374c4
--- /dev/null
+++ b/conf/obmc-console@.socket.in
@@ -0,0 +1,10 @@
+[Unit]
+Description=Console server domain socket listener
+
+[Socket]
+ListenStream=@obmc-console.%i
+Accept=no
+Service=obmc-console@%i.service
+
+[Install]
+WantedBy=sockets.target
diff --git a/configure.ac b/configure.ac
index 045ea36..6b0fb98 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,6 +74,7 @@
                  conf/80-obmc-console-uart.rules
                  conf/client.2200.conf
                  conf/obmc-console@.service
+                 conf/obmc-console@.socket
                  conf/obmc-console-ssh@.service
                  conf/obmc-console-ssh@.service.d/use-socket.conf
                  conf/obmc-console-ssh.socket
diff --git a/socket-handler.c b/socket-handler.c
index a11ab24..42690be 100644
--- a/socket-handler.c
+++ b/socket-handler.c
@@ -29,6 +29,7 @@
 
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <systemd/sd-daemon.h>
 
 #include "console-server.h"
 
@@ -314,12 +315,6 @@
 	sh->clients = NULL;
 	sh->n_clients = 0;
 
-	sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
-	if(sh->sd < 0) {
-		warn("Can't create socket");
-		return -1;
-	}
-
 	memset(&addr, 0, sizeof(addr));
 	addr.sun_family = AF_UNIX;
 	len = console_socket_path(&addr, config_get_value(config, "socket-id"));
@@ -328,24 +323,36 @@
 			warn("Failed to configure socket: %s", strerror(errno));
 		else
 			warn("Socket name length exceeds buffer limits");
-		goto cleanup;
+		return -1;
 	}
 
-	addrlen = sizeof(addr) - sizeof(addr.sun_path) + len;
+	/* Try to take a socket from systemd first */
+	if (sd_listen_fds(0) == 1 &&
+		sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, 1, addr.sun_path, len) > 0) {
+		sh->sd = SD_LISTEN_FDS_START;
+	} else {
+		sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
+		if(sh->sd < 0) {
+			warn("Can't create socket");
+			return -1;
+		}
 
-	rc = bind(sh->sd, (struct sockaddr *)&addr, addrlen);
-	if (rc) {
-		socket_path_t name;
-		console_socket_path_readable(&addr, addrlen, name);
-		warn("Can't bind to socket path %s (terminated at first null)",
-				name);
-		goto cleanup;
-	}
+		addrlen = sizeof(addr) - sizeof(addr.sun_path) + len;
 
-	rc = listen(sh->sd, 1);
-	if (rc) {
-		warn("Can't listen for incoming connections");
-		goto cleanup;
+		rc = bind(sh->sd, (struct sockaddr *)&addr, addrlen);
+		if (rc) {
+			socket_path_t name;
+			console_socket_path_readable(&addr, addrlen, name);
+			warn("Can't bind to socket path %s (terminated at first null)",
+					name);
+			goto cleanup;
+		}
+
+		rc = listen(sh->sd, 1);
+		if (rc) {
+			warn("Can't listen for incoming connections");
+			goto cleanup;
+		}
 	}
 
 	sh->poller = console_poller_register(console, handler, socket_poll,