From dc832ec714a9cf830ccc834e219c054bd24c21e4 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 18 Feb 2013 18:21:52 +0000 Subject: [PATCH 4/5] core: if running as user, pick up the X11 display from logind Otherwise, user-bus-activated services that are GUIs, like gnome-terminal, will not be able to access the appropriate display. Signed-off-by: Simon McVittie --- src/core/manager.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/manager.h | 8 +++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/core/manager.c b/src/core/manager.c index 28f169d..0727623 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -277,6 +277,27 @@ static int manager_setup_signals(Manager *m) { return 0; } +static int manager_setup_login_monitor(Manager *m) { + int r; + struct epoll_event ev; + + r = sd_login_monitor_new("uid", &m->login_monitor); + if (r < 0) + return r; + m->login_monitor_watch.type = WATCH_LOGIN_MONITOR; + m->login_monitor_watch.fd = sd_login_monitor_get_fd(m->login_monitor); + + zero(ev); + ev.events = EPOLLIN; + ev.data.ptr = &m->login_monitor_watch; + + if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->login_monitor_watch.fd, &ev) < 0) + return -errno; + + return 0; +} + + static void manager_strip_environment(Manager *m) { assert(m); @@ -382,6 +403,12 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) { m->taint_usr = dir_is_empty("/usr") > 0; + if (running_as != SYSTEMD_SYSTEM) { + r = manager_setup_login_monitor(m); + if (r < 0) + goto fail; + } + *_m = m; return 0; @@ -583,6 +610,8 @@ void manager_free(Manager *m) { for (i = 0; i < RLIMIT_NLIMITS; i++) free(m->rlimit[i]); + sd_login_monitor_unref(m->login_monitor); + free(m); } @@ -1417,6 +1446,46 @@ static int manager_process_signal_fd(Manager *m) { return 0; } +static int manager_process_login_monitor_fd(Manager *m) { + int r; + int i; + char *d = NULL; + char *env; + char **e; + + assert(m); + assert(m->login_monitor); + + sd_login_monitor_flush(m->login_monitor); + + /* Something has changed. Reload our idea of what $DISPLAY should be */ + r = sd_uid_get_display(getuid(), &d); + + if (r < 0 && r != -ENOENT) + return r; + + if (r == -ENOENT || isempty(d)) { + free(d); + m->environment = strv_env_unset(m->environment, "DISPLAY"); + } else { + r = asprintf(&env, "DISPLAY=%s", d); + free(d); + if (r < 0) + return -ENOMEM; + + e = strv_env_set(m->environment, env); + free(env); + + if (!e) + return -ENOMEM; + + strv_free(m->environment); + m->environment = e; + } + + return 0; +} + static int process_event(Manager *m, struct epoll_event *ev) { int r; Watch *w; @@ -1525,6 +1594,15 @@ static int process_event(Manager *m, struct epoll_event *ev) { } break; + + case WATCH_LOGIN_MONITOR: + if (ev->events != EPOLLIN) + return -EINVAL; + + if ((r = manager_process_login_monitor_fd(m)) < 0) + return r; + + break; } default: diff --git a/src/core/manager.h b/src/core/manager.h index cc4edf8..8d36561 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -27,6 +27,7 @@ #include #include "fdset.h" +#include "sd-login.h" /* Enforce upper limit how many names we allow */ #define MANAGER_MAX_NAMES 131072 /* 128K */ @@ -61,7 +62,8 @@ enum WatchType { WATCH_UDEV, WATCH_DBUS_WATCH, WATCH_DBUS_TIMEOUT, - WATCH_TIME_CHANGE + WATCH_TIME_CHANGE, + WATCH_LOGIN_MONITOR }; struct Watch { @@ -230,6 +232,10 @@ struct Manager { char *switch_root; char *switch_root_init; + + /* if we are a user manager */ + sd_login_monitor *login_monitor; + Watch login_monitor_watch; }; int manager_new(SystemdRunningAs running_as, Manager **m); -- 1.7.10.4