View | Details | Raw Unified | Return to bug 440863
Collapse All | Expand All

(-)a/common/Makefile.am (+4 lines)
Lines 83-88 libgdmcommon_la_SOURCES = \ Link Here
83
	gdm-settings-backend.h	\
83
	gdm-settings-backend.h	\
84
	gdm-settings-desktop-backend.c 	\
84
	gdm-settings-desktop-backend.c 	\
85
	gdm-settings-desktop-backend.h	\
85
	gdm-settings-desktop-backend.h	\
86
	gdm-settings-system-backend.c 	\
87
	gdm-settings-system-backend.h	\
86
	gdm-settings-keys.h	\
88
	gdm-settings-keys.h	\
87
	gdm-settings-utils.h	\
89
	gdm-settings-utils.h	\
88
	gdm-settings-utils.c	\
90
	gdm-settings-utils.c	\
Lines 90-95 libgdmcommon_la_SOURCES = \ Link Here
90
	gdm-settings-direct.h	\
92
	gdm-settings-direct.h	\
91
	gdm-settings-client.h	\
93
	gdm-settings-client.h	\
92
	gdm-settings-client.c	\
94
	gdm-settings-client.c	\
95
	gdm-sysconfig.c		\
96
	gdm-sysconfig.h		\
93
	gdm-log.h		\
97
	gdm-log.h		\
94
	gdm-log.c		\
98
	gdm-log.c		\
95
	gdm-md5.h		\
99
	gdm-md5.h		\
(-)a/common/gdm-settings-system-backend.c (+283 lines)
Line 0 Link Here
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2
 *
3
 * Copyright (C) 2008 Hans Petter Jansson <hpj@copyleft.no>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 *
19
 */
20
21
#include "config.h"
22
23
#include <stdlib.h>
24
#include <stdio.h>
25
#include <fcntl.h>
26
#include <unistd.h>
27
#include <string.h>
28
#include <signal.h>
29
#include <sys/stat.h>
30
#include <sys/types.h>
31
32
#include <glib.h>
33
#include <glib/gi18n.h>
34
#include <glib/gstdio.h>
35
#include <glib-object.h>
36
37
#include "gdm-sysconfig.h"
38
#include "gdm-settings-keys.h"
39
#include "gdm-settings-system-backend.h"
40
41
#include "gdm-marshal.h"
42
#include "gdm-log.h"
43
44
#define SYSCONFIG_AUTOLOGIN_KEY "DISPLAYMANAGER_AUTOLOGIN"
45
46
#define GDM_SETTINGS_SYSTEM_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SETTINGS_SYSTEM_BACKEND, GdmSettingsSystemBackendPrivate))
47
48
struct GdmSettingsSystemBackendPrivate
49
{
50
        char       *filename;
51
        gchar     **lines;
52
        gboolean    dirty;
53
        guint       save_id;
54
55
        gchar      *set_autologin_user;
56
        gboolean    set_autologin_enabled;
57
};
58
59
static void     gdm_settings_system_backend_class_init (GdmSettingsSystemBackendClass *klass);
60
static void     gdm_settings_system_backend_init       (GdmSettingsSystemBackend      *settings_system_backend);
61
static void     gdm_settings_system_backend_finalize   (GObject                       *object);
62
63
G_DEFINE_TYPE (GdmSettingsSystemBackend, gdm_settings_system_backend, GDM_TYPE_SETTINGS_BACKEND)
64
65
static gboolean
66
gdm_settings_system_backend_get_value (GdmSettingsBackend *backend,
67
                                       const char         *key,
68
                                       char              **value,
69
                                       GError            **error)
70
{
71
        GdmSettingsSystemBackend        *system_backend = (GdmSettingsSystemBackend *) backend;
72
        GdmSettingsSystemBackendPrivate *priv;
73
        gchar                           *val;
74
        gboolean                         ret;
75
76
        g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (backend), FALSE);
77
        g_return_val_if_fail (key != NULL, FALSE);
78
79
        priv = system_backend->priv;
80
        ret = FALSE;
81
82
        if (value != NULL) {
83
                *value = NULL;
84
        }
85
86
        if (strcasecmp (key, GDM_KEY_AUTO_LOGIN_ENABLE) &&
87
            strcasecmp (key, GDM_KEY_AUTO_LOGIN_USER)) {
88
                g_set_error (error, GDM_SETTINGS_BACKEND_ERROR, GDM_SETTINGS_BACKEND_ERROR_KEY_NOT_FOUND, "Key not found");
89
                goto out;
90
        }
