aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Rostovtsev <tetromino@gentoo.org>2012-09-05 01:29:46 -0400
committerAlexandre Rostovtsev <tetromino@gentoo.org>2012-09-05 01:33:18 -0400
commita0e3c463acbda2d81081e223ef999fdab59a0304 (patch)
tree1f5e363ed7898caa5db90d2eacc880b6cc9da506
parentRespect --debug switch when using >=glib-2.31.2 (diff)
downloadopenrc-settingsd-a0e3c463acbda2d81081e223ef999fdab59a0304.tar.gz
openrc-settingsd-a0e3c463acbda2d81081e223ef999fdab59a0304.tar.bz2
openrc-settingsd-a0e3c463acbda2d81081e223ef999fdab59a0304.zip
Finish SetVConsoleKeyboard() and SetX11Keyboard() implementation
Also, fix xorg.conf.d parser so it works as intended.
-rw-r--r--Makefile.am5
-rw-r--r--TODO2
-rw-r--r--data/kbd-model-map73
-rw-r--r--src/localed.c730
-rw-r--r--src/shell-utils.c80
-rw-r--r--src/shell-utils.h14
6 files changed, 828 insertions, 76 deletions
diff --git a/Makefile.am b/Makefile.am
index 7ae61ed..b0694bf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,10 +5,15 @@ EXTRA_DIST = \
data/locale1.xml \
$(NULL)
+pkgdata_DATA = \
+ data/kbd-model-map \
+ $(NULL)
+
AM_CPPFLAGS = \
-include $(top_builddir)/config.h \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DLIBEXECDIR=\""$(libexecdir)"\" \
+ -DPKGDATADIR=\""$(pkgdatadir)"\" \
$(OPENRC_SETTINGSD_CFLAGS) \
-I$(top_srcdir)/src \
-I$(top_builddir)/src \
diff --git a/TODO b/TODO
index a7feb33..d75749a 100644
--- a/TODO
+++ b/TODO
@@ -9,7 +9,7 @@ document that this case is not supported?
Write an init.d file to read RC_SYS so that we can piggyback on openrc's
built-in virtualization detection.
-Implement localed and timedated.
+Implement timedated.
Do something about runtime dependency on systemd's org.freedesktop.hostname1.policy,
org.freedesktop.locale1.policy, and org.freedesktop.timedate1.policy files.
diff --git a/data/kbd-model-map b/data/kbd-model-map
new file mode 100644
index 0000000..5876801
--- /dev/null
+++ b/data/kbd-model-map
@@ -0,0 +1,73 @@
+# Shamelessly stolen from systemd-44 source (src/locale/kbd-model-map)
+# Generated from system-config-keyboard's model list
+# consolelayout xlayout xmodel xvariant xoptions
+sg ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp
+nl nl pc105 - terminate:ctrl_alt_bksp
+mk-utf mkd,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+trq tr pc105 - terminate:ctrl_alt_bksp
+guj in,us pc105 guj terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+uk gb pc105 - terminate:ctrl_alt_bksp
+is-latin1 is pc105 - terminate:ctrl_alt_bksp
+de de pc105 - terminate:ctrl_alt_bksp
+gur gur,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+la-latin1 latam pc105 - terminate:ctrl_alt_bksp
+us us pc105+inet - terminate:ctrl_alt_bksp
+ko kr pc105 - terminate:ctrl_alt_bksp
+ro-std ro pc105 std terminate:ctrl_alt_bksp
+de-latin1 de pc105 - terminate:ctrl_alt_bksp
+tml-inscript in,us pc105 tam terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+slovene si pc105 - terminate:ctrl_alt_bksp
+hu101 hu pc105 qwerty terminate:ctrl_alt_bksp
+jp106 jp jp106 - terminate:ctrl_alt_bksp
+croat hr pc105 - terminate:ctrl_alt_bksp
+ben-probhat in,us pc105 ben_probhat terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+fi-latin1 fi pc105 - terminate:ctrl_alt_bksp
+it2 it pc105 - terminate:ctrl_alt_bksp
+hu hu pc105 - terminate:ctrl_alt_bksp
+sr-latin rs pc105 latin terminate:ctrl_alt_bksp
+fi fi pc105 - terminate:ctrl_alt_bksp
+fr_CH ch pc105 fr terminate:ctrl_alt_bksp
+dk-latin1 dk pc105 - terminate:ctrl_alt_bksp
+fr fr pc105 - terminate:ctrl_alt_bksp
+it it pc105 - terminate:ctrl_alt_bksp
+tml-uni in,us pc105 tam_TAB terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ua-utf ua,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+fr-latin1 fr pc105 - terminate:ctrl_alt_bksp
+sg-latin1 ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp
+be-latin1 be pc105 - terminate:ctrl_alt_bksp
+dk dk pc105 - terminate:ctrl_alt_bksp
+fr-pc fr pc105 - terminate:ctrl_alt_bksp
+bg_pho-utf8 bg,us pc105 ,phonetic terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+it-ibm it pc105 - terminate:ctrl_alt_bksp
+cz-us-qwertz cz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ar-digits ara,us pc105 digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+br-abnt2 br abnt2 - terminate:ctrl_alt_bksp
+ro ro pc105 - terminate:ctrl_alt_bksp
+us-acentos us pc105 intl terminate:ctrl_alt_bksp
+pt-latin1 pt pc105 - terminate:ctrl_alt_bksp
+ro-std-cedilla ro pc105 std_cedilla terminate:ctrl_alt_bksp
+tj tj pc105 - terminate:ctrl_alt_bksp
+ar-qwerty ara,us pc105 qwerty terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ar-azerty-digits ara,us pc105 azerty_digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ben in,us pc105 ben terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+de-latin1-nodeadkeys de pc105 nodeadkeys terminate:ctrl_alt_bksp
+no no pc105 - terminate:ctrl_alt_bksp
+bg_bds-utf8 bg,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+dvorak us pc105 dvorak terminate:ctrl_alt_bksp
+ru ru,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+cz-lat2 cz pc105 qwerty terminate:ctrl_alt_bksp
+pl2 pl pc105 - terminate:ctrl_alt_bksp
+es es pc105 - terminate:ctrl_alt_bksp
+ro-cedilla ro pc105 cedilla terminate:ctrl_alt_bksp
+ie ie pc105 - terminate:ctrl_alt_bksp
+ar-azerty ara,us pc105 azerty terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+ar-qwerty-digits ara,us pc105 qwerty_digits terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+et ee pc105 - terminate:ctrl_alt_bksp
+sk-qwerty sk pc105 - terminate:ctrl_alt_bksp,qwerty
+dev dev,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
+fr-latin9 fr pc105 latin9 terminate:ctrl_alt_bksp
+fr_CH-latin1 ch pc105 fr terminate:ctrl_alt_bksp
+cf ca(fr) pc105 - terminate:ctrl_alt_bksp
+sv-latin1 se pc105 - terminate:ctrl_alt_bksp
+sr-cy rs pc105 - terminate:ctrl_alt_bksp
+gr gr,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll
diff --git a/src/localed.c b/src/localed.c
index 706a8ed..2e8e44e 100644
--- a/src/localed.c
+++ b/src/localed.c
@@ -16,6 +16,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -58,6 +59,211 @@ static GFile *x11_gentoo_file = NULL;
static GFile *x11_systemd_file = NULL;
G_LOCK_DEFINE_STATIC (xorg_conf);
+/* keyboard model map file parser */
+
+static GFile *kbd_model_map_file = NULL;
+
+GRegex *kbd_model_map_line_comment_re = NULL;
+GRegex *kbd_model_map_line_re = NULL;
+
+struct kbd_model_map_entry {
+ gchar *vconsole_keymap;
+ gchar *x11_layout;
+ gchar *x11_model;
+ gchar *x11_variant;
+ gchar *x11_options;
+};
+
+static void
+kbd_model_map_regex_destroy ()
+{
+ if (kbd_model_map_line_comment_re != NULL) {
+ g_regex_unref (kbd_model_map_line_comment_re);
+ kbd_model_map_line_comment_re = NULL;
+ }
+ if (kbd_model_map_line_re != NULL) {
+ g_regex_unref (kbd_model_map_line_re);
+ kbd_model_map_line_re = NULL;
+ }
+}
+
+static void
+kbd_model_map_regex_init ()
+{
+ if (kbd_model_map_line_comment_re == NULL) {
+ kbd_model_map_line_comment_re = g_regex_new ("^\\s*(?:#.*)?$", G_REGEX_ANCHORED, 0, NULL);
+ g_assert (kbd_model_map_line_comment_re != NULL);
+ }
+ if (kbd_model_map_line_re == NULL) {
+ kbd_model_map_line_re = g_regex_new ("^\\s*(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)", G_REGEX_ANCHORED, 0, NULL);
+ g_assert (kbd_model_map_line_re != NULL);
+ }
+}
+
+static gboolean
+kbd_model_map_entry_matches_vconsole (const struct kbd_model_map_entry *entry,
+ const gchar *vconsole_keymap)
+{
+ return !g_strcmp0 (vconsole_keymap, entry->vconsole_keymap);
+}
+
+static gboolean
+matches_delimeted (const gchar *left,
+ const gchar *right,
+ const gchar *delimeter,
+ unsigned int *failure_score)
+{
+ gboolean ret = FALSE;
+ gchar **leftv = NULL, **rightv = NULL;
+ gchar **leftcur = NULL, **rightcur = NULL;
+
+ if (left == NULL || left[0] == 0)
+ leftv = g_new0 (gchar *, 1);
+ else
+ leftv = g_strsplit (left, delimeter, 0);
+
+ if (right == NULL || right[0] == 0)
+ rightv = g_new0 (gchar *, 1);
+ else
+ rightv = g_strsplit (right, delimeter, 0);
+
+ if (failure_score != NULL)
+ *failure_score = 0;
+
+ for (leftcur = leftv; *leftcur != NULL; leftcur++) {
+ gboolean found = FALSE;
+ for (rightcur = rightv; *rightcur != NULL; rightcur++)
+ if (!g_strcmp0 (*leftcur, *rightcur)) {
+ found = TRUE;
+ break;
+ }
+ if (found)
+ ret = TRUE;
+ else if (failure_score != NULL)
+ (*failure_score)++;
+ }
+
+ for (rightcur = rightv; *rightcur != NULL; rightcur++) {
+ gboolean found = FALSE;
+ for (leftcur = leftv; *leftcur != NULL; leftcur++)
+ if (!g_strcmp0 (*rightcur, *leftcur)) {
+ found = TRUE;
+ break;
+ }
+ if (found)
+ ret = TRUE;
+ else if (failure_score != NULL)
+ (*failure_score)++;
+ }
+
+ g_strfreev (leftv);
+ g_strfreev (rightv);
+ return ret;
+}
+
+static gboolean
+kbd_model_map_entry_matches_x11 (const struct kbd_model_map_entry *entry,
+ const gchar *_x11_layout,
+ const gchar *_x11_model,
+ const gchar *_x11_variant,
+ const gchar *_x11_options,
+ unsigned int *failure_score)
+{
+ unsigned int x11_layout_failures;
+ gboolean ret = FALSE;
+
+ ret = matches_delimeted (_x11_layout, entry->x11_layout, ",", &x11_layout_failures);
+ if (failure_score != NULL)
+ *failure_score = 10000 * !ret +
+ 100 * x11_layout_failures +
+ (g_strcmp0 (_x11_model, entry->x11_model) ? 1 : 0) +
+ 10 * (g_strcmp0 (_x11_variant, entry->x11_variant) ? 1 : 0) +
+ !matches_delimeted (_x11_options, entry->x11_options, ",", NULL);
+ return ret;
+}
+
+static void
+kbd_model_map_entry_free (struct kbd_model_map_entry *entry)
+{
+ if (entry == NULL)
+ return;
+
+ g_free (entry->vconsole_keymap);
+ g_free (entry->x11_layout);
+ g_free (entry->x11_model);
+ g_free (entry->x11_variant);
+ g_free (entry->x11_options);
+
+ g_free (entry);
+}
+
+static GList*
+kbd_model_map_load (GError **error)
+{
+ GList *ret = NULL;
+ gchar *filename = NULL, *filebuf = NULL, *line = NULL, *newline = NULL;
+ struct kbd_model_map_entry *entry = NULL;
+
+ filename = g_file_get_path (kbd_model_map_file);
+ g_debug ("Parsing keyboard model map file file: '%s'", filename);
+
+ if (!g_file_load_contents (kbd_model_map_file, NULL, &filebuf, NULL, NULL, error)) {
+ g_prefix_error (error, "Unable to read '%s':", filename);
+ goto out;
+ }
+
+ for (line = filebuf; *line != 0; line = newline + 1) {
+ struct kbd_model_map_entry *entry = NULL;
+ GMatchInfo *match_info = NULL;
+
+ if ((newline = strstr (line, "\n")) != NULL)
+ *newline = 0;
+ else
+ newline = line + strlen (line) - 1;
+
+ if (g_regex_match (kbd_model_map_line_comment_re, line, 0, &match_info)) {
+ g_match_info_free (match_info);
+ continue;
+ }
+
+ if (!g_regex_match (kbd_model_map_line_re, line, 0, &match_info)) {
+ g_propagate_error (error,
+ g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "Failed to parse line '%s' in '%s'", line, filename));
+ g_match_info_free (match_info);
+ if (ret != NULL) {
+ g_list_free_full (ret, (GDestroyNotify)kbd_model_map_entry_free);
+ ret = NULL;
+ }
+ goto out;
+ }
+ entry = g_new0 (struct kbd_model_map_entry, 1);
+ entry->vconsole_keymap = g_match_info_fetch (match_info, 1);
+ entry->x11_layout = g_match_info_fetch (match_info, 2);
+ entry->x11_model = g_match_info_fetch (match_info, 3);
+ entry->x11_variant = g_match_info_fetch (match_info, 4);
+ entry->x11_options = g_match_info_fetch (match_info, 5);
+
+ // "-" in the map file stands for an empty string
+ if (!g_strcmp0 (entry->x11_model, "-"))
+ entry->x11_model[0] = 0;
+ if (!g_strcmp0 (entry->x11_variant, "-"))
+ entry->x11_variant[0] = 0;
+ if (!g_strcmp0 (entry->x11_options, "-"))
+ entry->x11_options[0] = 0;
+
+ ret = g_list_prepend (ret, entry);
+ g_match_info_free (match_info);
+ }
+ out:
+ if (ret != NULL)
+ ret = g_list_reverse (ret);
+
+ g_free (filename);
+ g_free (filebuf);
+ return ret;
+}
+
/* Trivial /etc/X11/xorg.conf.d/30-keyboard.conf parser */
enum XORG_CONFD_LINE_TYPE {
@@ -141,7 +347,7 @@ static void
xorg_confd_regex_init ()
{
if (xorg_confd_line_comment_re == NULL) {
- xorg_confd_line_comment_re = g_regex_new ("^\\s*#", G_REGEX_ANCHORED|G_REGEX_CASELESS, 0, NULL);
+ xorg_confd_line_comment_re = g_regex_new ("^\\s*#", G_REGEX_ANCHORED, 0, NULL);
g_assert (xorg_confd_line_comment_re != NULL);
}
if (xorg_confd_line_section_input_class_re == NULL) {
@@ -190,7 +396,6 @@ xorg_confd_line_entry_free (struct xorg_confd_line_entry *entry)
g_free (entry);
}
-/* Note that string and value are not duplicated */
static struct xorg_confd_line_entry *
xorg_confd_line_entry_new (const gchar *string,
const gchar *value,
@@ -202,6 +407,7 @@ xorg_confd_line_entry_new (const gchar *string,
entry->string = g_strdup (string);
entry->value = g_strdup (value);
entry->type = type;
+ return entry;
}
static void
@@ -226,9 +432,7 @@ xorg_confd_parser_new (GFile *xorg_confd_file,
GError **error)
{
struct xorg_confd_parser *parser = NULL;
- gchar *filebuf = NULL;
- gchar **linebuf = NULL;
- gchar **lines = NULL;
+ gchar *filebuf = NULL, *line = NULL, *newline = NULL;
GList *input_class_section_start = NULL;
gboolean in_section = FALSE, in_xkb_section = FALSE;
@@ -244,63 +448,64 @@ xorg_confd_parser_new (GFile *xorg_confd_file,
goto fail;
}
- lines = g_strsplit (filebuf, "\n", 0);
- if (lines == NULL)
- goto out;
-
- for (linebuf = lines; *linebuf != NULL; linebuf++) {
+ for (line = filebuf; *line != 0; line = newline + 1) {
struct xorg_confd_line_entry *entry = NULL;
GMatchInfo *match_info = NULL;
gboolean matched = FALSE;
- entry = xorg_confd_line_entry_new (*linebuf, NULL, XORG_CONFD_LINE_TYPE_UNKNOWN);
+ if ((newline = strstr (line, "\n")) != NULL)
+ *newline = 0;
+ else
+ newline = line + strlen (line) - 1;
+
+ entry = xorg_confd_line_entry_new (line, NULL, XORG_CONFD_LINE_TYPE_UNKNOWN);
- if (g_regex_match (xorg_confd_line_comment_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as comment", *linebuf);
+ if (g_regex_match (xorg_confd_line_comment_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as comment", line);
entry->type = XORG_CONFD_LINE_TYPE_COMMENT;
- } else if (g_regex_match (xorg_confd_line_section_input_class_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as InputClass section", *linebuf);
+ } else if (g_regex_match (xorg_confd_line_section_input_class_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as InputClass section", line);
if (in_section)
goto no_match;
in_section = TRUE;
entry->type = XORG_CONFD_LINE_TYPE_SECTION_INPUT_CLASS;
- } else if (g_regex_match (xorg_confd_line_section_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as non-InputClass section", *linebuf);
+ } else if (g_regex_match (xorg_confd_line_section_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as non-InputClass section", line);
if (in_section)
goto no_match;
in_section = TRUE;
entry->type = XORG_CONFD_LINE_TYPE_SECTION_OTHER;
- } else if (g_regex_match (xorg_confd_line_end_section_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as end of section", *linebuf);
+ } else if (g_regex_match (xorg_confd_line_end_section_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as end of section", line);
if (!in_section)
goto no_match;
entry->type = XORG_CONFD_LINE_TYPE_END_SECTION;
- } else if (g_regex_match (xorg_confd_line_match_is_keyboard_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as MatchIsKeyboard declaration", *linebuf);
+ } else if (g_regex_match (xorg_confd_line_match_is_keyboard_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as MatchIsKeyboard declaration", line);
if (!in_section)
goto no_match;
entry->type = XORG_CONFD_LINE_TYPE_MATCH_IS_KEYBOARD;
in_xkb_section = TRUE;
- } else if (g_regex_match (xorg_confd_line_xkb_layout_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as XkbLayout option", *linebuf);
+ } else if (g_regex_match (xorg_confd_line_xkb_layout_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as XkbLayout option", line);
if (!in_section)
goto no_match;
entry->type = XORG_CONFD_LINE_TYPE_XKB_LAYOUT;
entry->value = g_match_info_fetch (match_info, 2);
- } else if (g_regex_match (xorg_confd_line_xkb_model_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as XkbModel option", *linebuf);
+ } else if (g_regex_match (xorg_confd_line_xkb_model_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as XkbModel option", line);
if (!in_section)
goto no_match;
entry->type = XORG_CONFD_LINE_TYPE_XKB_MODEL;
entry->value = g_match_info_fetch (match_info, 2);
- } else if (g_regex_match (xorg_confd_line_xkb_variant_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as XkbVariant option", *linebuf);
+ } else if (g_regex_match (xorg_confd_line_xkb_variant_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as XkbVariant option", line);
if (!in_section)
goto no_match;
entry->type = XORG_CONFD_LINE_TYPE_XKB_VARIANT;
entry->value = g_match_info_fetch (match_info, 2);
- } else if (g_regex_match (xorg_confd_line_xkb_options_re, *linebuf, 0, &match_info)) {
- g_debug ("Parsed line '%s' as XkbOptions option", *linebuf);
+ } else if (g_regex_match (xorg_confd_line_xkb_options_re, line, 0, &match_info)) {
+ g_debug ("Parsed line '%s' as XkbOptions option", line);
if (!in_section)
goto no_match;
entry->type = XORG_CONFD_LINE_TYPE_XKB_OPTIONS;
@@ -308,7 +513,7 @@ xorg_confd_parser_new (GFile *xorg_confd_file,
}
if (entry->type == XORG_CONFD_LINE_TYPE_UNKNOWN)
- g_debug ("Parsing line '%s' as unknown", *linebuf);
+ g_debug ("Parsing line '%s' as unknown", line);
g_match_info_free (match_info);
parser->line_list = g_list_prepend (parser->line_list, entry);
@@ -342,7 +547,6 @@ xorg_confd_parser_new (GFile *xorg_confd_file,
out:
g_free (filebuf);
- g_strfreev (lines);
return parser;
parse_fail:
@@ -351,7 +555,6 @@ xorg_confd_parser_new (GFile *xorg_confd_file,
"Unable to parse '%s'", parser->filename));
fail:
g_free (filebuf);
- g_strfreev (lines);
xorg_confd_parser_free (parser);
return NULL;
}
@@ -402,17 +605,24 @@ xorg_confd_parser_line_set_or_delete (GList *line,
if (value == NULL || !g_strcmp0 (value, "")) {
/* If value is null, we delete the line and return previous one */
- GList *prev = line->prev;
- prev->next = line->next;
- prev->next->prev = prev;
+ g_debug ("Deleting entry '%s'", entry->string);
+ GList *prev, *next;
+
+ prev = line->prev;
+ next = line->next;
line->prev = NULL;
line->next = NULL;
g_list_free_full (line, (GDestroyNotify)xorg_confd_line_entry_free);
+ if (prev != NULL)
+ prev->next = next;
+ if (next != NULL)
+ next->prev = prev;
return prev;
}
entry->value = g_strdup (value);
- replacement = g_strdup_printf ("\1\"%s\"", value);
- replaced = g_regex_replace (re, entry->string, 0, 0, replacement, 0, NULL);
+ replacement = g_strdup_printf ("\\1\"%s\"", value);
+ replaced = g_regex_replace (re, entry->string, -1, 0, replacement, 0, NULL);
+ g_debug ("Setting entry '%s' to new value '%s' i.e. '%s'", entry->string, value, replaced);
g_free (replacement);
g_free (entry->string);
entry->string = replaced;
@@ -429,24 +639,25 @@ xorg_confd_parser_set_xkb (struct xorg_confd_parser *parser,
{
GList *curr = NULL, *end = NULL;
gboolean layout_found = FALSE, model_found = FALSE, variant_found = FALSE, options_found = FALSE;
+ struct xorg_confd_line_entry *entry = NULL;
+ gchar *string = NULL;
if (parser == NULL)
return;
if (parser->section == NULL) {
- struct xorg_confd_line_entry *entry = NULL;
GList *section = NULL;
- entry = xorg_confd_line_entry_new ("Section \"InputClass\"\n", NULL, XORG_CONFD_LINE_TYPE_SECTION_INPUT_CLASS);
+ entry = xorg_confd_line_entry_new ("Section \"InputClass\"", NULL, XORG_CONFD_LINE_TYPE_SECTION_INPUT_CLASS);
section = g_list_prepend (section, entry);
- entry = xorg_confd_line_entry_new (" Identifier \"keyboard-all\"\n", NULL, XORG_CONFD_LINE_TYPE_UNKNOWN);
+ entry = xorg_confd_line_entry_new (" Identifier \"keyboard-all\"", NULL, XORG_CONFD_LINE_TYPE_UNKNOWN);
section = g_list_prepend (section, entry);
- entry = entry = xorg_confd_line_entry_new (" MatchIsKeyboard \"on\"\n", NULL, XORG_CONFD_LINE_TYPE_MATCH_IS_KEYBOARD);
+ entry = entry = xorg_confd_line_entry_new (" MatchIsKeyboard \"on\"", NULL, XORG_CONFD_LINE_TYPE_MATCH_IS_KEYBOARD);
section = g_list_prepend (section, entry);
- entry = entry = xorg_confd_line_entry_new ("EndSection\n", NULL, XORG_CONFD_LINE_TYPE_END_SECTION);
+ entry = entry = xorg_confd_line_entry_new ("EndSection", NULL, XORG_CONFD_LINE_TYPE_END_SECTION);
section = g_list_prepend (section, entry);
section = g_list_reverse (section);
@@ -455,7 +666,7 @@ xorg_confd_parser_set_xkb (struct xorg_confd_parser *parser,
}
for (curr = parser->section; curr != NULL; curr = curr->next) {
- struct xorg_confd_line_entry *entry = (struct xorg_confd_line_entry *) curr->data;
+ entry = (struct xorg_confd_line_entry *) curr->data;
if (entry->type == XORG_CONFD_LINE_TYPE_END_SECTION) {
end = curr;
@@ -474,38 +685,31 @@ xorg_confd_parser_set_xkb (struct xorg_confd_parser *parser,
curr = xorg_confd_parser_line_set_or_delete (curr, options, xorg_confd_line_xkb_options_re);
}
}
- if (!layout_found && layout != NULL && g_strcmp0 (layout, "")) {
- struct xorg_confd_line_entry *entry;
- gchar *string;
+ if (!layout_found && layout != NULL && g_strcmp0 (layout, "")) {
string = g_strdup_printf (" Option \"XkbLayout\" \"%s\"", layout);
+ g_debug ("Inserting new entry: '%s'", string);
entry = xorg_confd_line_entry_new (string, layout, XORG_CONFD_LINE_TYPE_XKB_LAYOUT);
parser->line_list = g_list_insert_before (parser->line_list, end, entry);
g_free (string);
}
if (!model_found && model != NULL && g_strcmp0 (model, "")) {
- struct xorg_confd_line_entry *entry;
- gchar *string;
-
string = g_strdup_printf (" Option \"XkbModel\" \"%s\"", model);
+ g_debug ("Inserting new entry: '%s'", string);
entry = xorg_confd_line_entry_new (string, model, XORG_CONFD_LINE_TYPE_XKB_MODEL);
parser->line_list = g_list_insert_before (parser->line_list, end, entry);
g_free (string);
}
if (!variant_found && variant != NULL && g_strcmp0 (variant, "")) {
- struct xorg_confd_line_entry *entry;
- gchar *string;
-
string = g_strdup_printf (" Option \"XkbVariant\" \"%s\"", variant);
+ g_debug ("Inserting new entry: '%s'", string);
entry = xorg_confd_line_entry_new (string, variant, XORG_CONFD_LINE_TYPE_XKB_VARIANT);
parser->line_list = g_list_insert_before (parser->line_list, end, entry);
g_free (string);
}
if (!options_found && options != NULL && g_strcmp0 (options, "")) {
- struct xorg_confd_line_entry *entry;
- gchar *string;
-
string = g_strdup_printf (" Option \"XkbOptions\" \"%s\"", options);
+ g_debug ("Inserting new entry: '%s'", string);
entry = xorg_confd_line_entry_new (string, options, XORG_CONFD_LINE_TYPE_XKB_OPTIONS);
parser->line_list = g_list_insert_before (parser->line_list, end, entry);
g_free (string);
@@ -556,19 +760,268 @@ xorg_confd_parser_save (const struct xorg_confd_parser *parser,
/* End of trivial /etc/X11/xorg.conf.d/30-keyboard.conf parser */
static gboolean
+locale_name_is_valid (gchar *name)
+{
+ return g_regex_match_simple ("^[a-zA-Z0-9_.@-]*$", name, G_REGEX_MULTILINE, 0);
+}
+
+struct invoked_locale {
+ GDBusMethodInvocation *invocation;
+ gchar **locale; /* newly allocated */
+};
+
+static void
+invoked_locale_free (struct invoked_locale *data)
+{
+ if (data == NULL)
+ return;
+ g_strfreev (data->locale);
+ g_free (data);
+}
+
+static void
+on_handle_set_locale_authorized_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ struct invoked_locale *data;
+ gchar **loc, **var, **val, **locale_values = NULL;
+ ShellUtilsTrivial *locale_file_parsed = NULL;
+
+ data = (struct invoked_locale *) user_data;
+ if (!check_polkit_finish (res, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto out;
+ }
+
+ G_LOCK (locale);
+ locale_values = g_new0 (gchar *, g_strv_length (locale_variables) + 1);
+ /* Don't allow unknown locale variables or invalid values */
+ if (data->locale != NULL) {
+ for (loc = data->locale; *loc != NULL; loc++) {
+ gboolean found = FALSE;
+ for (val = locale_values, var = locale_variables; *var != NULL; val++, var++) {
+ size_t varlen;
+ gchar *unquoted = NULL;
+
+ varlen = strlen (*var);
+ if (g_str_has_prefix (*loc, *var) && (*loc)[varlen] == '=' &&
+ (unquoted = g_shell_unquote (*loc + varlen + 1, NULL)) != NULL &&
+ locale_name_is_valid (unquoted)) {
+ found = TRUE;
+ if (*val != NULL)
+ g_free (*val);
+ *val = unquoted;
+ } else
+ g_free (unquoted);
+ }
+ if (!found) {
+ g_dbus_method_invocation_return_dbus_error (data->invocation, DBUS_ERROR_INVALID_ARGS,
+ "Invalid locale variable name or value");
+ G_UNLOCK (locale);
+ goto out;
+ }
+ }
+ }
+
+ if ((locale_file_parsed = shell_utils_trivial_new (locale_file, &err)) == NULL) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ G_UNLOCK (locale);
+ goto out;
+ }
+
+ if (shell_utils_trivial_is_empty (locale_file_parsed)) {
+ /* Simply write the new env file */
+ shell_utils_trivial_free (locale_file_parsed);
+ if ((locale_file_parsed = shell_utils_trivial_new_from_string (locale_file, "# Configuration file for eselect\n# This file has been automatically generated\n", &err)) == NULL) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ G_UNLOCK (locale);
+ goto out;
+ }
+ }
+
+ for (val = locale_values, var = locale_variables; *var != NULL; val++, var++) {
+ if (*val == NULL)
+ shell_utils_trivial_clear_variable (locale_file_parsed, *var);
+ else
+ shell_utils_trivial_set_variable (locale_file_parsed, *var, *val, TRUE);
+ }
+
+ if (!shell_utils_trivial_save (locale_file_parsed, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ G_UNLOCK (locale);
+ goto out;
+ }
+
+ g_strfreev (locale);
+ locale = g_new0 (gchar *, g_strv_length (locale_variables) + 1);
+ loc = locale;
+ for (val = locale_values, var = locale_variables; *var != NULL; val++, var++) {
+ if (*val != NULL) {
+ *loc = g_strdup_printf ("%s=%s", *var, *val);
+ loc++;
+ }
+ }
+
+ openrc_settingsd_localed_locale1_complete_set_locale (locale1, data->invocation);
+ openrc_settingsd_localed_locale1_set_locale (locale1, (const gchar * const *) locale);
+ G_UNLOCK (locale);
+
+ out:
+ shell_utils_trivial_free (locale_file_parsed);
+ g_strfreev (locale_values);
+ invoked_locale_free (data);
+ if (err != NULL)
+ g_error_free (err);
+}
+
+static gboolean
on_handle_set_locale (OpenrcSettingsdLocaledLocale1 *locale1,
GDBusMethodInvocation *invocation,
const gchar * const *_locale,
const gboolean user_interaction,
gpointer user_data)
{
- g_dbus_method_invocation_return_dbus_error (invocation,
- DBUS_ERROR_NOT_SUPPORTED,
- SERVICE_NAME " is in read-only mode");
+ if (read_only)
+ g_dbus_method_invocation_return_dbus_error (invocation,
+ DBUS_ERROR_NOT_SUPPORTED,
+ SERVICE_NAME " is in read-only mode");
+ else {
+ struct invoked_locale *data;
+ data = g_new0 (struct invoked_locale, 1);
+ data->invocation = invocation;
+ data->locale = g_strdupv ((gchar**)_locale);
+ check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.locale1.set-locale", user_interaction, on_handle_set_locale_authorized_cb, data);
+ }
return TRUE;
}
+struct invoked_vconsole_keyboard {
+ GDBusMethodInvocation *invocation;
+ gchar *vconsole_keymap; /* newly allocated */
+ gchar *vconsole_keymap_toggle; /* newly allocated */
+ gboolean convert;
+};
+
+static void
+invoked_vconsole_keyboard_free (struct invoked_vconsole_keyboard *data)
+{
+ if (data == NULL)
+ return;
+ g_free (data->vconsole_keymap);
+ g_free (data->vconsole_keymap_toggle);
+ g_free (data);
+}
+
+static void
+on_handle_set_vconsole_keyboard_authorized_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ struct invoked_vconsole_keyboard *data;
+ GList *kbd_model_map = NULL;
+ struct kbd_model_map_entry *best_entry = NULL;
+ struct xorg_confd_parser *x11_parser = NULL;
+
+ data = (struct invoked_vconsole_keyboard *) user_data;
+ if (!check_polkit_finish (res, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto out;
+ }
+
+ G_LOCK (keymaps);
+ if (data->convert) {
+ GList *cur;
+
+ G_LOCK (xorg_conf);
+ kbd_model_map = kbd_model_map_load (&err);
+ if (err != NULL) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto unlock;
+ }
+
+ for (cur = kbd_model_map; cur->next != NULL; cur = cur->next) {
+ struct kbd_model_map_entry *cur_entry = NULL;
+ cur_entry = (struct kbd_model_map_entry *) cur->data;
+ if (kbd_model_map_entry_matches_vconsole (cur_entry, data->vconsole_keymap)) {
+ best_entry = cur_entry;
+ break;
+ }
+ }
+ }
+
+ /* We do not set vconsole_keymap_toggle because there is no good equivalent for it in OpenRC */
+ if (!shell_utils_trivial_set_and_save (keymaps_file, &err, "keymap", NULL, data->vconsole_keymap, NULL)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto unlock;
+ }
+
+ g_free (vconsole_keymap);
+ vconsole_keymap = g_strdup (data->vconsole_keymap);
+ openrc_settingsd_localed_locale1_set_vconsole_keymap (locale1, vconsole_keymap);
+
+ if (data->convert) {
+ if (best_entry == NULL) {
+ gchar *filename;
+ filename = g_file_get_path (kbd_model_map_file);
+ g_printerr ("Failed to find conversion entry for console keymap '%s' in '%s'\n", data->vconsole_keymap, filename);
+ g_free (filename);
+ G_UNLOCK (xorg_conf);
+ } else {
+ unsigned int failure_score = 0;
+
+ kbd_model_map_entry_matches_x11 (best_entry, x11_layout, x11_model, x11_variant, x11_options, &failure_score);
+ if (failure_score > 0) {
+ /* The xkb data has changed, so we want to update it */
+ if (!g_file_query_exists (x11_gentoo_file, NULL) && g_file_query_exists (x11_systemd_file, NULL))
+ x11_parser = xorg_confd_parser_new (x11_systemd_file, &err);
+ else
+ x11_parser = xorg_confd_parser_new (x11_gentoo_file, &err);
+
+ if (x11_parser == NULL) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto unlock;
+ }
+ xorg_confd_parser_set_xkb (x11_parser, best_entry->x11_layout, best_entry->x11_model, best_entry->x11_variant, best_entry->x11_options);
+ if (!xorg_confd_parser_save (x11_parser, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto unlock;
+ }
+ g_free (x11_layout);
+ g_free (x11_model);
+ g_free (x11_variant);
+ g_free (x11_options);
+ x11_layout = g_strdup (best_entry->x11_layout);
+ x11_model = g_strdup (best_entry->x11_model);
+ x11_variant = g_strdup (best_entry->x11_variant);
+ x11_options = g_strdup (best_entry->x11_options);
+ openrc_settingsd_localed_locale1_set_x11_layout (locale1, x11_layout);
+ openrc_settingsd_localed_locale1_set_x11_model (locale1, x11_model);
+ openrc_settingsd_localed_locale1_set_x11_variant (locale1, x11_variant);
+ openrc_settingsd_localed_locale1_set_x11_options (locale1, x11_options);
+ }
+ }
+ }
+ /* We do not modify vconsole_keymap_toggle because there is no good equivalent for it in OpenRC */
+ openrc_settingsd_localed_locale1_complete_set_vconsole_keyboard (locale1, data->invocation);
+
+ unlock:
+ if (data->convert)
+ G_UNLOCK (xorg_conf);
+ G_UNLOCK (keymaps);
+
+ out:
+ if (kbd_model_map != NULL)
+ g_list_free_full (kbd_model_map, (GDestroyNotify)kbd_model_map_entry_free);
+ xorg_confd_parser_free (x11_parser);
+ invoked_vconsole_keyboard_free (data);
+ if (err != NULL)
+ g_error_free (err);
+}
+
static gboolean
on_handle_set_vconsole_keyboard (OpenrcSettingsdLocaledLocale1 *locale1,
GDBusMethodInvocation *invocation,
@@ -578,13 +1031,146 @@ on_handle_set_vconsole_keyboard (OpenrcSettingsdLocaledLocale1 *locale1,
const gboolean user_interaction,
gpointer user_data)
{
- g_dbus_method_invocation_return_dbus_error (invocation,
- DBUS_ERROR_NOT_SUPPORTED,
- SERVICE_NAME " is in read-only mode");
+ if (read_only)
+ g_dbus_method_invocation_return_dbus_error (invocation,
+ DBUS_ERROR_NOT_SUPPORTED,
+ SERVICE_NAME " is in read-only mode");
+ else {
+ struct invoked_vconsole_keyboard *data;
+ data = g_new0 (struct invoked_vconsole_keyboard, 1);
+ data->invocation = invocation;
+ data->vconsole_keymap = g_strdup (keymap);
+ data->vconsole_keymap_toggle = g_strdup (keymap_toggle);
+ data->convert = convert;
+ check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.locale1.set-keyboard", user_interaction, on_handle_set_vconsole_keyboard_authorized_cb, data);
+ }
return TRUE;
}
+struct invoked_x11_keyboard {
+ GDBusMethodInvocation *invocation;
+ gchar *x11_layout; /* newly allocated */
+ gchar *x11_model; /* newly allocated */
+ gchar *x11_variant; /* newly allocated */
+ gchar *x11_options; /* newly allocated */
+ gboolean convert;
+};
+
+static void
+invoked_x11_keyboard_free (struct invoked_x11_keyboard *data)
+{
+ if (data == NULL)
+ return;
+ g_free (data->x11_layout);
+ g_free (data->x11_model);
+ g_free (data->x11_variant);
+ g_free (data->x11_options);
+ g_free (data);
+}
+
+static void
+on_handle_set_x11_keyboard_authorized_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ struct invoked_x11_keyboard *data;
+ GList *kbd_model_map = NULL;
+ struct kbd_model_map_entry *best_entry = NULL;
+ unsigned int best_failure_score = UINT_MAX;
+ struct xorg_confd_parser *x11_parser = NULL;
+
+ data = (struct invoked_x11_keyboard *) user_data;
+ if (!check_polkit_finish (res, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto out;
+ }
+
+ G_LOCK (xorg_conf);
+ if (data->convert) {
+ GList *cur;
+
+ G_LOCK (keymaps);
+ kbd_model_map = kbd_model_map_load (&err);
+ if (err != NULL) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto unlock;
+ }
+
+ for (cur = kbd_model_map; cur->next != NULL; cur = cur->next) {
+ struct kbd_model_map_entry *cur_entry = NULL;
+ unsigned int cur_failure_score = 0;
+
+ cur_entry = (struct kbd_model_map_entry *) cur->data;
+ if (kbd_model_map_entry_matches_x11 (cur_entry, data->x11_layout, data->x11_model, data->x11_variant, data->x11_options, &cur_failure_score))
+ if (cur_failure_score < best_failure_score) {
+ best_entry = cur_entry;
+ best_failure_score = cur_failure_score;
+ }
+ }
+ }
+
+ if (!g_file_query_exists (x11_gentoo_file, NULL) && g_file_query_exists (x11_systemd_file, NULL))
+ x11_parser = xorg_confd_parser_new (x11_systemd_file, &err);
+ else
+ x11_parser = xorg_confd_parser_new (x11_gentoo_file, &err);
+
+ if (x11_parser == NULL) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto unlock;
+ }
+ xorg_confd_parser_set_xkb (x11_parser, data->x11_layout, data->x11_model, data->x11_variant, data->x11_options);
+ if (!xorg_confd_parser_save (x11_parser, &err)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto unlock;
+ }
+ g_free (x11_layout);
+ g_free (x11_model);
+ g_free (x11_variant);
+ g_free (x11_options);
+ x11_layout = g_strdup (data->x11_layout);
+ x11_model = g_strdup (data->x11_model);
+ x11_variant = g_strdup (data->x11_variant);
+ x11_options = g_strdup (data->x11_options);
+ openrc_settingsd_localed_locale1_set_x11_layout (locale1, x11_layout);
+ openrc_settingsd_localed_locale1_set_x11_model (locale1, x11_model);
+ openrc_settingsd_localed_locale1_set_x11_variant (locale1, x11_variant);
+ openrc_settingsd_localed_locale1_set_x11_options (locale1, x11_options);
+
+ if (data->convert) {
+ if (best_entry == NULL) {
+ gchar *filename;
+ filename = g_file_get_path (kbd_model_map_file);
+ g_printerr ("Failed to find conversion entry for x11 layout '%s' in '%s'\n", data->x11_layout, filename);
+ g_free (filename);
+ } else {
+ if (!shell_utils_trivial_set_and_save (keymaps_file, &err, "keymap", NULL, best_entry->vconsole_keymap, NULL)) {
+ g_dbus_method_invocation_return_gerror (data->invocation, err);
+ goto unlock;
+ }
+ g_free (vconsole_keymap);
+ vconsole_keymap = g_strdup (best_entry->vconsole_keymap);
+ openrc_settingsd_localed_locale1_set_vconsole_keymap (locale1, vconsole_keymap);
+ }
+ }
+
+ openrc_settingsd_localed_locale1_complete_set_x11_keyboard (locale1, data->invocation);
+
+ unlock:
+ if (data->convert)
+ G_UNLOCK (keymaps);
+ G_UNLOCK (xorg_conf);
+
+ out:
+ if (kbd_model_map != NULL)
+ g_list_free_full (kbd_model_map, (GDestroyNotify)kbd_model_map_entry_free);
+ xorg_confd_parser_free (x11_parser);
+ invoked_x11_keyboard_free (data);
+ if (err != NULL)
+ g_error_free (err);
+}
+
static gboolean
on_handle_set_x11_keyboard (OpenrcSettingsdLocaledLocale1 *locale1,
GDBusMethodInvocation *invocation,
@@ -596,9 +1182,21 @@ on_handle_set_x11_keyboard (OpenrcSettingsdLocaledLocale1 *locale1,
const gboolean user_interaction,
gpointer user_data)
{
- g_dbus_method_invocation_return_dbus_error (invocation,
- DBUS_ERROR_NOT_SUPPORTED,
- SERVICE_NAME " is in read-only mode");
+ if (read_only)
+ g_dbus_method_invocation_return_dbus_error (invocation,
+ DBUS_ERROR_NOT_SUPPORTED,
+ SERVICE_NAME " is in read-only mode");
+ else {
+ struct invoked_x11_keyboard *data;
+ data = g_new0 (struct invoked_x11_keyboard, 1);
+ data->invocation = invocation;
+ data->x11_layout = g_strdup (layout);
+ data->x11_model = g_strdup (model);
+ data->x11_variant = g_strdup (variant);
+ data->x11_options = g_strdup (options);
+ data->convert = convert;
+ check_polkit_async (g_dbus_method_invocation_get_sender (invocation), "org.freedesktop.locale1.set-keyboard", user_interaction, on_handle_set_x11_keyboard_authorized_cb, data);
+ }
return TRUE;
}
@@ -666,6 +1264,7 @@ localed_init (gboolean _read_only)
struct xorg_confd_parser *x11_parser = NULL;
read_only = _read_only;
+ kbd_model_map_file = g_file_new_for_path (PKGDATADIR "/kbd-model-map");
locale_file = g_file_new_for_path (SYSCONFDIR "/env.d/02locale");
keymaps_file = g_file_new_for_path (SYSCONFDIR "/conf.d/keymaps");
@@ -703,6 +1302,7 @@ localed_init (gboolean _read_only)
/* We don't have a good equivalent for this in openrc at the moment */
vconsole_keymap_toggle = g_strdup ("");
+ kbd_model_map_regex_init ();
xorg_confd_regex_init ();
if (!g_file_query_exists (x11_gentoo_file, NULL) && g_file_query_exists (x11_systemd_file, NULL))
@@ -735,6 +1335,7 @@ localed_destroy (void)
bus_id = 0;
read_only = FALSE;
g_strfreev (locale);
+ kbd_model_map_regex_destroy ();
xorg_confd_regex_destroy ();
g_free (vconsole_keymap);
g_free (vconsole_keymap_toggle);
@@ -747,4 +1348,5 @@ localed_destroy (void)
g_object_unref (keymaps_file);
g_object_unref (x11_gentoo_file);
g_object_unref (x11_systemd_file);
+ g_object_unref (kbd_model_map_file);
}
diff --git a/src/shell-utils.c b/src/shell-utils.c
index db67303..545c5dd 100644
--- a/src/shell-utils.c
+++ b/src/shell-utils.c
@@ -131,31 +131,51 @@ shell_utils_trivial_new (GFile *file,
GError **error)
{
gchar *filebuf = NULL;
- ShellUtilsTrivial *ret = NULL;
GError *local_err = NULL;
- gchar *s;
if (file == NULL)
return NULL;
- ret = g_new0 (ShellUtilsTrivial, 1);
- g_object_ref (file);
- ret->file = file;
- ret->filename = g_file_get_path (file);
-
if (!g_file_load_contents (file, NULL, &filebuf, NULL, NULL, &local_err)) {
if (local_err != NULL) {
/* Inability to parse or open is a failure; file not existing at all is *not* a failure */
if (local_err->code == G_IO_ERROR_NOT_FOUND) {
+ ShellUtilsTrivial *ret = NULL;
+
g_error_free (local_err);
+ ret = g_new0 (ShellUtilsTrivial, 1);
+ g_object_ref (file);
+ ret->file = file;
+ ret->filename = g_file_get_path (file);
return ret;
+ } else {
+ gchar *filename;
+ filename = g_file_get_path (file);
+ g_propagate_prefixed_error (error, local_err, "Unable to read '%s':", filename);
+ g_free (filename);
}
-
- g_propagate_prefixed_error (error, local_err, "Unable to read '%s':", ret->filename);
}
- shell_utils_trivial_free (ret);
return NULL;
}
+ return shell_utils_trivial_new_from_string (file, filebuf, error);
+}
+
+ShellUtilsTrivial *
+shell_utils_trivial_new_from_string (GFile *file,
+ gchar *filebuf,
+ GError **error)
+{
+ ShellUtilsTrivial *ret = NULL;
+ GError *local_err = NULL;
+ gchar *s;
+
+ if (file == NULL || filebuf == NULL)
+ return NULL;
+
+ ret = g_new0 (ShellUtilsTrivial, 1);
+ g_object_ref (file);
+ ret->file = file;
+ ret->filename = g_file_get_path (file);
gboolean want_separator = FALSE; /* Do we expect the next entry to be a separator or comment? */
s = filebuf;
@@ -308,6 +328,14 @@ no_match:
}
gboolean
+shell_utils_trivial_is_empty (ShellUtilsTrivial *trivial)
+{
+ if (trivial == NULL || trivial->entry_list == NULL)
+ return TRUE;
+ return FALSE;
+}
+
+gboolean
shell_utils_trivial_set_variable (ShellUtilsTrivial *trivial,
const gchar *variable,
const gchar *value,
@@ -350,6 +378,38 @@ shell_utils_trivial_set_variable (ShellUtilsTrivial *trivial,
return ret;
}
+void
+shell_utils_trivial_clear_variable (ShellUtilsTrivial *trivial,
+ const gchar *variable)
+{
+ GList *curr = NULL;
+ gboolean ret = FALSE;
+
+ g_assert (trivial != NULL);
+ g_assert (variable != NULL);
+
+ for (curr = trivial->entry_list; curr != NULL; ) {
+ struct ShellEntry *entry;
+
+ entry = (struct ShellEntry *)(curr->data);
+ if (entry->type == SHELL_ENTRY_TYPE_ASSIGNMENT && g_strcmp0 (variable, entry->variable) == 0) {
+ GList *prev, *next;
+
+ prev = curr->prev;
+ next = curr->next;
+ curr->prev = NULL;
+ curr->next = NULL;
+ g_list_free_full (curr, (GDestroyNotify)shell_entry_free);
+ if (prev != NULL)
+ prev->next = next;
+ if (next != NULL)
+ next->prev = prev;
+ curr = next;
+ } else
+ curr = curr->next;
+ }
+}
+
gboolean
shell_utils_trivial_save (ShellUtilsTrivial *trivial,
GError **error)
diff --git a/src/shell-utils.h b/src/shell-utils.h
index 9ca40e9..629d017 100644
--- a/src/shell-utils.h
+++ b/src/shell-utils.h
@@ -22,7 +22,7 @@
#include <glib.h>
#include <gio/gio.h>
-typedef struct _ShellUtilsTrivial ShellUtilsTrivial;
+typedef struct _ShellUtilsTrivial ShellUtilsTrivial;
struct _ShellUtilsTrivial
{
@@ -46,15 +46,27 @@ ShellUtilsTrivial *
shell_utils_trivial_new (GFile *file,
GError **error);
+ShellUtilsTrivial *
+shell_utils_trivial_new_from_string (GFile *file,
+ gchar *filebuf,
+ GError **error);
+
void
shell_utils_trivial_free (ShellUtilsTrivial *trivial);
gboolean
+shell_utils_trivial_is_empty (ShellUtilsTrivial *trivial);
+
+gboolean
shell_utils_trivial_set_variable (ShellUtilsTrivial *trivial,
const gchar *variable,
const gchar *value,
gboolean add_if_unset);
+void
+shell_utils_trivial_clear_variable (ShellUtilsTrivial *trivial,
+ const gchar *variable);
+
gboolean
shell_utils_trivial_save (ShellUtilsTrivial *trivial,
GError **error);