If $NOTIFY_SOCKET environment variable is present and its
value starts with / or @ and fits in struct sockaddr_unix,
use it to send READY=1 message to a session manager like
systemd.  This allows qemu to be used in a systemd Type=notify
service.

Signed-off-by: Michael Tokarev <[email protected]>
---
 os-posix.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/os-posix.c b/os-posix.c
index 52925c23d3..ab27252115 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -282,6 +282,41 @@ void os_setup_limits(void)
     }
 }
 
+static void sd_notify_ready(void)
+{
+#ifdef CONFIG_LINUX
+    static const char message[] = "READY=1";
+    static const char sock_env[] = "NOTIFY_SOCKET";
+
+    struct sockaddr_un sun;
+    int sock;
+    const char *sock_path;
+
+    sock_path = getenv(sock_env);
+    if (!sock_path ||
+        (*sock_path != '/' && *sock_path != '@') ||
+        strlen(sock_path) >= sizeof(sun.sun_path)) {
+        return;
+    }
+
+    memset(&sun, 0, sizeof(sun));
+    sun.sun_family = AF_UNIX;
+    strcpy(sun.sun_path, sock_path);
+    if (*sock_path == '@') {
+        sun.sun_path[0] = '\0';
+    }
+
+    sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+    if (sock >= 0) {
+        /* ignore errors */
+        sendto(sock, message, sizeof(message) - 1, 0,
+               (struct sockaddr *)&sun, sizeof(sun));
+        close(sock);
+    }
+    unsetenv(sock_env);
+#endif
+}
+
 void os_setup_post(void)
 {
     int fd = 0;
@@ -297,6 +332,7 @@ void os_setup_post(void)
         }
     }
 
+    sd_notify_ready();
     change_root();
     change_process_uid();
 
-- 
2.47.3


Reply via email to