int session_send_changed(Session *s, const char *properties) { DBusMessage *m; int r = -ENOMEM; char *p = NULL; assert(s); if (!s->started) return 0; p = session_bus_path(s); if (!p) return -ENOMEM; m = bus_properties_changed_new(p, "org.freedesktop.login1.Session", properties); if (!m) goto finish; if (!dbus_connection_send(s->manager->bus, m, NULL)) goto finish; r = 0; finish: if (m) dbus_message_unref(m); free(p); return r; }
static int convert_x11_to_vconsole(DBusConnection *connection) { bool modified = false; assert(connection); if (isempty(state.x11_layout)) { modified = !isempty(state.vc_keymap) || !isempty(state.vc_keymap_toggle); free_data_x11(); } else { FILE *f; unsigned n = 0; unsigned best_matching = 0; char *new_keymap = NULL; f = fopen(SYSTEMD_KBD_MODEL_MAP, "re"); if (!f) return -errno; for (;;) { char **a; unsigned matching = 0; int r; r = read_next_mapping(f, &n, &a); if (r < 0) { fclose(f); return r; } if (r == 0) break; /* Determine how well matching this entry is */ if (streq_ptr(state.x11_layout, a[1])) /* If we got an exact match, this is best */ matching = 10; else { size_t x; x = strcspn(state.x11_layout, ","); /* We have multiple X layouts, look * for an entry that matches our key * with the everything but the first * layout stripped off. */ if (x > 0 && strlen(a[1]) == x && strncmp(state.x11_layout, a[1], x) == 0) matching = 5; else { size_t w; /* If that didn't work, strip * off the other layouts from * the entry, too */ w = strcspn(a[1], ","); if (x > 0 && x == w && memcmp(state.x11_layout, a[1], x) == 0) matching = 1; } } if (matching > 0 && streq_ptr(state.x11_model, a[2])) { matching++; if (streq_ptr(state.x11_variant, a[3])) { matching++; if (streq_ptr(state.x11_options, a[4])) matching++; } } /* The best matching entry so far, then let's * save that */ if (matching > best_matching) { best_matching = matching; free(new_keymap); new_keymap = strdup(a[0]); if (!new_keymap) { strv_free(a); fclose(f); return -ENOMEM; } } strv_free(a); } fclose(f); if (!streq_ptr(state.vc_keymap, new_keymap)) { free(state.vc_keymap); state.vc_keymap = new_keymap; free(state.vc_keymap_toggle); state.vc_keymap_toggle = NULL; modified = true; } else free(new_keymap); } if (modified) { dbus_bool_t b; DBusMessage *changed; int r; r = write_data_vconsole(); if (r < 0) log_error("Failed to set virtual console keymap: %s", strerror(-r)); changed = bus_properties_changed_new( "/org/freedesktop/locale1", "org.freedesktop.locale1", "VConsoleKeymap\0" "VConsoleKeymapToggle\0"); if (!changed) return -ENOMEM; b = dbus_connection_send(connection, changed, NULL); dbus_message_unref(changed); if (!b) return -ENOMEM; return load_vconsole_keymap(connection, NULL); } return 0; }
static int convert_vconsole_to_x11(DBusConnection *connection) { bool modified = false; assert(connection); if (isempty(state.vc_keymap)) { modified = !isempty(state.x11_layout) || !isempty(state.x11_model) || !isempty(state.x11_variant) || !isempty(state.x11_options); free_data_x11(); } else { FILE *f; unsigned n = 0; f = fopen(SYSTEMD_KBD_MODEL_MAP, "re"); if (!f) return -errno; for (;;) { char **a; int r; r = read_next_mapping(f, &n, &a); if (r < 0) { fclose(f); return r; } if (r == 0) break; if (!streq(state.vc_keymap, a[0])) { strv_free(a); continue; } if (!streq_ptr(state.x11_layout, strnulldash(a[1])) || !streq_ptr(state.x11_model, strnulldash(a[2])) || !streq_ptr(state.x11_variant, strnulldash(a[3])) || !streq_ptr(state.x11_options, strnulldash(a[4]))) { if (free_and_set(&state.x11_layout, strnulldash(a[1])) < 0 || free_and_set(&state.x11_model, strnulldash(a[2])) < 0 || free_and_set(&state.x11_variant, strnulldash(a[3])) < 0 || free_and_set(&state.x11_options, strnulldash(a[4])) < 0) { strv_free(a); fclose(f); return -ENOMEM; } modified = true; } strv_free(a); break; } fclose(f); } if (modified) { dbus_bool_t b; DBusMessage *changed; int r; r = write_data_x11(); if (r < 0) log_error("Failed to set X11 keyboard layout: %s", strerror(-r)); changed = bus_properties_changed_new( "/org/freedesktop/locale1", "org.freedesktop.locale1", "X11Layout\0" "X11Model\0" "X11Variant\0" "X11Options\0"); if (!changed) return -ENOMEM; b = dbus_connection_send(connection, changed, NULL); dbus_message_unref(changed); if (!b) return -ENOMEM; } return 0; }