1 /* GConf
2 * Copyright (C) 1999, 2000 Red Hat Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #if HAVE_CORBA
21 #include "GConfX.h"
22 #endif
23
24 #include "gconf.h"
25 #include "gconf-internals.h"
26 #include "gconf-sources.h"
27 #include "gconf-locale.h"
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <sys/types.h>
34 #ifdef HAVE_SYS_WAIT_H
35 #include <sys/wait.h>
36 #endif
37 #include <sys/time.h>
38 #include <unistd.h>
39
40 #ifdef HAVE_CORBA
41 /* Returns TRUE if there was an error, frees exception, sets err */
42 static gboolean gconf_handle_corba_exception(CORBA_Environment* ev, GError** err);
43 /* just returns TRUE if there's an exception indicating the server is
44 probably hosed; no side effects */
45 static gboolean gconf_server_broken(CORBA_Environment* ev);
46 static void gconf_detach_config_server(void);
47
48 /* Maximum number of times to try re-spawning the server if it's down. */
49 #define MAX_RETRIES 1
50 #endif /* HAVE_CORBA */
51
52 /* copied from gutf8.c where it exists as a (unfortunately) non-exported function */
53 static gchar *
utf8_make_valid(const gchar * name)54 utf8_make_valid (const gchar *name)
55 {
56 GString *string;
57 const gchar *remainder, *invalid;
58 gint remaining_bytes, valid_bytes;
59
60 string = NULL;
61 remainder = name;
62 remaining_bytes = strlen (name);
63
64 while (remaining_bytes != 0)
65 {
66 if (g_utf8_validate (remainder, remaining_bytes, &invalid))
67 break;
68 valid_bytes = invalid - remainder;
69
70 if (string == NULL)
71 string = g_string_sized_new (remaining_bytes);
72
73 g_string_append_len (string, remainder, valid_bytes);
74 /* append U+FFFD REPLACEMENT CHARACTER */
75 g_string_append (string, "\357\277\275");
76
77 remaining_bytes -= valid_bytes + 1;
78 remainder = invalid + 1;
79 }
80
81 if (string == NULL)
82 return g_strdup (name);
83
84 g_string_append (string, remainder);
85
86 g_assert (g_utf8_validate (string->str, -1, NULL));
87
88 return g_string_free (string, FALSE);
89 }
90
91 gboolean
gconf_key_check(const gchar * key,GError ** err)92 gconf_key_check(const gchar* key, GError** err)
93 {
94 gchar* why = NULL;
95
96 if (key == NULL)
97 {
98 if (err)
99 *err = gconf_error_new (GCONF_ERROR_BAD_KEY,
100 _("Key is NULL"));
101 return FALSE;
102 }
103 else if (!gconf_valid_key (key, &why))
104 {
105 if (err) {
106 gchar *utf8_key = utf8_make_valid (key);
107 *err = gconf_error_new (GCONF_ERROR_BAD_KEY, _("\"%s\": %s"),
108 utf8_key, why);
109 g_free (utf8_key);
110 }
111 g_free(why);
112 return FALSE;
113 }
114 return TRUE;
115 }
116
117 #ifdef HAVE_CORBA
118 typedef struct _CnxnTable CnxnTable;
119
120 struct _GConfEngine {
121 guint refcount;
122
123 ConfigDatabase database;
124
125 CnxnTable* ctable;
126
127 /* If non-NULL, this is a local engine;
128 local engines don't do notification! */
129 GConfSources* local_sources;
130
131 /* A list of addresses that make up this db;
132 * NULL if it uses the default db
133 */
134 GSList *addresses;
135
136 /* A concatentation of the addresses above.
137 */
138 char *persistent_address;
139
140 gpointer user_data;
141 GDestroyNotify dnotify;
142
143 gpointer owner;
144 int owner_use_count;
145
146 /* If TRUE, this is a local engine (and therefore
147 * has no ctable and no notifications)
148 */
149 guint is_local : 1;
150 };
151
152 typedef struct _GConfCnxn GConfCnxn;
153
154 struct _GConfCnxn {
155 gchar* namespace_section;
156 guint client_id;
157 CORBA_unsigned_long server_id; /* id returned from server */
158 GConfEngine* conf; /* engine we're associated with */
159 GConfNotifyFunc func;
160 gpointer user_data;
161 };
162
163 static GConfEngine *default_engine = NULL;
164
165 static GConfCnxn* gconf_cnxn_new (GConfEngine *conf,
166 const gchar *namespace_section,
167 CORBA_unsigned_long server_id,
168 GConfNotifyFunc func,
169 gpointer user_data);
170 static void gconf_cnxn_destroy (GConfCnxn *cnxn);
171 static void gconf_cnxn_notify (GConfCnxn *cnxn,
172 GConfEntry *entry);
173
174
175 static ConfigServer gconf_get_config_server (gboolean start_if_not_found,
176 GError **err);
177
178 /* Forget our current server object reference, so the next call to
179 gconf_get_config_server will have to try to respawn the server */
180 static ConfigListener gconf_get_config_listener (void);
181
182 static void gconf_engine_detach (GConfEngine *conf);
183 static gboolean gconf_engine_connect (GConfEngine *conf,
184 gboolean start_if_not_found,
185 GError **err);
186 static void gconf_engine_set_database (GConfEngine *conf,
187 ConfigDatabase db);
188 static ConfigDatabase gconf_engine_get_database (GConfEngine *conf,
189 gboolean start_if_not_found,
190 GError **err);
191
192
193 #define CHECK_OWNER_USE(engine) \
194 do { if ((engine)->owner && (engine)->owner_use_count == 0) \
195 g_warning ("%s: You can't use a GConfEngine that has an active GConfClient wrapper object. Use GConfClient API instead.", G_STRFUNC); \
196 } while (0)
197
198 static void register_engine (GConfEngine *conf);
199 static void unregister_engine (GConfEngine *conf);
200 static GConfEngine *lookup_engine (GSList *addresses);
201 static GConfEngine *lookup_engine_by_database (ConfigDatabase db);
202
203
204 /* We'll use client-specific connection numbers to return to library
205 users, so if gconfd dies we can transparently re-register all our
206 listener functions. */
207
208 struct _CnxnTable {
209 /* Hash from server-returned connection ID to GConfCnxn */
210 GHashTable* server_ids;
211 /* Hash from our connection ID to GConfCnxn */
212 GHashTable* client_ids;
213 };
214
215 static CnxnTable* ctable_new (void);
216 static void ctable_destroy (CnxnTable *ct);
217 static void ctable_insert (CnxnTable *ct,
218 GConfCnxn *cnxn);
219 static void ctable_remove (CnxnTable *ct,
220 GConfCnxn *cnxn);
221 static GSList* ctable_remove_by_conf (CnxnTable *ct,
222 GConfEngine *conf);
223 static GConfCnxn* ctable_lookup_by_client_id (CnxnTable *ct,
224 guint client_id);
225 static GConfCnxn* ctable_lookup_by_server_id (CnxnTable *ct,
226 CORBA_unsigned_long server_id);
227 static void ctable_reinstall (CnxnTable *ct,
228 GConfCnxn *cnxn,
229 guint old_server_id,
230 guint new_server_id);
231
232
233 static GConfEngine*
gconf_engine_blank(gboolean remote)234 gconf_engine_blank (gboolean remote)
235 {
236 GConfEngine* conf;
237
238 _gconf_init_i18n ();
239
240 conf = g_new0(GConfEngine, 1);
241
242 conf->refcount = 1;
243
244 conf->owner = NULL;
245 conf->owner_use_count = 0;
246
247 if (remote)
248 {
249 conf->database = CORBA_OBJECT_NIL;
250 conf->ctable = ctable_new();
251 conf->local_sources = NULL;
252 conf->is_local = FALSE;
253 }
254 else
255 {
256 conf->database = CORBA_OBJECT_NIL;
257 conf->ctable = NULL;
258 conf->local_sources = NULL;
259 conf->is_local = TRUE;
260 }
261
262 return conf;
263 }
264
265 void
gconf_engine_set_owner(GConfEngine * engine,gpointer client)266 gconf_engine_set_owner (GConfEngine *engine,
267 gpointer client)
268 {
269 g_return_if_fail (engine->owner_use_count == 0);
270
271 engine->owner = client;
272 }
273
274 void
gconf_engine_push_owner_usage(GConfEngine * engine,gpointer client)275 gconf_engine_push_owner_usage (GConfEngine *engine,
276 gpointer client)
277 {
278 g_return_if_fail (engine->owner == client);
279
280 engine->owner_use_count += 1;
281 }
282
283 void
gconf_engine_pop_owner_usage(GConfEngine * engine,gpointer client)284 gconf_engine_pop_owner_usage (GConfEngine *engine,
285 gpointer client)
286 {
287 g_return_if_fail (engine->owner == client);
288 g_return_if_fail (engine->owner_use_count > 0);
289
290 engine->owner_use_count -= 1;
291 }
292
293 static GHashTable *engines_by_db = NULL;
294
295 static GConfEngine *
lookup_engine_by_database(ConfigDatabase db)296 lookup_engine_by_database (ConfigDatabase db)
297 {
298 if (engines_by_db)
299 return g_hash_table_lookup (engines_by_db, db);
300 else
301 return NULL;
302 }
303
304 static void
database_rec_release(gpointer rec)305 database_rec_release (gpointer rec)
306 {
307 GConfEngine *conf = rec;
308 CORBA_Environment ev;
309
310 CORBA_exception_init (&ev);
311
312 CORBA_Object_release (conf->database, &ev);
313 conf->database = CORBA_OBJECT_NIL;
314
315 CORBA_exception_free (&ev);
316 }
317
318 /* This takes ownership of the ConfigDatabase */
319 static void
gconf_engine_set_database(GConfEngine * conf,ConfigDatabase db)320 gconf_engine_set_database (GConfEngine *conf,
321 ConfigDatabase db)
322 {
323 gconf_engine_detach (conf);
324
325 conf->database = db;
326
327 if (engines_by_db == NULL)
328 engines_by_db = g_hash_table_new_full (
329 (GHashFunc) gconf_CORBA_Object_hash,
330 (GCompareFunc) gconf_CORBA_Object_equal,
331 NULL,
332 database_rec_release);
333
334 g_hash_table_insert (engines_by_db, conf->database, conf);
335 }
336
337 static void
gconf_engine_detach(GConfEngine * conf)338 gconf_engine_detach (GConfEngine *conf)
339 {
340 if (conf->database != CORBA_OBJECT_NIL)
341 {
342 g_hash_table_remove (engines_by_db, conf->database);
343 }
344 }
345
346 static gboolean
gconf_engine_connect(GConfEngine * conf,gboolean start_if_not_found,GError ** err)347 gconf_engine_connect (GConfEngine *conf,
348 gboolean start_if_not_found,
349 GError **err)
350 {
351 ConfigServer cs;
352 ConfigDatabase db;
353 int tries = 0;
354 CORBA_Environment ev;
355
356 g_return_val_if_fail (!conf->is_local, TRUE);
357
358 CORBA_exception_init(&ev);
359
360 if (!CORBA_Object_is_nil (conf->database, &ev))
361 return TRUE;
362
363 RETRY:
364
365 cs = gconf_get_config_server(start_if_not_found, err);
366
367 if (cs == CORBA_OBJECT_NIL)
368 return FALSE; /* Error should already be set */
369
370 if (conf->addresses == NULL)
371 {
372 db = ConfigServer_get_default_database (cs, &ev);
373 }
374 else if (conf->addresses->next == NULL) /* single element list */
375 {
376 db = ConfigServer_get_database (cs, conf->addresses->data, &ev);
377 }
378 else
379 {
380 ConfigServer2_AddressList *address_list;
381 GSList *tmp;
382 int i;
383
384 address_list = ConfigServer2_AddressList__alloc ();
385 address_list->_length = address_list->_maximum = g_slist_length (conf->addresses);
386 address_list->_buffer = ConfigServer2_AddressList_allocbuf (address_list->_length);
387 address_list->_release = CORBA_TRUE;
388
389 i = 0;
390 tmp = conf->addresses;
391 while (tmp != NULL)
392 {
393 g_assert (i < address_list->_length);
394
395 address_list->_buffer [i] = CORBA_string_dup (tmp->data);
396
397 tmp = tmp->next;
398 i++;
399 }
400
401 db = ConfigServer2_get_database_for_addresses ((ConfigServer2) cs, address_list, &ev);
402
403 CORBA_free (address_list);
404 }
405
406 if (gconf_server_broken(&ev))
407 {
408 if (tries < MAX_RETRIES)
409 {
410 ++tries;
411 CORBA_exception_free(&ev);
412 gconf_detach_config_server();
413 goto RETRY;
414 }
415 }
416
417 if (gconf_handle_corba_exception(&ev, err))
418 return FALSE;
419
420 if (CORBA_Object_is_nil (db, &ev))
421 {
422 if (err)
423 *err = gconf_error_new(GCONF_ERROR_BAD_ADDRESS,
424 _("Server couldn't resolve the address `%s'"),
425 conf->persistent_address);
426
427 return FALSE;
428 }
429
430 gconf_engine_set_database (conf, db);
431
432 return TRUE;
433 }
434
435 static ConfigDatabase
gconf_engine_get_database(GConfEngine * conf,gboolean start_if_not_found,GError ** err)436 gconf_engine_get_database (GConfEngine *conf,
437 gboolean start_if_not_found,
438 GError **err)
439 {
440 if (!gconf_engine_connect (conf, start_if_not_found, err))
441 return CORBA_OBJECT_NIL;
442 else
443 return conf->database;
444 }
445
446 static gboolean
gconf_engine_is_local(GConfEngine * conf)447 gconf_engine_is_local(GConfEngine* conf)
448 {
449 return conf->is_local;
450 }
451
452 static GHashTable *engines_by_address = NULL;
453
454 static void
register_engine(GConfEngine * conf)455 register_engine (GConfEngine *conf)
456 {
457 g_return_if_fail (conf->addresses != NULL);
458
459 g_assert (conf->persistent_address == NULL);
460
461 conf->persistent_address =
462 gconf_address_list_get_persistent_name (conf->addresses);
463
464 if (engines_by_address == NULL)
465 engines_by_address = g_hash_table_new (g_str_hash, g_str_equal);
466
467 g_hash_table_insert (engines_by_address, conf->persistent_address, conf);
468 }
469
470 static void
unregister_engine(GConfEngine * conf)471 unregister_engine (GConfEngine *conf)
472 {
473 g_return_if_fail (engines_by_address != NULL);
474
475 g_assert (conf->persistent_address != NULL);
476
477 g_hash_table_remove (engines_by_address, conf->persistent_address);
478 g_free (conf->persistent_address);
479 conf->persistent_address = NULL;
480
481 if (g_hash_table_size (engines_by_address) == 0)
482 {
483 g_hash_table_destroy (engines_by_address);
484
485 engines_by_address = NULL;
486 }
487 }
488
489 static GConfEngine *
lookup_engine(GSList * addresses)490 lookup_engine (GSList *addresses)
491 {
492 if (engines_by_address != NULL)
493 {
494 GConfEngine *retval;
495 char *key;
496
497 key = gconf_address_list_get_persistent_name (addresses);
498
499 retval = g_hash_table_lookup (engines_by_address, key);
500
501 g_free (key);
502
503 return retval;
504 }
505
506 return NULL;
507 }
508
509
510 /*
511 * Public Interface
512 */
513
514 GConfEngine*
gconf_engine_get_local(const gchar * address,GError ** err)515 gconf_engine_get_local (const gchar* address,
516 GError** err)
517 {
518 GConfEngine* conf;
519 GConfSource* source;
520 GConfSources* sources;
521
522 g_return_val_if_fail(address != NULL, NULL);
523 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
524
525 source = gconf_resolve_address(address, err);
526
527 if (source == NULL)
528 return NULL;
529
530 sources = gconf_sources_new_from_source(source);
531 if (sources == NULL)
532 return NULL;
533
534 conf = gconf_engine_blank(FALSE);
535
536 conf->local_sources = sources;
537
538 g_assert (gconf_engine_is_local (conf));
539
540 return conf;
541 }
542
543 GConfEngine *
gconf_engine_get_local_for_addresses(GSList * addresses,GError ** err)544 gconf_engine_get_local_for_addresses (GSList *addresses,
545 GError **err)
546 {
547 GConfEngine *conf;
548 GConfSources* sources;
549
550 g_return_val_if_fail (addresses != NULL, NULL);
551 g_return_val_if_fail (err == NULL || *err == NULL, NULL);
552
553 sources = gconf_sources_new_from_addresses (addresses, err);
554
555 if (sources == NULL)
556 return NULL;
557
558 conf = gconf_engine_blank (FALSE);
559
560 conf->local_sources = sources;
561
562 g_assert (gconf_engine_is_local (conf));
563
564 return conf;
565 }
566
567 /**
568 * gconf_engine_get_default: (skip)
569 *
570 * Returns the default #GConfEngine. All clients should use this, unless
571 * they are special configuration-related tools. The caller of this
572 * function assumes one reference count, and must call
573 * gconf_engine_unref() at some point. It's fairly important to unref the
574 * #GConfEngine, to cleanly close the connection to
575 * <application>gconfd</application>. So if possible close the connection
576 * before exiting your application.
577 *
578 * Return value: (transfer full): the default #GConfEngine.
579 */
580 GConfEngine*
gconf_engine_get_default(void)581 gconf_engine_get_default (void)
582 {
583 GConfEngine* conf = NULL;
584 const gchar* source_path;
585 GError* err = NULL;
586
587 if (default_engine)
588 conf = default_engine;
589
590 if (conf == NULL)
591 {
592 conf = gconf_engine_blank(TRUE);
593
594 default_engine = conf;
595
596 source_path = g_getenv ("GCONF_DEFAULT_SOURCE_PATH");
597 if (source_path != NULL)
598 {
599 conf->addresses = gconf_load_source_path (source_path, &err);
600 if (err)
601 {
602 g_warning ("Could not parse GCONF_DEFAULT_SOURCE_PATH: %s",
603 err->message);
604 g_error_free (err);
605 }
606 }
607 else
608 conf->addresses = NULL;
609
610 /* Ignore errors, we never return a NULL default database, and
611 * since we aren't starting if it isn't found, we'll probably
612 * get errors half the time anyway.
613 */
614 gconf_engine_connect (conf, FALSE, NULL);
615 }
616 else
617 conf->refcount += 1;
618
619 return conf;
620 }
621
622 GConfEngine*
gconf_engine_get_for_address(const char * address,GError ** err)623 gconf_engine_get_for_address (const char *address,
624 GError **err)
625 {
626 GConfEngine *conf;
627 GSList *addresses;
628
629 addresses = g_slist_append (NULL, g_strdup (address));
630
631 conf = lookup_engine (addresses);
632
633 if (conf == NULL)
634 {
635 conf = gconf_engine_blank (TRUE);
636
637 conf->addresses = addresses;
638
639 if (!gconf_engine_connect (conf, TRUE, err))
640 {
641 gconf_engine_unref (conf);
642 return NULL;
643 }
644
645 register_engine (conf);
646 }
647 else
648 {
649 g_free (addresses->data);
650 g_slist_free (addresses);
651 conf->refcount += 1;
652 }
653
654 return conf;
655 }
656
657 GConfEngine*
gconf_engine_get_for_addresses(GSList * addresses,GError ** err)658 gconf_engine_get_for_addresses (GSList *addresses, GError** err)
659 {
660 GConfEngine* conf;
661
662 conf = lookup_engine (addresses);
663
664 if (conf == NULL)
665 {
666 GSList *tmp;
667
668 conf = gconf_engine_blank (TRUE);
669
670 conf->addresses = NULL;
671
672 tmp = addresses;
673 while (tmp != NULL)
674 {
675 conf->addresses = g_slist_append (conf->addresses,
676 g_strdup (tmp->data));
677 tmp = tmp->next;
678 }
679
680 if (!gconf_engine_connect (conf, TRUE, err))
681 {
682 gconf_engine_unref (conf);
683 return NULL;
684 }
685
686 register_engine (conf);
687 }
688 else
689 conf->refcount += 1;
690
691 return conf;
692 }
693
694 void
gconf_engine_ref(GConfEngine * conf)695 gconf_engine_ref(GConfEngine* conf)
696 {
697 g_return_if_fail(conf != NULL);
698 g_return_if_fail(conf->refcount > 0);
699
700 conf->refcount += 1;
701 }
702
703 void
gconf_engine_unref(GConfEngine * conf)704 gconf_engine_unref(GConfEngine* conf)
705 {
706 g_return_if_fail(conf != NULL);
707 g_return_if_fail(conf->refcount > 0);
708
709 conf->refcount -= 1;
710
711 if (conf->refcount == 0)
712 {
713 if (gconf_engine_is_local(conf))
714 {
715 if (conf->local_sources != NULL)
716 gconf_sources_free(conf->local_sources);
717 }
718 else
719 {
720 /* Remove all connections associated with this GConf */
721 GSList* removed;
722 GSList* tmp;
723 CORBA_Environment ev;
724
725 CORBA_exception_init(&ev);
726
727 /* FIXME CnxnTable only has entries for this GConfEngine now,
728 * it used to be global and shared among GConfEngine objects.
729 */
730 removed = ctable_remove_by_conf (conf->ctable, conf);
731
732 tmp = removed;
733 while (tmp != NULL)
734 {
735 GConfCnxn* gcnxn = tmp->data;
736
737 if (!CORBA_Object_is_nil (conf->database, &ev))
738 {
739 GError* err = NULL;
740
741 ConfigDatabase_remove_listener(conf->database,
742 gcnxn->server_id,
743 &ev);
744
745 if (gconf_handle_corba_exception(&ev, &err))
746 {
747 /* Don't set error because realistically this
748 doesn't matter to clients */
749 #ifdef GCONF_ENABLE_DEBUG
750 g_warning("Failure removing listener %u from the configuration server: %s",
751 (guint)gcnxn->server_id,
752 err->message);
753 #endif
754 }
755 }
756
757 gconf_cnxn_destroy(gcnxn);
758
759 tmp = g_slist_next(tmp);
760 }
761
762 g_slist_free(removed);
763
764 if (conf->dnotify)
765 {
766 (* conf->dnotify) (conf->user_data);
767 }
768
769 if (conf->addresses)
770 {
771 gconf_address_list_free (conf->addresses);
772 conf->addresses = NULL;
773 }
774
775 if (conf->persistent_address)
776 {
777 unregister_engine (conf);
778 }
779
780 /* Release the ConfigDatabase */
781 gconf_engine_detach (conf);
782
783 ctable_destroy (conf->ctable);
784 }
785
786 if (conf == default_engine)
787 default_engine = NULL;
788
789 g_free(conf);
790 }
791 }
792
793 void
gconf_engine_set_user_data(GConfEngine * engine,gpointer data,GDestroyNotify dnotify)794 gconf_engine_set_user_data (GConfEngine *engine,
795 gpointer data,
796 GDestroyNotify dnotify)
797 {
798 if (engine->dnotify)
799 {
800 (* engine->dnotify) (engine->user_data);
801 }
802
803 engine->dnotify = dnotify;
804 engine->user_data = data;
805 }
806
807 gpointer
gconf_engine_get_user_data(GConfEngine * engine)808 gconf_engine_get_user_data (GConfEngine *engine)
809 {
810 return engine->user_data;
811 }
812
813 /**
814 * gconf_engine_notify_add: (skip)
815 * @conf: a #GConfEngine to monitor for changes.
816 * @namespace_section: the directory or key to watch; you will be notified of changes at or below this point.
817 * @func: the callback to invoke when a notification is received from the server.
818 * @user_data: the data to pass to the callback.
819 * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
820 * Return value: an ID for the notification request, or 0 on error.
821 *
822 * Registers a notification request with the <application>gconfd</application>
823 * server. The server will notify the client when any key at or below
824 * @namespace_section is set or unset. Try to watch the smallest possible part of
825 * the namespace; otherwise you will slow down the server and your application with
826 * unnecessary notifications. Note that you should prefer gconf_client_notify_add()
827 * if you're using the #GObject wrapper library, because
828 * gconf_client_notify_add() does not require a client-server conversation for
829 * every callback. gconf_engine_notify_add() requests a different server notification for
830 * every callback. The function returns an ID you can use to remove the
831 * notification request; 0 is an invalid ID, and is returned if an error occurs.
832 *
833 * Returns value: an ID for the notification request, or 0 on error.
834 */
835 guint
gconf_engine_notify_add(GConfEngine * conf,const gchar * namespace_section,GConfNotifyFunc func,gpointer user_data,GError ** err)836 gconf_engine_notify_add(GConfEngine* conf,
837 const gchar* namespace_section,
838 GConfNotifyFunc func,
839 gpointer user_data,
840 GError** err)
841 {
842 ConfigDatabase db;
843 ConfigListener cl;
844 gulong id;
845 CORBA_Environment ev;
846 GConfCnxn* cnxn;
847 gint tries = 0;
848 ConfigDatabase3_PropList properties;
849 #define NUM_PROPERTIES 1
850 ConfigStringProperty properties_buffer[1];
851
852 g_return_val_if_fail(!gconf_engine_is_local(conf), 0);
853
854 CHECK_OWNER_USE (conf);
855
856 if (gconf_engine_is_local(conf))
857 {
858 if (err)
859 *err = gconf_error_new(GCONF_ERROR_LOCAL_ENGINE,
860 _("Can't add notifications to a local configuration source"));
861
862 return 0;
863 }
864
865 properties._buffer = properties_buffer;
866 properties._length = NUM_PROPERTIES;
867 properties._maximum = NUM_PROPERTIES;
868 properties._release = CORBA_FALSE; /* don't free static buffer */
869
870 properties._buffer[0].key = "name";
871 properties._buffer[0].value = g_get_prgname ();
872 if (properties._buffer[0].value == NULL)
873 properties._buffer[0].value = "unknown";
874
875 CORBA_exception_init(&ev);
876
877 RETRY:
878
879 db = gconf_engine_get_database (conf, TRUE, err);
880
881 if (db == CORBA_OBJECT_NIL)
882 return 0;
883
884 cl = gconf_get_config_listener ();
885
886 /* Should have aborted the program in this case probably */
887 g_return_val_if_fail(cl != CORBA_OBJECT_NIL, 0);
888
889 id = ConfigDatabase3_add_listener_with_properties (db,
890 (gchar*)namespace_section,
891 cl,
892 &properties,
893 &ev);
894
895 if (ev._major == CORBA_SYSTEM_EXCEPTION &&
896 CORBA_exception_id (&ev) &&
897 strcmp (CORBA_exception_id (&ev), "IDL:CORBA/BAD_OPERATION:1.0") == 0)
898 {
899 CORBA_exception_free (&ev);
900 CORBA_exception_init (&ev);
901
902 id = ConfigDatabase_add_listener(db,
903 (gchar*)namespace_section,
904 cl, &ev);
905 }
906
907 if (gconf_server_broken(&ev))
908 {
909 if (tries < MAX_RETRIES)
910 {
911 ++tries;
912 CORBA_exception_free(&ev);
913 gconf_engine_detach (conf);
914 goto RETRY;
915 }
916 }
917
918 if (gconf_handle_corba_exception(&ev, err))
919 return 0;
920
921 cnxn = gconf_cnxn_new(conf, namespace_section, id, func, user_data);
922
923 ctable_insert(conf->ctable, cnxn);
924
925 return cnxn->client_id;
926 }
927
928 void
gconf_engine_notify_remove(GConfEngine * conf,guint client_id)929 gconf_engine_notify_remove(GConfEngine* conf,
930 guint client_id)
931 {
932 GConfCnxn* gcnxn;
933 CORBA_Environment ev;
934 ConfigDatabase db;
935 gint tries = 0;
936
937 CHECK_OWNER_USE (conf);
938
939 if (gconf_engine_is_local(conf))
940 return;
941
942 CORBA_exception_init(&ev);
943
944 RETRY:
945
946 db = gconf_engine_get_database (conf, TRUE, NULL);
947
948 if (db == CORBA_OBJECT_NIL)
949 return;
950
951 gcnxn = ctable_lookup_by_client_id(conf->ctable, client_id);
952
953 g_return_if_fail(gcnxn != NULL);
954
955 ConfigDatabase_remove_listener(db,
956 gcnxn->server_id,
957 &ev);
958
959 if (gconf_server_broken(&ev))
960 {
961 if (tries < MAX_RETRIES)
962 {
963 ++tries;
964 CORBA_exception_free(&ev);
965 gconf_engine_detach (conf);
966 goto RETRY;
967 }
968 }
969
970 if (gconf_handle_corba_exception(&ev, NULL))
971 {
972 ; /* do nothing */
973 }
974
975
976 /* We want to do this even if the CORBA fails, so if we restart gconfd and
977 reinstall listeners we don't reinstall this one. */
978 ctable_remove(conf->ctable, gcnxn);
979
980 gconf_cnxn_destroy(gcnxn);
981 }
982
983 GConfValue *
gconf_engine_get_fuller(GConfEngine * conf,const gchar * key,const gchar * locale,gboolean use_schema_default,gboolean * is_default_p,gboolean * is_writable_p,gchar ** schema_name_p,GError ** err)984 gconf_engine_get_fuller (GConfEngine *conf,
985 const gchar *key,
986 const gchar *locale,
987 gboolean use_schema_default,
988 gboolean *is_default_p,
989 gboolean *is_writable_p,
990 gchar **schema_name_p,
991 GError **err)
992 {
993 GConfValue* val;
994 ConfigValue* cv;
995 CORBA_Environment ev;
996 ConfigDatabase db;
997 gint tries = 0;
998 CORBA_boolean is_default = FALSE;
999 CORBA_boolean is_writable = TRUE;
1000 CORBA_char *corba_schema_name = NULL;
1001
1002 g_return_val_if_fail(conf != NULL, NULL);
1003 g_return_val_if_fail(key != NULL, NULL);
1004 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1005
1006 CHECK_OWNER_USE (conf);
1007
1008 if (!gconf_key_check(key, err))
1009 return NULL;
1010
1011 if (gconf_engine_is_local(conf))
1012 {
1013 gchar** locale_list;
1014 gboolean tmp_is_default = FALSE;
1015 gboolean tmp_is_writable = TRUE;
1016 gchar *tmp_schema_name = NULL;
1017
1018 locale_list = gconf_split_locale(locale);
1019
1020 val = gconf_sources_query_value(conf->local_sources,
1021 key,
1022 (const gchar**)locale_list,
1023 use_schema_default,
1024 &tmp_is_default,
1025 &tmp_is_writable,
1026 schema_name_p ? &tmp_schema_name : NULL,
1027 err);
1028
1029 if (locale_list != NULL)
1030 g_strfreev(locale_list);
1031
1032 if (is_default_p)
1033 *is_default_p = tmp_is_default;
1034
1035 if (is_writable_p)
1036 *is_writable_p = tmp_is_writable;
1037
1038 if (schema_name_p)
1039 *schema_name_p = tmp_schema_name;
1040 else
1041 g_free (tmp_schema_name);
1042
1043 return val;
1044 }
1045
1046 g_assert(!gconf_engine_is_local(conf));
1047
1048 CORBA_exception_init(&ev);
1049
1050 RETRY:
1051
1052 db = gconf_engine_get_database (conf, TRUE, err);
1053
1054 if (db == CORBA_OBJECT_NIL)
1055 {
1056 g_return_val_if_fail(err == NULL || *err != NULL, NULL);
1057
1058 return NULL;
1059 }
1060
1061 if (schema_name_p)
1062 *schema_name_p = NULL;
1063
1064
1065 corba_schema_name = NULL;
1066 cv = ConfigDatabase2_lookup_with_schema_name (db,
1067 (gchar*)key, (gchar*)
1068 (locale ? locale : gconf_current_locale()),
1069 use_schema_default,
1070 &corba_schema_name,
1071 &is_default,
1072 &is_writable,
1073 &ev);
1074
1075 if (ev._major == CORBA_SYSTEM_EXCEPTION &&
1076 CORBA_exception_id (&ev) &&
1077 strcmp (CORBA_exception_id (&ev), "IDL:CORBA/BAD_OPERATION:1.0") == 0)
1078 {
1079 CORBA_exception_free (&ev);
1080 CORBA_exception_init (&ev);
1081
1082 cv = ConfigDatabase_lookup_with_locale(db,
1083 (gchar*)key, (gchar*)
1084 (locale ? locale : gconf_current_locale()),
1085 use_schema_default,
1086 &is_default,
1087 &is_writable,
1088 &ev);
1089 }
1090
1091 if (gconf_server_broken(&ev))
1092 {
1093 if (tries < MAX_RETRIES)
1094 {
1095 ++tries;
1096 CORBA_exception_free(&ev);
1097 gconf_engine_detach (conf);
1098 goto RETRY;
1099 }
1100 }
1101
1102 if (gconf_handle_corba_exception(&ev, err))
1103 {
1104 /* NOTE: don't free cv since we got an exception! */
1105 return NULL;
1106 }
1107 else
1108 {
1109 val = gconf_value_from_corba_value(cv);
1110 CORBA_free(cv);
1111
1112 if (is_default_p)
1113 *is_default_p = !!is_default;
1114 if (is_writable_p)
1115 *is_writable_p = !!is_writable;
1116
1117 /* we can't get a null pointer through corba
1118 * so the server sent us an empty string
1119 */
1120 if (corba_schema_name && corba_schema_name[0] != '/')
1121 {
1122 CORBA_free (corba_schema_name);
1123 corba_schema_name = NULL;
1124 }
1125
1126 if (schema_name_p)
1127 *schema_name_p = g_strdup (corba_schema_name);
1128
1129 if (corba_schema_name)
1130 CORBA_free (corba_schema_name);
1131
1132 return val;
1133 }
1134 }
1135
1136
1137 GConfValue *
gconf_engine_get_full(GConfEngine * conf,const gchar * key,const gchar * locale,gboolean use_schema_default,gboolean * is_default_p,gboolean * is_writable_p,GError ** err)1138 gconf_engine_get_full (GConfEngine *conf,
1139 const gchar *key,
1140 const gchar *locale,
1141 gboolean use_schema_default,
1142 gboolean *is_default_p,
1143 gboolean *is_writable_p,
1144 GError **err)
1145 {
1146 return gconf_engine_get_fuller (conf, key, locale, use_schema_default,
1147 is_default_p, is_writable_p,
1148 NULL, err);
1149 }
1150
1151 GConfEntry*
gconf_engine_get_entry(GConfEngine * conf,const gchar * key,const gchar * locale,gboolean use_schema_default,GError ** err)1152 gconf_engine_get_entry(GConfEngine* conf,
1153 const gchar* key,
1154 const gchar* locale,
1155 gboolean use_schema_default,
1156 GError** err)
1157 {
1158 gboolean is_writable = TRUE;
1159 gboolean is_default = FALSE;
1160 GConfValue *val;
1161 GError *error;
1162 GConfEntry *entry;
1163 gchar *schema_name;
1164
1165 CHECK_OWNER_USE (conf);
1166
1167 schema_name = NULL;
1168 error = NULL;
1169 val = gconf_engine_get_fuller (conf, key, locale, use_schema_default,
1170 &is_default, &is_writable,
1171 &schema_name, &error);
1172 if (error != NULL)
1173 {
1174 g_propagate_error (err, error);
1175 return NULL;
1176 }
1177
1178 entry = gconf_entry_new_nocopy (g_strdup (key),
1179 val);
1180
1181 gconf_entry_set_is_default (entry, is_default);
1182 gconf_entry_set_is_writable (entry, is_writable);
1183 gconf_entry_set_schema_name (entry, schema_name);
1184 g_free (schema_name);
1185
1186 return entry;
1187 }
1188
1189 GConfValue*
gconf_engine_get(GConfEngine * conf,const gchar * key,GError ** err)1190 gconf_engine_get (GConfEngine* conf, const gchar* key, GError** err)
1191 {
1192 return gconf_engine_get_with_locale(conf, key, NULL, err);
1193 }
1194
1195 GConfValue*
gconf_engine_get_with_locale(GConfEngine * conf,const gchar * key,const gchar * locale,GError ** err)1196 gconf_engine_get_with_locale(GConfEngine* conf, const gchar* key,
1197 const gchar* locale,
1198 GError** err)
1199 {
1200 return gconf_engine_get_full(conf, key, locale, TRUE,
1201 NULL, NULL, err);
1202 }
1203
1204 GConfValue*
gconf_engine_get_without_default(GConfEngine * conf,const gchar * key,GError ** err)1205 gconf_engine_get_without_default(GConfEngine* conf, const gchar* key,
1206 GError** err)
1207 {
1208 return gconf_engine_get_full(conf, key, NULL, FALSE, NULL, NULL, err);
1209 }
1210
1211 GConfValue*
gconf_engine_get_default_from_schema(GConfEngine * conf,const gchar * key,GError ** err)1212 gconf_engine_get_default_from_schema (GConfEngine* conf,
1213 const gchar* key,
1214 GError** err)
1215 {
1216 GConfValue* val;
1217 ConfigValue* cv;
1218 CORBA_Environment ev;
1219 ConfigDatabase db;
1220 gint tries = 0;
1221
1222 g_return_val_if_fail(conf != NULL, NULL);
1223 g_return_val_if_fail(key != NULL, NULL);
1224 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1225
1226 CHECK_OWNER_USE (conf);
1227
1228 if (!gconf_key_check(key, err))
1229 return NULL;
1230
1231 if (gconf_engine_is_local(conf))
1232 {
1233 gchar** locale_list;
1234
1235 locale_list = gconf_split_locale(gconf_current_locale());
1236
1237 val = gconf_sources_query_default_value(conf->local_sources,
1238 key,
1239 (const gchar**)locale_list,
1240 NULL,
1241 err);
1242
1243 if (locale_list != NULL)
1244 g_strfreev(locale_list);
1245
1246 return val;
1247 }
1248
1249 g_assert(!gconf_engine_is_local(conf));
1250
1251 CORBA_exception_init(&ev);
1252
1253 RETRY:
1254
1255 db = gconf_engine_get_database (conf, TRUE, err);
1256
1257 if (db == CORBA_OBJECT_NIL)
1258 {
1259 g_return_val_if_fail(err == NULL || *err != NULL, NULL);
1260
1261 return NULL;
1262 }
1263
1264 cv = ConfigDatabase_lookup_default_value(db,
1265 (gchar*)key,
1266 (gchar*)gconf_current_locale(),
1267 &ev);
1268
1269 if (gconf_server_broken(&ev))
1270 {
1271 if (tries < MAX_RETRIES)
1272 {
1273 ++tries;
1274 CORBA_exception_free(&ev);
1275 gconf_engine_detach (conf);
1276 goto RETRY;
1277 }
1278 }
1279
1280 if (gconf_handle_corba_exception(&ev, err))
1281 {
1282 /* NOTE: don't free cv since we got an exception! */
1283 return NULL;
1284 }
1285 else
1286 {
1287 val = gconf_value_from_corba_value(cv);
1288 CORBA_free(cv);
1289
1290 return val;
1291 }
1292 }
1293
1294 gboolean
gconf_engine_set(GConfEngine * conf,const gchar * key,const GConfValue * value,GError ** err)1295 gconf_engine_set (GConfEngine* conf, const gchar* key,
1296 const GConfValue* value, GError** err)
1297 {
1298 ConfigValue* cv;
1299 CORBA_Environment ev;
1300 ConfigDatabase db;
1301 gint tries = 0;
1302
1303 g_return_val_if_fail(conf != NULL, FALSE);
1304 g_return_val_if_fail(key != NULL, FALSE);
1305 g_return_val_if_fail(value != NULL, FALSE);
1306 g_return_val_if_fail(value->type != GCONF_VALUE_INVALID, FALSE);
1307 g_return_val_if_fail( (value->type != GCONF_VALUE_STRING) ||
1308 (gconf_value_get_string(value) != NULL) , FALSE );
1309 g_return_val_if_fail( (value->type != GCONF_VALUE_LIST) ||
1310 (gconf_value_get_list_type(value) != GCONF_VALUE_INVALID), FALSE);
1311 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
1312
1313 CHECK_OWNER_USE (conf);
1314
1315 if (!gconf_key_check(key, err))
1316 return FALSE;
1317
1318 if (!gconf_value_validate (value, err))
1319 return FALSE;
1320
1321 if (gconf_engine_is_local(conf))
1322 {
1323 GError* error = NULL;
1324
1325 gconf_sources_set_value(conf->local_sources, key, value, NULL, &error);
1326
1327 if (error != NULL)
1328 {
1329 if (err)
1330 *err = error;
1331 else
1332 {
1333 g_error_free(error);
1334 }
1335 return FALSE;
1336 }
1337
1338 return TRUE;
1339 }
1340
1341 g_assert(!gconf_engine_is_local(conf));
1342
1343 CORBA_exception_init(&ev);
1344
1345 RETRY:
1346
1347 db = gconf_engine_get_database (conf, TRUE, err);
1348
1349 if (db == CORBA_OBJECT_NIL)
1350 {
1351 g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
1352
1353 return FALSE;
1354 }
1355
1356 cv = gconf_corba_value_from_gconf_value (value);
1357
1358 ConfigDatabase_set(db,
1359 (gchar*)key, cv,
1360 &ev);
1361
1362 CORBA_free(cv);
1363
1364 if (gconf_server_broken(&ev))
1365 {
1366 if (tries < MAX_RETRIES)
1367 {
1368 ++tries;
1369 CORBA_exception_free(&ev);
1370 gconf_engine_detach (conf);
1371 goto RETRY;
1372 }
1373 }
1374
1375 if (gconf_handle_corba_exception(&ev, err))
1376 return FALSE;
1377
1378 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
1379
1380 return TRUE;
1381 }
1382
1383 gboolean
gconf_engine_unset(GConfEngine * conf,const gchar * key,GError ** err)1384 gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err)
1385 {
1386 CORBA_Environment ev;
1387 ConfigDatabase db;
1388 gint tries = 0;
1389
1390 g_return_val_if_fail (conf != NULL, FALSE);
1391 g_return_val_if_fail (key != NULL, FALSE);
1392 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1393
1394 CHECK_OWNER_USE (conf);
1395
1396 if (!gconf_key_check(key, err))
1397 return FALSE;
1398
1399 if (gconf_engine_is_local(conf))
1400 {
1401 GError* error = NULL;
1402
1403 gconf_sources_unset_value(conf->local_sources, key, NULL, NULL, &error);
1404
1405 if (error != NULL)
1406 {
1407 if (err)
1408 *err = error;
1409 else
1410 {
1411 g_error_free(error);
1412 }
1413 return FALSE;
1414 }
1415
1416 return TRUE;
1417 }
1418
1419 g_assert(!gconf_engine_is_local(conf));
1420
1421 CORBA_exception_init(&ev);
1422
1423 RETRY:
1424
1425 db = gconf_engine_get_database (conf, TRUE, err);
1426
1427 if (db == CORBA_OBJECT_NIL)
1428 {
1429 g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
1430
1431 return FALSE;
1432 }
1433
1434 ConfigDatabase_unset (db,
1435 (gchar*)key,
1436 &ev);
1437
1438 if (gconf_server_broken (&ev))
1439 {
1440 if (tries < MAX_RETRIES)
1441 {
1442 ++tries;
1443 CORBA_exception_free(&ev);
1444 gconf_engine_detach(conf);
1445 goto RETRY;
1446 }
1447 }
1448
1449 if (gconf_handle_corba_exception (&ev, err))
1450 return FALSE;
1451
1452 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1453
1454 return TRUE;
1455 }
1456
1457 /**
1458 * gconf_engine_recursive_unset:
1459 * @engine: a #GConfEngine
1460 * @key: a key or directory name
1461 * @flags: change how the unset is done
1462 * @err: return location for a #GError, or %NULL to ignore errors
1463 *
1464 * Unsets all keys below @key, including @key itself. If any unset
1465 * fails, continues on to unset as much as it can. The first
1466 * failure is returned in @err.
1467 *
1468 * Returns: %FALSE if error is set
1469 **/
1470 gboolean
gconf_engine_recursive_unset(GConfEngine * conf,const char * key,GConfUnsetFlags flags,GError ** err)1471 gconf_engine_recursive_unset (GConfEngine *conf,
1472 const char *key,
1473 GConfUnsetFlags flags,
1474 GError **err)
1475 {
1476 CORBA_Environment ev;
1477 ConfigDatabase3 db;
1478 gint tries = 0;
1479 ConfigDatabase3_UnsetFlags corba_flags;
1480
1481 g_return_val_if_fail (conf != NULL, FALSE);
1482 g_return_val_if_fail (key != NULL, FALSE);
1483 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1484
1485 CHECK_OWNER_USE (conf);
1486
1487 if (!gconf_key_check (key, err))
1488 return FALSE;
1489
1490 if (gconf_engine_is_local (conf))
1491 {
1492 GError* error = NULL;
1493
1494 gconf_sources_recursive_unset (conf->local_sources, key, NULL,
1495 flags, NULL, &error);
1496
1497 if (error != NULL)
1498 {
1499 if (err)
1500 *err = error;
1501 else
1502 {
1503 g_error_free (error);
1504 }
1505 return FALSE;
1506 }
1507
1508 return TRUE;
1509 }
1510
1511 g_assert (!gconf_engine_is_local (conf));
1512
1513 CORBA_exception_init(&ev);
1514
1515 corba_flags = 0;
1516 if (flags & GCONF_UNSET_INCLUDING_SCHEMA_NAMES)
1517 corba_flags |= ConfigDatabase3_UNSET_INCLUDING_SCHEMA_NAMES;
1518
1519 RETRY:
1520
1521 db = (ConfigDatabase3) gconf_engine_get_database (conf, TRUE, err);
1522
1523 if (db == CORBA_OBJECT_NIL)
1524 {
1525 g_return_val_if_fail (err == NULL || *err != NULL, FALSE);
1526
1527 return FALSE;
1528 }
1529
1530 ConfigDatabase3_recursive_unset (db, key, corba_flags, &ev);
1531
1532 if (gconf_server_broken (&ev))
1533 {
1534 if (tries < MAX_RETRIES)
1535 {
1536 ++tries;
1537 CORBA_exception_free(&ev);
1538 gconf_engine_detach(conf);
1539 goto RETRY;
1540 }
1541 }
1542
1543 if (gconf_handle_corba_exception (&ev, err))
1544 return FALSE;
1545
1546 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1547
1548 return TRUE;
1549 }
1550
1551 gboolean
gconf_engine_associate_schema(GConfEngine * conf,const gchar * key,const gchar * schema_key,GError ** err)1552 gconf_engine_associate_schema (GConfEngine* conf, const gchar* key,
1553 const gchar* schema_key, GError** err)
1554 {
1555 CORBA_Environment ev;
1556 ConfigDatabase db;
1557 gint tries = 0;
1558
1559 g_return_val_if_fail (conf != NULL, FALSE);
1560 g_return_val_if_fail (key != NULL, FALSE);
1561 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1562
1563 if (!gconf_key_check (key, err))
1564 return FALSE;
1565
1566 if (schema_key && !gconf_key_check (schema_key, err))
1567 return FALSE;
1568
1569 if (gconf_engine_is_local(conf))
1570 {
1571 GError* error = NULL;
1572
1573 gconf_sources_set_schema (conf->local_sources, key, schema_key, &error);
1574
1575 if (error != NULL)
1576 {
1577 if (err)
1578 *err = error;
1579 else
1580 {
1581 g_error_free(error);
1582 }
1583 return FALSE;
1584 }
1585
1586 return TRUE;
1587 }
1588
1589 g_assert (!gconf_engine_is_local (conf));
1590
1591 CORBA_exception_init (&ev);
1592
1593 RETRY:
1594
1595 db = gconf_engine_get_database (conf, TRUE, err);
1596
1597 if (db == CORBA_OBJECT_NIL)
1598 {
1599 g_return_val_if_fail (err == NULL || *err != NULL, FALSE);
1600
1601 return FALSE;
1602 }
1603
1604 ConfigDatabase_set_schema (db,
1605 key,
1606 /* empty string means unset */
1607 schema_key ? schema_key : "",
1608 &ev);
1609
1610 if (gconf_server_broken (&ev))
1611 {
1612 if (tries < MAX_RETRIES)
1613 {
1614 ++tries;
1615 CORBA_exception_free (&ev);
1616 gconf_engine_detach (conf);
1617 goto RETRY;
1618 }
1619 }
1620
1621 if (gconf_handle_corba_exception(&ev, err))
1622 return FALSE;
1623
1624 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1625
1626 return TRUE;
1627 }
1628
1629
1630 static void
qualify_entries(GSList * entries,const char * dir)1631 qualify_entries (GSList *entries, const char *dir)
1632 {
1633 GSList *tmp = entries;
1634 while (tmp != NULL)
1635 {
1636 GConfEntry *entry = tmp->data;
1637 gchar *full;
1638
1639 full = gconf_concat_dir_and_key (dir, entry->key);
1640
1641 g_free (entry->key);
1642 entry->key = full;
1643
1644 tmp = g_slist_next (tmp);
1645 }
1646 }
1647
1648 /**
1649 * gconf_engine_all_entries:
1650 * @conf: a #GConfEngine.
1651 * @dir: Directory to list.
1652 * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
1653 *
1654 * Lists the key-value pairs in @dir. Does not list subdirectories; for
1655 * that use gconf_engine_all_dirs(). The returned list contains #GConfEntry
1656 * objects. A #GConfEntry contains an <emphasis>absolute</emphasis> key
1657 * and a value. The list is not recursive, it contains only the immediate
1658 * children of @dir. To free the returned list, gconf_entry_free()
1659 * each list element, then g_slist_free() the list itself.
1660 *
1661 * Returns value: (element-type GConfEntry) (transfer full): List of #GConfEntry.
1662 */
1663 GSList*
gconf_engine_all_entries(GConfEngine * conf,const gchar * dir,GError ** err)1664 gconf_engine_all_entries(GConfEngine* conf, const gchar* dir, GError** err)
1665 {
1666 GSList* pairs = NULL;
1667 ConfigDatabase_ValueList* values;
1668 ConfigDatabase_KeyList* keys;
1669 ConfigDatabase_IsDefaultList* is_defaults;
1670 ConfigDatabase_IsWritableList* is_writables;
1671 ConfigDatabase2_SchemaNameList *schema_names;
1672 CORBA_Environment ev;
1673 ConfigDatabase db;
1674 guint i;
1675 gint tries = 0;
1676
1677 g_return_val_if_fail(conf != NULL, NULL);
1678 g_return_val_if_fail(dir != NULL, NULL);
1679 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1680
1681 CHECK_OWNER_USE (conf);
1682
1683 if (!gconf_key_check(dir, err))
1684 return NULL;
1685
1686
1687 if (gconf_engine_is_local(conf))
1688 {
1689 GError* error = NULL;
1690 gchar** locale_list;
1691 GSList* retval;
1692
1693 locale_list = gconf_split_locale(gconf_current_locale());
1694
1695 retval = gconf_sources_all_entries(conf->local_sources,
1696 dir,
1697 (const gchar**)locale_list,
1698 &error);
1699
1700 if (locale_list)
1701 g_strfreev(locale_list);
1702
1703 if (error != NULL)
1704 {
1705 if (err)
1706 *err = error;
1707 else
1708 {
1709 g_error_free(error);
1710 }
1711
1712 g_assert(retval == NULL);
1713
1714 return NULL;
1715 }
1716
1717 qualify_entries (retval, dir);
1718
1719 return retval;
1720 }
1721
1722 g_assert(!gconf_engine_is_local(conf));
1723
1724 CORBA_exception_init(&ev);
1725
1726 RETRY:
1727
1728 db = gconf_engine_get_database (conf, TRUE, err);
1729
1730 if (db == CORBA_OBJECT_NIL)
1731 {
1732 g_return_val_if_fail(err == NULL || *err != NULL, NULL);
1733
1734 return NULL;
1735 }
1736
1737 schema_names = NULL;
1738
1739 ConfigDatabase2_all_entries_with_schema_name (db,
1740 (gchar*)dir,
1741 (gchar*)gconf_current_locale(),
1742 &keys, &values, &schema_names,
1743 &is_defaults, &is_writables,
1744 &ev);
1745
1746 if (ev._major == CORBA_SYSTEM_EXCEPTION &&
1747 CORBA_exception_id (&ev) &&
1748 strcmp (CORBA_exception_id (&ev), "IDL:CORBA/BAD_OPERATION:1.0") == 0)
1749 {
1750 CORBA_exception_free (&ev);
1751 CORBA_exception_init (&ev);
1752
1753 ConfigDatabase_all_entries(db,
1754 (gchar*)dir,
1755 (gchar*)gconf_current_locale(),
1756 &keys, &values, &is_defaults, &is_writables,
1757 &ev);
1758 }
1759
1760 if (gconf_server_broken(&ev))
1761 {
1762 if (tries < MAX_RETRIES)
1763 {
1764 ++tries;
1765 CORBA_exception_free(&ev);
1766 gconf_engine_detach (conf);
1767 goto RETRY;
1768 }
1769 }
1770
1771 if (gconf_handle_corba_exception(&ev, err))
1772 return NULL;
1773
1774 if (keys->_length != values->_length)
1775 {
1776 g_warning("Received unmatched key/value sequences in %s",
1777 G_STRFUNC);
1778 return NULL;
1779 }
1780
1781 i = 0;
1782 while (i < keys->_length)
1783 {
1784 GConfEntry* pair;
1785
1786 pair =
1787 gconf_entry_new_nocopy(gconf_concat_dir_and_key (dir, keys->_buffer[i]),
1788 gconf_value_from_corba_value(&(values->_buffer[i])));
1789
1790 gconf_entry_set_is_default (pair, is_defaults->_buffer[i]);
1791 gconf_entry_set_is_writable (pair, is_writables->_buffer[i]);
1792 if (schema_names)
1793 {
1794 /* empty string means no schema name */
1795 if (*(schema_names->_buffer[i]) != '\0')
1796 gconf_entry_set_schema_name (pair, schema_names->_buffer[i]);
1797 }
1798
1799 pairs = g_slist_prepend(pairs, pair);
1800
1801 ++i;
1802 }
1803
1804 CORBA_free(keys);
1805 CORBA_free(values);
1806 CORBA_free(is_defaults);
1807 CORBA_free(is_writables);
1808 if (schema_names)
1809 CORBA_free (schema_names);
1810
1811 return pairs;
1812 }
1813
1814
1815 static void
qualify_keys(GSList * keys,const char * dir)1816 qualify_keys (GSList *keys, const char *dir)
1817 {
1818 GSList *tmp = keys;
1819 while (tmp != NULL)
1820 {
1821 char *key = tmp->data;
1822 gchar *full;
1823
1824 full = gconf_concat_dir_and_key (dir, key);
1825
1826 g_free (tmp->data);
1827 tmp->data = full;
1828
1829 tmp = g_slist_next (tmp);
1830 }
1831 }
1832
1833 /**
1834 * gconf_engine_all_dirs:
1835 * @conf: a #GConfEngine.
1836 * @dir: Directory to get subdirectories from.
1837 * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
1838 *
1839 * Lists the subdirectories in @dir. The returned list contains
1840 * allocated strings. Each string is the absolute path of a
1841 * subdirectory. You should g_free() each string in the list, then
1842 * g_slist_free() the list itself.
1843 *
1844 * Returns value: (element-type utf8) (transfer full): List of allocated subdirectory names.
1845 */
1846 GSList*
gconf_engine_all_dirs(GConfEngine * conf,const gchar * dir,GError ** err)1847 gconf_engine_all_dirs(GConfEngine* conf, const gchar* dir, GError** err)
1848 {
1849 GSList* subdirs = NULL;
1850 ConfigDatabase_KeyList* keys;
1851 CORBA_Environment ev;
1852 ConfigDatabase db;
1853 guint i;
1854 gint tries = 0;
1855
1856 g_return_val_if_fail(conf != NULL, NULL);
1857 g_return_val_if_fail(dir != NULL, NULL);
1858 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1859
1860 CHECK_OWNER_USE (conf);
1861
1862 if (!gconf_key_check(dir, err))
1863 return NULL;
1864
1865 if (gconf_engine_is_local(conf))
1866 {
1867 GError* error = NULL;
1868 GSList* retval;
1869
1870 retval = gconf_sources_all_dirs(conf->local_sources,
1871 dir,
1872 &error);
1873
1874 if (error != NULL)
1875 {
1876 if (err)
1877 *err = error;
1878 else
1879 {
1880 g_error_free(error);
1881 }
1882
1883 g_assert(retval == NULL);
1884
1885 return NULL;
1886 }
1887
1888 qualify_keys (retval, dir);
1889
1890 return retval;
1891 }
1892
1893 g_assert(!gconf_engine_is_local(conf));
1894
1895 CORBA_exception_init(&ev);
1896
1897 RETRY:
1898
1899 db = gconf_engine_get_database (conf, TRUE, err);
1900
1901 if (db == CORBA_OBJECT_NIL)
1902 {
1903 g_return_val_if_fail(((err == NULL) || (*err && ((*err)->code == GCONF_ERROR_NO_SERVER))), NULL);
1904
1905 return NULL;
1906 }
1907
1908 ConfigDatabase_all_dirs(db,
1909 (gchar*)dir,
1910 &keys,
1911 &ev);
1912
1913 if (gconf_server_broken(&ev))
1914 {
1915 if (tries < MAX_RETRIES)
1916 {
1917 ++tries;
1918 CORBA_exception_free(&ev);
1919 gconf_engine_detach (conf);
1920 goto RETRY;
1921 }
1922 }
1923
1924 if (gconf_handle_corba_exception(&ev, err))
1925 return NULL;
1926
1927 i = 0;
1928 while (i < keys->_length)
1929 {
1930 gchar* s;
1931
1932 s = gconf_concat_dir_and_key (dir, keys->_buffer[i]);
1933
1934 subdirs = g_slist_prepend(subdirs, s);
1935
1936 ++i;
1937 }
1938
1939 CORBA_free(keys);
1940
1941 return subdirs;
1942 }
1943
1944 /* annoyingly, this is REQUIRED for local sources */
1945 void
gconf_engine_suggest_sync(GConfEngine * conf,GError ** err)1946 gconf_engine_suggest_sync(GConfEngine* conf, GError** err)
1947 {
1948 CORBA_Environment ev;
1949 ConfigDatabase db;
1950 gint tries = 0;
1951
1952 g_return_if_fail(conf != NULL);
1953 g_return_if_fail(err == NULL || *err == NULL);
1954
1955 CHECK_OWNER_USE (conf);
1956
1957 if (gconf_engine_is_local(conf))
1958 {
1959 GError* error = NULL;
1960
1961 gconf_sources_sync_all(conf->local_sources,
1962 &error);
1963
1964 if (error != NULL)
1965 {
1966 if (err)
1967 *err = error;
1968 else
1969 {
1970 g_error_free(error);
1971 }
1972 return;
1973 }
1974
1975 return;
1976 }
1977
1978 g_assert(!gconf_engine_is_local(conf));
1979
1980 CORBA_exception_init(&ev);
1981
1982 RETRY:
1983
1984 db = gconf_engine_get_database (conf, TRUE, err);
1985
1986 if (db == CORBA_OBJECT_NIL)
1987 {
1988 g_return_if_fail(err == NULL || *err != NULL);
1989
1990 return;
1991 }
1992
1993 ConfigDatabase_sync(db, &ev);
1994
1995 if (gconf_server_broken(&ev))
1996 {
1997 if (tries < MAX_RETRIES)
1998 {
1999 ++tries;
2000 CORBA_exception_free(&ev);
2001 gconf_engine_detach (conf);
2002 goto RETRY;
2003 }
2004 }
2005
2006 if (gconf_handle_corba_exception(&ev, err))
2007 ; /* nothing additional */
2008 }
2009
2010 void
gconf_clear_cache(GConfEngine * conf,GError ** err)2011 gconf_clear_cache(GConfEngine* conf, GError** err)
2012 {
2013 CORBA_Environment ev;
2014 ConfigDatabase db;
2015 gint tries = 0;
2016
2017 g_return_if_fail(conf != NULL);
2018 g_return_if_fail(err == NULL || *err == NULL);
2019
2020 /* don't disallow non-owner use here since you can't do this
2021 * via GConfClient API and calling this function won't break
2022 * GConfClient anyway
2023 */
2024
2025 if (gconf_engine_is_local(conf))
2026 {
2027 gconf_sources_clear_cache(conf->local_sources);
2028
2029 return;
2030 }
2031
2032 g_assert(!gconf_engine_is_local(conf));
2033
2034 CORBA_exception_init(&ev);
2035
2036 RETRY:
2037
2038 db = gconf_engine_get_database (conf, TRUE, err);
2039
2040 if (db == CORBA_OBJECT_NIL)
2041 {
2042 g_return_if_fail(err == NULL || *err != NULL);
2043
2044 return;
2045 }
2046
2047 ConfigDatabase_clear_cache(db, &ev);
2048
2049 if (gconf_server_broken(&ev))
2050 {
2051 if (tries < MAX_RETRIES)
2052 {
2053 ++tries;
2054 CORBA_exception_free(&ev);
2055 gconf_engine_detach (conf);
2056 goto RETRY;
2057 }
2058 }
2059
2060 if (gconf_handle_corba_exception(&ev, err))
2061 ; /* nothing additional */
2062 }
2063
2064 void
gconf_synchronous_sync(GConfEngine * conf,GError ** err)2065 gconf_synchronous_sync(GConfEngine* conf, GError** err)
2066 {
2067 CORBA_Environment ev;
2068 ConfigDatabase db;
2069 gint tries = 0;
2070
2071 g_return_if_fail(conf != NULL);
2072 g_return_if_fail(err == NULL || *err == NULL);
2073
2074 if (gconf_engine_is_local(conf))
2075 {
2076 GError* error = NULL;
2077
2078 gconf_sources_sync_all(conf->local_sources, &error);
2079
2080 if (error != NULL)
2081 {
2082 if (err)
2083 *err = error;
2084 else
2085 {
2086 g_error_free(error);
2087 }
2088 return;
2089 }
2090
2091 return;
2092 }
2093
2094 g_assert(!gconf_engine_is_local(conf));
2095
2096 CORBA_exception_init(&ev);
2097
2098 RETRY:
2099
2100 db = gconf_engine_get_database (conf, TRUE, err);
2101
2102 if (db == CORBA_OBJECT_NIL)
2103 {
2104 g_return_if_fail(err == NULL || *err != NULL);
2105
2106 return;
2107 }
2108
2109 ConfigDatabase_synchronous_sync(db, &ev);
2110
2111 if (gconf_server_broken(&ev))
2112 {
2113 if (tries < MAX_RETRIES)
2114 {
2115 ++tries;
2116 CORBA_exception_free(&ev);
2117 gconf_engine_detach (conf);
2118 goto RETRY;
2119 }
2120 }
2121
2122 if (gconf_handle_corba_exception(&ev, err))
2123 ; /* nothing additional */
2124 }
2125
2126 gboolean
gconf_engine_dir_exists(GConfEngine * conf,const gchar * dir,GError ** err)2127 gconf_engine_dir_exists(GConfEngine *conf, const gchar *dir, GError** err)
2128 {
2129 CORBA_Environment ev;
2130 ConfigDatabase db;
2131 CORBA_boolean server_ret;
2132 gint tries = 0;
2133
2134 g_return_val_if_fail(conf != NULL, FALSE);
2135 g_return_val_if_fail(dir != NULL, FALSE);
2136 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
2137
2138 CHECK_OWNER_USE (conf);
2139
2140 if (!gconf_key_check(dir, err))
2141 return FALSE;
2142
2143 if (gconf_engine_is_local(conf))
2144 {
2145 return gconf_sources_dir_exists(conf->local_sources,
2146 dir,
2147 err);
2148 }
2149
2150 g_assert(!gconf_engine_is_local(conf));
2151
2152 CORBA_exception_init(&ev);
2153
2154 RETRY:
2155
2156 db = gconf_engine_get_database(conf, TRUE, err);
2157
2158 if (db == CORBA_OBJECT_NIL)
2159 {
2160 g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
2161
2162 return FALSE;
2163 }
2164
2165 server_ret = ConfigDatabase_dir_exists(db,
2166 (gchar*)dir,
2167 &ev);
2168
2169 if (gconf_server_broken(&ev))
2170 {
2171 if (tries < MAX_RETRIES)
2172 {
2173 ++tries;
2174 CORBA_exception_free(&ev);
2175 gconf_engine_detach (conf);
2176 goto RETRY;
2177 }
2178 }
2179
2180 if (gconf_handle_corba_exception(&ev, err))
2181 ; /* nothing */
2182
2183 return (server_ret == CORBA_TRUE);
2184 }
2185
2186 void
gconf_engine_remove_dir(GConfEngine * conf,const gchar * dir,GError ** err)2187 gconf_engine_remove_dir (GConfEngine* conf,
2188 const gchar* dir,
2189 GError** err)
2190 {
2191 CORBA_Environment ev;
2192 ConfigDatabase db;
2193 gint tries = 0;
2194
2195 g_return_if_fail(conf != NULL);
2196 g_return_if_fail(dir != NULL);
2197 g_return_if_fail(err == NULL || *err == NULL);
2198
2199 /* FIXME we have no GConfClient method for doing this */
2200 /* CHECK_OWNER_USE (conf); */
2201
2202 if (!gconf_key_check(dir, err))
2203 return;
2204
2205 if (gconf_engine_is_local(conf))
2206 {
2207 gconf_sources_remove_dir(conf->local_sources, dir, err);
2208 return;
2209 }
2210
2211 CORBA_exception_init(&ev);
2212
2213 RETRY:
2214
2215 db = gconf_engine_get_database (conf, TRUE, err);
2216
2217 if (db == CORBA_OBJECT_NIL)
2218 {
2219 g_return_if_fail(err == NULL || *err != NULL);
2220 return;
2221 }
2222
2223 ConfigDatabase_remove_dir(db, (gchar*)dir, &ev);
2224
2225 if (gconf_server_broken(&ev))
2226 {
2227 if (tries < MAX_RETRIES)
2228 {
2229 ++tries;
2230 CORBA_exception_free(&ev);
2231 gconf_engine_detach (conf);
2232 goto RETRY;
2233 }
2234 }
2235 gconf_handle_corba_exception(&ev, err);
2236
2237 return;
2238 }
2239
2240 gboolean
gconf_engine_key_is_writable(GConfEngine * conf,const gchar * key,GError ** err)2241 gconf_engine_key_is_writable (GConfEngine *conf,
2242 const gchar *key,
2243 GError **err)
2244 {
2245 gboolean is_writable = TRUE;
2246 GConfValue *val;
2247
2248 CHECK_OWNER_USE (conf);
2249
2250 /* FIXME implement IDL to allow getting only writability
2251 * (not that urgent since GConfClient caches this crap
2252 * anyway)
2253 */
2254
2255 val = gconf_engine_get_full(conf, key, NULL, TRUE,
2256 NULL, &is_writable, err);
2257
2258 gconf_value_free (val);
2259
2260 return is_writable;
2261 }
2262
2263 /*
2264 * Connection maintenance
2265 */
2266
2267 static GConfCnxn*
gconf_cnxn_new(GConfEngine * conf,const gchar * namespace_section,CORBA_unsigned_long server_id,GConfNotifyFunc func,gpointer user_data)2268 gconf_cnxn_new(GConfEngine* conf,
2269 const gchar* namespace_section,
2270 CORBA_unsigned_long server_id,
2271 GConfNotifyFunc func,
2272 gpointer user_data)
2273 {
2274 GConfCnxn* cnxn;
2275 static guint next_id = 1;
2276
2277 cnxn = g_new0(GConfCnxn, 1);
2278
2279 cnxn->namespace_section = g_strdup(namespace_section);
2280 cnxn->conf = conf;
2281 cnxn->server_id = server_id;
2282 cnxn->client_id = next_id;
2283 cnxn->func = func;
2284 cnxn->user_data = user_data;
2285
2286 ++next_id;
2287
2288 return cnxn;
2289 }
2290
2291 static void
gconf_cnxn_destroy(GConfCnxn * cnxn)2292 gconf_cnxn_destroy(GConfCnxn* cnxn)
2293 {
2294 g_free(cnxn->namespace_section);
2295 g_free(cnxn);
2296 }
2297
2298 static void
gconf_cnxn_notify(GConfCnxn * cnxn,GConfEntry * entry)2299 gconf_cnxn_notify(GConfCnxn* cnxn,
2300 GConfEntry *entry)
2301 {
2302 (*cnxn->func)(cnxn->conf, cnxn->client_id,
2303 entry,
2304 cnxn->user_data);
2305 }
2306
2307 /*
2308 * CORBA glue
2309 */
2310
2311 static ConfigServer server = CORBA_OBJECT_NIL;
2312
2313 /* errors in here should be GCONF_ERROR_NO_SERVER */
2314 static ConfigServer
try_to_contact_server(gboolean start_if_not_found,GError ** err)2315 try_to_contact_server (gboolean start_if_not_found,
2316 GError **err)
2317 {
2318 CORBA_Environment ev;
2319
2320 /* Try to launch server */
2321 server = gconf_activate_server (start_if_not_found,
2322 err);
2323
2324 /* Try to ping server, by adding ourselves as a client */
2325 CORBA_exception_init (&ev);
2326
2327 if (!CORBA_Object_is_nil (server, &ev))
2328 {
2329 ConfigServer_add_client (server,
2330 gconf_get_config_listener (),
2331 &ev);
2332
2333 if (ev._major != CORBA_NO_EXCEPTION)
2334 {
2335 g_set_error (err,
2336 GCONF_ERROR,
2337 GCONF_ERROR_NO_SERVER,
2338 _("Adding client to server's list failed, CORBA error: %s"),
2339 CORBA_exception_id (&ev));
2340
2341 CORBA_Object_release (server, &ev);
2342 server = CORBA_OBJECT_NIL;
2343 CORBA_exception_free(&ev);
2344 }
2345 }
2346
2347 #ifdef GCONF_ENABLE_DEBUG
2348 if (server == CORBA_OBJECT_NIL && start_if_not_found)
2349 g_return_val_if_fail (err == NULL || *err != NULL, server);
2350 #endif
2351
2352 return server;
2353 }
2354
2355 /* All errors set in here should be GCONF_ERROR_NO_SERVER; should
2356 only set errors if start_if_not_found is TRUE */
2357 static ConfigServer
gconf_get_config_server(gboolean start_if_not_found,GError ** err)2358 gconf_get_config_server(gboolean start_if_not_found, GError** err)
2359 {
2360 g_return_val_if_fail(err == NULL || *err == NULL, server);
2361
2362 if (server != CORBA_OBJECT_NIL)
2363 return server;
2364
2365 server = try_to_contact_server(start_if_not_found, err);
2366
2367 return server; /* return what we have, NIL or not */
2368 }
2369
2370 static ConfigListener listener = CORBA_OBJECT_NIL;
2371
2372 static void
gconf_detach_config_server(void)2373 gconf_detach_config_server(void)
2374 {
2375 CORBA_Environment ev;
2376
2377 CORBA_exception_init(&ev);
2378
2379 if (listener != CORBA_OBJECT_NIL)
2380 {
2381 CORBA_Object_release(listener, &ev);
2382 listener = CORBA_OBJECT_NIL;
2383 }
2384
2385 if (server != CORBA_OBJECT_NIL)
2386 {
2387 CORBA_Object_release(server, &ev);
2388
2389 if (ev._major != CORBA_NO_EXCEPTION)
2390 {
2391 g_warning("Exception releasing gconfd server object: %s",
2392 CORBA_exception_id(&ev));
2393 }
2394
2395 server = CORBA_OBJECT_NIL;
2396 }
2397
2398 CORBA_exception_free(&ev);
2399
2400 if (engines_by_db != NULL)
2401 {
2402 g_hash_table_destroy (engines_by_db);
2403 engines_by_db = NULL;
2404 }
2405 }
2406
2407 /**
2408 * gconf_debug_shutdown:
2409 * @void:
2410 *
2411 * Detach from the configuration server and release
2412 * all related resources.
2413 *
2414 * Returns: 1 if an exception occurs, 0 otherwise.
2415 **/
2416 int
gconf_debug_shutdown(void)2417 gconf_debug_shutdown (void)
2418 {
2419 gconf_detach_config_server ();
2420
2421 return gconf_orb_release ();
2422 }
2423
2424 static void notify (PortableServer_Servant servant,
2425 ConfigDatabase db,
2426 CORBA_unsigned_long cnxn,
2427 const CORBA_char *key,
2428 const ConfigValue *value,
2429 CORBA_boolean is_default,
2430 CORBA_boolean is_writable,
2431 CORBA_Environment *ev);
2432 static void ping (PortableServer_Servant _servant,
2433 CORBA_Environment *ev);
2434 static void update_listener (PortableServer_Servant _servant,
2435 ConfigDatabase db,
2436 const CORBA_char *address,
2437 const CORBA_unsigned_long old_cnxn,
2438 const CORBA_char *key,
2439 const CORBA_unsigned_long new_cnxn,
2440 CORBA_Environment *ev);
2441 static void invalidate_cached_values(PortableServer_Servant _servant,
2442 ConfigDatabase database,
2443 const ConfigListener_KeyList *keys,
2444 CORBA_Environment *ev);
2445 static void drop_all_caches (PortableServer_Servant _servant,
2446 CORBA_Environment *ev);
2447
2448
2449
2450 static PortableServer_ServantBase__epv base_epv = {
2451 NULL,
2452 NULL,
2453 NULL
2454 };
2455
2456 static POA_ConfigListener__epv listener_epv = {
2457 NULL,
2458 notify,
2459 ping,
2460 update_listener,
2461 invalidate_cached_values,
2462 drop_all_caches
2463 };
2464
2465 static POA_ConfigListener__vepv poa_listener_vepv = { &base_epv, &listener_epv };
2466 static POA_ConfigListener poa_listener_servant = { NULL, &poa_listener_vepv };
2467
2468 static void
notify(PortableServer_Servant servant,ConfigDatabase db,CORBA_unsigned_long server_id,const CORBA_char * key,const ConfigValue * value,CORBA_boolean is_default,CORBA_boolean is_writable,CORBA_Environment * ev)2469 notify(PortableServer_Servant servant,
2470 ConfigDatabase db,
2471 CORBA_unsigned_long server_id,
2472 const CORBA_char* key,
2473 const ConfigValue* value,
2474 CORBA_boolean is_default,
2475 CORBA_boolean is_writable,
2476 CORBA_Environment *ev)
2477 {
2478 GConfCnxn* cnxn;
2479 GConfValue* gvalue;
2480 GConfEngine* conf;
2481 GConfEntry* entry;
2482
2483 conf = lookup_engine_by_database (db);
2484
2485 if (conf == NULL)
2486 {
2487 #ifdef GCONF_ENABLE_DEBUG
2488 g_warning ("Client received notify for unknown database object");
2489 #endif
2490 return;
2491 }
2492
2493 cnxn = ctable_lookup_by_server_id(conf->ctable, server_id);
2494
2495 if (cnxn == NULL)
2496 {
2497 #ifdef GCONF_ENABLE_DEBUG
2498 g_warning("Client received notify for unknown connection ID %u",
2499 (guint)server_id);
2500 #endif
2501 return;
2502 }
2503
2504 gvalue = gconf_value_from_corba_value(value);
2505
2506 entry = gconf_entry_new_nocopy (g_strdup (key),
2507 gvalue);
2508 gconf_entry_set_is_default (entry, is_default);
2509 gconf_entry_set_is_writable (entry, is_writable);
2510
2511 gconf_cnxn_notify(cnxn, entry);
2512
2513 gconf_entry_free (entry);
2514 }
2515
2516 static void
ping(PortableServer_Servant _servant,CORBA_Environment * ev)2517 ping (PortableServer_Servant _servant, CORBA_Environment * ev)
2518 {
2519 /* This one is easy :-) */
2520
2521 return;
2522 }
2523
2524 static void
update_listener(PortableServer_Servant _servant,ConfigDatabase db,const CORBA_char * address,const CORBA_unsigned_long old_cnxn_id,const CORBA_char * key,const CORBA_unsigned_long new_cnxn_id,CORBA_Environment * ev_ignored)2525 update_listener (PortableServer_Servant _servant,
2526 ConfigDatabase db,
2527 const CORBA_char *address,
2528 const CORBA_unsigned_long old_cnxn_id,
2529 const CORBA_char *key,
2530 const CORBA_unsigned_long new_cnxn_id,
2531 CORBA_Environment *ev_ignored)
2532 {
2533 GConfCnxn* cnxn;
2534 GConfEngine* conf;
2535 CORBA_Environment ev;
2536
2537 conf = lookup_engine_by_database (db);
2538
2539 /* See if we have an old engine with a now-invalid object
2540 reference, and update its reference. */
2541 if (conf == NULL)
2542 {
2543 CORBA_exception_init (&ev);
2544
2545 if (strcmp (address, "def") == 0)
2546 conf = default_engine;
2547 else
2548 {
2549 GSList *addresses;
2550
2551 addresses = gconf_persistent_name_get_address_list (address);
2552
2553 conf = lookup_engine (addresses);
2554
2555 gconf_address_list_free (addresses);
2556 }
2557
2558 if (conf)
2559 gconf_engine_set_database (conf,
2560 CORBA_Object_duplicate (db, &ev));
2561 }
2562
2563 if (conf == NULL)
2564 {
2565 #ifdef GCONF_ENABLE_DEBUG
2566 g_warning("Client received listener update for unknown database "
2567 "(this is not a big deal, this warning only appears if GConf is compiled with debugging)");
2568 #endif
2569 return;
2570 }
2571
2572 cnxn = ctable_lookup_by_server_id (conf->ctable, old_cnxn_id);
2573
2574 if (cnxn == NULL)
2575 {
2576 #ifdef GCONF_ENABLE_DEBUG
2577 g_warning("Client received listener update for unknown listener ID %u "
2578 "(this is not a big deal, this warning only appears if GConf is compiled with debugging)",
2579 (guint)old_cnxn_id);
2580 #endif
2581 return;
2582 }
2583
2584 ctable_reinstall (conf->ctable, cnxn, old_cnxn_id, new_cnxn_id);
2585 }
2586
2587 static void
invalidate_cached_values(PortableServer_Servant _servant,ConfigDatabase database,const ConfigListener_KeyList * keys,CORBA_Environment * ev)2588 invalidate_cached_values (PortableServer_Servant _servant,
2589 ConfigDatabase database,
2590 const ConfigListener_KeyList *keys,
2591 CORBA_Environment *ev)
2592 {
2593 #if 0
2594 g_warning ("FIXME process %d received request to invalidate some cached GConf values from the server, but right now we don't know how to do that (not implemented).", (int) getpid());
2595 #endif
2596 }
2597
2598 static void
drop_all_caches(PortableServer_Servant _servant,CORBA_Environment * ev)2599 drop_all_caches (PortableServer_Servant _servant,
2600 CORBA_Environment *ev)
2601 {
2602 #if 0
2603 g_warning ("FIXME process %d received request to invalidate all cached GConf values from the server, but right now we don't know how to do that (not implemented).", (int) getpid());
2604 #endif
2605 }
2606
2607 static ConfigListener
gconf_get_config_listener(void)2608 gconf_get_config_listener(void)
2609 {
2610 if (listener == CORBA_OBJECT_NIL)
2611 {
2612 CORBA_Environment ev;
2613 PortableServer_POA poa;
2614 PortableServer_POAManager poa_mgr;
2615
2616 CORBA_exception_init (&ev);
2617 POA_ConfigListener__init (&poa_listener_servant, &ev);
2618
2619 g_assert (ev._major == CORBA_NO_EXCEPTION);
2620
2621 poa =
2622 (PortableServer_POA) CORBA_ORB_resolve_initial_references (gconf_orb_get (),
2623 "RootPOA", &ev);
2624
2625 g_assert (ev._major == CORBA_NO_EXCEPTION);
2626
2627 poa_mgr = PortableServer_POA__get_the_POAManager (poa, &ev);
2628 PortableServer_POAManager_activate (poa_mgr, &ev);
2629
2630 g_assert (ev._major == CORBA_NO_EXCEPTION);
2631
2632 listener = PortableServer_POA_servant_to_reference(poa,
2633 &poa_listener_servant,
2634 &ev);
2635
2636 CORBA_Object_release ((CORBA_Object) poa_mgr, &ev);
2637 CORBA_Object_release ((CORBA_Object) poa, &ev);
2638
2639 g_assert (listener != CORBA_OBJECT_NIL);
2640 g_assert (ev._major == CORBA_NO_EXCEPTION);
2641 }
2642
2643 return listener;
2644 }
2645 #endif /* HAVE_CORBA */
2646
2647 void
gconf_preinit(gpointer app,gpointer mod_info)2648 gconf_preinit (gpointer app, gpointer mod_info)
2649 {
2650 /* Deprecated */
2651 }
2652
2653 void
gconf_postinit(gpointer app,gpointer mod_info)2654 gconf_postinit (gpointer app, gpointer mod_info)
2655 {
2656 /* Deprecated */
2657 }
2658
2659 /* All deprecated */
2660 const char gconf_version[] = VERSION;
2661
2662 struct
2663 {
2664 const char * longName;
2665 char shortName;
2666 int argInfo;
2667 void * arg;
2668 int val;
2669 const char * descrip;
2670 const char * argDescrip;
2671 } gconf_options[] = { { NULL } };
2672
2673 /* Also deprecated */
2674 gboolean
gconf_init(int argc,char ** argv,GError ** err)2675 gconf_init (int argc, char **argv, GError** err)
2676 {
2677
2678 return TRUE;
2679 }
2680
2681 gboolean
gconf_is_initialized(void)2682 gconf_is_initialized (void)
2683 {
2684 return TRUE;
2685 }
2686
2687 /*
2688 * Ampersand and <> are not allowed due to the XML backend; shell
2689 * special characters aren't allowed; others are just in case we need
2690 * some magic characters someday. hyphen, underscore, period, colon
2691 * are allowed as separators. % disallowed to avoid printf confusion.
2692 */
2693
2694 /* Key/dir validity is exactly the same, except that '/' must be a dir,
2695 but we are sort of ignoring that for now. */
2696
2697 /* Also, keys can contain only ASCII */
2698
2699 static const gchar invalid_chars[] = " \t\r\n\"$&<>,+=#!()'|{}[]?~`;%\\";
2700
2701 gboolean
gconf_valid_key(const gchar * key,gchar ** why_invalid)2702 gconf_valid_key (const gchar* key, gchar** why_invalid)
2703 {
2704 const gchar* s = key;
2705 gboolean just_saw_slash = FALSE;
2706
2707 /* Key must start with the root */
2708 if (*key != '/')
2709 {
2710 if (why_invalid != NULL)
2711 *why_invalid = g_strdup(_("Must begin with a slash '/'"));
2712 return FALSE;
2713 }
2714
2715 /* Root key is a valid dir */
2716 if (*key == '/' && key[1] == '\0')
2717 return TRUE;
2718
2719 while (*s)
2720 {
2721 if (just_saw_slash)
2722 {
2723 /* Can't have two slashes in a row, since it would mean
2724 * an empty spot.
2725 * Can't have a period right after a slash,
2726 * because it would be a pain for filesystem-based backends.
2727 */
2728 if (*s == '/' || *s == '.')
2729 {
2730 if (why_invalid != NULL)
2731 {
2732 if (*s == '/')
2733 *why_invalid = g_strdup(_("Can't have two slashes '/' in a row"));
2734 else
2735 *why_invalid = g_strdup(_("Can't have a period '.' right after a slash '/'"));
2736 }
2737 return FALSE;
2738 }
2739 }
2740
2741 if (*s == '/')
2742 {
2743 just_saw_slash = TRUE;
2744 }
2745 else
2746 {
2747 const gchar* inv = invalid_chars;
2748 guchar c = (unsigned char) *s;
2749
2750 just_saw_slash = FALSE;
2751
2752 if (c > 127)
2753 {
2754 if (why_invalid != NULL)
2755 *why_invalid = g_strdup_printf (_("'\\%o' is not an ASCII character and thus isn't allowed in key names"),
2756 (guint) c);
2757 return FALSE;
2758 }
2759
2760 while (*inv)
2761 {
2762 if (*inv == *s)
2763 {
2764 if (why_invalid != NULL)
2765 *why_invalid = g_strdup_printf(_("`%c' is an invalid character in key/directory names"), *s);
2766 return FALSE;
2767 }
2768 ++inv;
2769 }
2770 }
2771
2772 ++s;
2773 }
2774
2775 /* Can't end with slash */
2776 if (just_saw_slash)
2777 {
2778 if (why_invalid != NULL)
2779 *why_invalid = g_strdup(_("Key/directory may not end with a slash '/'"));
2780 return FALSE;
2781 }
2782 else
2783 return TRUE;
2784 }
2785
2786 /**
2787 * gconf_escape_key:
2788 * @arbitrary_text: some text in any encoding or format
2789 * @len: length of @arbitrary_text in bytes, or -1 if @arbitrary_text is nul-terminated
2790 *
2791 * Escape @arbitrary_text such that it's a valid key element (i.e. one
2792 * part of the key path). The escaped key won't pass gconf_valid_key()
2793 * because it isn't a whole key (i.e. it doesn't have a preceding
2794 * slash), but prepending a slash to the escaped text should always
2795 * result in a valid key.
2796 *
2797 * Return value: a nul-terminated valid GConf key
2798 **/
2799 char*
gconf_escape_key(const char * arbitrary_text,int len)2800 gconf_escape_key (const char *arbitrary_text,
2801 int len)
2802 {
2803 const char *p;
2804 const char *end;
2805 GString *retval;
2806
2807 g_return_val_if_fail (arbitrary_text != NULL, NULL);
2808
2809 /* Nearly all characters we would normally use for escaping aren't allowed in key
2810 * names, so we use @ for that.
2811 *
2812 * Invalid chars and @ itself are escaped as @xxx@ where xxx is the
2813 * Latin-1 value in decimal
2814 */
2815
2816 if (len < 0)
2817 len = strlen (arbitrary_text);
2818
2819 retval = g_string_sized_new (len);
2820
2821 p = arbitrary_text;
2822 end = arbitrary_text + len;
2823 while (p != end)
2824 {
2825 if (*p == '/' || *p == '.' || *p == '@' || ((guchar) *p) > 127 ||
2826 strchr (invalid_chars, *p))
2827 {
2828 g_string_append_printf (retval, "@%u@", (guchar) *p);
2829 }
2830 else
2831 g_string_append_c (retval, *p);
2832
2833 ++p;
2834 }
2835
2836 return g_string_free (retval, FALSE);
2837 }
2838
2839 /**
2840 * gconf_unescape_key:
2841 * @escaped_key: a key created with gconf_escape_key()
2842 * @len: length of @escaped_key in bytes, or -1 if @escaped_key is nul-terminated
2843 *
2844 * Converts a string escaped with gconf_escape_key() back into its original
2845 * form.
2846 *
2847 * Return value: the original string that was escaped to create @escaped_key
2848 **/
2849 char*
gconf_unescape_key(const char * escaped_key,int len)2850 gconf_unescape_key (const char *escaped_key,
2851 int len)
2852 {
2853 const char *p;
2854 const char *end;
2855 const char *start_seq;
2856 GString *retval;
2857
2858 g_return_val_if_fail (escaped_key != NULL, NULL);
2859
2860 if (len < 0)
2861 len = strlen (escaped_key);
2862
2863 retval = g_string_new (NULL);
2864
2865 p = escaped_key;
2866 end = escaped_key + len;
2867 start_seq = NULL;
2868 while (p != end)
2869 {
2870 if (start_seq)
2871 {
2872 if (*p == '@')
2873 {
2874 /* *p is the @ that ends a seq */
2875 char *end_seq;
2876 guchar val;
2877
2878 val = strtoul (start_seq, &end_seq, 10);
2879 if (start_seq != end_seq)
2880 g_string_append_c (retval, val);
2881
2882 start_seq = NULL;
2883 }
2884 }
2885 else
2886 {
2887 if (*p == '@')
2888 start_seq = p + 1;
2889 else
2890 g_string_append_c (retval, *p);
2891 }
2892
2893 ++p;
2894 }
2895
2896 return g_string_free (retval, FALSE);
2897 }
2898
2899
2900 gboolean
gconf_key_is_below(const gchar * above,const gchar * below)2901 gconf_key_is_below (const gchar* above, const gchar* below)
2902 {
2903 int len;
2904
2905 if (above[0] == '/' && above[1] == '\0')
2906 return TRUE;
2907
2908 len = strlen (above);
2909 if (strncmp (below, above, len) == 0)
2910 {
2911 /* only if this is a complete key component,
2912 * so that /foo is not above /foofoo/bar */
2913 if (below[len] == '\0' || below[len] == '/')
2914 return TRUE;
2915 else
2916 return FALSE;
2917 }
2918 else
2919 return FALSE;
2920 }
2921
2922 gchar*
gconf_unique_key(void)2923 gconf_unique_key (void)
2924 {
2925 /* This function is hardly cryptographically random but should be
2926 "good enough" */
2927
2928 static guint serial = 0;
2929 gchar* key;
2930 guint t, ut, p, u, r;
2931 GTimeVal tv;
2932
2933 g_get_current_time(&tv);
2934
2935 t = tv.tv_sec;
2936 ut = tv.tv_usec;
2937
2938 p = getpid();
2939
2940 #ifdef HAVE_GETUID
2941 u = getuid();
2942 #else
2943 u = 0;
2944 #endif
2945
2946 /* don't bother to seed; if it's based on the time or any other
2947 changing info we can get, we may as well just use that changing
2948 info. since we don't seed we'll at least get a different number
2949 on every call to this function in the same executable. */
2950 r = rand();
2951
2952 /* The letters may increase uniqueness by preventing "melds"
2953 i.e. 01t01k01 and 0101t0k1 are not the same */
2954 key = g_strdup_printf("%ut%uut%uu%up%ur%uk%u",
2955 /* Duplicate keys must be generated
2956 by two different program instances */
2957 serial,
2958 /* Duplicate keys must be generated
2959 in the same microsecond */
2960 t,
2961 ut,
2962 /* Duplicate keys must be generated by
2963 the same user */
2964 u,
2965 /* Duplicate keys must be generated by
2966 two programs that got the same PID */
2967 p,
2968 /* Duplicate keys must be generated with the
2969 same random seed and the same index into
2970 the series of pseudorandom values */
2971 r,
2972 /* Duplicate keys must result from running
2973 this function at the same stack location */
2974 GPOINTER_TO_UINT(&key));
2975
2976 ++serial;
2977
2978 return key;
2979 }
2980
2981 #ifdef HAVE_CORBA
2982 /*
2983 * Table of connections
2984 */
2985
2986 static gint
corba_unsigned_long_equal(gconstpointer v1,gconstpointer v2)2987 corba_unsigned_long_equal (gconstpointer v1,
2988 gconstpointer v2)
2989 {
2990 return *((const CORBA_unsigned_long*) v1) == *((const CORBA_unsigned_long*) v2);
2991 }
2992
2993 static guint
corba_unsigned_long_hash(gconstpointer v)2994 corba_unsigned_long_hash (gconstpointer v)
2995 {
2996 /* for our purposes we can just assume 32 bits are significant */
2997 return (guint)(*(const CORBA_unsigned_long*) v);
2998 }
2999
3000 static CnxnTable*
ctable_new(void)3001 ctable_new(void)
3002 {
3003 CnxnTable* ct;
3004
3005 ct = g_new(CnxnTable, 1);
3006
3007 ct->server_ids = g_hash_table_new (corba_unsigned_long_hash,
3008 corba_unsigned_long_equal);
3009 ct->client_ids = g_hash_table_new (g_int_hash, g_int_equal);
3010
3011 return ct;
3012 }
3013
3014 static void
ctable_destroy(CnxnTable * ct)3015 ctable_destroy(CnxnTable* ct)
3016 {
3017 g_hash_table_destroy (ct->server_ids);
3018 g_hash_table_destroy (ct->client_ids);
3019 g_free(ct);
3020 }
3021
3022 static void
ctable_insert(CnxnTable * ct,GConfCnxn * cnxn)3023 ctable_insert(CnxnTable* ct, GConfCnxn* cnxn)
3024 {
3025 g_hash_table_insert (ct->server_ids, &cnxn->server_id, cnxn);
3026 g_hash_table_insert (ct->client_ids, &cnxn->client_id, cnxn);
3027 }
3028
3029 static void
ctable_remove(CnxnTable * ct,GConfCnxn * cnxn)3030 ctable_remove(CnxnTable* ct, GConfCnxn* cnxn)
3031 {
3032 g_hash_table_remove (ct->server_ids, &cnxn->server_id);
3033 g_hash_table_remove (ct->client_ids, &cnxn->client_id);
3034 }
3035
3036 struct RemoveData {
3037 GSList* removed;
3038 GConfEngine* conf;
3039 gboolean save_removed;
3040 };
3041
3042 static gboolean
remove_by_conf(gpointer key,gpointer value,gpointer user_data)3043 remove_by_conf(gpointer key, gpointer value, gpointer user_data)
3044 {
3045 struct RemoveData* rd = user_data;
3046 GConfCnxn* cnxn = value;
3047
3048 if (cnxn->conf == rd->conf)
3049 {
3050 if (rd->save_removed)
3051 rd->removed = g_slist_prepend(rd->removed, cnxn);
3052
3053 return TRUE; /* remove this one */
3054 }
3055 else
3056 return FALSE; /* or not */
3057 }
3058
3059 /* FIXME this no longer makes any sense, because a CnxnTable
3060 belongs to a GConfEngine and all entries have the same
3061 GConfEngine.
3062 */
3063
3064 /* We return a list of the removed GConfCnxn */
3065 static GSList*
ctable_remove_by_conf(CnxnTable * ct,GConfEngine * conf)3066 ctable_remove_by_conf(CnxnTable* ct, GConfEngine* conf)
3067 {
3068 guint client_ids_removed;
3069 guint server_ids_removed;
3070 struct RemoveData rd;
3071
3072 rd.removed = NULL;
3073 rd.conf = conf;
3074 rd.save_removed = TRUE;
3075
3076 client_ids_removed = g_hash_table_foreach_remove (ct->server_ids,
3077 remove_by_conf,
3078 &rd);
3079
3080 rd.save_removed = FALSE;
3081
3082 server_ids_removed = g_hash_table_foreach_remove(ct->client_ids,
3083 remove_by_conf,
3084 &rd);
3085
3086 g_assert(client_ids_removed == server_ids_removed);
3087 g_assert(client_ids_removed == g_slist_length(rd.removed));
3088
3089 return rd.removed;
3090 }
3091
3092 static GConfCnxn*
ctable_lookup_by_client_id(CnxnTable * ct,guint client_id)3093 ctable_lookup_by_client_id(CnxnTable* ct, guint client_id)
3094 {
3095 return g_hash_table_lookup(ct->client_ids, &client_id);
3096 }
3097
3098 static GConfCnxn*
ctable_lookup_by_server_id(CnxnTable * ct,CORBA_unsigned_long server_id)3099 ctable_lookup_by_server_id(CnxnTable* ct, CORBA_unsigned_long server_id)
3100 {
3101 return g_hash_table_lookup (ct->server_ids, &server_id);
3102 }
3103
3104 static void
ctable_reinstall(CnxnTable * ct,GConfCnxn * cnxn,guint old_server_id,guint new_server_id)3105 ctable_reinstall (CnxnTable* ct,
3106 GConfCnxn *cnxn,
3107 guint old_server_id,
3108 guint new_server_id)
3109 {
3110 g_return_if_fail (cnxn->server_id == old_server_id);
3111
3112 g_hash_table_remove (ct->server_ids, &old_server_id);
3113
3114 cnxn->server_id = new_server_id;
3115
3116 g_hash_table_insert (ct->server_ids, &cnxn->server_id, cnxn);
3117 }
3118
3119 /*
3120 * Daemon control
3121 */
3122
3123 void
gconf_shutdown_daemon(GError ** err)3124 gconf_shutdown_daemon (GError** err)
3125 {
3126 CORBA_Environment ev;
3127 ConfigServer cs;
3128
3129 cs = gconf_get_config_server (FALSE, err); /* Don't want to spawn it if it's already down */
3130
3131 if (err && *err && (*err)->code == GCONF_ERROR_NO_SERVER)
3132 {
3133 /* No server is hardly an error here */
3134 g_error_free (*err);
3135 *err = NULL;
3136 }
3137
3138 if (cs == CORBA_OBJECT_NIL)
3139 {
3140
3141 return;
3142 }
3143
3144 CORBA_exception_init (&ev);
3145
3146 ConfigServer_shutdown (cs, &ev);
3147
3148 if (ev._major != CORBA_NO_EXCEPTION)
3149 {
3150 if (err)
3151 *err = gconf_error_new (GCONF_ERROR_FAILED, _("Failure shutting down configuration server: %s"),
3152 CORBA_exception_id (&ev));
3153
3154 CORBA_exception_free(&ev);
3155 }
3156 }
3157
3158 gboolean
gconf_ping_daemon(void)3159 gconf_ping_daemon(void)
3160 {
3161 ConfigServer cs;
3162
3163 cs = gconf_get_config_server(FALSE, NULL); /* ignore error, since whole point is to see if server is reachable */
3164
3165 if (cs == CORBA_OBJECT_NIL)
3166 return FALSE;
3167 else
3168 return TRUE;
3169 }
3170
3171 gboolean
gconf_spawn_daemon(GError ** err)3172 gconf_spawn_daemon(GError** err)
3173 {
3174 ConfigServer cs;
3175
3176 cs = gconf_get_config_server(TRUE, err);
3177
3178 if (cs == CORBA_OBJECT_NIL)
3179 {
3180 g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
3181 return FALSE; /* Failed to spawn, error should be set */
3182 }
3183 else
3184 return TRUE;
3185 }
3186 #endif /* HAVE_CORBA */
3187
3188 /*
3189 * Sugar functions
3190 */
3191
3192 gdouble
gconf_engine_get_float(GConfEngine * conf,const gchar * key,GError ** err)3193 gconf_engine_get_float (GConfEngine* conf, const gchar* key,
3194 GError** err)
3195 {
3196 GConfValue* val;
3197 static const gdouble deflt = 0.0;
3198
3199 g_return_val_if_fail(conf != NULL, 0.0);
3200 g_return_val_if_fail(key != NULL, 0.0);
3201
3202 val = gconf_engine_get (conf, key, err);
3203
3204 if (val == NULL)
3205 return deflt;
3206 else
3207 {
3208 gdouble retval;
3209
3210 if (val->type != GCONF_VALUE_FLOAT)
3211 {
3212 if (err)
3213 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected float, got %s"),
3214 gconf_value_type_to_string(val->type));
3215 gconf_value_free(val);
3216 return deflt;
3217 }
3218
3219 retval = gconf_value_get_float(val);
3220
3221 gconf_value_free(val);
3222
3223 return retval;
3224 }
3225 }
3226
3227 gint
gconf_engine_get_int(GConfEngine * conf,const gchar * key,GError ** err)3228 gconf_engine_get_int (GConfEngine* conf, const gchar* key,
3229 GError** err)
3230 {
3231 GConfValue* val;
3232 static const gint deflt = 0;
3233
3234 g_return_val_if_fail(conf != NULL, 0);
3235 g_return_val_if_fail(key != NULL, 0);
3236
3237 val = gconf_engine_get (conf, key, err);
3238
3239 if (val == NULL)
3240 return deflt;
3241 else
3242 {
3243 gint retval;
3244
3245 if (val->type != GCONF_VALUE_INT)
3246 {
3247 if (err)
3248 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected int, got %s"),
3249 gconf_value_type_to_string(val->type));
3250 gconf_value_free(val);
3251 return deflt;
3252 }
3253
3254 retval = gconf_value_get_int(val);
3255
3256 gconf_value_free(val);
3257
3258 return retval;
3259 }
3260 }
3261
3262 gchar*
gconf_engine_get_string(GConfEngine * conf,const gchar * key,GError ** err)3263 gconf_engine_get_string(GConfEngine* conf, const gchar* key,
3264 GError** err)
3265 {
3266 GConfValue* val;
3267 static const gchar* deflt = NULL;
3268
3269 g_return_val_if_fail(conf != NULL, NULL);
3270 g_return_val_if_fail(key != NULL, NULL);
3271
3272 val = gconf_engine_get (conf, key, err);
3273
3274 if (val == NULL)
3275 return g_strdup(deflt);
3276 else
3277 {
3278 gchar* retval;
3279
3280 if (val->type != GCONF_VALUE_STRING)
3281 {
3282 if (err)
3283 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected string, got %s"),
3284 gconf_value_type_to_string(val->type));
3285 gconf_value_free(val);
3286 return g_strdup(deflt);
3287 }
3288
3289 retval = gconf_value_steal_string (val);
3290 gconf_value_free (val);
3291
3292 return retval;
3293 }
3294 }
3295
3296 gboolean
gconf_engine_get_bool(GConfEngine * conf,const gchar * key,GError ** err)3297 gconf_engine_get_bool (GConfEngine* conf, const gchar* key,
3298 GError** err)
3299 {
3300 GConfValue* val;
3301 static const gboolean deflt = FALSE;
3302
3303 g_return_val_if_fail(conf != NULL, FALSE);
3304 g_return_val_if_fail(key != NULL, FALSE);
3305
3306 val = gconf_engine_get (conf, key, err);
3307
3308 if (val == NULL)
3309 return deflt;
3310 else
3311 {
3312 gboolean retval;
3313
3314 if (val->type != GCONF_VALUE_BOOL)
3315 {
3316 if (err)
3317 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected bool, got %s"),
3318 gconf_value_type_to_string(val->type));
3319 gconf_value_free(val);
3320 return deflt;
3321 }
3322
3323 retval = gconf_value_get_bool(val);
3324
3325 gconf_value_free(val);
3326
3327 return retval;
3328 }
3329 }
3330
3331 /**
3332 * gconf_engine_get_schema: (skip)
3333 * @conf: a #GConfEngine.
3334 * @key: key you want the value of.
3335 * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
3336 * @Returns: the value of @key as an allocated #GConfSchema, or <symbol>NULL</symbol> if no value was obtained.
3337 *
3338 * Requests the schema (%GCONF_VALUE_SCHEMA) stored at @key.
3339 * Automatically performs type-checking, so if a non-schema is stored at
3340 * @key, an error is returned. If no value is set or an error occurs,
3341 * <symbol>NULL</symbol> is returned.
3342 *
3343 * Return value: (transfer full): the value of @key as an allocated #GConfSchema, or <symbol>NULL</symbol> if no value was obtained.
3344 */
3345 GConfSchema*
gconf_engine_get_schema(GConfEngine * conf,const gchar * key,GError ** err)3346 gconf_engine_get_schema (GConfEngine* conf, const gchar* key, GError** err)
3347 {
3348 GConfValue* val;
3349
3350 g_return_val_if_fail(conf != NULL, NULL);
3351 g_return_val_if_fail(key != NULL, NULL);
3352
3353 val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), err);
3354
3355 if (val == NULL)
3356 return NULL;
3357 else
3358 {
3359 GConfSchema* retval;
3360
3361 if (val->type != GCONF_VALUE_SCHEMA)
3362 {
3363 if (err)
3364 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected schema, got %s"),
3365 gconf_value_type_to_string(val->type));
3366 gconf_value_free(val);
3367 return NULL;
3368 }
3369
3370 retval = gconf_value_steal_schema (val);
3371 gconf_value_free (val);
3372
3373 return retval;
3374 }
3375 }
3376
3377 /**
3378 * gconf_engine_get_list: (skip)
3379 * @conf: a #GConfEngine.
3380 * @key: key you want the value of.
3381 * @list_type: type of each list element.
3382 * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
3383 *
3384 * Requests the list (%GCONF_VALUE_LIST) stored at @key. Automatically
3385 * performs type-checking, so if a non-list is stored at @key, or the
3386 * list does not contain elements of type @list_type, an error is
3387 * returned. If no value is set or an error occurs, <symbol>NULL</symbol>
3388 * is returned. Note that <symbol>NULL</symbol> is also the empty list,
3389 * so if you need to distinguish the empty list from an unset value, you
3390 * must use gconf_engine_get () to obtain a raw #GConfValue.
3391 *
3392 * <emphasis>Remember that GConf lists can only store primitive types:
3393 * %GCONF_VALUE_FLOAT, %GCONF_VALUE_INT, %GCONF_VALUE_BOOL,
3394 * %GCONF_VALUE_STRING, %GCONF_VALUE_SCHEMA.</emphasis> Also remember
3395 * that lists must be uniform, you may not mix types in the same list.
3396 *
3397 * The type of the list elements depends on @list_type. A #GConfValue
3398 * with type %GCONF_VALUE_LIST normally stores a list of more #GConfValue
3399 * objects. gconf_engine_get_list() automatically converts to primitive C
3400 * types. Thus, the list->data fields in the returned list
3401 * contain:
3402 *
3403 * <informaltable pgwide="1" frame="none">
3404 * <tgroup cols="2"><colspec colwidth="2*"/><colspec colwidth="8*"/>
3405 * <tbody>
3406 *
3407 * <row>
3408 * <entry>%GCONF_VALUE_INT</entry>
3409 * <entry>The integer itself, converted with GINT_TO_POINTER()</entry>
3410 * </row>
3411 *
3412 * <row>
3413 * <entry>%GCONF_VALUE_BOOL</entry>
3414 * <entry>The bool itself, converted with GINT_TO_POINTER()</entry>
3415 * </row>
3416 *
3417 * <row>
3418 * <entry>%GCONF_VALUE_FLOAT</entry>
3419 * <entry>A pointer to #gdouble, which should be freed with g_free()</entry>
3420 * </row>
3421 *
3422 * <row>
3423 * <entry>%GCONF_VALUE_STRING</entry>
3424 * <entry>A pointer to #gchar, which should be freed with g_free()</entry>
3425 * </row>
3426 *
3427 * <row>
3428 * <entry>%GCONF_VALUE_SCHEMA</entry>
3429 * <entry>A pointer to #GConfSchema, which should be freed with gconf_schema_free()</entry>
3430 * </row>
3431 *
3432 * </tbody></tgroup></informaltable>
3433 *
3434 * In the %GCONF_VALUE_FLOAT and %GCONF_VALUE_STRING cases, you must
3435 * g_free() each list element. In the %GCONF_VALUE_SCHEMA case you must
3436 * gconf_schema_free() each element. In all cases you must free the
3437 * list itself with g_slist_free().
3438 *
3439 * Return value: an allocated list, with elements as described above.
3440 */
3441 GSList*
gconf_engine_get_list(GConfEngine * conf,const gchar * key,GConfValueType list_type,GError ** err)3442 gconf_engine_get_list (GConfEngine* conf, const gchar* key,
3443 GConfValueType list_type, GError** err)
3444 {
3445 GConfValue* val;
3446
3447 g_return_val_if_fail(conf != NULL, NULL);
3448 g_return_val_if_fail(key != NULL, NULL);
3449 g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, NULL);
3450 g_return_val_if_fail(list_type != GCONF_VALUE_LIST, NULL);
3451 g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, NULL);
3452 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
3453
3454 val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), err);
3455
3456 if (val == NULL)
3457 return NULL;
3458 else
3459 {
3460 /* This type-checks the value */
3461 return gconf_value_list_to_primitive_list_destructive(val, list_type, err);
3462 }
3463 }
3464
3465 gboolean
gconf_engine_get_pair(GConfEngine * conf,const gchar * key,GConfValueType car_type,GConfValueType cdr_type,gpointer car_retloc,gpointer cdr_retloc,GError ** err)3466 gconf_engine_get_pair (GConfEngine* conf, const gchar* key,
3467 GConfValueType car_type, GConfValueType cdr_type,
3468 gpointer car_retloc, gpointer cdr_retloc,
3469 GError** err)
3470 {
3471 GConfValue* val;
3472 GError* error = NULL;
3473
3474 g_return_val_if_fail(conf != NULL, FALSE);
3475 g_return_val_if_fail(key != NULL, FALSE);
3476 g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, FALSE);
3477 g_return_val_if_fail(car_type != GCONF_VALUE_LIST, FALSE);
3478 g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, FALSE);
3479 g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, FALSE);
3480 g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, FALSE);
3481 g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, FALSE);
3482 g_return_val_if_fail(car_retloc != NULL, FALSE);
3483 g_return_val_if_fail(cdr_retloc != NULL, FALSE);
3484 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3485
3486 val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), &error);
3487
3488 if (error != NULL)
3489 {
3490 g_assert(val == NULL);
3491
3492 if (err)
3493 *err = error;
3494 else
3495 g_error_free(error);
3496
3497 return FALSE;
3498 }
3499
3500 if (val == NULL)
3501 {
3502 return TRUE;
3503 }
3504 else
3505 {
3506 /* Destroys val */
3507 return gconf_value_pair_to_primitive_pair_destructive(val,
3508 car_type, cdr_type,
3509 car_retloc, cdr_retloc,
3510 err);
3511 }
3512 }
3513
3514 /*
3515 * Setters
3516 */
3517
3518 static gboolean
error_checked_set(GConfEngine * conf,const gchar * key,GConfValue * gval,GError ** err)3519 error_checked_set(GConfEngine* conf, const gchar* key,
3520 GConfValue* gval, GError** err)
3521 {
3522 GError* my_err = NULL;
3523
3524 gconf_engine_set (conf, key, gval, &my_err);
3525
3526 gconf_value_free(gval);
3527
3528 if (my_err != NULL)
3529 {
3530 if (err)
3531 *err = my_err;
3532 else
3533 g_error_free(my_err);
3534 return FALSE;
3535 }
3536 else
3537 return TRUE;
3538 }
3539
3540 gboolean
gconf_engine_set_float(GConfEngine * conf,const gchar * key,gdouble val,GError ** err)3541 gconf_engine_set_float (GConfEngine* conf, const gchar* key,
3542 gdouble val, GError** err)
3543 {
3544 GConfValue* gval;
3545
3546 g_return_val_if_fail(conf != NULL, FALSE);
3547 g_return_val_if_fail(key != NULL, FALSE);
3548 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3549
3550 gval = gconf_value_new(GCONF_VALUE_FLOAT);
3551
3552 gconf_value_set_float(gval, val);
3553
3554 return error_checked_set(conf, key, gval, err);
3555 }
3556
3557 gboolean
gconf_engine_set_int(GConfEngine * conf,const gchar * key,gint val,GError ** err)3558 gconf_engine_set_int (GConfEngine* conf, const gchar* key,
3559 gint val, GError** err)
3560 {
3561 GConfValue* gval;
3562
3563 g_return_val_if_fail(conf != NULL, FALSE);
3564 g_return_val_if_fail(key != NULL, FALSE);
3565 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3566
3567 gval = gconf_value_new(GCONF_VALUE_INT);
3568
3569 gconf_value_set_int(gval, val);
3570
3571 return error_checked_set(conf, key, gval, err);
3572 }
3573
3574 gboolean
gconf_engine_set_string(GConfEngine * conf,const gchar * key,const gchar * val,GError ** err)3575 gconf_engine_set_string (GConfEngine* conf, const gchar* key,
3576 const gchar* val, GError** err)
3577 {
3578 GConfValue* gval;
3579
3580 g_return_val_if_fail (val != NULL, FALSE);
3581 g_return_val_if_fail (conf != NULL, FALSE);
3582 g_return_val_if_fail (key != NULL, FALSE);
3583 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
3584
3585 g_return_val_if_fail (g_utf8_validate (val, -1, NULL), FALSE);
3586
3587 gval = gconf_value_new(GCONF_VALUE_STRING);
3588
3589 gconf_value_set_string(gval, val);
3590
3591 return error_checked_set(conf, key, gval, err);
3592 }
3593
3594 gboolean
gconf_engine_set_bool(GConfEngine * conf,const gchar * key,gboolean val,GError ** err)3595 gconf_engine_set_bool (GConfEngine* conf, const gchar* key,
3596 gboolean val, GError** err)
3597 {
3598 GConfValue* gval;
3599
3600 g_return_val_if_fail(conf != NULL, FALSE);
3601 g_return_val_if_fail(key != NULL, FALSE);
3602 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3603
3604 gval = gconf_value_new(GCONF_VALUE_BOOL);
3605
3606 gconf_value_set_bool(gval, !!val); /* canonicalize the bool */
3607
3608 return error_checked_set(conf, key, gval, err);
3609 }
3610
3611 gboolean
gconf_engine_set_schema(GConfEngine * conf,const gchar * key,const GConfSchema * val,GError ** err)3612 gconf_engine_set_schema (GConfEngine* conf, const gchar* key,
3613 const GConfSchema* val, GError** err)
3614 {
3615 GConfValue* gval;
3616
3617 g_return_val_if_fail(conf != NULL, FALSE);
3618 g_return_val_if_fail(key != NULL, FALSE);
3619 g_return_val_if_fail(val != NULL, FALSE);
3620 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3621
3622 gval = gconf_value_new(GCONF_VALUE_SCHEMA);
3623
3624 gconf_value_set_schema(gval, val);
3625
3626 return error_checked_set(conf, key, gval, err);
3627 }
3628
3629 gboolean
gconf_engine_set_list(GConfEngine * conf,const gchar * key,GConfValueType list_type,GSList * list,GError ** err)3630 gconf_engine_set_list (GConfEngine* conf, const gchar* key,
3631 GConfValueType list_type,
3632 GSList* list,
3633 GError** err)
3634 {
3635 GConfValue* value_list;
3636 GError *tmp_err = NULL;
3637
3638 g_return_val_if_fail(conf != NULL, FALSE);
3639 g_return_val_if_fail(key != NULL, FALSE);
3640 g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, FALSE);
3641 g_return_val_if_fail(list_type != GCONF_VALUE_LIST, FALSE);
3642 g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, FALSE);
3643 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3644
3645 value_list = gconf_value_list_from_primitive_list(list_type, list, &tmp_err);
3646
3647 if (tmp_err)
3648 {
3649 g_propagate_error (err, tmp_err);
3650 return FALSE;
3651 }
3652
3653 /* destroys the value_list */
3654
3655 return error_checked_set(conf, key, value_list, err);
3656 }
3657
3658 gboolean
gconf_engine_set_pair(GConfEngine * conf,const gchar * key,GConfValueType car_type,GConfValueType cdr_type,gconstpointer address_of_car,gconstpointer address_of_cdr,GError ** err)3659 gconf_engine_set_pair (GConfEngine* conf, const gchar* key,
3660 GConfValueType car_type, GConfValueType cdr_type,
3661 gconstpointer address_of_car,
3662 gconstpointer address_of_cdr,
3663 GError** err)
3664 {
3665 GConfValue* pair;
3666 GError *tmp_err = NULL;
3667
3668 g_return_val_if_fail(conf != NULL, FALSE);
3669 g_return_val_if_fail(key != NULL, FALSE);
3670 g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, FALSE);
3671 g_return_val_if_fail(car_type != GCONF_VALUE_LIST, FALSE);
3672 g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, FALSE);
3673 g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, FALSE);
3674 g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, FALSE);
3675 g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, FALSE);
3676 g_return_val_if_fail(address_of_car != NULL, FALSE);
3677 g_return_val_if_fail(address_of_cdr != NULL, FALSE);
3678 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3679
3680
3681 pair = gconf_value_pair_from_primitive_pair(car_type, cdr_type,
3682 address_of_car, address_of_cdr,
3683 &tmp_err);
3684
3685 if (tmp_err)
3686 {
3687 g_propagate_error (err, tmp_err);
3688 return FALSE;
3689 }
3690
3691 return error_checked_set(conf, key, pair, err);
3692 }
3693
3694 #ifdef HAVE_CORBA
3695 /* CORBA Util */
3696
3697 /* Set GConfError from an exception, free exception, etc. */
3698
3699 static GConfError
corba_errno_to_gconf_errno(ConfigErrorType corba_err)3700 corba_errno_to_gconf_errno(ConfigErrorType corba_err)
3701 {
3702 switch (corba_err)
3703 {
3704 case ConfigFailed:
3705 return GCONF_ERROR_FAILED;
3706 case ConfigNoPermission:
3707 return GCONF_ERROR_NO_PERMISSION;
3708 case ConfigBadAddress:
3709 return GCONF_ERROR_BAD_ADDRESS;
3710 case ConfigBadKey:
3711 return GCONF_ERROR_BAD_KEY;
3712 case ConfigParseError:
3713 return GCONF_ERROR_PARSE_ERROR;
3714 case ConfigCorrupt:
3715 return GCONF_ERROR_CORRUPT;
3716 case ConfigTypeMismatch:
3717 return GCONF_ERROR_TYPE_MISMATCH;
3718 case ConfigIsDir:
3719 return GCONF_ERROR_IS_DIR;
3720 case ConfigIsKey:
3721 return GCONF_ERROR_IS_KEY;
3722 case ConfigOverridden:
3723 return GCONF_ERROR_OVERRIDDEN;
3724 case ConfigLockFailed:
3725 return GCONF_ERROR_LOCK_FAILED;
3726 case ConfigNoWritableDatabase:
3727 return GCONF_ERROR_NO_WRITABLE_DATABASE;
3728 case ConfigInShutdown:
3729 return GCONF_ERROR_IN_SHUTDOWN;
3730 default:
3731 g_assert_not_reached();
3732 return GCONF_ERROR_SUCCESS; /* warnings */
3733 }
3734 }
3735
3736 static gboolean
gconf_server_broken(CORBA_Environment * ev)3737 gconf_server_broken(CORBA_Environment* ev)
3738 {
3739 switch (ev->_major)
3740 {
3741 case CORBA_SYSTEM_EXCEPTION:
3742 return TRUE;
3743
3744 case CORBA_USER_EXCEPTION:
3745 {
3746 ConfigException* ce;
3747
3748 ce = CORBA_exception_value(ev);
3749
3750 return ce->err_no == ConfigInShutdown;
3751 }
3752
3753 default:
3754 return FALSE;
3755 }
3756 }
3757
3758 static gboolean
gconf_handle_corba_exception(CORBA_Environment * ev,GError ** err)3759 gconf_handle_corba_exception(CORBA_Environment* ev, GError** err)
3760 {
3761 switch (ev->_major)
3762 {
3763 case CORBA_NO_EXCEPTION:
3764 CORBA_exception_free (ev);
3765 return FALSE;
3766 case CORBA_SYSTEM_EXCEPTION:
3767 if (err)
3768 *err = gconf_error_new (GCONF_ERROR_NO_SERVER, _("CORBA error: %s"),
3769 CORBA_exception_id (ev));
3770 CORBA_exception_free (ev);
3771 return TRUE;
3772 case CORBA_USER_EXCEPTION:
3773 {
3774 ConfigException* ce;
3775
3776 ce = CORBA_exception_value (ev);
3777
3778 if (err)
3779 *err = gconf_error_new (corba_errno_to_gconf_errno (ce->err_no),
3780 "%s", ce->message);
3781 CORBA_exception_free (ev);
3782 return TRUE;
3783 }
3784 default:
3785 g_assert_not_reached();
3786 return TRUE;
3787 }
3788 }
3789 #endif
3790
3791 /*
3792 * Enumeration conversions
3793 */
3794
3795 gboolean
gconf_string_to_enum(GConfEnumStringPair lookup_table[],const gchar * str,gint * enum_value_retloc)3796 gconf_string_to_enum (GConfEnumStringPair lookup_table[],
3797 const gchar* str,
3798 gint* enum_value_retloc)
3799 {
3800 int i = 0;
3801
3802 while (lookup_table[i].str != NULL)
3803 {
3804 if (g_ascii_strcasecmp (lookup_table[i].str, str) == 0)
3805 {
3806 *enum_value_retloc = lookup_table[i].enum_value;
3807 return TRUE;
3808 }
3809
3810 ++i;
3811 }
3812
3813 return FALSE;
3814 }
3815
3816 const gchar*
gconf_enum_to_string(GConfEnumStringPair lookup_table[],gint enum_value)3817 gconf_enum_to_string (GConfEnumStringPair lookup_table[],
3818 gint enum_value)
3819 {
3820 int i = 0;
3821
3822 while (lookup_table[i].str != NULL)
3823 {
3824 if (lookup_table[i].enum_value == enum_value)
3825 return lookup_table[i].str;
3826
3827 ++i;
3828 }
3829
3830 return NULL;
3831 }
3832