+/* Where clients shall send notification messages to */
+#define NOTIFY_SOCKET "/org/freedesktop/systemd1/notify"
+
+static int manager_setup_notify(Manager *m) {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_un un;
+ } sa;
+ struct epoll_event ev;
+ char *ne[2], **t;
+ int one = 1;
+
+ assert(m);
+
+ m->notify_watch.type = WATCH_NOTIFY;
+ if ((m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
+ log_error("Failed to allocate notification socket: %m");
+ return -errno;
+ }
+
+ zero(sa);
+ sa.sa.sa_family = AF_UNIX;
+
+ if (m->running_as == MANAGER_SESSION)
+ snprintf(sa.un.sun_path+1, sizeof(sa.un.sun_path)-1, NOTIFY_SOCKET "/%llu", random_ull());
+ else
+ strncpy(sa.un.sun_path+1, NOTIFY_SOCKET, sizeof(sa.un.sun_path)-1);
+
+ if (bind(m->notify_watch.fd, &sa.sa, sizeof(sa)) < 0) {
+ log_error("bind() failed: %m");
+ return -errno;
+ }
+
+ if (setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
+ log_error("SO_PASSCRED failed: %m");
+ return -errno;
+ }
+
+ zero(ev);
+ ev.events = EPOLLIN;
+ ev.data.ptr = &m->notify_watch;
+
+ if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0)
+ return -errno;
+
+ if (asprintf(&ne[0], "NOTIFY_SOCKET=@%s", sa.un.sun_path+1) < 0)
+ return -ENOMEM;
+
+ ne[1] = NULL;
+ t = strv_env_merge(2, m->environment, ne);
+ free(ne[0]);
+
+ if (!t)
+ return -ENOMEM;
+
+ strv_free(m->environment);
+ m->environment = t;
+
+ return 0;
+}
+