91
92
        if (!strcasecmp (key, GDM_KEY_AUTO_LOGIN_ENABLE)) {
93
                if (priv->dirty) {
94
                        val = g_strdup (priv->set_autologin_enabled ? "true" : "false");
95
                } else {
96
                        const gchar *new_val;
97
98
                        val = gdm_sysconfig_get_value ((const gchar **) priv->lines, SYSCONFIG_AUTOLOGIN_KEY);
99
100
                        new_val = (val && *val) ? "true" : "false";
101
                        g_free (val);
102
                        val = g_strdup (new_val);
103
                }
104
        } else {
105
                if (priv->dirty && priv->set_autologin_user) {
106
                        val = g_strdup (priv->set_autologin_user);
107
                } else {
108
                        val = gdm_sysconfig_get_value ((const gchar **) priv->lines, SYSCONFIG_AUTOLOGIN_KEY);
109
                }
110
        }
111
112
        if (value != NULL && val != NULL && *val != '\0') {
113
                *value = val;
114
        } else {
115
                g_free (val);
116
        }
117
118
        ret = TRUE;
119
120
 out:
121
        return ret;
122
}
123
124
static void
125
save_settings (GdmSettingsSystemBackend *backend)
126
{
127
        GError   *local_error;
128
        char     *contents;
129
        gsize     length;
130
131
        if (! backend->priv->dirty) {
132
                return;
133
        }
134
135
        g_debug ("Saving settings to %s", backend->priv->filename);
136
137
        if (!backend->priv->set_autologin_enabled) {
138
                g_free (backend->priv->set_autologin_user);
139
                backend->priv->set_autologin_user = g_strdup ("");
140
        }
141
142
        if (!gdm_sysconfig_set_value (backend->priv->lines, SYSCONFIG_AUTOLOGIN_KEY, backend->priv->set_autologin_user))
143
                g_warning ("Unable to set key %s to '%s'.", SYSCONFIG_AUTOLOGIN_KEY,
144
                           backend->priv->set_autologin_user);
145
146
        if (!gdm_sysconfig_save_file (backend->priv->filename, backend->priv->lines))
147
                g_warning ("Unable to save settings to %s.", backend->priv->filename);
148
149
        backend->priv->dirty = FALSE;
150
}
151
152
static gboolean
153
save_settings_timer (GdmSettingsSystemBackend *backend)
154
{
155
        save_settings (backend);
156
        backend->priv->save_id = 0;
157
        return FALSE;
158
}
159
160
static void
161
queue_save (GdmSettingsSystemBackend *backend)
162
{
163
        if (! backend->priv->dirty) {
164
                return;
165
        }
166
167
        if (backend->priv->save_id != 0) {
168
                /* already pending */
169
                return;
170
        }
171
172
        backend->priv->save_id = g_timeout_add_seconds (5, (GSourceFunc)save_settings_timer, backend);
173
}
174
175
static gboolean
176
gdm_settings_system_backend_set_value (GdmSettingsBackend *backend,
177
                                       const char         *key,
178
                                       const char         *value,
179
                                       GError            **error)
180
{
181
        GdmSettingsSystemBackend        *system_backend = (GdmSettingsSystemBackend *) backend;
182
        GdmSettingsSystemBackendPrivate *priv;
183
        gchar                           *old_val = NULL;
184
185
        g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (backend), FALSE);
186
        g_return_val_if_fail (key != NULL, FALSE);
187
188
        priv = system_backend->priv;
189
190
        if (strcasecmp ("key", GDM_KEY_AUTO_LOGIN_ENABLE) &&
191
            strcasecmp ("key", GDM_KEY_AUTO_LOGIN_USER)) {
192
                g_set_error (error, GDM_SETTINGS_BACKEND_ERROR, GDM_SETTINGS_BACKEND_ERROR_KEY_NOT_FOUND, "Key not found");
193
                return FALSE;
194
        }
195
196
        gdm_settings_system_backend_get_value (backend, key, &old_val, NULL);
197
198
        if (!strcasecmp ("key", GDM_KEY_AUTO_LOGIN_ENABLE)) {
199
                gchar t = 0;
200
201
                if (value)
202
                        t = g_ascii_tolower (*value);
203
204
                if (t == 'y' || t == 't')
205
                        priv->set_autologin_enabled = TRUE;
206
                else
207
                        priv->set_autologin_enabled = FALSE;
208
        } else {
209
                g_free (priv->set_autologin_user);
210
                priv->set_autologin_user = g_strdup (value);
211
        }
