* [gentoo-commits] proj/openrc-settingsd:master commit in: src/, /, data/
@ 2012-02-09 8:42 Alexandre Restovtsev
0 siblings, 0 replies; 3+ messages in thread
From: Alexandre Restovtsev @ 2012-02-09 8:42 UTC (permalink / raw
To: gentoo-commits
commit: 5879972108bc28629f41c56d34592642df0c4588
Author: Alexandre Rostovtsev <tetromino <AT> gentoo <DOT> org>
AuthorDate: Thu Feb 9 08:26:48 2012 +0000
Commit: Alexandre Restovtsev <tetromino <AT> gmail <DOT> com>
CommitDate: Thu Feb 9 08:40:24 2012 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/openrc-settingsd.git;a=commit;h=58799721
Add beginnings of localed (read-only and no xorg.conf support)
---
.gitignore | 1 +
Makefile.am | 21 +++++-
README | 22 +++++
TODO | 2 +-
data/locale1.xml | 30 +++++++
src/localed.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/localed.h | 31 +++++++
src/main.c | 3 +
src/shell-utils.c | 83 ++++++++++++++++----
src/shell-utils.h | 5 +
10 files changed, 406 insertions(+), 19 deletions(-)
diff --git a/.gitignore b/.gitignore
index b0d689f..8fae933 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
/openrc-settingsd
/stamp-h1
/src/hostname1-generated.[ch]
+/src/locale1-generated.[ch]
# Relative rules
*.o
diff --git a/Makefile.am b/Makefile.am
index f2a770a..7ae61ed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,6 +2,7 @@ ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
EXTRA_DIST = \
data/hostname1.xml \
+ data/locale1.xml \
$(NULL)
AM_CPPFLAGS = \
@@ -22,10 +23,18 @@ hostnamed_built_sources = \
src/hostname1-generated.h \
$(NULL)
+localed_built_sources = \
+ src/locale1-generated.c \
+ src/locale1-generated.h \
+ $(NULL)
+
openrc_settingsd_SOURCES = \
$(hostnamed_built_sources) \
+ $(localed_built_sources) \
src/hostnamed.c \
src/hostnamed.h \
+ src/localed.c \
+ src/localed.h \
src/bus-utils.c \
src/bus-utils.h \
src/shell-utils.c \
@@ -41,5 +50,13 @@ $(hostnamed_built_sources) : data/hostname1.xml
$(srcdir)/data/hostname1.xml; \
mv hostname1-generated.{c,h} $(top_srcdir)/src/ )
-BUILT_SOURCES = $(hostnamed_built_sources)
-CLEANFILES = $(hostnamed_built_sources)
+$(localed_built_sources) : data/locale1.xml
+ ( $(GDBUS_CODEGEN) \
+ --interface-prefix org.freedesktop. \
+ --c-namespace OpenrcSettingsdLocaled \
+ --generate-c-code locale1-generated \
+ $(srcdir)/data/locale1.xml; \
+ mv locale1-generated.{c,h} $(top_srcdir)/src/ )
+
+BUILT_SOURCES = $(hostnamed_built_sources) $(localed_built_sources)
+CLEANFILES = $(hostnamed_built_sources) $(localed_built_sources)
diff --git a/README b/README
index 62bd904..bd6adac 100644
--- a/README
+++ b/README
@@ -16,6 +16,28 @@ Hostnamed:
PRETTY_HOSTNAME="Foo !"
ICON_NAME="computer-desktop"
+Localed:
+
+ See http://www.freedesktop.org/wiki/Software/systemd/localed for the DBus
+ protocol description.
+
+ The system locale variables are set in /etc/env.d/02locale.
+
+ Virtual console keymap is set in /etc/conf.d/keymaps as
+ keymap="foo"
+ The virtual console keymap toggle is not supported.
+
+/*
+ Not implemented yet.
+
+ X11 keyboard options are set in /etc/X11/xorg.conf.d/30-keyboard.conf
+ (falling back to 00-keyboard.conf if it exists and 30-keyboard.conf does
+ not) in an InputClass section.
+ Localed will attempt to detect if multiple InputClass sections with
+ keyboard options exist in /etc/X11/xorg.conf and /etc/X11/xorg.conf.d/,
+ and if that is the case, will refuse to modify X11 keyboard settings.
+*/
+
Note that openrc-settingsd expects any shell-syntax settings files that it
modifies to be in UTF-8 encoding, and to consist only of comments and simple
scalar assignments, i.e. something like
diff --git a/TODO b/TODO
index e8694da..a7feb33 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-Add nss-myhostname detection (and add nss-myhostnane to portage)
+Add nss-myhostname detection
Source /etc/rc.conf after /etc/conf.d/$service; do something intelligent
if the relevant variable is set in /etc/rc.conf (go to read-only mode?)
diff --git a/data/locale1.xml b/data/locale1.xml
new file mode 100644
index 0000000..dfd98d3
--- /dev/null
+++ b/data/locale1.xml
@@ -0,0 +1,30 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/org/freedesktop/locale1">
+ <interface name="org.freedesktop.locale1">
+ <method name="SetLocale">
+ <arg direction="in" type="as" name="locale"/>
+ <arg direction="in" type="b" name="user_interaction"/>
+ </method>
+ <method name="SetVConsoleKeyboard">
+ <arg direction="in" type="s" name="keymap"/>
+ <arg direction="in" type="s" name="keymap_toggle"/>
+ <arg direction="in" type="b" name="convert"/>
+ <arg direction="in" type="b" name="user_interaction"/>
+ </method>
+ <method name="SetX11Keyboard">
+ <arg direction="in" type="s" name="layout"/>
+ <arg direction="in" type="s" name="model"/>
+ <arg direction="in" type="s" name="variant"/>
+ <arg direction="in" type="s" name="options"/>
+ <arg direction="in" type="b" name="convert"/>
+ <arg direction="in" type="b" name="user_interaction"/>
+ </method>
+ <property name="Locale" type="as" access="read"/>
+ <property name="VConsoleKeymap" type="s" access="read"/>
+ <property name="VConsoleKeymapToggle" type="s" access="read"/>
+ <property name="X11Layout" type="s" access="read"/>
+ <property name="X11Model" type="s" access="read"/>
+ <property name="X11Variant" type="s" access="read"/>
+ <property name="X11Options" type="s" access="read"/>
+ </interface>
+</node>
diff --git a/src/localed.c b/src/localed.c
new file mode 100644
index 0000000..12d9ad7
--- /dev/null
+++ b/src/localed.c
@@ -0,0 +1,227 @@
+/*
+ Copyright 2012 Alexandre Rostovtsev
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <stdlib.h>
+
+#include <dbus/dbus-protocol.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "localed.h"
+#include "locale1-generated.h"
+#include "bus-utils.h"
+#include "shell-utils.h"
+
+#include "config.h"
+
+#define SERVICE_NAME "openrc-settingsd localed"
+
+static guint bus_id = 0;
+static gboolean read_only = FALSE;
+
+static OpenrcSettingsdLocaledLocale1 *locale1 = NULL;
+
+static gchar *locale_variables[] = {
+ "LANG", "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE", "LC_MONETARY", "LC_MESSAGES", "LC_PAPER", "LC_NAME", "LC_ADDRESS", "LC_TELEPHONE", "LC_MEASUREMENT", "LC_IDENTIFICATION", NULL
+};
+
+static gchar **locale = NULL; /* Expected format is { "LANG=foo", "LC_TIME=bar", NULL } */
+static GFile *locale_file = NULL;
+G_LOCK_DEFINE_STATIC (locale);
+
+static gchar *vconsole_keymap = NULL;
+static gchar *vconsole_keymap_toggle = NULL;
+static GFile *keymaps_file = NULL;
+G_LOCK_DEFINE_STATIC (keymaps);
+
+static gchar *x11_layout = NULL;
+static gchar *x11_model = NULL;
+static gchar *x11_variant = NULL;
+static gchar *x11_options = NULL;
+G_LOCK_DEFINE_STATIC (xorg_conf);
+
+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");
+
+ return TRUE;
+}
+
+static gboolean
+on_handle_set_vconsole_keyboard (OpenrcSettingsdLocaledLocale1 *locale1,
+ GDBusMethodInvocation *invocation,
+ const gchar *keymap,
+ const gchar *keymap_toggle,
+ const gboolean convert,
+ 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");
+
+ return TRUE;
+}
+
+static gboolean
+on_handle_set_x11_keyboard (OpenrcSettingsdLocaledLocale1 *locale1,
+ GDBusMethodInvocation *invocation,
+ const gchar *layout,
+ const gchar *model,
+ const gchar *variant,
+ const gchar *options,
+ const gboolean convert,
+ 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");
+
+ return TRUE;
+}
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+ const gchar *bus_name,
+ gpointer user_data)
+{
+ gchar *name;
+ GError *err = NULL;
+
+ g_debug ("Acquired a message bus connection");
+
+ locale1 = openrc_settingsd_localed_locale1_skeleton_new ();
+
+ openrc_settingsd_localed_locale1_set_locale (locale1, (const gchar * const *) locale);
+ openrc_settingsd_localed_locale1_set_vconsole_keymap (locale1, vconsole_keymap);
+ openrc_settingsd_localed_locale1_set_vconsole_keymap_toggle (locale1, vconsole_keymap_toggle);
+ 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);
+
+ g_signal_connect (locale1, "handle-set-locale", G_CALLBACK (on_handle_set_locale), NULL);
+ g_signal_connect (locale1, "handle-set-vconsole-keyboard", G_CALLBACK (on_handle_set_vconsole_keyboard), NULL);
+ g_signal_connect (locale1, "handle-set-x11-keyboard", G_CALLBACK (on_handle_set_x11_keyboard), NULL);
+
+ if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (locale1),
+ connection,
+ "/org/freedesktop/locale1",
+ &err)) {
+ if (err != NULL) {
+ g_printerr ("Failed to export interface on /org/freedesktop/locale1: %s\n", err->message);
+ g_error_free (err);
+ }
+ }
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+ const gchar *bus_name,
+ gpointer user_data)
+{
+ g_debug ("Acquired the name %s", bus_name);
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+ const gchar *bus_name,
+ gpointer user_data)
+{
+ if (connection == NULL)
+ g_printerr ("Failed to acquire a dbus connection\n");
+ else
+ g_printerr ("Failed to acquire dbus name %s\n", bus_name);
+ exit(-1);
+}
+
+void
+localed_init (gboolean _read_only)
+{
+ GError *err = NULL;
+ gchar **locale_values = NULL;
+
+ read_only = _read_only;
+ locale_file = g_file_new_for_path (SYSCONFDIR "/env.d/02locale");
+ keymaps_file = g_file_new_for_path (SYSCONFDIR "/conf.d/keymaps");
+
+ locale = g_new0 (gchar *, g_strv_length (locale_variables) + 1);
+ locale_values = shell_utils_trivial_source_var_list (locale_file, (const gchar * const *)locale_variables, &err);
+ if (locale_values != NULL) {
+ gchar **variable, **value, **loc;
+ loc = locale;
+ for (variable = locale_variables, value = locale_values; *variable != NULL; variable++, value++) {
+ if (*value != NULL) {
+ *loc = g_strdup_printf ("%s=%s", *variable, *value);
+ loc++;
+ }
+ }
+
+ g_strfreev (locale_values);
+ }
+ if (err != NULL) {
+ g_debug ("%s", err->message);
+ g_clear_error (&err);
+ }
+
+ vconsole_keymap = shell_utils_source_var (keymaps_file, "${keymap}", &err);
+ if (vconsole_keymap == NULL)
+ vconsole_keymap = g_strdup ("");
+ if (err != NULL) {
+ g_debug ("%s", err->message);
+ g_clear_error (&err);
+ }
+
+ /* We don't have a good equivalent for this in openrc at the moment */
+ vconsole_keymap_toggle = g_strdup ("");
+
+ bus_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
+ "org.freedesktop.locale1",
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ NULL,
+ NULL);
+}
+
+void
+localed_destroy (void)
+{
+ g_bus_unown_name (bus_id);
+ bus_id = 0;
+ read_only = FALSE;
+ g_strfreev (locale);
+ g_free (vconsole_keymap);
+ g_free (vconsole_keymap_toggle);
+ g_free (x11_layout);
+ g_free (x11_model);
+ g_free (x11_variant);
+ g_free (x11_options);
+
+ g_object_unref (locale_file);
+ g_object_unref (keymaps_file);
+}
diff --git a/src/localed.h b/src/localed.h
new file mode 100644
index 0000000..dff55c6
--- /dev/null
+++ b/src/localed.h
@@ -0,0 +1,31 @@
+/*
+ Copyright 2012 Alexandre Rostovtsev
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef OPENRC_LOCALED_H
+#define OPENRC_LOCALED_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+void
+localed_init (gboolean read_only);
+
+void
+localed_destroy (void);
+
+#endif
diff --git a/src/main.c b/src/main.c
index c7165f0..fabb96c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -23,6 +23,7 @@
#include <gio/gio.h>
#include "hostnamed.h"
+#include "localed.h"
#include "shell-utils.h"
#include "config.h"
@@ -68,10 +69,12 @@ main (gint argc, gchar *argv[])
shell_utils_init ();
hostnamed_init (read_only);
+ localed_init (read_only);
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
g_main_loop_unref (loop);
+ localed_destroy ();
hostnamed_destroy ();
shell_utils_destroy ();
return 0;
diff --git a/src/shell-utils.c b/src/shell-utils.c
index 30026a9..db67303 100644
--- a/src/shell-utils.c
+++ b/src/shell-utils.c
@@ -45,6 +45,7 @@ struct ShellEntry {
enum ShellEntryType type;
gchar *string;
gchar *variable; /* only relevant for assignments */
+ gchar *unquoted_value; /* only relevant for assignments */
};
gchar *
@@ -104,10 +105,9 @@ shell_entry_free (struct ShellEntry *entry)
if (entry == NULL)
return;
- if (entry->string != NULL)
- g_free (entry->string);
- if (entry->variable != NULL)
- g_free (entry->variable);
+ g_free (entry->string);
+ g_free (entry->variable);
+ g_free (entry->unquoted_value);
g_free (entry);
}
@@ -132,7 +132,7 @@ shell_utils_trivial_new (GFile *file,
{
gchar *filebuf = NULL;
ShellUtilsTrivial *ret = NULL;
- GError *local_err;
+ GError *local_err = NULL;
gchar *s;
if (file == NULL)
@@ -214,6 +214,7 @@ shell_utils_trivial_new (GFile *file,
matched = g_regex_match (var_equals_regex, s, 0, &match_info);
if (matched) {
+ gchar *raw_value = NULL, *temp1 = NULL, *temp2 = NULL;
/* If we expect a separator and get an assignment instead, fail */
if (want_separator)
goto no_match;
@@ -231,7 +232,6 @@ shell_utils_trivial_new (GFile *file,
while (*s != 0) {
g_debug ("Scanning string for values: ``%s''", s);
gboolean matched2 = FALSE;
- gchar *temp1 = NULL, *temp2 = NULL;
matched2 = g_regex_match (single_quoted_regex, s, 0, &match_info);
if (matched2)
@@ -256,18 +256,36 @@ shell_utils_trivial_new (GFile *file,
break;
append_value:
+
+ if (raw_value == NULL) {
+ raw_value = g_match_info_fetch (match_info, 0);
+ s += strlen (raw_value);
+ g_debug ("Scanned value: ``%s''", raw_value);
+ } else {
+ temp1 = raw_value;
+ temp2 = g_match_info_fetch (match_info, 0);
+ raw_value = g_strconcat (temp1, temp2, NULL);
+ s += strlen (temp2);
+ g_debug ("Scanned value: ``%s''", temp2);
+ g_free (temp1);
+ g_free (temp2);
+ }
+ g_match_info_free (match_info);
+ match_info = NULL;
+ }
+
+ if (raw_value != NULL) {
+ entry->unquoted_value = g_shell_unquote (raw_value, &local_err);
+ g_debug ("Unquoted value: ``%s''", entry->unquoted_value);
temp1 = entry->string;
- temp2 = g_match_info_fetch (match_info, 0);
+ temp2 = raw_value;
entry->string = g_strconcat (temp1, temp2, NULL);
- s += strlen (temp2);
- g_debug ("Scanned value: ``%s''", temp2);
g_free (temp1);
g_free (temp2);
- g_match_info_free (match_info);
- match_info = NULL;
+ ret->entry_list = g_list_prepend (ret->entry_list, entry);
+ if (local_err != NULL)
+ goto no_match;
}
-
- ret->entry_list = g_list_prepend (ret->entry_list, entry);
continue;
}
@@ -275,9 +293,12 @@ no_match:
/* Nothing matches, parsing has failed! */
g_match_info_free (match_info);
match_info = NULL;
- g_propagate_error (error,
- g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED,
- "Unable to parse '%s'", ret->filename));
+ if (local_err != NULL)
+ g_propagate_prefixed_error (error, local_err, "Unable to parse '%s':", ret->filename);
+ else
+ g_propagate_error (error,
+ g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "Unable to parse '%s'", ret->filename));
shell_utils_trivial_free (ret);
return NULL;
}
@@ -420,6 +441,36 @@ shell_utils_trivial_set_and_save (GFile *file,
return ret;
}
+gchar **
+shell_utils_trivial_source_var_list (GFile *file,
+ const gchar * const *var_names,
+ GError **error)
+{
+ ShellUtilsTrivial *trivial;
+ gchar **ret = NULL, **value;
+ const gchar* const* var_name;
+
+ if (var_names == NULL)
+ return NULL;
+
+ if ((trivial = shell_utils_trivial_new (file, error)) == NULL)
+ return NULL;
+
+ ret = g_new0 (gchar *, g_strv_length ((gchar **)var_names) + 1);
+ for (var_name = var_names, value = ret; *var_name != NULL; var_name++, value++) {
+ GList *curr;
+ for (curr = trivial->entry_list; curr != NULL; curr = curr->next) {
+ struct ShellEntry *entry;
+
+ entry = (struct ShellEntry *)(curr->data);
+ if (entry->type == SHELL_ENTRY_TYPE_ASSIGNMENT && g_strcmp0 (*var_name, entry->variable) == 0)
+ *value = g_strdup (entry->unquoted_value);
+ }
+ }
+ shell_utils_trivial_free (trivial);
+ return ret;
+}
+
void
shell_utils_destroy (void)
{
diff --git a/src/shell-utils.h b/src/shell-utils.h
index 5e1863d..9ca40e9 100644
--- a/src/shell-utils.h
+++ b/src/shell-utils.h
@@ -66,4 +66,9 @@ shell_utils_trivial_set_and_save (GFile *file,
const gchar *first_alt_var_name,
const gchar *first_value,
...);
+
+gchar **
+shell_utils_trivial_source_var_list (GFile *file,
+ const gchar * const *var_names,
+ GError **error);
#endif
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [gentoo-commits] proj/openrc-settingsd:master commit in: src/, /, data/
@ 2012-09-05 5:33 Alexandre Restovtsev
0 siblings, 0 replies; 3+ messages in thread
From: Alexandre Restovtsev @ 2012-09-05 5:33 UTC (permalink / raw
To: gentoo-commits
commit: a0e3c463acbda2d81081e223ef999fdab59a0304
Author: Alexandre Rostovtsev <tetromino <AT> gentoo <DOT> org>
AuthorDate: Wed Sep 5 05:29:46 2012 +0000
Commit: Alexandre Restovtsev <tetromino <AT> gmail <DOT> com>
CommitDate: Wed Sep 5 05:33:18 2012 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/openrc-settingsd.git;a=commit;h=a0e3c463
Finish SetVConsoleKeyboard() and SetX11Keyboard() implementation
Also, fix xorg.conf.d parser so it works as intended.
---
Makefile.am | 5 +
TODO | 2 +-
data/kbd-model-map | 73 ++++++
src/localed.c | 730 +++++++++++++++++++++++++++++++++++++++++++++++-----
src/shell-utils.c | 80 +++++-
src/shell-utils.h | 14 +-
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);
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [gentoo-commits] proj/openrc-settingsd:master commit in: src/, /, data/
@ 2012-09-07 16:04 Alexandre Restovtsev
0 siblings, 0 replies; 3+ messages in thread
From: Alexandre Restovtsev @ 2012-09-07 16:04 UTC (permalink / raw
To: gentoo-commits
commit: a14f465d4576bf5895f67c3a7d68d862acda149c
Author: Alexandre Rostovtsev <tetromino <AT> gentoo <DOT> org>
AuthorDate: Fri Sep 7 15:49:54 2012 +0000
Commit: Alexandre Restovtsev <tetromino <AT> gmail <DOT> com>
CommitDate: Fri Sep 7 15:49:54 2012 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/openrc-settingsd.git;a=commit;h=a14f465d
Add man page and homepage information, and --version support
---
Makefile.am | 2 +
README | 10 +++--
configure.ac | 2 +-
data/openrc-settingsd.8 | 67 +++++++++++++++++++++++++++++++++
data/org.freedesktop.hostname1.policy | 2 +-
data/org.freedesktop.locale1.policy | 2 +-
data/org.freedesktop.timedate1.policy | 2 +-
src/main.c | 7 +++
8 files changed, 86 insertions(+), 8 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 0802620..bdfb3dd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -60,6 +60,8 @@ data/init.d/openrc-settingsd : data/init.d/openrc-settingsd.in
%.service : %.service.in
$(do_subst) < $(srcdir)/$< > $(srcdir)/$@
+dist_man_MANS = data/openrc-settingsd.8
+
AM_CPPFLAGS = \
-include $(top_builddir)/config.h \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
diff --git a/README b/README
index e279f16..344fea5 100644
--- a/README
+++ b/README
@@ -1,10 +1,12 @@
-openrc-settingsd provides an implementation of the the hostnamed, localed,
+OpenRC-settingsd provides an implementation of the the hostnamed, localed,
and timedated D-Bus services for OpenRC-based systems - in particular, for
typical installations of Gentoo Linux.
It is maintained by Gentoo's GNOME desktop team, which can be contacted
via gnome@gentoo.org, or in #gentoo-desktop on Freenode IRC.
+Homepage: http://gnome.gentoo.org/openrc-settingsd.xml
+
Bugs should be reported to Gentoo Bugzilla (https://bugs.gentoo.org/)
using "GNOME" as the component.
@@ -50,10 +52,10 @@ Timedated:
The timezone is set in /etc/timezone and /etc/localtime.
- openrc-settingsd attempts to auto-detect an appropriate ntp implementation.
+ OpenRC-settingsd attempts to auto-detect an appropriate ntp implementation.
To avoid auto-detection, use the --ntp-service command line option.
-Note that openrc-settingsd expects any shell-syntax settings files that it
+Note that OpenRC-settingsd expects any shell-syntax settings files that it
modifies to be in UTF-8 encoding, and to consist only of comments and simple
scalar assignments, i.e. something like
@@ -61,5 +63,5 @@ scalar assignments, i.e. something like
foo="bar"
baz='Let'\''s go!'
-If openrc-settingsd fails to parse a settings file, it will refuse to modify
+If OpenRC-settingsd fails to parse a settings file, it will refuse to modify
it.
diff --git a/configure.ac b/configure.ac
index a7ccb04..3e0480a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ([2.60])
-AC_INIT([openrc-settingsd], [0])
+AC_INIT([openrc-settingsd], [0], [https://bugs.gentoo.org/], [openrc-settingsd], [http://gnome.gentoo.org/openrc-settingsd.xml])
AC_CONFIG_SRCDIR([src/main.c])
AM_INIT_AUTOMAKE([check-news foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz])
AC_PROG_CC_STDC
diff --git a/data/openrc-settingsd.8 b/data/openrc-settingsd.8
new file mode 100644
index 0000000..6e4666c
--- /dev/null
+++ b/data/openrc-settingsd.8
@@ -0,0 +1,67 @@
+.TH "OPENRC-SETTINGSD" "8" "September 2012" "OpenRC-settingsd" "openrc-settingsd"
+.SH "NAME"
+openrc\-settingsd \- system settings D\-Bus service for OpenRC
+.SH "SYNOPSIS"
+\fBopenrc\-settingsd\fR [\fB\-\-help\fR] [\fB\-\-debug\fR] [\fB\-\-read\-only\fR]
+[\fB\-\-foreground\fR] [\fB\-\-update\-rc\-status\fR] [\fB\-\-ntp\-service\fR=\fISERVICE\fR]
+.SH "DESCRIPTION"
+.PP
+The \fBopenrc\-settingsd\fR daemon implements the standard hostnamed (i.e.
+\fIorg.freedesktop.hostname1\fR), localed (i.e. \fIorg.freedesktop.locale1\fR), and
+timedated (\fIorg.freedesktop.timedate1\fR) D\-Bus interfaces for OpenRC systems.
+Users and administrators should not need to launch the \fBopenrc\-settingsd\fR
+executable manually. Depending on the installation, it will either be launched
+automatically via D\-Bus activation when needed, or started by the administrator
+as an OpenRC service using \fI/etc/init.d/openrc\-settingsd\fR.
+.SH "OPTIONS"
+.PP
+\fB\-\-help\fR
+.RS 4
+Show help options.
+.RE
+.PP
+\fB\-\-debug\fR
+.RS 4
+Enable debugging messages. Not recommended unless in foreground mode.
+.RE
+.PP
+\fB\-\-read\-only\fR
+.RS 4
+Run daemon in read-only mode. It will read settings files, but will not
+modify them.
+.RE
+.PP
+\fB\-\-foreground\fR
+.RS 4
+Run in foreground mode (i.e. not daemonized). Messages will be logged to stderr
+instead of the system log.
+.RE
+.PP
+\fB\-\-update\-rc\-status\fR
+.RS 4
+Automatically set the status of the \fIopenrc\-settingsd\fR service to \fIstarted\fR
+when the daemon successfully starts, and to \fIstopped\fR when the daemon stops. If
+\fBopenrc\-settingsd\fR is manually launched with this argument, the administrator
+will be able to stop it via \fI/etc/init.d/openrc\-settingsd\fR\ \fIstop\fR.
+.RE
+.PP
+\fB\-\-ntp\-service\fR=\fISERVICE\fR
+.RS 4
+Specify which OpenRC service to use as the NTP service. If this option is not used,
+\fBopenrc\-settingsd\fR will attempt to autodetect an appropriate ntp implementation.
+.RE
+.SH "AUTHORS"
+.PP
+Written by
+.MT tetromino@gentoo.org
+Alexandre Rostovtsev
+.ME .
+.SH "BUGS"
+.PP
+Bug reports should be submitted to the
+.UR https://bugs.gentoo.org/
+Gentoo Bugzilla
+.UE ; use \fIGNOME\fR as the component.
+.SH "SEE ALSO"
+.PP
+\fBdbus\-daemon\fR(1), \fBpolkit\fR(8), \fBrc\fR(8)
\ No newline at end of file
diff --git a/data/org.freedesktop.hostname1.policy b/data/org.freedesktop.hostname1.policy
index 74851e2..4717ce1 100644
--- a/data/org.freedesktop.hostname1.policy
+++ b/data/org.freedesktop.hostname1.policy
@@ -3,7 +3,7 @@
<policyconfig>
<vendor>Gentoo Linux</vendor>
- <vendor_url>http://git.overlays.gentoo.org/gitweb/?p=proj/openrc-settingsd.git</vendor_url>
+ <vendor_url>http://www.gentoo.org/proj/en/desktop/gnome/openrc-settingsd.xml</vendor_url>
<action id="org.freedesktop.hostname1.set-hostname">
<description>Set local host name</description>
diff --git a/data/org.freedesktop.locale1.policy b/data/org.freedesktop.locale1.policy
index e56cc74..640ea39 100644
--- a/data/org.freedesktop.locale1.policy
+++ b/data/org.freedesktop.locale1.policy
@@ -3,7 +3,7 @@
<policyconfig>
<vendor>Gentoo Linux</vendor>
- <vendor_url>http://git.overlays.gentoo.org/gitweb/?p=proj/openrc-settingsd.git</vendor_url>
+ <vendor_url>http://www.gentoo.org/proj/en/desktop/gnome/openrc-settingsd.xml</vendor_url>
<action id="org.freedesktop.locale1.set-locale">
<description>Set system locale environment variables</description>
diff --git a/data/org.freedesktop.timedate1.policy b/data/org.freedesktop.timedate1.policy
index 9bc276b..fafafed 100644
--- a/data/org.freedesktop.timedate1.policy
+++ b/data/org.freedesktop.timedate1.policy
@@ -3,7 +3,7 @@
<policyconfig>
<vendor>Gentoo Linux</vendor>
- <vendor_url>http://git.overlays.gentoo.org/gitweb/?p=proj/openrc-settingsd.git</vendor_url>
+ <vendor_url>http://www.gentoo.org/proj/en/desktop/gnome/openrc-settingsd.xml</vendor_url>
<action id="org.freedesktop.timedate1.set-time">
<description>Set system time</description>
diff --git a/src/main.c b/src/main.c
index 8374218..78b6013 100644
--- a/src/main.c
+++ b/src/main.c
@@ -42,6 +42,7 @@ static gboolean foreground = FALSE;
static gboolean use_syslog = FALSE;
static gboolean read_only = FALSE;
static gboolean update_rc_status = FALSE;
+static gboolean print_version = FALSE;
static gchar *ntp_preferred_service = NULL;
static guint components_started = 0;
@@ -56,6 +57,7 @@ static GOptionEntry option_entries[] =
{ "read-only", 0, 0, G_OPTION_ARG_NONE, &read_only, "Run in read-only mode", NULL },
{ "ntp-service", 0, 0, G_OPTION_ARG_STRING, &ntp_preferred_service, "Preferred rc NTP service for timedated", NULL },
{ "update-rc-status", 0, 0, G_OPTION_ARG_NONE, &update_rc_status, "Force openrc-settingsd rc service to be marked as started", NULL },
+ { "version", 0, 0, G_OPTION_ARG_NONE, &print_version, "Show version information", NULL },
{ NULL }
};
@@ -209,6 +211,11 @@ main (gint argc, gchar *argv[])
return 1;
}
+ if (print_version) {
+ g_print ("%s\n", PACKAGE_STRING);
+ return 0;
+ }
+
if (!foreground) {
if (daemon_retval_init () < 0) {
g_critical ("Failed to create pipe");
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2012-09-07 16:05 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-07 16:04 [gentoo-commits] proj/openrc-settingsd:master commit in: src/, /, data/ Alexandre Restovtsev
-- strict thread matches above, loose matches on Subject: below --
2012-09-05 5:33 Alexandre Restovtsev
2012-02-09 8:42 Alexandre Restovtsev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox