diff --git a/accountsservice-sysconfig.patch b/accountsservice-sysconfig.patch new file mode 100644 index 0000000..26fdb80 --- /dev/null +++ b/accountsservice-sysconfig.patch @@ -0,0 +1,671 @@ +commit 17b2f0915c0ee6e3bb1e3800691bd8d8843aad49 +Author: Vincent Untz +Date: Wed Jul 20 16:48:41 2011 +0200 + + Use autologin configuration from sysconfig (SUSE-ism) + +diff --git a/src/Makefile.am b/src/Makefile.am +index 90fce6c..d65a6c8 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -23,6 +23,8 @@ libexec_PROGRAMS = accounts-daemon + accounts_daemon_SOURCES = \ + $(enums_h_sources) \ + $(BUILT_SOURCES) \ ++ gdm-sysconfig.c \ ++ gdm-sysconfig.h \ + types.h \ + daemon.h \ + daemon.c \ +diff --git a/src/daemon.c b/src/daemon.c +index ec319a9..3291de8 100644 +--- a/src/daemon.c ++++ b/src/daemon.c +@@ -46,6 +46,7 @@ + #include "daemon.h" + #include "daemon-glue.h" + #include "util.h" ++#include "gdm-sysconfig.h" + + #define PATH_PASSWD "/etc/passwd" + #define PATH_SHADOW "/etc/shadow" +@@ -455,7 +456,7 @@ reload_autologin_timeout (Daemon *daemon) + daemon->priv->autologin_id = 0; + + if (!load_autologin (daemon, &name, &enabled, &error)) { +- g_debug ("failed to load gdms custom.conf: %s", error->message); ++ g_debug ("failed to load autologin config: %s", error->message); + g_error_free (error); + g_free (name); + +@@ -1200,6 +1201,43 @@ daemon_local_check_auth (Daemon *daemon, + g_object_unref (subject); + } + ++#define SYSCONFIG_FILE "/etc/sysconfig/displaymanager" ++#define SYSCONFIG_AUTOLOGIN_KEY "DISPLAYMANAGER_AUTOLOGIN" ++ ++gboolean ++load_autologin_suse (Daemon *daemon, ++ gchar **name, ++ gboolean *enabled, ++ GError **error) ++{ ++ *name = gdm_sysconfig_load_value (SYSCONFIG_FILE, SYSCONFIG_AUTOLOGIN_KEY); ++ *enabled = (name && *name); ++ ++ return TRUE; ++} ++ ++static gboolean ++save_autologin_suse (Daemon *daemon, ++ const gchar *name, ++ gboolean enabled, ++ GError **error) ++{ ++ const gchar *user; ++ gboolean result; ++ ++ if (enabled && name) ++ user = name; ++ else ++ user = ""; ++ ++ result = gdm_sysconfig_save_value (SYSCONFIG_FILE, SYSCONFIG_AUTOLOGIN_KEY, user); ++ ++ if (!result) ++ g_set_error (error, ERROR, ERROR_FAILED, "Could not save autologin configuration in sysconfig"); ++ ++ return result; ++} ++ + gboolean + load_autologin (Daemon *daemon, + gchar **name, +@@ -1211,6 +1249,8 @@ load_autologin (Daemon *daemon, + GError *local_error; + gchar *string; + ++ return load_autologin_suse (daemon, name, enabled, error); ++ + filename = "/etc/gdm/custom.conf"; + + keyfile = g_key_file_new (); +@@ -1261,6 +1301,8 @@ save_autologin (Daemon *daemon, + gchar *data; + gboolean result; + ++ return save_autologin_suse (daemon, name, enabled, error); ++ + filename = "/etc/gdm/custom.conf"; + + keyfile = g_key_file_new (); +diff --git a/src/gdm-sysconfig.c b/src/gdm-sysconfig.c +new file mode 100644 +index 0000000..56c86cd +--- /dev/null ++++ b/src/gdm-sysconfig.c +@@ -0,0 +1,484 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2008 Hans Petter Jansson ++ * ++ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ */ ++ ++/* Parser for shell-script-like key-value files. Far from complete, but ++ * deals with a couple of common shell oddities. For instance, the following ++ * are parsed correctly: ++ * ++ * KEY=value\0 ++ * KEY = value#comment\0 ++ * KEY = " value with spaces" \0 ++ * KEY = ' it\'s a value with "embedded" quotes'\0 ++ * KEY = "if quotes aren't closed, we assume the string ends at EOL\0 ++ * ++ * It should be good enough for the config files in /etc/sysconfig/. ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "gdm-sysconfig.h" ++ ++#define SPACE_CHARS " \t" ++#define KEY_ALLOW_CHARS "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ++ ++static gchar ** ++load_settings_file (const gchar *file_name) ++{ ++ GIOChannel *channel; ++ GPtrArray *lines; ++ gchar *str; ++ ++ g_debug ("Loading settings from %s", file_name); ++ ++ channel = g_io_channel_new_file (file_name, "r", NULL); ++ if (!channel) { ++ g_debug ("Failed to open %s", file_name); ++ return NULL; ++ } ++ ++ lines = g_ptr_array_new (); ++ ++ while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) { ++ if (str) { ++ gchar *p0; ++ ++ /* Remove line separators */ ++ ++ for (p0 = str + strlen (str) - 1; p0 >= str && strchr ("\r\n", *p0); p0--) ++ *p0 = '\0'; ++ ++ g_ptr_array_add (lines, str); ++ g_debug ("%s", str); ++ } else { ++ g_ptr_array_add (lines, g_strdup ("")); ++ g_debug ("%s", ""); ++ } ++ } ++ ++ g_io_channel_shutdown (channel, FALSE, NULL); ++ g_io_channel_unref (channel); ++ ++ g_ptr_array_add (lines, NULL); ++ ++ return (gchar **) g_ptr_array_free (lines, FALSE); ++} ++ ++static gboolean ++save_settings_file (const gchar *file_name, gchar **lines) ++{ ++ GIOStatus last_status = G_IO_STATUS_ERROR; ++ GIOChannel *channel = NULL; ++ gchar *temp_file_name; ++ gint i; ++ ++ temp_file_name = g_strdup_printf ("%s.new.%u", file_name, g_random_int ()); ++ ++ channel = g_io_channel_new_file (temp_file_name, "w", NULL); ++ if (!channel) ++ goto out; ++ ++ if (!lines) ++ goto out; ++ ++ for (i = 0; lines [i]; i++) { ++ gsize bytes_written; ++ ++ if (lines [i] [0] != '\0') ++ last_status = g_io_channel_write_chars (channel, ++ lines [i], strlen (lines [i]), ++ &bytes_written, ++ NULL); ++ ++ if (last_status != G_IO_STATUS_NORMAL) ++ break; ++ ++ last_status = g_io_channel_write_unichar (channel, '\n', NULL); ++ ++ if (last_status != G_IO_STATUS_NORMAL) ++ break; ++ } ++ ++out: ++ if (channel) { ++ g_io_channel_shutdown (channel, FALSE, NULL); ++ g_io_channel_unref (channel); ++ } ++ ++ if (last_status == G_IO_STATUS_NORMAL && g_rename (temp_file_name, file_name) != 0) ++ last_status = G_IO_STATUS_ERROR; ++ ++ g_free (temp_file_name); ++ return last_status == G_IO_STATUS_NORMAL ? TRUE : FALSE; ++} ++ ++static const gchar * ++skip_from_start_to_key (const gchar *line) ++{ ++ const gchar *p0; ++ ++ /* Skip initial space */ ++ ++ p0 = line + strspn (line, SPACE_CHARS); ++ ++ /* Ignore comments and other junk */ ++ ++ if (*p0 && strchr (KEY_ALLOW_CHARS, *p0)) ++ return p0; ++ ++ return NULL; ++} ++ ++static const gchar * ++skip_from_start_to_value_of_key (const gchar *line, const gchar *key_normal, gint key_len) ++{ ++ const gchar *p0, *p1; ++ gchar *potential_key_normal; ++ gboolean result; ++ ++ p0 = skip_from_start_to_key (line); ++ if (!p0) ++ return NULL; ++ ++ /* There's at least one key-like character, figure out how many */ ++ ++ p1 = p0 + strspn (p0, KEY_ALLOW_CHARS); ++ ++ /* Is this the key we're looking for? */ ++ ++ if (p1 - p0 != key_len) ++ return NULL; ++ ++ potential_key_normal = g_ascii_strdown (p0, p1 - p0); ++ result = strcmp (key_normal, potential_key_normal) == 0 ? TRUE : FALSE; ++ g_free (potential_key_normal); ++ ++ if (!result) ++ return NULL; ++ ++ /* It's the right key; skip over key-value separator */ ++ ++ p0 = p1 + strspn (p1, SPACE_CHARS); ++ if (*p0 != '=') ++ return NULL; ++ ++ p0++; ++ p0 += strspn (p0, SPACE_CHARS); ++ ++ return p0; ++} ++ ++static const gchar * ++skip_over_value (const gchar *value_start, gchar *quotes_out) ++{ ++ const gchar *p0 = value_start; ++ const gchar *p1; ++ gchar quotes; ++ ++ /* Is the value quoted? */ ++ ++ quotes = *p0; ++ if (quotes == '\'' || quotes == '"') { ++ /* Quoted sequence opened; find closing quote, but skip over escaped ones. If ++ * there's no closing quote on this line, assume the EOL closes it. */ ++ ++ *quotes_out = quotes; ++ ++ p1 = p0; ++ do { ++ p1++; ++ p1 = strchr (p1, quotes); ++ if (!p1) { ++ /* Hit EOL */ ++ ++ p1 = p0 + strlen (p0) - 1; ++ break; ++ } ++ } while (*(p1 - 1) == '\\'); ++ } else { ++ /* No quotes; look for comment or EOL */ ++ ++ *quotes_out = 0; ++ ++ p1 = strchr (p0, '#'); ++ if (!p1) ++ p1 = p0 + strlen (p0); ++ ++ for (p1--; p1 >= p0; p1--) ++ if (!strchr (SPACE_CHARS, *p1)) ++ break; ++ } ++ ++ return p1 + 1; ++} ++ ++static gchar * ++get_value_of_key (const gchar *line, const gchar *key_normal, gint key_len) ++{ ++ const gchar *p0, *p1; ++ gchar quotes; ++ gchar *value; ++ gchar *temp; ++ ++ p0 = skip_from_start_to_value_of_key (line, key_normal, key_len); ++ if (!p0) ++ return NULL; ++ ++ p1 = skip_over_value (p0, "es); ++ ++ if (quotes != 0) { ++ if (p1 - p0 > 2) { ++ temp = g_strndup (p0 + 1, p1 - p0 - 2); ++ value = g_strcompress (temp); ++ g_free (temp); ++ } else { ++ value = g_strdup (""); ++ } ++ } else { ++ temp = g_strndup (p0, p1 - p0); ++ value = g_strcompress (temp); ++ g_free (temp); ++ g_strchomp (value); ++ } ++ ++ return value; ++} ++ ++static gchar * ++get_value (const gchar **lines, const gchar *key) ++{ ++ gchar *value = NULL; ++ gchar *key_normal; ++ gint key_len; ++ gint i; ++ ++ g_debug ("Getting value of %s", key); ++ ++ if (!lines) { ++ g_debug ("Missing configuration data"); ++ return NULL; ++ } ++ ++ key_normal = g_ascii_strdown (key, -1); ++ key_len = strlen (key_normal); ++ ++ for (i = 0; lines [i]; i++) { ++ value = get_value_of_key (lines [i], key_normal, key_len); ++ if (value) ++ break; ++ } ++ ++ g_free (key_normal); ++ ++ g_debug ("Got value of %s: %s", key, value); ++ ++ return value; ++} ++ ++static gchar * ++set_value_of_key (const gchar *line, const gchar *key_normal, gint key_len, const gchar *key, const gchar *value) ++{ ++ const gchar *p0, *p1, *p2; ++ gchar quotes; ++ gchar *escaped_value; ++ gchar *quoted_escaped_value; ++ gint quoted_escaped_value_len; ++ gchar *new_line; ++ gint len; ++ ++ p0 = skip_from_start_to_value_of_key (line, key_normal, key_len); ++ if (!p0) ++ return NULL; ++ ++ escaped_value = g_strescape (value, ""); ++ quoted_escaped_value = g_strdup_printf ("\"%s\"", escaped_value); ++ g_free (escaped_value); ++ quoted_escaped_value_len = strlen (quoted_escaped_value); ++ ++ p1 = skip_over_value (p0, "es); ++ p2 = p1 + strlen (p1); ++ len = (p0 - line) + quoted_escaped_value_len + (p2 - p1); ++ ++ new_line = g_malloc (len + 1); ++ memcpy (new_line, line, p0 - line); ++ memcpy (new_line + (p0 - line), quoted_escaped_value, quoted_escaped_value_len); ++ memcpy (new_line + (p0 - line) + quoted_escaped_value_len, p1, p2 - p1); ++ ++ *(new_line + len) = '\0'; ++ ++ g_free (quoted_escaped_value); ++ ++ return new_line; ++} ++ ++static gboolean ++set_value (gchar **lines, const gchar *key, const gchar *value) ++{ ++ gboolean result = FALSE; ++ gchar *key_normal; ++ gint key_len; ++ gint i; ++ ++ if (!lines) ++ return FALSE; ++ ++ key_normal = g_ascii_strdown (key, -1); ++ key_len = strlen (key_normal); ++ ++ for (i = 0; lines [i]; i++) { ++ gchar *new_line; ++ ++ new_line = set_value_of_key (lines [i], key_normal, key_len, key, value); ++ if (new_line) { ++ g_free (lines [i]); ++ lines [i] = new_line; ++ result = TRUE; ++ break; ++ } ++ } ++ ++ g_free (key_normal); ++ ++ return result; ++} ++ ++gchar ** ++gdm_sysconfig_load_file (const gchar *file_name) ++{ ++ g_return_val_if_fail (file_name != NULL, NULL); ++ ++ return load_settings_file (file_name); ++} ++ ++gboolean ++gdm_sysconfig_save_file (const gchar *file_name, const gchar **sysconfig) ++{ ++ g_return_val_if_fail (file_name != NULL, FALSE); ++ g_return_val_if_fail (sysconfig != NULL, FALSE); ++ ++ return save_settings_file (file_name, sysconfig); ++} ++ ++gchar * ++gdm_sysconfig_get_value (const gchar **sysconfig, const gchar *key) ++{ ++ g_return_val_if_fail (sysconfig != NULL, NULL); ++ g_return_val_if_fail (key != NULL, NULL); ++ ++ return get_value (sysconfig, key); ++} ++ ++gboolean ++gdm_sysconfig_set_value (gchar **sysconfig, const gchar *key, const gchar *value) ++{ ++ g_return_val_if_fail (sysconfig != NULL, FALSE); ++ g_return_val_if_fail (key != NULL, FALSE); ++ g_return_val_if_fail (value != NULL, FALSE); ++ ++ return set_value (sysconfig, key, value); ++} ++ ++gboolean ++gdm_sysconfig_get_value_boolean (const gchar **sysconfig, const gchar *key, gboolean *value) ++{ ++ char *val; ++ gboolean val_bool; ++ ++ g_return_val_if_fail (sysconfig != NULL, FALSE); ++ g_return_val_if_fail (key != NULL, FALSE); ++ ++ val = get_value (sysconfig, key); ++ if (val == NULL) { ++ return FALSE; ++ } ++ ++ if (!strcasecmp (val, "yes")) { ++ val_bool = TRUE; ++ } else if (!strcasecmp (val, "no")) { ++ val_bool = FALSE; ++ } else { ++ g_free (val); ++ return FALSE; ++ } ++ ++ g_free (val); ++ ++ if (value != NULL) { ++ *value = val_bool; ++ } ++ ++ return TRUE; ++} ++ ++gboolean ++gdm_sysconfig_set_value_boolean (gchar **sysconfig, const gchar *key, gboolean value) ++{ ++ g_return_val_if_fail (sysconfig != NULL, FALSE); ++ g_return_val_if_fail (key != NULL, FALSE); ++ ++ return set_value (sysconfig, key, value ? "yes" : "no"); ++} ++ ++gchar * ++gdm_sysconfig_load_value (const gchar *file_name, const gchar *key) ++{ ++ gchar **lines; ++ gchar *value; ++ ++ g_return_val_if_fail (file_name != NULL, NULL); ++ g_return_val_if_fail (key != NULL, NULL); ++ ++ lines = load_settings_file (file_name); ++ if (!lines) ++ return NULL; ++ ++ value = get_value (lines, key); ++ ++ g_strfreev (lines); ++ return value; ++} ++ ++gboolean ++gdm_sysconfig_save_value (const gchar *file_name, const gchar *key, const gchar *value) ++{ ++ gchar **lines; ++ gboolean result; ++ ++ g_return_val_if_fail (file_name != NULL, FALSE); ++ g_return_val_if_fail (key != NULL, FALSE); ++ g_return_val_if_fail (value != NULL, FALSE); ++ ++ lines = load_settings_file (file_name); ++ if (!lines) ++ return FALSE; ++ ++ result = set_value (lines, key, value); ++ if (result) ++ result = save_settings_file (file_name, lines); ++ ++ g_strfreev (lines); ++ return result; ++} +diff --git a/src/gdm-sysconfig.h b/src/gdm-sysconfig.h +new file mode 100644 +index 0000000..b00aa4e +--- /dev/null ++++ b/src/gdm-sysconfig.h +@@ -0,0 +1,43 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2008 Hans Petter Jansson ++ * ++ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ */ ++ ++ ++#ifndef __GDM_SYSCONFIG_H ++#define __GDM_SYSCONFIG_H ++ ++#include ++ ++G_BEGIN_DECLS ++ ++gchar **gdm_sysconfig_load_file (const gchar *file_name); ++gboolean gdm_sysconfig_save_file (const gchar *file_name, const gchar **sysconfig); ++ ++gchar *gdm_sysconfig_get_value (const gchar **sysconfig, const gchar *key); ++gboolean gdm_sysconfig_set_value (gchar **sysconfig, const gchar *key, const gchar *value); ++ ++gboolean gdm_sysconfig_get_value_boolean (const gchar **sysconfig, const gchar *key, gboolean *value); ++gboolean gdm_sysconfig_set_value_boolean (gchar **sysconfig, const gchar *key, gboolean value); ++ ++gchar *gdm_sysconfig_load_value (const gchar *file_name, const gchar *key); ++gboolean gdm_sysconfig_save_value (const gchar *file_name, const gchar *key, const gchar *value); ++ ++G_END_DECLS ++ ++#endif /* __GDM_SYSCONFIG_H */ +Index: accountsservice-0.6.13/src/Makefile.in +=================================================================== +--- accountsservice-0.6.13.orig/src/Makefile.in ++++ accountsservice-0.6.13/src/Makefile.in +@@ -48,7 +48,7 @@ CONFIG_CLEAN_VPATH_FILES = + am__installdirs = "$(DESTDIR)$(libexecdir)" + PROGRAMS = $(libexec_PROGRAMS) + am__objects_1 = +-am_accounts_daemon_OBJECTS = $(am__objects_1) daemon.$(OBJEXT) \ ++am_accounts_daemon_OBJECTS = $(am__objects_1) gdm-sysconfig.$(OBJEXT) daemon.$(OBJEXT) \ + user.$(OBJEXT) util.$(OBJEXT) main.$(OBJEXT) + accounts_daemon_OBJECTS = $(am_accounts_daemon_OBJECTS) + am__DEPENDENCIES_1 = +@@ -312,6 +312,8 @@ BUILT_SOURCES = \ + accounts_daemon_SOURCES = \ + $(enums_h_sources) \ + $(BUILT_SOURCES) \ ++ gdm-sysconfig.c \ ++ gdm-sysconfig.h \ + types.h \ + daemon.h \ + daemon.c \ +@@ -416,6 +418,7 @@ mostlyclean-compile: + distclean-compile: + -rm -f *.tab.c + ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdm-sysconfig.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/user.Po@am__quote@ diff --git a/accountsservice.changes b/accountsservice.changes index 8f669c0..34f1182 100644 --- a/accountsservice.changes +++ b/accountsservice.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Jul 20 16:51:05 CEST 2011 - vuntz@opensuse.org + +- Add accountsservice-sysconfig.patch: read and write autologin + configuration from sysconfig, as done in gdm. Fix bnc#688071. + ------------------------------------------------------------------- Wed Jul 20 09:02:02 CEST 2011 - vuntz@opensuse.org diff --git a/accountsservice.spec b/accountsservice.spec index be7be4e..b08ef3a 100644 --- a/accountsservice.spec +++ b/accountsservice.spec @@ -25,6 +25,9 @@ Summary: D-Bus Service to Manipulate User Account Information Url: http://www.fedoraproject.org/wiki/Features/UserAccountDialog Group: System/Daemons Source: http://www.freedesktop.org/software/accountsservice/%{name}-%{version}.tar.xz +# WARNING: do not remove/significantly change patch0 without updating the relevant patch in gdm too +# PATCH-FIX-OPENSUSE accountsservice-sysconfig.patch bnc#688071 vuntz@opensuse.org -- Read/write autologin configuration from sysconfig, like gdm (see gdm-sysconfig-settings.patch) +Patch0: accountsservice-sysconfig.patch BuildRequires: intltool # Only needed because we don't (and won't) support building xz tarballs by default... See bnc#697467 BuildRequires: xz @@ -68,6 +71,7 @@ querying and manipulating user account information. %lang_package %prep %setup -q +%patch0 -p1 %build %configure --disable-static