212
213
        GDM_SETTINGS_SYSTEM_BACKEND (backend)->priv->dirty = TRUE;
214
        queue_save (GDM_SETTINGS_SYSTEM_BACKEND (backend));
215
216
        gdm_settings_backend_value_changed (backend, key, old_val, value);
217
218
        g_free (old_val);
219
220
        return TRUE;
221
}
222
223
static void
224
gdm_settings_system_backend_class_init (GdmSettingsSystemBackendClass *klass)
225
{
226
        GObjectClass            *object_class = G_OBJECT_CLASS (klass);
227
        GdmSettingsBackendClass *backend_class = GDM_SETTINGS_BACKEND_CLASS (klass);
228
229
        object_class->finalize = gdm_settings_system_backend_finalize;
230
231
        backend_class->get_value = gdm_settings_system_backend_get_value;
232
        backend_class->set_value = gdm_settings_system_backend_set_value;
233
234
        g_type_class_add_private (klass, sizeof (GdmSettingsSystemBackendPrivate));
235
}
236
237
static void
238
gdm_settings_system_backend_init (GdmSettingsSystemBackend *backend)
239
{
240
        gboolean res;
241
        GError  *error;
242
243
        gdm_log_set_debug (TRUE);
244
245
        backend->priv = GDM_SETTINGS_SYSTEM_BACKEND_GET_PRIVATE (backend);
246
247
        backend->priv->filename = g_strdup ("/etc/sysconfig/displaymanager");
248
        backend->priv->lines = gdm_sysconfig_load_file (backend->priv->filename);
249
250
        if (!backend->priv->lines) {
251
                g_warning ("Unable to load file '%s'", backend->priv->filename);
252
        }
253
}
254
255
static void
256
gdm_settings_system_backend_finalize (GObject *object)
257
{
258
        GdmSettingsSystemBackend *backend;
259
260
        g_return_if_fail (object != NULL);
261
        g_return_if_fail (GDM_IS_SETTINGS_SYSTEM_BACKEND (object));
262
263
        backend = GDM_SETTINGS_SYSTEM_BACKEND (object);
264
265
        g_return_if_fail (backend->priv != NULL);
266
267
        save_settings (backend);
268
        g_strfreev (backend->priv->lines);
269
        g_free (backend->priv->filename);
270
        g_free (backend->priv->set_autologin_user);
271
272
        G_OBJECT_CLASS (gdm_settings_system_backend_parent_class)->finalize (object);
273
}
274
275
GdmSettingsBackend *
276
gdm_settings_system_backend_new (void)
277
{
278
        GObject *object;
279
280
        object = g_object_new (GDM_TYPE_SETTINGS_SYSTEM_BACKEND, NULL);
281
282
        return GDM_SETTINGS_BACKEND (object);
283
}
(-)a/common/gdm-settings-system-backend.h (+56 lines)
Line 0 Link Here
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2
 *
3
 * Copyright (C) 2008 Hans Petter Jansson <hpj@copyleft.no>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 *
19
 */
