X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-terminal%2Fsysview.c;h=70a6ca726c5184ec3decea93b37708c6309dff53;hb=ed7fb9cb235d2aedb755dcb8a5a5d9cdffba1519;hp=23d564d6a0407417c57ed0d4a0ea329cefd98911;hpb=965f7a3f9bf7afb85be62198fabc70ffa033d8b1;p=elogind.git diff --git a/src/libsystemd-terminal/sysview.c b/src/libsystemd-terminal/sysview.c index 23d564d6a..70a6ca726 100644 --- a/src/libsystemd-terminal/sysview.c +++ b/src/libsystemd-terminal/sysview.c @@ -104,6 +104,12 @@ sysview_device *sysview_device_free(sysview_device *device) { return NULL; } +const char *sysview_device_get_name(sysview_device *device) { + assert_return(device, NULL); + + return device->name; +} + unsigned int sysview_device_get_type(sysview_device *device) { assert_return(device, (unsigned)-1); @@ -243,18 +249,36 @@ sysview_session *sysview_session_free(sysview_session *session) { return NULL; } +void sysview_session_set_userdata(sysview_session *session, void *userdata) { + assert(session); + + session->userdata = userdata; +} + +void *sysview_session_get_userdata(sysview_session *session) { + assert_return(session, NULL); + + return session->userdata; +} + const char *sysview_session_get_name(sysview_session *session) { assert_return(session, NULL); return session->name; } +sysview_seat *sysview_session_get_seat(sysview_session *session) { + assert_return(session, NULL); + + return session->seat; +} + static int session_take_control_fn(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error) { sysview_session *session = userdata; - int error; + int r, error; session->slot_take_control = sd_bus_slot_unref(session->slot_take_control); @@ -269,7 +293,12 @@ static int session_take_control_fn(sd_bus *bus, error = 0; } - return context_raise_session_control(session->seat->context, session, error); + r = context_raise_session_control(session->seat->context, session, error); + if (r < 0) + log_debug("sysview: callback failed while signalling session control '%d' on session '%s': %s", + error, session->name, strerror(-r)); + + return 0; } int sysview_session_take_control(sysview_session *session) { @@ -368,6 +397,10 @@ int sysview_seat_new(sysview_seat **out, sysview_context *c, const char *name) { if (!seat->name) return -ENOMEM; + r = sd_bus_path_encode("/org/freedesktop/login1/seat", seat->name, &seat->path); + if (r < 0) + return r; + seat->session_map = hashmap_new(&string_hash_ops); if (!seat->session_map) return -ENOMEM; @@ -399,6 +432,7 @@ sysview_seat *sysview_seat_free(sysview_seat *seat) { hashmap_free(seat->device_map); hashmap_free(seat->session_map); + free(seat->path); free(seat->name); free(seat); @@ -411,6 +445,29 @@ const char *sysview_seat_get_name(sysview_seat *seat) { return seat->name; } +int sysview_seat_switch_to(sysview_seat *seat, uint32_t nr) { + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + int r; + + assert_return(seat, -EINVAL); + assert_return(seat->context->sysbus, -EINVAL); + + r = sd_bus_message_new_method_call(seat->context->sysbus, + &m, + "org.freedesktop.login1", + seat->path, + "org.freedesktop.login1.Seat", + "SwitchTo"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "u", nr); + if (r < 0) + return r; + + return sd_bus_send(seat->context->sysbus, m, NULL); +} + /* * Contexts */ @@ -517,10 +574,11 @@ static int context_raise_session_detach(sysview_context *c, sysview_session *ses return context_raise(c, &event, 0); } -static int context_raise_device_change(sysview_context *c, sysview_device *device, struct udev_device *ud) { +static int context_raise_session_refresh(sysview_context *c, sysview_session *session, sysview_device *device, struct udev_device *ud) { sysview_event event = { - .type = SYSVIEW_EVENT_DEVICE_CHANGE, - .device_change = { + .type = SYSVIEW_EVENT_SESSION_REFRESH, + .session_refresh = { + .session = session, .device = device, .ud = ud, } @@ -529,10 +587,10 @@ static int context_raise_device_change(sysview_context *c, sysview_device *devic return context_raise(c, &event, 0); } -static int context_add_device(sysview_context *c, sysview_device *device) { +static void context_add_device(sysview_context *c, sysview_device *device) { sysview_session *session; - int r, error = 0; Iterator i; + int r; assert(c); assert(device); @@ -545,20 +603,16 @@ static int context_add_device(sysview_context *c, sysview_device *device) { continue; r = context_raise_session_attach(c, session, device); - if (r != 0) - error = r; + if (r < 0) + log_debug("sysview: callback failed while attaching device '%s' to session '%s': %s", + device->name, session->name, strerror(-r)); } - - if (error < 0) - log_debug("sysview: error while adding device '%s': %s", - device->name, strerror(-r)); - return error; } -static int context_remove_device(sysview_context *c, sysview_device *device) { +static void context_remove_device(sysview_context *c, sysview_device *device) { sysview_session *session; - int r, error = 0; Iterator i; + int r; assert(c); assert(device); @@ -570,22 +624,40 @@ static int context_remove_device(sysview_context *c, sysview_device *device) { continue; r = context_raise_session_detach(c, session, device); - if (r != 0) - error = r; + if (r < 0) + log_debug("sysview: callback failed while detaching device '%s' from session '%s': %s", + device->name, session->name, strerror(-r)); } - if (error < 0) - log_debug("sysview: error while removing device '%s': %s", - device->name, strerror(-r)); sysview_device_free(device); - return error; } -static int context_add_session(sysview_context *c, sysview_seat *seat, const char *id) { +static void context_change_device(sysview_context *c, sysview_device *device, struct udev_device *ud) { + sysview_session *session; + Iterator i; + int r; + + assert(c); + assert(device); + + log_debug("sysview: change device '%s'", device->name); + + HASHMAP_FOREACH(session, device->seat->session_map, i) { + if (!session->public) + continue; + + r = context_raise_session_refresh(c, session, device, ud); + if (r < 0) + log_debug("sysview: callback failed while changing device '%s' on session '%s': %s", + device->name, session->name, strerror(-r)); + } +} + +static void context_add_session(sysview_context *c, sysview_seat *seat, const char *id) { sysview_session *session; sysview_device *device; - int r, error = 0; Iterator i; + int r; assert(c); assert(seat); @@ -593,7 +665,7 @@ static int context_add_session(sysview_context *c, sysview_seat *seat, const cha session = sysview_find_session(c, id); if (session) - return 0; + return; log_debug("sysview: add session '%s' on seat '%s'", id, seat->name); @@ -610,35 +682,33 @@ static int context_add_session(sysview_context *c, sysview_seat *seat, const cha if (seat->public) { session->public = true; r = context_raise_session_add(c, session); - if (r != 0) { + if (r < 0) { + log_debug("sysview: callback failed while adding session '%s': %s", + session->name, strerror(-r)); session->public = false; goto error; } HASHMAP_FOREACH(device, seat->device_map, i) { r = context_raise_session_attach(c, session, device); - if (r != 0) - error = r; + if (r < 0) + log_debug("sysview: callback failed while attaching device '%s' to new session '%s': %s", + device->name, session->name, strerror(-r)); } - - r = error; - if (r != 0) - goto error; } - return 0; + return; error: if (r < 0) log_debug("sysview: error while adding session '%s': %s", id, strerror(-r)); - return r; } -static int context_remove_session(sysview_context *c, sysview_session *session) { +static void context_remove_session(sysview_context *c, sysview_session *session) { sysview_device *device; - int r, error = 0; Iterator i; + int r; assert(c); assert(session); @@ -648,27 +718,25 @@ static int context_remove_session(sysview_context *c, sysview_session *session) if (session->public) { HASHMAP_FOREACH(device, session->seat->device_map, i) { r = context_raise_session_detach(c, session, device); - if (r != 0) - error = r; + if (r < 0) + log_debug("sysview: callback failed while detaching device '%s' from old session '%s': %s", + device->name, session->name, strerror(-r)); } session->public = false; r = context_raise_session_remove(c, session); - if (r != 0) - error = r; + if (r < 0) + log_debug("sysview: callback failed while removing session '%s': %s", + session->name, strerror(-r)); } if (!session->custom) sysview_session_release_control(session); - if (error < 0) - log_debug("sysview: error while removing session '%s': %s", - session->name, strerror(-error)); sysview_session_free(session); - return error; } -static int context_add_seat(sysview_context *c, const char *id) { +static void context_add_seat(sysview_context *c, const char *id) { sysview_seat *seat; int r; @@ -677,7 +745,7 @@ static int context_add_seat(sysview_context *c, const char *id) { seat = sysview_find_seat(c, id); if (seat) - return 0; + return; log_debug("sysview: add seat '%s'", id); @@ -687,54 +755,45 @@ static int context_add_seat(sysview_context *c, const char *id) { seat->public = true; r = context_raise_seat_add(c, seat); - if (r != 0) { + if (r < 0) { + log_debug("sysview: callback failed while adding seat '%s': %s", + seat->name, strerror(-r)); seat->public = false; - goto error; } - return 0; + return; error: if (r < 0) log_debug("sysview: error while adding seat '%s': %s", id, strerror(-r)); - return r; } -static int context_remove_seat(sysview_context *c, sysview_seat *seat) { +static void context_remove_seat(sysview_context *c, sysview_seat *seat) { sysview_session *session; sysview_device *device; - int r, error = 0; + int r; assert(c); assert(seat); log_debug("sysview: remove seat '%s'", seat->name); - while ((device = hashmap_first(seat->device_map))) { - r = context_remove_device(c, device); - if (r != 0) - error = r; - } + while ((device = hashmap_first(seat->device_map))) + context_remove_device(c, device); - while ((session = hashmap_first(seat->session_map))) { - r = context_remove_session(c, session); - if (r != 0) - error = r; - } + while ((session = hashmap_first(seat->session_map))) + context_remove_session(c, session); if (seat->public) { seat->public = false; r = context_raise_seat_remove(c, seat); - if (r != 0) - error = r; + if (r < 0) + log_debug("sysview: callback failed while removing seat '%s': %s", + seat->name, strerror(-r)); } - if (error < 0) - log_debug("sysview: error while removing seat '%s': %s", - seat->name, strerror(-error)); sysview_seat_free(seat); - return error; } int sysview_context_new(sysview_context **out, @@ -879,12 +938,12 @@ static int context_ud_hotplug(sysview_context *c, struct udev_device *d) { if (!device) return 0; - return context_remove_device(c, device); + context_remove_device(c, device); } else if (streq_ptr(action, "change")) { if (!device) return 0; - return context_raise_device_change(c, device, d); + context_change_device(c, device, d); } else if (!action || streq_ptr(action, "add")) { struct udev_device *p; unsigned int type, t; @@ -895,7 +954,7 @@ static int context_ud_hotplug(sysview_context *c, struct udev_device *d) { if (streq(subsystem, "input") && startswith(sysname, "event") && safe_atou(sysname + 5, &t) >= 0) type = SYSVIEW_DEVICE_EVDEV; - else if (streq(subsystem, "drm") && startswith(sysname, "card") && safe_atou(sysname + 4, &t) >= 0) + else if (streq(subsystem, "drm") && startswith(sysname, "card")) type = SYSVIEW_DEVICE_DRM; else type = (unsigned)-1; @@ -922,7 +981,7 @@ static int context_ud_hotplug(sysview_context *c, struct udev_device *d) { return r; } - return context_add_device(c, device); + context_add_device(c, device); } return 0; @@ -1049,7 +1108,8 @@ static int context_ld_seat_new(sysview_context *c, sd_bus_message *signal) { return r; } - return context_add_seat(c, id); + context_add_seat(c, id); + return 0; } static int context_ld_seat_removed(sysview_context *c, sd_bus_message *signal) { @@ -1068,7 +1128,8 @@ static int context_ld_seat_removed(sysview_context *c, sd_bus_message *signal) { if (!seat) return 0; - return context_remove_seat(c, seat); + context_remove_seat(c, seat); + return 0; } static int context_ld_session_new(sysview_context *c, sd_bus_message *signal) { @@ -1115,14 +1176,13 @@ static int context_ld_session_new(sysview_context *c, sd_bus_message *signal) { } r = context_raise_session_filter(c, id, seatid, username, uid); - if (r <= 0) { - if (r < 0) - log_debug("sysview: cannot filter new session '%s' on seat '%s': %s", - id, seatid, strerror(-r)); - return r; - } + if (r < 0) + log_debug("sysview: callback failed while filtering session '%s': %s", + id, strerror(-r)); + else if (r > 0) + context_add_session(c, seat, id); - return context_add_session(c, seat, id); + return 0; error: log_debug("sysview: failed retrieving information for new session '%s': %s", @@ -1146,7 +1206,8 @@ static int context_ld_session_removed(sysview_context *c, sd_bus_message *signal if (!session) return 0; - return context_remove_session(c, session); + context_remove_session(c, session); + return 0; } static int context_ld_manager_signal_fn(sd_bus *bus, @@ -1221,9 +1282,7 @@ static int context_ld_list_seats_fn(sd_bus *bus, if (r < 0) goto error; - r = context_add_seat(c, id); - if (r != 0) - return r; + context_add_seat(c, id); r = sd_bus_message_exit_container(reply); if (r < 0) @@ -1284,15 +1343,11 @@ static int context_ld_list_sessions_fn(sd_bus *bus, seat = sysview_find_seat(c, seatid); if (seat) { r = context_raise_session_filter(c, id, seatid, username, uid); - if (r < 0) { - log_debug("sysview: cannot filter listed session '%s' on seat '%s': %s", - id, seatid, strerror(-r)); - return r; - } else if (r > 0) { - r = context_add_session(c, seat, id); - if (r != 0) - return r; - } + if (r < 0) + log_debug("sysview: callback failed while filtering session '%s': %s", + id, strerror(-r)); + else if (r > 0) + context_add_session(c, seat, id); } r = sd_bus_message_exit_container(reply); @@ -1416,20 +1471,6 @@ void sysview_context_stop(sysview_context *c) { log_debug("sysview: stop"); - c->running = false; - c->scanned = false; - c->event_fn = NULL; - c->userdata = NULL; - c->scan_src = sd_event_source_unref(c->scan_src); - context_ud_stop(c); - context_ld_stop(c); - - /* - * Event-callbacks are already cleared, hence we can safely ignore - * return codes of the context_remove_*() helpers. They cannot be - * originated from user-callbacks, so we already handled them. - */ - while ((device = hashmap_first(c->device_map))) context_remove_device(c, device); @@ -1438,6 +1479,14 @@ void sysview_context_stop(sysview_context *c) { while ((seat = hashmap_first(c->seat_map))) context_remove_seat(c, seat); + + c->running = false; + c->scanned = false; + c->event_fn = NULL; + c->userdata = NULL; + c->scan_src = sd_event_source_unref(c->scan_src); + context_ud_stop(c); + context_ld_stop(c); } static int context_scan_fn(sd_event_source *s, void *userdata) {