20
21
22
#ifndef __GDM_SETTINGS_SYSTEM_BACKEND_H
23
#define __GDM_SETTINGS_SYSTEM_BACKEND_H
24
25
#include <glib-object.h>
26
#include "gdm-settings-backend.h"
27
28
G_BEGIN_DECLS
29
30
#define GDM_TYPE_SETTINGS_SYSTEM_BACKEND         (gdm_settings_system_backend_get_type ())
31
#define GDM_SETTINGS_SYSTEM_BACKEND(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_SETTINGS_SYSTEM_BACKEND, GdmSettingsSystemBackend))
32
#define GDM_SETTINGS_SYSTEM_BACKEND_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_SETTINGS_SYSTEM_BACKEND, GdmSettingsSystemBackendClass))
33
#define GDM_IS_SETTINGS_SYSTEM_BACKEND(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_SETTINGS_SYSTEM_BACKEND))
34
#define GDM_IS_SETTINGS_SYSTEM_BACKEND_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_SETTINGS_SYSTEM_BACKEND))
35
#define GDM_SETTINGS_SYSTEM_BACKEND_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_SETTINGS_SYSTEM_BACKEND, GdmSettingsSystemBackendClass))
36
37
typedef struct GdmSettingsSystemBackendPrivate GdmSettingsSystemBackendPrivate;
38
39
typedef struct
40
{
41
        GdmSettingsBackend               parent;
42
        GdmSettingsSystemBackendPrivate *priv;
43
} GdmSettingsSystemBackend;
44
45
typedef struct
46
{
47
        GdmSettingsBackendClass   parent_class;
48
} GdmSettingsSystemBackendClass;
49
50
GType                      gdm_settings_system_backend_get_type        (void);
51
52
GdmSettingsBackend        *gdm_settings_system_backend_new             (void);
53
54
G_END_DECLS
55
56
#endif /* __GDM_SETTINGS_SYSTEM_BACKEND_H */
(-)a/common/gdm-settings.c (-17 / +54 lines)
Lines 41-46 Link Here
41
#include "gdm-settings-glue.h"
41
#include "gdm-settings-glue.h"
42
42
43
#include "gdm-settings-desktop-backend.h"
43
#include "gdm-settings-desktop-backend.h"
44
#include "gdm-settings-system-backend.h"
44
45
45
#include "gdm-marshal.h"
46
#include "gdm-marshal.h"
46
47
Lines 53-59 Link Here
53
struct GdmSettingsPrivate
54
struct GdmSettingsPrivate
54
{
55
{
55
        DBusGConnection    *connection;
56
        DBusGConnection    *connection;
56
        GdmSettingsBackend *backend;
57
        GList              *backends;
57
};
58
};
58
59
59
enum {
60
enum {
Lines 94-108 gdm_settings_get_value (GdmSettings *settings, Link Here
94
{
95
{
95
        GError  *local_error;
96
        GError  *local_error;
96
        gboolean res;
97
        gboolean res;
98
        GList   *l;
97
99
98
        g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
100
        g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
99
        g_return_val_if_fail (key != NULL, FALSE);
101
        g_return_val_if_fail (key != NULL, FALSE);
100
102
101
        local_error = NULL;
103
        local_error = NULL;
102
        res = gdm_settings_backend_get_value (settings->priv->backend,
104
103
                                              key,
105
        for (l = settings->priv->backends; l; l = g_list_next (l)) {
104
                                              value,
106
                GdmSettingsBackend *backend = l->data;
105
                                              &local_error);
107
108
                if (local_error) {
109
                        g_error_free (local_error);
110
                        local_error = NULL;
111
                }
112
113
                res = gdm_settings_backend_get_value (backend,
114
                                                      key,
115
                                                      value,
116
                                                      &local_error);
117
                if (res)
118
                        break;
119
        }
120
106
        if (! res) {
121
        if (! res) {
107
                g_propagate_error (error, local_error);
122
                g_propagate_error (error, local_error);
108
        }
123
        }
Lines 122-127 gdm_settings_set_value (GdmSettings *settings, Link Here
122
{
137
{
123
        GError  *local_error;
138
        GError  *local_error;
124
        gboolean res;
139
        gboolean res;
140
        GList   *l;
125
141
126
        g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
142
        g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
127
        g_return_val_if_fail (key != NULL, FALSE);
143
        g_return_val_if_fail (key != NULL, FALSE);
Lines 129-138 gdm_settings_set_value (GdmSettings *settings, Link Here
129
        g_debug ("Setting value %s", key);
145
        g_debug ("Setting value %s", key);
130
146
131
        local_error = NULL;
147
        local_error = NULL;
132
        res = gdm_settings_backend_set_value (settings->priv->backend,
148
133
                                              key,
149
        for (l = settings->priv->backends; l; l = g_list_next (l)) {
134
                                              value,
150
                GdmSettingsBackend *backend = l->data;
135
                                              &local_error);
151
152
                if (local_error) {
153
                        g_error_free (local_error);
154
                        local_error = NULL;
155
                }
156
157
                res = gdm_settings_backend_set_value (backend,
158
                                                      key,
159
                                                      value,
160
                                                      &local_error);
161
                if (res)
162
                        break;
163
        }
164
136
        if (! res) {
165
        if (! res) {
137
                g_propagate_error (error, local_error);
166
                g_propagate_error (error, local_error);
138
        }
167
        }
Lines 210-222 backend_value_changed (GdmSettingsBackend *backend, Link Here
210
static void
239
static void
211
gdm_settings_init (GdmSettings *settings)
240
gdm_settings_init (GdmSettings *settings)
212
{
241
{
242
        GList *l;
243
213
        settings->priv = GDM_SETTINGS_GET_PRIVATE (settings);
244
        settings->priv = GDM_SETTINGS_GET_PRIVATE (settings);
214
245
215
        settings->priv->backend = gdm_settings_desktop_backend_new ();
246
        settings->priv->backends = g_list_prepend (NULL, gdm_settings_desktop_backend_new ());
216
        g_signal_connect (settings->priv->backend,
247
        settings->priv->backends = g_list_prepend (settings->priv->backends, gdm_settings_system_backend_new ());
217
                          "value-changed",
248
218
                          G_CALLBACK (backend_value_changed),
249
        for (l = settings->priv->backends; l; l = g_list_next (l)) {
219
                          settings);
250
                GdmSettingsBackend *backend = l->data;
251
252
                g_signal_connect (backend,
253
                                  "value-changed",
254
                                  G_CALLBACK (backend_value_changed),
255
                                  settings);
256
        }
220
}
257
}
221
258
222
static void
259
static void
Lines 231-239 gdm_settings_finalize (GObject *object) Link Here
231
268
232
        g_return_if_fail (settings->priv != NULL);
269
        g_return_if_fail (settings->priv != NULL);
233
270
234
        if (settings->priv->backend != NULL) {
271
        g_list_foreach (settings->priv->backends, (GFunc) g_object_unref, NULL);
235
                g_object_unref (settings->priv->backend);
272
        g_list_free (settings->priv->backends);
236
        }
273
        settings->priv->backends = NULL;
237
274
238
        G_OBJECT_CLASS (gdm_settings_parent_class)->finalize (object);
275
        G_OBJECT_CLASS (gdm_settings_parent_class)->finalize (object);
239
}
276
}
(-)a/common/gdm-sysconfig.c (+439 lines)
Line 0 Link Here
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2
 *
3
 * Copyright (C) 2008 Hans Petter Jansson <hpj@novell.com>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 *
19
 */
20
21
/* Parser for shell-script-like key-value files. Far from complete, but
22
 * deals with a couple of common shell oddities. For instance, the following
23
 * are parsed correctly:
24
 *
25
 * KEY=value\0
26
 * KEY = value#comment\0
27
 * KEY = " value with spaces"  \0
28
 * KEY = ' it\'s a value with "embedded" quotes'\0
29
 * KEY = "if quotes aren't closed, we assume the string ends at EOL\0
30
 *
31
 * It should be good enough for the config files in /etc/sysconfig/.
32
 */
33
34
#include "config.h"
35
36
#include <unistd.h>
37
#include <string.h>
38
39
#include <glib.h>
40
#include <glib/gi18n.h>
41
42
#include "gdm-sysconfig.h"
43
44
#define SPACE_CHARS     " \t"
45
#define KEY_ALLOW_CHARS "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
46
47
static gchar **
48
load_settings_file (const gchar *file_name)
49
{
50
        GIOChannel *channel;
51
        GPtrArray  *lines;
52
        gchar      *str;
53
54
        g_debug ("Loading settings from %s", file_name);
55
56
        channel = g_io_channel_new_file (file_name, "r", NULL);
57
        if (!channel) {
58
                g_debug ("Failed to open %s", file_name);
59
                return NULL;
60
        }
61
62
        lines = g_ptr_array_new ();
63
64
        while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
65
                if (str) {
66
                        gchar *p0;
67
68
                        /* Remove line separators */
69
70
                        for (p0 = str + strlen (str) - 1; p0 >= str && strchr ("\r\n", *p0); p0--)
71
                                *p0 = '\0';
72
73
                        g_ptr_array_add (lines, str);
74
                        g_debug ("%s", str);
75
                } else {
76
                        g_ptr_array_add (lines, g_strdup (""));
77
                        g_debug ("", str);
78
                }
79
        }
80
81
        g_io_channel_shutdown (channel, FALSE, NULL);
82
        g_io_channel_unref (channel);
83
84
        g_ptr_array_add (lines, NULL);
85
86
        return (gchar **) g_ptr_array_free (lines, FALSE);
87
}
88
89
static gboolean
90
save_settings_file (const gchar *file_name, gchar **lines)
91
{
92
        GIOStatus   last_status = G_IO_STATUS_ERROR;
93
        GIOChannel *channel     = NULL;
94
        gchar      *temp_file_name;
95
        gint        i;
96
97
        temp_file_name = g_strdup_printf ("%s.new.%u", file_name, g_random_int ());
98
99
        channel = g_io_channel_new_file (temp_file_name, "w", NULL);
100
        if (!channel)
101
                goto out;
102
103
        if (!lines)
104
                goto out;
105
106
        for (i = 0; lines [i]; i++) {
107
                gsize bytes_written;
108
109
                if (lines [i] [0] != '\0')
110
                        last_status = g_io_channel_write_chars (channel,
111
                                                                lines [i], strlen (lines [i]),
112
                                                                &bytes_written,
113
                                                                NULL);
114
115
                if (last_status != G_IO_STATUS_NORMAL)
116
                        break;
117
118
                last_status = g_io_channel_write_unichar (channel, '\n', NULL);
119
120
                if (last_status != G_IO_STATUS_NORMAL)
121
                        break;
122
        }
123
124
out:
125
        if (channel) {
126
                g_io_channel_shutdown (channel, FALSE, NULL);
127
                g_io_channel_unref (channel);
128
        }
129
130
        if (last_status == G_IO_STATUS_NORMAL && g_rename (temp_file_name, file_name) != 0)
131
                last_status = G_IO_STATUS_ERROR;
132
133
        g_free (temp_file_name);
134
        return last_status == G_IO_STATUS_NORMAL ? TRUE : FALSE;
135
}
136
137
static const gchar *
138
skip_from_start_to_key (const gchar *line)
139
{
140
        const gchar *p0;
141
142
        /* Skip initial space */
143
144
        p0 = line + strspn (line, SPACE_CHARS);
145
146
        /* Ignore comments and other junk */
147
148
        if (*p0 && strchr (KEY_ALLOW_CHARS, *p0))
149
                return p0;
150
151
        return NULL;
152
}
153
154
static const gchar *
155
skip_from_start_to_value_of_key (const gchar *line, const gchar *key_normal, gint key_len)
156
{
157
        const gchar *p0, *p1;
158
        gchar       *potential_key_normal;
159
        gboolean     result;
160
161
        p0 = skip_from_start_to_key (line);
162
        if (!p0)
163
                return NULL;
164
165
        /* There's at least one key-like character, figure out how many */
166
167
        p1 = p0 + strspn (p0, KEY_ALLOW_CHARS);
168
169
        /* Is this the key we're looking for? */
170
171
        if (p1 - p0 != key_len)
172
                return NULL;
173
174
        potential_key_normal = g_ascii_strdown (p0, p1 - p0);
175
        result = strcmp (key_normal, potential_key_normal) == 0 ? TRUE : FALSE;
176
        g_free (potential_key_normal);
177
178
        if (!result)
179
                return NULL;
180
181
        /* It's the right key; skip over key-value separator */
182
183
        p0 = p1 + strspn (p1, SPACE_CHARS);
184
        if (*p0 != '=')
185
                return NULL;
186
187
        p0++;
188
        p0 += strspn (p0, SPACE_CHARS);
189
190
        return p0;
191
}
192
193
static const gchar *
194
skip_over_value (const gchar *value_start, gchar *quotes_out)
195
{
196
        const gchar *p0 = value_start;
197
        const gchar *p1;
198
        gchar        quotes;
199
200
        /* Is the value quoted? */
201
202
        quotes = *p0;
203
        if (quotes == '\'' || quotes == '"') {
204
                /* Quoted sequence opened; find closing quote, but skip over escaped ones. If
205
                 * there's no closing quote on this line, assume the EOL closes it. */
206
207
                *quotes_out = quotes;
208
209
                p1 = p0;
210
                do {
211
                        p1++;
212
                        p1 = strchr (p1, quotes);
213
                        if (!p1) {
214
                                /* Hit EOL */
215
216
                                p1 = p0 + strlen (p0) - 1;
217
                                break;
218
                        }
219
                } while (*(p1 - 1) == '\\');
220
        } else {
221
                /* No quotes; look for comment or EOL */
222
223
                *quotes_out = 0;
224
225
                p1 = strchr (p0, '#');
226
                if (!p1)
227
                        p1 = p0 + strlen (p0);
228
229
                for (p1--; p1 >= p0; p1--)
230
                        if (!strchr (SPACE_CHARS, *p1))
231
                                break;
232
        }
233
234
        return p1 + 1;
235
}
236
237
static gchar *
238
get_value_of_key (const gchar *line, const gchar *key_normal, gint key_len)
239
{
240
        const gchar *p0, *p1;
241
        gchar        quotes;
242
        gchar       *value;
243
        gchar       *temp;
244
245
        p0 = skip_from_start_to_value_of_key (line, key_normal, key_len);
246
        if (!p0)
247
                return NULL;
248
249
        p1 = skip_over_value (p0, &quotes);
250
251
        if (quotes != 0) {
252
                if (p1 - p0 > 2) {
253
                        temp = g_strndup (p0 + 1, p1 - p0 - 2);
254
                        value = g_strcompress (temp);
255
                        g_free (temp);
256
                } else {
257
                        value = g_strdup ("");
258
                }
259
        } else {
260
                temp = g_strndup (p0, p1 - p0);                
261
                value = g_strcompress (temp);
262
                g_free (temp);
263
                g_strchomp (value);
264
        }
265
266
        return value;
267
}
268
269
static gchar *
270
get_value (const gchar **lines, const gchar *key)
271
{
272
        gchar *value = NULL;
273
        gchar *key_normal;
274
        gint   key_len;
275
        gint   i;
276
277
        g_debug ("Getting value of %s", key);
278
279
        if (!lines) {
280
                g_debug ("Missing configuration data");
281
                return NULL;
282
        }
283
284
        key_normal = g_ascii_strdown (key, -1);
285
        key_len    = strlen (key_normal);
286
287
        for (i = 0; lines [i]; i++) {
288
                value = get_value_of_key (lines [i], key_normal, key_len);
289
                if (value)
290
                        break;
291
        }
292
293
        g_free (key_normal);
294
295
        g_debug ("Got value of %s: %s", key, value);
296
297
        return value;
298
}
299
300
static gchar *
301
set_value_of_key (const gchar *line, const gchar *key_normal, gint key_len, const gchar *key, const gchar *value)
302
{
303
        const gchar *p0, *p1, *p2;
304
        gchar        quotes;
305
        gchar       *escaped_value;
306
        gint         escaped_value_len;
307
        gchar       *new_line;
308
        gint         len;
309
310
        p0 = skip_from_start_to_value_of_key (line, key_normal, key_len);
311
        if (!p0)
312
                return NULL;
313
314
        escaped_value = g_strescape (value, "");
315
        escaped_value_len = strlen (escaped_value);
316
317
        p1 = skip_over_value (p0, &quotes);
318
        p2 = p1 + strlen (p1);
319
        len = (p0 - line) + escaped_value_len + (p2 - p1);
320
321
        new_line = g_malloc (len + 1);
322
        memcpy (new_line,                                   line,          p0 - line);
323
        memcpy (new_line + (p0 - line),                     escaped_value, escaped_value_len);
324
        memcpy (new_line + (p0 - line) + escaped_value_len, p1,            p2 - p1);
325
326
        *(new_line + len - 1) = '\0';
327
328
        g_free (escaped_value);
329
330
        return new_line;
331
}
332
333
static gboolean
334
set_value (gchar **lines, const gchar *key, const gchar *value)
335
{
336
        gboolean  result = FALSE;
337
        gchar    *key_normal;
338
        gint      key_len;
339
        gint      i;
340
341
        if (!lines)
342
                return FALSE;
343
344
        key_normal = g_ascii_strdown (key, -1);
345
        key_len    = strlen (key_normal);
346
347
        for (i = 0; lines [i]; i++) {
348
                gchar *new_line;
349
350
                new_line = set_value_of_key (lines [i], key_normal, key_len, key, value);
351
                if (new_line) {
352
                        g_free (lines [i]);
353
                        lines [i] = new_line;
354
                        result = TRUE;
355
                        break;
356
                }
357
        }
358
359
        g_free (key_normal);
360
361
        return result;
362
}
363
364
gchar **
365
gdm_sysconfig_load_file (const gchar *file_name)
366
{
367
        g_return_val_if_fail (file_name != NULL, NULL);
368
369
        return load_settings_file (file_name);
370
}
371
372
gboolean
373
gdm_sysconfig_save_file (const gchar *file_name, const gchar **sysconfig)
374
{
375
        g_return_val_if_fail (file_name != NULL, FALSE);
376
        g_return_val_if_fail (sysconfig != NULL, FALSE);
377
378
        return save_settings_file (file_name, sysconfig);
379
}
380
381
gchar *
382
gdm_sysconfig_get_value (const gchar **sysconfig, const gchar *key)
383
{
384
        g_return_val_if_fail (sysconfig != NULL, NULL);
385
        g_return_val_if_fail (key != NULL, NULL);
386
387
        return get_value (sysconfig, key);
388
}
389
390
gboolean
391
gdm_sysconfig_set_value (gchar **sysconfig, const gchar *key, const gchar *value)
392
{
393
        g_return_val_if_fail (sysconfig != NULL, FALSE);
394
        g_return_val_if_fail (key != NULL, FALSE);
395
        g_return_val_if_fail (value != NULL, FALSE);
396
397
        return set_value (sysconfig, key, value);
398
}
399
400
gchar *
401
gdm_sysconfig_load_value (const gchar *file_name, const gchar *key)
402
{
403
        gchar **lines;
404
        gchar  *value;
405
406
        g_return_val_if_fail (file_name != NULL, NULL);
407
        g_return_val_if_fail (key != NULL, NULL);
408
409
        lines = load_settings_file (file_name);
410
        if (!lines)
411
                return NULL;
412
413
        value = get_value (lines, key);
414
415
        g_strfreev (lines);
416
        return value;
417
}
418
419
gboolean
420
gdm_sysconfig_save_value (const gchar *file_name, const gchar *key, const gchar *value)
421
{
422
        gchar    **lines;
423
        gboolean   result;
424
425
        g_return_val_if_fail (file_name != NULL, FALSE);
426
        g_return_val_if_fail (key != NULL, FALSE);
427
        g_return_val_if_fail (value != NULL, FALSE);
428
429
        lines = load_settings_file (file_name);
430
        if (!lines)
431
                return FALSE;
432
433
        result = set_value (lines, key, value);
434
        if (result)
435
                result = save_settings_file (file_name, lines);
436
437
        g_strfreev (lines);
438
        return result;
439
}
(-)a/common/gdm-sysconfig.h (+40 lines)
Line 0 Link Here
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2
 *
3
 * Copyright (C) 2008 Hans Petter Jansson <hpj@novell.com>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 *
19
 */
20
21
22
#ifndef __GDM_SYSCONFIG_H
23
#define __GDM_SYSCONFIG_H
24
25
#include <glib-object.h>
26
27
G_BEGIN_DECLS
28
29
gchar    **gdm_sysconfig_load_file (const gchar *file_name);
30
gboolean   gdm_sysconfig_save_file (const gchar *file_name, const gchar **sysconfig);
31
32
gchar     *gdm_sysconfig_get_value (const gchar **sysconfig, const gchar *key);
33
gboolean   gdm_sysconfig_set_value (gchar **sysconfig, const gchar *key, const gchar *value);
34
35
gchar     *gdm_sysconfig_load_value (const gchar *file_name, const gchar *key);
36
gboolean   gdm_sysconfig_save_value (const gchar *file_name, const gchar *key, const gchar *value);
37
38
G_END_DECLS
39
40
#endif /* __GDM_SYSCONFIG_H */
(-)a/daemon/gdm-session-direct.c (-3 / +7 lines)
Lines 45-50 Link Here
45
#include <dbus/dbus-glib.h>
45
#include <dbus/dbus-glib.h>
46
#include <dbus/dbus-glib-lowlevel.h>
46
#include <dbus/dbus-glib-lowlevel.h>
47
47
48
#include "gdm-sysconfig.h"
49
48
#include "gdm-session-direct.h"
50
#include "gdm-session-direct.h"
49
#include "gdm-session.h"
51
#include "gdm-session.h"
50
#include "gdm-session-private.h"
52
#include "gdm-session-private.h"
Lines 600-608 get_default_language_name (GdmSessionDirect *session) Link Here
600
static const char *
602
static const char *
601
get_default_layout_name (GdmSessionDirect *session)
603
get_default_layout_name (GdmSessionDirect *session)
602
{
604
{
603
    if (session->priv->saved_layout != NULL) {
605
    if (!session->priv->saved_layout)
604
                return session->priv->saved_layout;
606
            session->priv->saved_layout = gdm_sysconfig_load_value ("/etc/sysconfig/keyboard", "KEYTABLE");
605
    }
607
608
    if (session->priv->saved_layout)
609
            return session->priv->saved_layout;
606
610
607
    return "us";
611
    return "us";
608
}
612
}

Return to bug 440863