~ubuntu-branches/ubuntu/oneiric/gconf/oneiric-proposed

« back to all changes in this revision

Viewing changes to gconf/gconf.c

  • Committer: Bazaar Package Importer
  • Author(s): Takuo KITAME
  • Date: 2002-03-17 01:51:39 UTC
  • Revision ID: james.westby@ubuntu.com-20020317015139-z4f8fdg1hoe049g0
Tags: upstream-1.0.9
ImportĀ upstreamĀ versionĀ 1.0.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
#include <popt.h>
 
21
#include "GConf.h"
 
22
#include "gconf.h"
 
23
#include "gconf-internals.h"
 
24
#include "gconf-sources.h"
 
25
#include "gconf-locale.h"
 
26
#include <string.h>
 
27
#include <stdio.h>
 
28
#include <stdlib.h>
 
29
#include <errno.h>
 
30
#include <time.h>
 
31
#include <sys/types.h>
 
32
#include <sys/wait.h>
 
33
#include <sys/time.h>
 
34
#include <unistd.h>
 
35
#include <liboaf/liboaf.h>
 
36
 
 
37
/* Returns TRUE if there was an error, frees exception, sets err */
 
38
static gboolean gconf_handle_corba_exception(CORBA_Environment* ev, GError** err);
 
39
/* just returns TRUE if there's an exception indicating the server is
 
40
   probably hosed; no side effects */
 
41
static gboolean gconf_server_broken(CORBA_Environment* ev);
 
42
 
 
43
/* Maximum number of times to try re-spawning the server if it's down. */
 
44
#define MAX_RETRIES 1
 
45
 
 
46
gboolean
 
47
gconf_key_check(const gchar* key, GError** err)
 
48
{
 
49
  gchar* why = NULL;
 
50
 
 
51
  if (!gconf_valid_key(key, &why))
 
52
    {
 
53
      if (err)
 
54
        *err = gconf_error_new(GCONF_ERROR_BAD_KEY, _("`%s': %s"),
 
55
                               key, why);
 
56
      g_free(why);
 
57
      return FALSE;
 
58
    }
 
59
  return TRUE;
 
60
}
 
61
 
 
62
typedef struct _CnxnTable CnxnTable;
 
63
 
 
64
struct _GConfEngine {
 
65
  guint refcount;
 
66
 
 
67
  ConfigDatabase database;
 
68
 
 
69
  CnxnTable* ctable;
 
70
 
 
71
  /* If non-NULL, this is a local engine;
 
72
     local engines don't do notification! */
 
73
  GConfSources* local_sources;
 
74
  
 
75
  /* An address if this is not the default engine;
 
76
   * NULL if it's the default
 
77
   */
 
78
  gchar *address;
 
79
 
 
80
  gpointer user_data;
 
81
  GDestroyNotify dnotify;
 
82
  
 
83
  guint is_default : 1;
 
84
 
 
85
  /* If TRUE, this is a local engine (and therefore
 
86
   * has no ctable and no notifications)
 
87
   */
 
88
  guint is_local : 1;
 
89
};
 
90
 
 
91
typedef struct _GConfCnxn GConfCnxn;
 
92
 
 
93
struct _GConfCnxn {
 
94
  gchar* namespace_section;
 
95
  guint client_id;
 
96
  CORBA_unsigned_long server_id; /* id returned from server */
 
97
  GConfEngine* conf;             /* engine we're associated with */
 
98
  GConfNotifyFunc func;
 
99
  gpointer user_data;
 
100
};
 
101
 
 
102
static GConfEngine *default_engine = NULL;
 
103
 
 
104
static GConfCnxn* gconf_cnxn_new     (GConfEngine         *conf,
 
105
                                      const gchar         *namespace_section,
 
106
                                      CORBA_unsigned_long  server_id,
 
107
                                      GConfNotifyFunc      func,
 
108
                                      gpointer             user_data);
 
109
static void       gconf_cnxn_destroy (GConfCnxn           *cnxn);
 
110
static void       gconf_cnxn_notify  (GConfCnxn           *cnxn,
 
111
                                      GConfEntry          *entry);
 
112
 
 
113
 
 
114
static ConfigServer   gconf_get_config_server    (gboolean     start_if_not_found,
 
115
                                                  GError **err);
 
116
 
 
117
/* Forget our current server object reference, so the next call to
 
118
   gconf_get_config_server will have to try to respawn the server */
 
119
static void           gconf_detach_config_server (void);
 
120
static ConfigListener gconf_get_config_listener  (void);
 
121
 
 
122
static void           gconf_engine_detach       (GConfEngine     *conf);
 
123
static gboolean       gconf_engine_connect      (GConfEngine     *conf,
 
124
                                                 gboolean         start_if_not_found,
 
125
                                                 GError         **err);
 
126
static void           gconf_engine_set_database (GConfEngine     *conf,
 
127
                                                 ConfigDatabase   db);
 
128
static ConfigDatabase gconf_engine_get_database (GConfEngine     *conf,
 
129
                                                 gboolean         start_if_not_found,
 
130
                                                 GError         **err);
 
131
 
 
132
 
 
133
static void         register_engine           (GConfEngine    *conf);
 
134
static void         unregister_engine         (GConfEngine    *conf);
 
135
static GConfEngine *lookup_engine             (const gchar    *address);
 
136
static GConfEngine *lookup_engine_by_database (ConfigDatabase  db);
 
137
 
 
138
 
 
139
/* We'll use client-specific connection numbers to return to library
 
140
   users, so if gconfd dies we can transparently re-register all our
 
141
   listener functions.  */
 
142
 
 
143
struct _CnxnTable {
 
144
  /* Hash from server-returned connection ID to GConfCnxn */
 
145
  GHashTable* server_ids;
 
146
  /* Hash from our connection ID to GConfCnxn */
 
147
  GHashTable* client_ids;
 
148
};
 
149
 
 
150
static CnxnTable* ctable_new                 (void);
 
151
static void       ctable_destroy             (CnxnTable           *ct);
 
152
static void       ctable_insert              (CnxnTable           *ct,
 
153
                                              GConfCnxn           *cnxn);
 
154
static void       ctable_remove              (CnxnTable           *ct,
 
155
                                              GConfCnxn           *cnxn);
 
156
static GSList*    ctable_remove_by_conf      (CnxnTable           *ct,
 
157
                                              GConfEngine         *conf);
 
158
static GConfCnxn* ctable_lookup_by_client_id (CnxnTable           *ct,
 
159
                                              guint                client_id);
 
160
static GConfCnxn* ctable_lookup_by_server_id (CnxnTable           *ct,
 
161
                                              CORBA_unsigned_long  server_id);
 
162
static void       ctable_reinstall           (CnxnTable           *ct,
 
163
                                              GConfCnxn           *cnxn,
 
164
                                              guint                old_server_id,
 
165
                                              guint                new_server_id);
 
166
 
 
167
 
 
168
static GConfEngine*
 
169
gconf_engine_blank (gboolean remote)
 
170
{
 
171
  GConfEngine* conf;
 
172
 
 
173
  conf = g_new0(GConfEngine, 1);
 
174
 
 
175
  conf->refcount = 1;
 
176
  
 
177
  if (remote)
 
178
    {
 
179
      conf->database = CORBA_OBJECT_NIL;
 
180
      conf->ctable = ctable_new();
 
181
      conf->local_sources = NULL;
 
182
      conf->is_local = FALSE;
 
183
      conf->is_default = TRUE;
 
184
    }
 
185
  else
 
186
    {
 
187
      conf->database = CORBA_OBJECT_NIL;
 
188
      conf->ctable = NULL;
 
189
      conf->local_sources = NULL;
 
190
      conf->is_local = TRUE;
 
191
      conf->is_default = FALSE;
 
192
    }
 
193
    
 
194
  return conf;
 
195
}
 
196
 
 
197
static GHashTable *engines_by_db = NULL;
 
198
 
 
199
static GConfEngine *
 
200
lookup_engine_by_database (ConfigDatabase db)
 
201
{
 
202
  if (engines_by_db)
 
203
    return g_hash_table_lookup (engines_by_db, db);
 
204
  else
 
205
    return NULL;
 
206
}
 
207
 
 
208
/* This takes ownership of the ConfigDatabase */
 
209
static void
 
210
gconf_engine_set_database (GConfEngine *conf,
 
211
                           ConfigDatabase db)
 
212
{
 
213
  gconf_engine_detach (conf);
 
214
 
 
215
  conf->database = db;
 
216
 
 
217
  if (engines_by_db == NULL)
 
218
    engines_by_db = g_hash_table_new ((GHashFunc) g_CORBA_Object_hash,
 
219
                                      (GCompareFunc) g_CORBA_Object_equal);
 
220
  
 
221
  g_hash_table_insert (engines_by_db, conf->database, conf);  
 
222
}
 
223
 
 
224
static void
 
225
gconf_engine_detach (GConfEngine *conf)
 
226
{
 
227
  CORBA_Environment ev;
 
228
 
 
229
  CORBA_exception_init (&ev);
 
230
  
 
231
  if (!CORBA_Object_is_nil (conf->database, &ev))
 
232
    {
 
233
      g_hash_table_remove (engines_by_db, conf->database);
 
234
      
 
235
      CORBA_Object_release (conf->database, &ev);
 
236
      conf->database = CORBA_OBJECT_NIL;
 
237
    }
 
238
}
 
239
 
 
240
static gboolean
 
241
gconf_engine_connect (GConfEngine *conf,
 
242
                      gboolean start_if_not_found,
 
243
                      GError **err)
 
244
{
 
245
  ConfigServer cs;
 
246
  ConfigDatabase db;
 
247
  int tries = 0;
 
248
  CORBA_Environment ev;
 
249
  
 
250
  g_return_val_if_fail (!conf->is_local, TRUE);
 
251
  
 
252
  CORBA_exception_init(&ev);
 
253
 
 
254
  if (!CORBA_Object_is_nil (conf->database, &ev))
 
255
    return TRUE;
 
256
  
 
257
 RETRY:
 
258
      
 
259
  cs = gconf_get_config_server(start_if_not_found, err);
 
260
      
 
261
  if (cs == CORBA_OBJECT_NIL)
 
262
    return FALSE; /* Error should already be set */
 
263
 
 
264
  if (conf->is_default)
 
265
    db = ConfigServer_get_default_database (cs, &ev);      
 
266
  else
 
267
    db = ConfigServer_get_database (cs, conf->address, &ev);
 
268
  
 
269
  if (gconf_server_broken(&ev))
 
270
    {
 
271
      if (tries < MAX_RETRIES)
 
272
        {
 
273
          ++tries;
 
274
          CORBA_exception_free(&ev);
 
275
          gconf_detach_config_server();
 
276
          goto RETRY;
 
277
        }
 
278
    }
 
279
  
 
280
  if (gconf_handle_corba_exception(&ev, err))
 
281
    return FALSE;
 
282
 
 
283
  if (CORBA_Object_is_nil (db, &ev))
 
284
    {
 
285
      if (err)
 
286
        *err = gconf_error_new(GCONF_ERROR_BAD_ADDRESS,
 
287
                               _("Server couldn't resolve the address `%s'"),
 
288
                               conf->address ? conf->address : "default");
 
289
          
 
290
      return FALSE;
 
291
    }
 
292
 
 
293
  gconf_engine_set_database (conf, db);
 
294
  
 
295
  return TRUE;
 
296
}
 
297
 
 
298
static ConfigDatabase
 
299
gconf_engine_get_database (GConfEngine *conf,
 
300
                           gboolean start_if_not_found,
 
301
                           GError **err)
 
302
{
 
303
  if (!gconf_engine_connect (conf, start_if_not_found, err))
 
304
    return CORBA_OBJECT_NIL;
 
305
  else
 
306
    return conf->database;
 
307
}
 
308
 
 
309
static gboolean
 
310
gconf_engine_is_local(GConfEngine* conf)
 
311
{
 
312
  return conf->is_local;
 
313
}
 
314
 
 
315
static GHashTable *engines_by_address = NULL;
 
316
 
 
317
static void
 
318
register_engine (GConfEngine *conf)
 
319
{
 
320
  g_return_if_fail (conf->address != NULL);
 
321
 
 
322
  if (engines_by_address == NULL)
 
323
    engines_by_address = g_hash_table_new (g_str_hash, g_str_equal);
 
324
 
 
325
  g_hash_table_insert (engines_by_address, conf->address, conf);
 
326
}
 
327
 
 
328
static void
 
329
unregister_engine (GConfEngine *conf)
 
330
{
 
331
  g_return_if_fail (conf->address != NULL);
 
332
  g_return_if_fail (engines_by_address != NULL);
 
333
  
 
334
  g_hash_table_remove (engines_by_address, conf->address);
 
335
 
 
336
  if (g_hash_table_size (engines_by_address) == 0)
 
337
    {
 
338
      g_hash_table_destroy (engines_by_address);
 
339
      
 
340
      engines_by_address = NULL;
 
341
    }
 
342
}
 
343
 
 
344
static GConfEngine *
 
345
lookup_engine (const gchar *address)
 
346
{
 
347
  if (engines_by_address)
 
348
    return g_hash_table_lookup (engines_by_address, address);
 
349
  else
 
350
    return NULL;
 
351
}
 
352
 
 
353
 
 
354
/*
 
355
 *  Public Interface
 
356
 */
 
357
 
 
358
GConfEngine*
 
359
gconf_engine_get_local      (const gchar* address,
 
360
                             GError** err)
 
361
{
 
362
  GConfEngine* conf;
 
363
  GConfSource* source;
 
364
 
 
365
  g_return_val_if_fail(address != NULL, NULL);
 
366
  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
 
367
  
 
368
  source = gconf_resolve_address(address, err);
 
369
 
 
370
  if (source == NULL)
 
371
    return NULL;
 
372
  
 
373
  conf = gconf_engine_blank(FALSE);
 
374
 
 
375
  conf->local_sources = gconf_sources_new_from_source(source);
 
376
 
 
377
  g_assert (gconf_engine_is_local (conf));
 
378
  
 
379
  return conf;
 
380
}
 
381
 
 
382
GConfEngine*
 
383
gconf_engine_get_default (void)
 
384
{
 
385
  GConfEngine* conf = NULL;
 
386
  
 
387
  if (default_engine)
 
388
    conf = default_engine;
 
389
 
 
390
  if (conf == NULL)
 
391
    {
 
392
      conf = gconf_engine_blank(TRUE);
 
393
 
 
394
      conf->is_default = TRUE;
 
395
 
 
396
      default_engine = conf;
 
397
      
 
398
      /* Ignore errors, we never return a NULL
 
399
       * default database
 
400
       */
 
401
      gconf_engine_connect (conf, TRUE, NULL);
 
402
    }
 
403
  else
 
404
    conf->refcount += 1;
 
405
  
 
406
  return conf;
 
407
}
 
408
 
 
409
GConfEngine*
 
410
gconf_engine_get_for_address (const gchar* address, GError** err)
 
411
{
 
412
  GConfEngine* conf;
 
413
  
 
414
  g_warning("Non-default configuration sources currently do not support change-notification, and are not yet recommended for use in applications.");
 
415
 
 
416
  conf = lookup_engine (address);
 
417
 
 
418
  if (conf == NULL)
 
419
    {
 
420
      conf = gconf_engine_blank(TRUE);
 
421
 
 
422
      conf->is_default = FALSE;
 
423
      conf->address = g_strdup (address);
 
424
 
 
425
      if (!gconf_engine_connect (conf, TRUE, err))
 
426
        {
 
427
          gconf_engine_unref (conf);
 
428
          return NULL;
 
429
        }
 
430
 
 
431
      register_engine (conf);
 
432
    }
 
433
  else
 
434
    conf->refcount += 1;
 
435
  
 
436
  return conf;
 
437
}
 
438
 
 
439
void
 
440
gconf_engine_ref             (GConfEngine* conf)
 
441
{
 
442
  g_return_if_fail(conf != NULL);
 
443
  g_return_if_fail(conf->refcount > 0);
 
444
 
 
445
  conf->refcount += 1;
 
446
}
 
447
 
 
448
void         
 
449
gconf_engine_unref        (GConfEngine* conf)
 
450
{
 
451
  g_return_if_fail(conf != NULL);
 
452
  g_return_if_fail(conf->refcount > 0);
 
453
 
 
454
  conf->refcount -= 1;
 
455
  
 
456
  if (conf->refcount == 0)
 
457
    {
 
458
      if (gconf_engine_is_local(conf))
 
459
        {
 
460
          if (conf->local_sources != NULL)
 
461
            gconf_sources_free(conf->local_sources);
 
462
        }
 
463
      else
 
464
        {
 
465
          /* Remove all connections associated with this GConf */
 
466
          GSList* removed;
 
467
          GSList* tmp;
 
468
          CORBA_Environment ev;
 
469
      
 
470
          CORBA_exception_init(&ev);
 
471
 
 
472
          /* FIXME CnxnTable only has entries for this GConfEngine now,
 
473
           * it used to be global and shared among GConfEngine objects.
 
474
           */
 
475
          removed = ctable_remove_by_conf (conf->ctable, conf);
 
476
  
 
477
          tmp = removed;
 
478
          while (tmp != NULL)
 
479
            {
 
480
              GConfCnxn* gcnxn = tmp->data;
 
481
 
 
482
              if (!CORBA_Object_is_nil (conf->database, &ev))
 
483
                {
 
484
                  GError* err = NULL;
 
485
              
 
486
                  ConfigDatabase_remove_listener(conf->database,
 
487
                                                 gcnxn->server_id,
 
488
                                                 &ev);
 
489
 
 
490
                  if (gconf_handle_corba_exception(&ev, &err))
 
491
                    {
 
492
                      /* Don't set error because realistically this
 
493
                         doesn't matter to clients */
 
494
#ifdef GCONF_ENABLE_DEBUG
 
495
                      g_warning("Failure removing listener %u from the config server: %s",
 
496
                                (guint)gcnxn->server_id,
 
497
                                err->message);
 
498
#endif
 
499
                    }
 
500
                }
 
501
 
 
502
              gconf_cnxn_destroy(gcnxn);
 
503
 
 
504
              tmp = g_slist_next(tmp);
 
505
            }
 
506
 
 
507
          g_slist_free(removed);
 
508
 
 
509
          if (conf->dnotify)
 
510
            {
 
511
              (* conf->dnotify) (conf->user_data);
 
512
            }
 
513
          
 
514
          /* do this after removing the notifications,
 
515
             to avoid funky race conditions */
 
516
          if (conf->address)
 
517
            unregister_engine (conf);
 
518
 
 
519
          /* Release the ConfigDatabase */
 
520
          gconf_engine_detach (conf);
 
521
          
 
522
          ctable_destroy (conf->ctable);
 
523
        }
 
524
 
 
525
      if (conf == default_engine)
 
526
        default_engine = NULL;
 
527
 
 
528
      g_free(conf);
 
529
    }
 
530
}
 
531
 
 
532
void
 
533
gconf_engine_set_user_data  (GConfEngine   *engine,
 
534
                             gpointer       data,
 
535
                             GDestroyNotify dnotify)
 
536
{
 
537
  if (engine->dnotify)
 
538
    {
 
539
      (* engine->dnotify) (engine->user_data);
 
540
    }
 
541
 
 
542
  engine->dnotify = dnotify;
 
543
  engine->user_data = data;
 
544
}
 
545
 
 
546
gpointer
 
547
gconf_engine_get_user_data  (GConfEngine   *engine)
 
548
{
 
549
  return engine->user_data;
 
550
}
 
551
 
 
552
guint
 
553
gconf_engine_notify_add(GConfEngine* conf,
 
554
                        const gchar* namespace_section,
 
555
                        GConfNotifyFunc func,
 
556
                        gpointer user_data,
 
557
                        GError** err)
 
558
{
 
559
  ConfigDatabase db;
 
560
  ConfigListener cl;
 
561
  gulong id;
 
562
  CORBA_Environment ev;
 
563
  GConfCnxn* cnxn;
 
564
  gint tries = 0;
 
565
 
 
566
  g_return_val_if_fail(!gconf_engine_is_local(conf), 0);
 
567
  
 
568
  if (gconf_engine_is_local(conf))
 
569
    {
 
570
      if (err)
 
571
        *err = gconf_error_new(GCONF_ERROR_LOCAL_ENGINE,
 
572
                               _("Can't add notifications to a local configuration source"));
 
573
 
 
574
      return 0;
 
575
    }
 
576
  
 
577
  CORBA_exception_init(&ev);
 
578
 
 
579
 RETRY:
 
580
  
 
581
  db = gconf_engine_get_database (conf, TRUE, err);
 
582
 
 
583
  if (db == CORBA_OBJECT_NIL)
 
584
    return 0;
 
585
 
 
586
  cl = gconf_get_config_listener ();
 
587
  
 
588
  /* Should have aborted the program in this case probably */
 
589
  g_return_val_if_fail(cl != CORBA_OBJECT_NIL, 0);
 
590
 
 
591
  id = ConfigDatabase_add_listener(db,
 
592
                                   (gchar*)namespace_section, 
 
593
                                   cl, &ev);
 
594
  
 
595
  if (gconf_server_broken(&ev))
 
596
    {
 
597
      if (tries < MAX_RETRIES)
 
598
        {
 
599
          ++tries;
 
600
          CORBA_exception_free(&ev);
 
601
          gconf_engine_detach (conf);
 
602
          goto RETRY;
 
603
        }
 
604
    }
 
605
  
 
606
  if (gconf_handle_corba_exception(&ev, err))
 
607
    return 0;
 
608
 
 
609
  cnxn = gconf_cnxn_new(conf, namespace_section, id, func, user_data);
 
610
 
 
611
  ctable_insert(conf->ctable, cnxn);
 
612
 
 
613
  return cnxn->client_id;
 
614
}
 
615
 
 
616
void         
 
617
gconf_engine_notify_remove(GConfEngine* conf,
 
618
                    guint client_id)
 
619
{
 
620
  GConfCnxn* gcnxn;
 
621
  CORBA_Environment ev;
 
622
  ConfigDatabase db;
 
623
  gint tries = 0;
 
624
 
 
625
  if (gconf_engine_is_local(conf))
 
626
    return;
 
627
  
 
628
  CORBA_exception_init(&ev);
 
629
 
 
630
 RETRY:
 
631
  
 
632
  db = gconf_engine_get_database (conf, TRUE, NULL);
 
633
 
 
634
  if (db == CORBA_OBJECT_NIL)
 
635
    return;
 
636
 
 
637
  gcnxn = ctable_lookup_by_client_id(conf->ctable, client_id);
 
638
 
 
639
  g_return_if_fail(gcnxn != NULL);
 
640
 
 
641
  ConfigDatabase_remove_listener(db,
 
642
                                 gcnxn->server_id,
 
643
                                 &ev);
 
644
 
 
645
  if (gconf_server_broken(&ev))
 
646
    {
 
647
      if (tries < MAX_RETRIES)
 
648
        {
 
649
          ++tries;
 
650
          CORBA_exception_free(&ev);
 
651
          gconf_engine_detach (conf);
 
652
          goto RETRY;
 
653
        }
 
654
    }
 
655
  
 
656
  if (gconf_handle_corba_exception(&ev, NULL))
 
657
    {
 
658
      ; /* do nothing */
 
659
    }
 
660
  
 
661
 
 
662
  /* We want to do this even if the CORBA fails, so if we restart gconfd and 
 
663
     reinstall listeners we don't reinstall this one. */
 
664
  ctable_remove(conf->ctable, gcnxn);
 
665
 
 
666
  gconf_cnxn_destroy(gcnxn);
 
667
}
 
668
 
 
669
GConfValue *
 
670
gconf_engine_get_fuller (GConfEngine *conf,
 
671
                         const gchar *key,
 
672
                         const gchar *locale,
 
673
                         gboolean use_schema_default,
 
674
                         gboolean *is_default_p,
 
675
                         gboolean *is_writable_p,
 
676
                         gchar   **schema_name_p,
 
677
                         GError **err)
 
678
{
 
679
  GConfValue* val;
 
680
  ConfigValue* cv;
 
681
  CORBA_Environment ev;
 
682
  ConfigDatabase db;
 
683
  gint tries = 0;
 
684
  CORBA_boolean is_default = FALSE;
 
685
  CORBA_boolean is_writable = TRUE;
 
686
  CORBA_char *corba_schema_name = NULL;
 
687
  
 
688
  g_return_val_if_fail(conf != NULL, NULL);
 
689
  g_return_val_if_fail(key != NULL, NULL);
 
690
  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
 
691
 
 
692
  if (!gconf_key_check(key, err))
 
693
    return NULL;
 
694
 
 
695
  if (gconf_engine_is_local(conf))
 
696
    {
 
697
      gchar** locale_list;
 
698
      gboolean tmp_is_default = FALSE;
 
699
      gboolean tmp_is_writable = TRUE;
 
700
      gchar *tmp_schema_name = NULL;
 
701
      
 
702
      locale_list = gconf_split_locale(locale);
 
703
      
 
704
      val = gconf_sources_query_value(conf->local_sources,
 
705
                                      key,
 
706
                                      (const gchar**)locale_list,
 
707
                                      use_schema_default,
 
708
                                      &tmp_is_default,
 
709
                                      &tmp_is_writable,
 
710
                                      schema_name_p ? &tmp_schema_name : NULL,
 
711
                                      err);
 
712
 
 
713
      if (locale_list != NULL)
 
714
        g_strfreev(locale_list);
 
715
      
 
716
      if (is_default_p)
 
717
        *is_default_p = tmp_is_default;
 
718
 
 
719
      if (is_writable_p)
 
720
        *is_writable_p = tmp_is_writable;
 
721
 
 
722
      if (schema_name_p)
 
723
        *schema_name_p = tmp_schema_name;
 
724
      else
 
725
        g_free (tmp_schema_name);
 
726
      
 
727
      return val;
 
728
    }
 
729
 
 
730
  g_assert(!gconf_engine_is_local(conf));
 
731
  
 
732
  CORBA_exception_init(&ev);
 
733
 
 
734
 RETRY:
 
735
  
 
736
  db = gconf_engine_get_database (conf, TRUE, err);
 
737
 
 
738
  if (db == CORBA_OBJECT_NIL)
 
739
    {
 
740
      g_return_val_if_fail(err == NULL || *err != NULL, NULL);
 
741
 
 
742
      return NULL;
 
743
    }
 
744
 
 
745
  if (schema_name_p)
 
746
    *schema_name_p = NULL;
 
747
 
 
748
 
 
749
  corba_schema_name = NULL;
 
750
  cv = ConfigDatabase2_lookup_with_schema_name (db,
 
751
                                                (gchar*)key, (gchar*)
 
752
                                                (locale ? locale : gconf_current_locale()),
 
753
                                                use_schema_default,
 
754
                                                &corba_schema_name,
 
755
                                                &is_default,
 
756
                                                &is_writable,
 
757
                                                &ev);
 
758
 
 
759
  if (ev._major == CORBA_SYSTEM_EXCEPTION &&
 
760
      CORBA_exception_id (&ev) &&
 
761
      strcmp (CORBA_exception_id (&ev), "IDL:CORBA/BAD_OPERATION:1.0") == 0)
 
762
    {
 
763
      CORBA_exception_free (&ev);
 
764
      CORBA_exception_init (&ev);
 
765
      
 
766
      cv = ConfigDatabase_lookup_with_locale(db,
 
767
                                             (gchar*)key, (gchar*)
 
768
                                             (locale ? locale : gconf_current_locale()),
 
769
                                             use_schema_default,
 
770
                                             &is_default,
 
771
                                             &is_writable,
 
772
                                             &ev);
 
773
    }
 
774
  
 
775
  if (gconf_server_broken(&ev))
 
776
    {
 
777
      if (tries < MAX_RETRIES)
 
778
        {
 
779
          ++tries;
 
780
          CORBA_exception_free(&ev);
 
781
          gconf_engine_detach (conf);
 
782
          goto RETRY;
 
783
        }
 
784
    }
 
785
  
 
786
  if (gconf_handle_corba_exception(&ev, err))
 
787
    {
 
788
      /* NOTE: don't free cv since we got an exception! */
 
789
      return NULL;
 
790
    }
 
791
  else
 
792
    {
 
793
      val = gconf_value_from_corba_value(cv);
 
794
      CORBA_free(cv);
 
795
 
 
796
      if (is_default_p)
 
797
        *is_default_p = !!is_default;
 
798
      if (is_writable_p)
 
799
        *is_writable_p = !!is_writable;
 
800
 
 
801
      /* we can't get a null pointer through corba
 
802
       * so the server sent us an empty string
 
803
       */
 
804
      if (corba_schema_name && corba_schema_name[0] != '/')
 
805
        {
 
806
          CORBA_free (corba_schema_name);
 
807
          corba_schema_name = NULL;
 
808
        }
 
809
 
 
810
      if (schema_name_p)
 
811
        *schema_name_p = g_strdup (corba_schema_name);
 
812
 
 
813
      if (corba_schema_name)
 
814
        CORBA_free (corba_schema_name);
 
815
      
 
816
      return val;
 
817
    }
 
818
}
 
819
 
 
820
 
 
821
GConfValue *
 
822
gconf_engine_get_full (GConfEngine *conf,
 
823
                       const gchar *key,
 
824
                       const gchar *locale,
 
825
                       gboolean use_schema_default,
 
826
                       gboolean *is_default_p,
 
827
                       gboolean *is_writable_p,
 
828
                       GError **err)
 
829
{
 
830
  return gconf_engine_get_fuller (conf, key, locale, use_schema_default,
 
831
                                  is_default_p, is_writable_p,
 
832
                                  NULL, err);
 
833
}
 
834
 
 
835
GConfEntry*
 
836
gconf_engine_get_entry(GConfEngine* conf,
 
837
                       const gchar* key,
 
838
                       const gchar* locale,
 
839
                       gboolean use_schema_default,
 
840
                       GError** err)
 
841
{
 
842
  gboolean is_writable = TRUE;
 
843
  gboolean is_default = FALSE;
 
844
  GConfValue *val;
 
845
  GError *error;
 
846
  GConfEntry *entry;
 
847
  gchar *schema_name;
 
848
 
 
849
  schema_name = NULL;
 
850
  error = NULL;
 
851
  val = gconf_engine_get_fuller (conf, key, locale, use_schema_default,
 
852
                                 &is_default, &is_writable,
 
853
                                 &schema_name, &error);
 
854
  if (error != NULL)
 
855
    {
 
856
      g_propagate_error (err, error);
 
857
      return NULL;
 
858
    }
 
859
 
 
860
  entry = gconf_entry_new_nocopy (g_strdup (key),
 
861
                                  val);
 
862
  
 
863
  entry->is_default = is_default;
 
864
  entry->is_writable = is_writable;
 
865
  entry->schema_name = schema_name; /* transfer memory ownership */
 
866
 
 
867
  return entry;
 
868
}
 
869
     
 
870
GConfValue*  
 
871
gconf_engine_get (GConfEngine* conf, const gchar* key, GError** err)
 
872
{
 
873
  return gconf_engine_get_with_locale(conf, key, NULL, err);
 
874
}
 
875
 
 
876
GConfValue*
 
877
gconf_engine_get_with_locale(GConfEngine* conf, const gchar* key,
 
878
                             const gchar* locale,
 
879
                             GError** err)
 
880
{
 
881
  return gconf_engine_get_full(conf, key, locale, TRUE,
 
882
                               NULL, NULL, err);
 
883
}
 
884
 
 
885
GConfValue*
 
886
gconf_engine_get_without_default(GConfEngine* conf, const gchar* key,
 
887
                                 GError** err)
 
888
{
 
889
  return gconf_engine_get_full(conf, key, NULL, FALSE, NULL, NULL, err);
 
890
}
 
891
 
 
892
GConfValue*
 
893
gconf_engine_get_default_from_schema (GConfEngine* conf,
 
894
                                      const gchar* key,
 
895
                                      GError** err)
 
896
{
 
897
  GConfValue* val;
 
898
  ConfigValue* cv;
 
899
  CORBA_Environment ev;
 
900
  ConfigDatabase db;
 
901
  gint tries = 0;
 
902
 
 
903
  g_return_val_if_fail(conf != NULL, NULL);
 
904
  g_return_val_if_fail(key != NULL, NULL);
 
905
  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
 
906
  
 
907
  if (!gconf_key_check(key, err))
 
908
    return NULL;
 
909
 
 
910
  if (gconf_engine_is_local(conf))
 
911
    {
 
912
      gchar** locale_list;
 
913
 
 
914
      locale_list = gconf_split_locale(gconf_current_locale());
 
915
      
 
916
      val = gconf_sources_query_default_value(conf->local_sources,
 
917
                                              key,
 
918
                                              (const gchar**)locale_list,
 
919
                                              NULL,
 
920
                                              err);
 
921
 
 
922
      if (locale_list != NULL)
 
923
        g_strfreev(locale_list);
 
924
      
 
925
      return val;
 
926
    }
 
927
 
 
928
  g_assert(!gconf_engine_is_local(conf));
 
929
  
 
930
  CORBA_exception_init(&ev);
 
931
 
 
932
 RETRY:
 
933
  
 
934
  db = gconf_engine_get_database (conf, TRUE, err);
 
935
 
 
936
  if (db == CORBA_OBJECT_NIL)
 
937
    {
 
938
      g_return_val_if_fail(err == NULL || *err != NULL, NULL);
 
939
 
 
940
      return NULL;
 
941
    }
 
942
 
 
943
  cv = ConfigDatabase_lookup_default_value(db,
 
944
                                           (gchar*)key,
 
945
                                           (gchar*)gconf_current_locale(),
 
946
                                           &ev);
 
947
  
 
948
  if (gconf_server_broken(&ev))
 
949
    {
 
950
      if (tries < MAX_RETRIES)
 
951
        {
 
952
          ++tries;
 
953
          CORBA_exception_free(&ev);
 
954
          gconf_engine_detach (conf);
 
955
          goto RETRY;
 
956
        }
 
957
    }
 
958
  
 
959
  if (gconf_handle_corba_exception(&ev, err))
 
960
    {
 
961
      /* NOTE: don't free cv since we got an exception! */
 
962
      return NULL;
 
963
    }
 
964
  else
 
965
    {
 
966
      val = gconf_value_from_corba_value(cv);
 
967
      CORBA_free(cv);
 
968
 
 
969
      return val;
 
970
    }
 
971
}
 
972
 
 
973
gboolean
 
974
gconf_engine_set (GConfEngine* conf, const gchar* key,
 
975
                  GConfValue* value, GError** err)
 
976
{
 
977
  ConfigValue* cv;
 
978
  CORBA_Environment ev;
 
979
  ConfigDatabase db;
 
980
  gint tries = 0;
 
981
 
 
982
  g_return_val_if_fail(conf != NULL, FALSE);
 
983
  g_return_val_if_fail(key != NULL, FALSE);
 
984
  g_return_val_if_fail(value != NULL, FALSE);
 
985
  g_return_val_if_fail(value->type != GCONF_VALUE_INVALID, FALSE);
 
986
  g_return_val_if_fail( (value->type != GCONF_VALUE_STRING) ||
 
987
                        (gconf_value_get_string(value) != NULL) , FALSE );
 
988
  g_return_val_if_fail( (value->type != GCONF_VALUE_LIST) ||
 
989
                        (gconf_value_get_list_type(value) != GCONF_VALUE_INVALID), FALSE);
 
990
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
991
  
 
992
  if (!gconf_key_check(key, err))
 
993
    return FALSE;
 
994
 
 
995
  if (!gconf_value_validate (value, err))
 
996
    return FALSE;
 
997
  
 
998
  if (gconf_engine_is_local(conf))
 
999
    {
 
1000
      GError* error = NULL;
 
1001
      
 
1002
      gconf_sources_set_value(conf->local_sources, key, value, &error);
 
1003
 
 
1004
      if (error != NULL)
 
1005
        {
 
1006
          if (err)
 
1007
            *err = error;
 
1008
          else
 
1009
            {
 
1010
              g_error_free(error);
 
1011
            }
 
1012
          return FALSE;
 
1013
        }
 
1014
      
 
1015
      return TRUE;
 
1016
    }
 
1017
 
 
1018
  g_assert(!gconf_engine_is_local(conf));
 
1019
  
 
1020
  CORBA_exception_init(&ev);
 
1021
 
 
1022
 RETRY:
 
1023
  
 
1024
  db = gconf_engine_get_database (conf, TRUE, err);
 
1025
 
 
1026
  if (db == CORBA_OBJECT_NIL)
 
1027
    {
 
1028
      g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
 
1029
 
 
1030
      return FALSE;
 
1031
    }
 
1032
 
 
1033
  cv = corba_value_from_gconf_value(value);
 
1034
 
 
1035
  ConfigDatabase_set(db,
 
1036
                     (gchar*)key, cv,
 
1037
                     &ev);
 
1038
 
 
1039
  CORBA_free(cv);
 
1040
 
 
1041
  if (gconf_server_broken(&ev))
 
1042
    {
 
1043
      if (tries < MAX_RETRIES)
 
1044
        {
 
1045
          ++tries;
 
1046
          CORBA_exception_free(&ev);
 
1047
          gconf_engine_detach (conf);
 
1048
          goto RETRY;
 
1049
        }
 
1050
    }
 
1051
  
 
1052
  if (gconf_handle_corba_exception(&ev, err))
 
1053
    return FALSE;
 
1054
 
 
1055
  g_return_val_if_fail(*err == NULL, FALSE);
 
1056
  
 
1057
  return TRUE;
 
1058
}
 
1059
 
 
1060
gboolean
 
1061
gconf_engine_unset(GConfEngine* conf, const gchar* key, GError** err)
 
1062
{
 
1063
  CORBA_Environment ev;
 
1064
  ConfigDatabase db;
 
1065
  gint tries = 0;
 
1066
 
 
1067
  g_return_val_if_fail(conf != NULL, FALSE);
 
1068
  g_return_val_if_fail(key != NULL, FALSE);
 
1069
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
1070
  
 
1071
  if (!gconf_key_check(key, err))
 
1072
    return FALSE;
 
1073
 
 
1074
  if (gconf_engine_is_local(conf))
 
1075
    {
 
1076
      GError* error = NULL;
 
1077
      
 
1078
      gconf_sources_unset_value(conf->local_sources, key, NULL, &error);
 
1079
 
 
1080
      if (error != NULL)
 
1081
        {
 
1082
          if (err)
 
1083
            *err = error;
 
1084
          else
 
1085
            {
 
1086
              g_error_free(error);
 
1087
            }
 
1088
          return FALSE;
 
1089
        }
 
1090
      
 
1091
      return TRUE;
 
1092
    }
 
1093
 
 
1094
  g_assert(!gconf_engine_is_local(conf));
 
1095
  
 
1096
  CORBA_exception_init(&ev);
 
1097
 
 
1098
 RETRY:
 
1099
  
 
1100
  db = gconf_engine_get_database (conf, TRUE, err);
 
1101
 
 
1102
  if (db == CORBA_OBJECT_NIL)
 
1103
    {
 
1104
      g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
 
1105
 
 
1106
      return FALSE;
 
1107
    }
 
1108
 
 
1109
  ConfigDatabase_unset(db,
 
1110
                     (gchar*)key,
 
1111
                     &ev);
 
1112
 
 
1113
  if (gconf_server_broken(&ev))
 
1114
    {
 
1115
      if (tries < MAX_RETRIES)
 
1116
        {
 
1117
          ++tries;
 
1118
          CORBA_exception_free(&ev);
 
1119
          gconf_engine_detach(conf);
 
1120
          goto RETRY;
 
1121
        }
 
1122
    }
 
1123
  
 
1124
  if (gconf_handle_corba_exception(&ev, err))
 
1125
    return FALSE;
 
1126
 
 
1127
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
1128
  
 
1129
  return TRUE;
 
1130
}
 
1131
 
 
1132
gboolean
 
1133
gconf_engine_associate_schema  (GConfEngine* conf, const gchar* key,
 
1134
                                const gchar* schema_key, GError** err)
 
1135
{
 
1136
  CORBA_Environment ev;
 
1137
  ConfigDatabase db;
 
1138
  gint tries = 0;
 
1139
 
 
1140
  g_return_val_if_fail(conf != NULL, FALSE);
 
1141
  g_return_val_if_fail(key != NULL, FALSE);
 
1142
  g_return_val_if_fail(schema_key != NULL, FALSE);
 
1143
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
1144
  
 
1145
  if (!gconf_key_check(key, err))
 
1146
    return FALSE;
 
1147
 
 
1148
  if (!gconf_key_check(schema_key, err))
 
1149
    return FALSE;
 
1150
 
 
1151
  if (gconf_engine_is_local(conf))
 
1152
    {
 
1153
      GError* error = NULL;
 
1154
      
 
1155
      gconf_sources_set_schema(conf->local_sources, key, schema_key, &error);
 
1156
 
 
1157
      if (error != NULL)
 
1158
        {
 
1159
          if (err)
 
1160
            *err = error;
 
1161
          else
 
1162
            {
 
1163
              g_error_free(error);
 
1164
            }
 
1165
          return FALSE;
 
1166
        }
 
1167
      
 
1168
      return TRUE;
 
1169
    }
 
1170
 
 
1171
  g_assert(!gconf_engine_is_local(conf));
 
1172
  
 
1173
  CORBA_exception_init(&ev);
 
1174
 
 
1175
 RETRY:
 
1176
  
 
1177
  db = gconf_engine_get_database(conf, TRUE, err);
 
1178
 
 
1179
  if (db == CORBA_OBJECT_NIL)
 
1180
    {
 
1181
      g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
 
1182
 
 
1183
      return FALSE;
 
1184
    }
 
1185
 
 
1186
  ConfigDatabase_set_schema(db,
 
1187
                            (gchar*)key,
 
1188
                            (gchar*)schema_key,
 
1189
                            &ev);
 
1190
 
 
1191
  if (gconf_server_broken(&ev))
 
1192
    {
 
1193
      if (tries < MAX_RETRIES)
 
1194
        {
 
1195
          ++tries;
 
1196
          CORBA_exception_free(&ev);
 
1197
          gconf_engine_detach (conf);
 
1198
          goto RETRY;
 
1199
        }
 
1200
    }
 
1201
  
 
1202
  if (gconf_handle_corba_exception(&ev, err))
 
1203
    return FALSE;
 
1204
 
 
1205
  g_return_val_if_fail(*err == NULL, FALSE);
 
1206
  
 
1207
  return TRUE;
 
1208
}
 
1209
 
 
1210
 
 
1211
static void
 
1212
qualify_entries (GSList *entries, const char *dir)
 
1213
{
 
1214
  GSList *tmp = entries;
 
1215
  while (tmp != NULL)
 
1216
    {
 
1217
      GConfEntry *entry = tmp->data;
 
1218
      gchar *full;
 
1219
 
 
1220
      full = gconf_concat_dir_and_key (dir, entry->key);
 
1221
 
 
1222
      g_free (entry->key);
 
1223
      entry->key = full;
 
1224
 
 
1225
      tmp = g_slist_next (tmp);
 
1226
    }
 
1227
}
 
1228
 
 
1229
GSList*      
 
1230
gconf_engine_all_entries(GConfEngine* conf, const gchar* dir, GError** err)
 
1231
{
 
1232
  GSList* pairs = NULL;
 
1233
  ConfigDatabase_ValueList* values;
 
1234
  ConfigDatabase_KeyList* keys;
 
1235
  ConfigDatabase_IsDefaultList* is_defaults;
 
1236
  ConfigDatabase_IsWritableList* is_writables;
 
1237
  ConfigDatabase2_SchemaNameList *schema_names;
 
1238
  CORBA_Environment ev;
 
1239
  ConfigDatabase db;
 
1240
  guint i;
 
1241
  gint tries = 0;
 
1242
 
 
1243
  g_return_val_if_fail(conf != NULL, NULL);
 
1244
  g_return_val_if_fail(dir != NULL, NULL);
 
1245
  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
 
1246
  
 
1247
  if (!gconf_key_check(dir, err))
 
1248
    return NULL;
 
1249
 
 
1250
 
 
1251
  if (gconf_engine_is_local(conf))
 
1252
    {
 
1253
      GError* error = NULL;
 
1254
      gchar** locale_list;
 
1255
      GSList* retval;
 
1256
      
 
1257
      locale_list = gconf_split_locale(gconf_current_locale());
 
1258
      
 
1259
      retval = gconf_sources_all_entries(conf->local_sources,
 
1260
                                         dir,
 
1261
                                         (const gchar**)locale_list,
 
1262
                                         &error);
 
1263
 
 
1264
      if (locale_list)
 
1265
        g_strfreev(locale_list);
 
1266
      
 
1267
      if (error != NULL)
 
1268
        {
 
1269
          if (err)
 
1270
            *err = error;
 
1271
          else
 
1272
            {
 
1273
              g_error_free(error);
 
1274
            }
 
1275
 
 
1276
          g_assert(retval == NULL);
 
1277
          
 
1278
          return NULL;
 
1279
        }
 
1280
 
 
1281
      qualify_entries (retval, dir);
 
1282
      
 
1283
      return retval;
 
1284
    }
 
1285
 
 
1286
  g_assert(!gconf_engine_is_local(conf));
 
1287
  
 
1288
  CORBA_exception_init(&ev);
 
1289
  
 
1290
 RETRY:
 
1291
  
 
1292
  db = gconf_engine_get_database (conf, TRUE, err);
 
1293
 
 
1294
  if (db == CORBA_OBJECT_NIL)
 
1295
    {
 
1296
      g_return_val_if_fail(err == NULL || *err != NULL, NULL);
 
1297
 
 
1298
      return NULL;
 
1299
    }
 
1300
 
 
1301
  schema_names = NULL;
 
1302
  
 
1303
  ConfigDatabase2_all_entries_with_schema_name (db,
 
1304
                                                (gchar*)dir,
 
1305
                                                (gchar*)gconf_current_locale(),
 
1306
                                                &keys, &values, &schema_names,
 
1307
                                                &is_defaults, &is_writables,
 
1308
                                                &ev);
 
1309
  
 
1310
  if (ev._major == CORBA_SYSTEM_EXCEPTION &&
 
1311
      CORBA_exception_id (&ev) &&
 
1312
      strcmp (CORBA_exception_id (&ev), "IDL:CORBA/BAD_OPERATION:1.0") == 0)
 
1313
    {
 
1314
      CORBA_exception_free (&ev);
 
1315
      CORBA_exception_init (&ev);
 
1316
      
 
1317
      ConfigDatabase_all_entries(db,
 
1318
                                 (gchar*)dir,
 
1319
                                 (gchar*)gconf_current_locale(),
 
1320
                                 &keys, &values, &is_defaults, &is_writables,
 
1321
                                 &ev);
 
1322
    }
 
1323
 
 
1324
  if (gconf_server_broken(&ev))
 
1325
    {
 
1326
      if (tries < MAX_RETRIES)
 
1327
        {
 
1328
          ++tries;
 
1329
          CORBA_exception_free(&ev);
 
1330
          gconf_engine_detach (conf);
 
1331
          goto RETRY;
 
1332
        }
 
1333
    }
 
1334
  
 
1335
  if (gconf_handle_corba_exception(&ev, err))
 
1336
    return NULL;
 
1337
  
 
1338
  if (keys->_length != values->_length)
 
1339
    {
 
1340
      g_warning("Received unmatched key/value sequences in %s",
 
1341
                G_GNUC_FUNCTION);
 
1342
      return NULL;
 
1343
    }
 
1344
 
 
1345
  i = 0;
 
1346
  while (i < keys->_length)
 
1347
    {
 
1348
      GConfEntry* pair;
 
1349
 
 
1350
      pair = 
 
1351
        gconf_entry_new_nocopy(gconf_concat_dir_and_key (dir, keys->_buffer[i]),
 
1352
                               gconf_value_from_corba_value(&(values->_buffer[i])));
 
1353
 
 
1354
      /* note, there's an accesor function for setting this that we are
 
1355
         cheating and not using */
 
1356
      pair->is_default = is_defaults->_buffer[i];
 
1357
      pair->is_writable = is_writables->_buffer[i];
 
1358
      if (schema_names)
 
1359
        {
 
1360
          /* empty string means no schema name */
 
1361
          if (*(schema_names->_buffer[i]) != '\0')
 
1362
            pair->schema_name = g_strdup (schema_names->_buffer[i]);
 
1363
        }
 
1364
      
 
1365
      pairs = g_slist_prepend(pairs, pair);
 
1366
      
 
1367
      ++i;
 
1368
    }
 
1369
  
 
1370
  CORBA_free(keys);
 
1371
  CORBA_free(values);
 
1372
  CORBA_free(is_defaults);
 
1373
  CORBA_free(is_writables);
 
1374
  if (schema_names)
 
1375
    CORBA_free (schema_names);
 
1376
  
 
1377
  return pairs;
 
1378
}
 
1379
 
 
1380
GSList*      
 
1381
gconf_engine_all_dirs(GConfEngine* conf, const gchar* dir, GError** err)
 
1382
{
 
1383
  GSList* subdirs = NULL;
 
1384
  ConfigDatabase_KeyList* keys;
 
1385
  CORBA_Environment ev;
 
1386
  ConfigDatabase db;
 
1387
  guint i;
 
1388
  gint tries = 0;
 
1389
 
 
1390
  g_return_val_if_fail(conf != NULL, NULL);
 
1391
  g_return_val_if_fail(dir != NULL, NULL);
 
1392
  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
 
1393
  
 
1394
  if (!gconf_key_check(dir, err))
 
1395
    return NULL;
 
1396
 
 
1397
  if (gconf_engine_is_local(conf))
 
1398
    {
 
1399
      GError* error = NULL;
 
1400
      GSList* retval;
 
1401
      
 
1402
      retval = gconf_sources_all_dirs(conf->local_sources,
 
1403
                                      dir,
 
1404
                                      &error);
 
1405
      
 
1406
      if (error != NULL)
 
1407
        {
 
1408
          if (err)
 
1409
            *err = error;
 
1410
          else
 
1411
            {
 
1412
              g_error_free(error);
 
1413
            }
 
1414
 
 
1415
          g_assert(retval == NULL);
 
1416
          
 
1417
          return NULL;
 
1418
        }
 
1419
 
 
1420
      qualify_entries (retval, dir);
 
1421
      
 
1422
      return retval;
 
1423
    }
 
1424
 
 
1425
  g_assert(!gconf_engine_is_local(conf));
 
1426
  
 
1427
  CORBA_exception_init(&ev);
 
1428
  
 
1429
 RETRY:
 
1430
  
 
1431
  db = gconf_engine_get_database (conf, TRUE, err);
 
1432
 
 
1433
  if (db == CORBA_OBJECT_NIL)
 
1434
    {
 
1435
      g_return_val_if_fail(((err == NULL) || (*err && ((*err)->code == GCONF_ERROR_NO_SERVER))), NULL);
 
1436
 
 
1437
      return NULL;
 
1438
    }
 
1439
  
 
1440
  ConfigDatabase_all_dirs(db,
 
1441
                          (gchar*)dir, 
 
1442
                          &keys,
 
1443
                          &ev);
 
1444
 
 
1445
  if (gconf_server_broken(&ev))
 
1446
    {
 
1447
      if (tries < MAX_RETRIES)
 
1448
        {
 
1449
          ++tries;
 
1450
          CORBA_exception_free(&ev);
 
1451
          gconf_engine_detach (conf);
 
1452
          goto RETRY;
 
1453
        }
 
1454
    }
 
1455
 
 
1456
  if (gconf_handle_corba_exception(&ev, err))
 
1457
    return NULL;
 
1458
  
 
1459
  i = 0;
 
1460
  while (i < keys->_length)
 
1461
    {
 
1462
      gchar* s;
 
1463
 
 
1464
      s = gconf_concat_dir_and_key (dir, keys->_buffer[i]);
 
1465
      
 
1466
      subdirs = g_slist_prepend(subdirs, s);
 
1467
      
 
1468
      ++i;
 
1469
    }
 
1470
  
 
1471
  CORBA_free(keys);
 
1472
 
 
1473
  return subdirs;
 
1474
}
 
1475
 
 
1476
/* annoyingly, this is REQUIRED for local sources */
 
1477
void 
 
1478
gconf_engine_suggest_sync(GConfEngine* conf, GError** err)
 
1479
{
 
1480
  CORBA_Environment ev;
 
1481
  ConfigDatabase db;
 
1482
  gint tries = 0;
 
1483
 
 
1484
  g_return_if_fail(conf != NULL);
 
1485
  g_return_if_fail(err == NULL || *err == NULL);
 
1486
 
 
1487
  if (gconf_engine_is_local(conf))
 
1488
    {
 
1489
      GError* error = NULL;
 
1490
      
 
1491
      gconf_sources_sync_all(conf->local_sources,
 
1492
                             &error);
 
1493
      
 
1494
      if (error != NULL)
 
1495
        {
 
1496
          if (err)
 
1497
            *err = error;
 
1498
          else
 
1499
            {
 
1500
              g_error_free(error);
 
1501
            }
 
1502
          return;
 
1503
        }
 
1504
      
 
1505
      return;
 
1506
    }
 
1507
 
 
1508
  g_assert(!gconf_engine_is_local(conf));
 
1509
  
 
1510
  CORBA_exception_init(&ev);
 
1511
 
 
1512
 RETRY:
 
1513
  
 
1514
  db = gconf_engine_get_database (conf, TRUE, err);
 
1515
 
 
1516
  if (db == CORBA_OBJECT_NIL)
 
1517
    {
 
1518
      g_return_if_fail(err == NULL || *err != NULL);
 
1519
 
 
1520
      return;
 
1521
    }
 
1522
 
 
1523
  ConfigDatabase_sync(db, &ev);
 
1524
 
 
1525
  if (gconf_server_broken(&ev))
 
1526
    {
 
1527
      if (tries < MAX_RETRIES)
 
1528
        {
 
1529
          ++tries;
 
1530
          CORBA_exception_free(&ev);
 
1531
          gconf_engine_detach (conf);
 
1532
          goto RETRY;
 
1533
        }
 
1534
    }
 
1535
  
 
1536
  if (gconf_handle_corba_exception(&ev, err))  
 
1537
    ; /* nothing additional */
 
1538
}
 
1539
 
 
1540
void 
 
1541
gconf_clear_cache(GConfEngine* conf, GError** err)
 
1542
{
 
1543
  CORBA_Environment ev;
 
1544
  ConfigDatabase db;
 
1545
  gint tries = 0;
 
1546
 
 
1547
  g_return_if_fail(conf != NULL);
 
1548
  g_return_if_fail(err == NULL || *err == NULL);
 
1549
 
 
1550
  if (gconf_engine_is_local(conf))
 
1551
    {
 
1552
      GError* error = NULL;
 
1553
      
 
1554
      gconf_sources_clear_cache(conf->local_sources);
 
1555
      
 
1556
      if (error != NULL)
 
1557
        {
 
1558
          if (err)
 
1559
            *err = error;
 
1560
          else
 
1561
            {
 
1562
              g_error_free(error);
 
1563
            }
 
1564
          return;
 
1565
        }
 
1566
      
 
1567
      return;
 
1568
    }
 
1569
 
 
1570
  g_assert(!gconf_engine_is_local(conf));
 
1571
  
 
1572
  CORBA_exception_init(&ev);
 
1573
 
 
1574
 RETRY:
 
1575
  
 
1576
  db = gconf_engine_get_database (conf, TRUE, err);
 
1577
 
 
1578
  if (db == CORBA_OBJECT_NIL)
 
1579
    {
 
1580
      g_return_if_fail(err == NULL || *err != NULL);
 
1581
 
 
1582
      return;
 
1583
    }
 
1584
 
 
1585
  ConfigDatabase_clear_cache(db, &ev);
 
1586
 
 
1587
  if (gconf_server_broken(&ev))
 
1588
    {
 
1589
      if (tries < MAX_RETRIES)
 
1590
        {
 
1591
          ++tries;
 
1592
          CORBA_exception_free(&ev);
 
1593
          gconf_engine_detach (conf);
 
1594
          goto RETRY;
 
1595
        }
 
1596
    }
 
1597
  
 
1598
  if (gconf_handle_corba_exception(&ev, err))  
 
1599
    ; /* nothing additional */
 
1600
}
 
1601
 
 
1602
void 
 
1603
gconf_synchronous_sync(GConfEngine* conf, GError** err)
 
1604
{
 
1605
  CORBA_Environment ev;
 
1606
  ConfigDatabase db;
 
1607
  gint tries = 0;
 
1608
 
 
1609
  g_return_if_fail(conf != NULL);
 
1610
  g_return_if_fail(err == NULL || *err == NULL);
 
1611
 
 
1612
  if (gconf_engine_is_local(conf))
 
1613
    {
 
1614
      GError* error = NULL;
 
1615
      
 
1616
      gconf_sources_sync_all(conf->local_sources, &error);
 
1617
      
 
1618
      if (error != NULL)
 
1619
        {
 
1620
          if (err)
 
1621
            *err = error;
 
1622
          else
 
1623
            {
 
1624
              g_error_free(error);
 
1625
            }
 
1626
          return;
 
1627
        }
 
1628
      
 
1629
      return;
 
1630
    }
 
1631
 
 
1632
  g_assert(!gconf_engine_is_local(conf));
 
1633
  
 
1634
  CORBA_exception_init(&ev);
 
1635
 
 
1636
 RETRY:
 
1637
  
 
1638
  db = gconf_engine_get_database (conf, TRUE, err);
 
1639
 
 
1640
  if (db == CORBA_OBJECT_NIL)
 
1641
    {
 
1642
      g_return_if_fail(err == NULL || *err != NULL);
 
1643
 
 
1644
      return;
 
1645
    }
 
1646
 
 
1647
  ConfigDatabase_synchronous_sync(db, &ev);
 
1648
 
 
1649
  if (gconf_server_broken(&ev))
 
1650
    {
 
1651
      if (tries < MAX_RETRIES)
 
1652
        {
 
1653
          ++tries;
 
1654
          CORBA_exception_free(&ev);
 
1655
          gconf_engine_detach (conf);
 
1656
          goto RETRY;
 
1657
        }
 
1658
    }
 
1659
  
 
1660
  if (gconf_handle_corba_exception(&ev, err))  
 
1661
    ; /* nothing additional */
 
1662
}
 
1663
 
 
1664
gboolean
 
1665
gconf_engine_dir_exists(GConfEngine *conf, const gchar *dir, GError** err)
 
1666
{
 
1667
  CORBA_Environment ev;
 
1668
  ConfigDatabase db;
 
1669
  CORBA_boolean server_ret;
 
1670
  gint tries = 0;
 
1671
 
 
1672
  g_return_val_if_fail(conf != NULL, FALSE);
 
1673
  g_return_val_if_fail(dir != NULL, FALSE);
 
1674
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
1675
  
 
1676
  if (!gconf_key_check(dir, err))
 
1677
    return FALSE;
 
1678
  
 
1679
  if (gconf_engine_is_local(conf))
 
1680
    {
 
1681
      return gconf_sources_dir_exists(conf->local_sources,
 
1682
                                      dir,
 
1683
                                      err);
 
1684
    }
 
1685
 
 
1686
  g_assert(!gconf_engine_is_local(conf));
 
1687
  
 
1688
  CORBA_exception_init(&ev);
 
1689
  
 
1690
 RETRY:
 
1691
  
 
1692
  db = gconf_engine_get_database(conf, TRUE, err);
 
1693
  
 
1694
  if (db == CORBA_OBJECT_NIL)
 
1695
    {
 
1696
      g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
 
1697
 
 
1698
      return FALSE;
 
1699
    }
 
1700
  
 
1701
  server_ret = ConfigDatabase_dir_exists(db,
 
1702
                                         (gchar*)dir,
 
1703
                                         &ev);
 
1704
  
 
1705
  if (gconf_server_broken(&ev))
 
1706
    {
 
1707
      if (tries < MAX_RETRIES)
 
1708
        {
 
1709
          ++tries;
 
1710
          CORBA_exception_free(&ev);
 
1711
          gconf_engine_detach (conf);
 
1712
          goto RETRY;
 
1713
        }
 
1714
    }
 
1715
  
 
1716
  if (gconf_handle_corba_exception(&ev, err))  
 
1717
    ; /* nothing */
 
1718
 
 
1719
  return (server_ret == CORBA_TRUE);
 
1720
}
 
1721
 
 
1722
void
 
1723
gconf_engine_remove_dir (GConfEngine* conf,
 
1724
                         const gchar* dir,
 
1725
                         GError** err)
 
1726
{
 
1727
  CORBA_Environment ev;
 
1728
  ConfigDatabase db;
 
1729
  gint tries = 0;
 
1730
 
 
1731
  g_return_if_fail(conf != NULL);
 
1732
  g_return_if_fail(dir != NULL);
 
1733
  g_return_if_fail(err == NULL || *err == NULL);
 
1734
  
 
1735
  if (!gconf_key_check(dir, err))
 
1736
    return;
 
1737
 
 
1738
  if (gconf_engine_is_local(conf))
 
1739
    {
 
1740
      gconf_sources_remove_dir(conf->local_sources, dir, err);
 
1741
      return;
 
1742
    }
 
1743
 
 
1744
  CORBA_exception_init(&ev);
 
1745
  
 
1746
 RETRY:
 
1747
  
 
1748
  db = gconf_engine_get_database (conf, TRUE, err);
 
1749
 
 
1750
  if (db == CORBA_OBJECT_NIL)
 
1751
    {
 
1752
      g_return_if_fail(err == NULL || *err != NULL);
 
1753
      return;
 
1754
    }
 
1755
  
 
1756
  ConfigDatabase_remove_dir(db, (gchar*)dir, &ev);
 
1757
 
 
1758
  if (gconf_server_broken(&ev))
 
1759
    {
 
1760
      if (tries < MAX_RETRIES)
 
1761
        {
 
1762
          ++tries;
 
1763
          CORBA_exception_free(&ev);
 
1764
          gconf_engine_detach (conf);
 
1765
          goto RETRY;
 
1766
        }
 
1767
    }
 
1768
  gconf_handle_corba_exception(&ev, err);
 
1769
  
 
1770
  return;
 
1771
}
 
1772
 
 
1773
gboolean
 
1774
gconf_engine_key_is_writable  (GConfEngine *conf,
 
1775
                               const gchar *key,
 
1776
                               GError     **err)
 
1777
{
 
1778
  gboolean is_writable = TRUE;
 
1779
  GConfValue *val;
 
1780
 
 
1781
  /* FIXME implement IDL to allow getting only writability
 
1782
   * (not that urgent since GConfClient caches this crap
 
1783
   * anyway)
 
1784
   */
 
1785
  
 
1786
  val = gconf_engine_get_full(conf, key, NULL, TRUE,
 
1787
                              NULL, &is_writable, err);
 
1788
 
 
1789
  gconf_value_free (val);
 
1790
  
 
1791
  return is_writable;
 
1792
}
 
1793
 
 
1794
/*
 
1795
 * Connection maintenance
 
1796
 */
 
1797
 
 
1798
static GConfCnxn* 
 
1799
gconf_cnxn_new(GConfEngine* conf,
 
1800
               const gchar* namespace_section,
 
1801
               CORBA_unsigned_long server_id,
 
1802
               GConfNotifyFunc func,
 
1803
               gpointer user_data)
 
1804
{
 
1805
  GConfCnxn* cnxn;
 
1806
  static guint next_id = 1;
 
1807
  
 
1808
  cnxn = g_new0(GConfCnxn, 1);
 
1809
 
 
1810
  cnxn->namespace_section = g_strdup(namespace_section);
 
1811
  cnxn->conf = conf;
 
1812
  cnxn->server_id = server_id;
 
1813
  cnxn->client_id = next_id;
 
1814
  cnxn->func = func;
 
1815
  cnxn->user_data = user_data;
 
1816
 
 
1817
  ++next_id;
 
1818
 
 
1819
  return cnxn;
 
1820
}
 
1821
 
 
1822
static void      
 
1823
gconf_cnxn_destroy(GConfCnxn* cnxn)
 
1824
{
 
1825
  g_free(cnxn->namespace_section);
 
1826
  g_free(cnxn);
 
1827
}
 
1828
 
 
1829
static void       
 
1830
gconf_cnxn_notify(GConfCnxn* cnxn,
 
1831
                  GConfEntry *entry)
 
1832
{
 
1833
  (*cnxn->func)(cnxn->conf, cnxn->client_id,
 
1834
                entry,
 
1835
                cnxn->user_data);
 
1836
}
 
1837
 
 
1838
/*
 
1839
 *  CORBA glue
 
1840
 */
 
1841
 
 
1842
static ConfigServer   server = CORBA_OBJECT_NIL;
 
1843
 
 
1844
/* errors in here should be GCONF_ERROR_NO_SERVER */
 
1845
static ConfigServer
 
1846
try_to_contact_server (gboolean start_if_not_found, GError** err)
 
1847
{
 
1848
  CORBA_Environment ev;
 
1849
 
 
1850
  /* Try to launch server */      
 
1851
  server = gconf_activate_server (start_if_not_found,
 
1852
                                  err);
 
1853
  
 
1854
  /* Try to ping server, by adding ourselves as a client */
 
1855
  CORBA_exception_init (&ev);
 
1856
  
 
1857
  if (!CORBA_Object_is_nil (server, &ev))
 
1858
    {
 
1859
      ConfigServer_add_client (server,
 
1860
                               gconf_get_config_listener (),
 
1861
                               &ev);
 
1862
      
 
1863
      if (ev._major != CORBA_NO_EXCEPTION)
 
1864
        {
 
1865
          server = CORBA_OBJECT_NIL;
 
1866
          if (err)
 
1867
            *err = gconf_error_new(GCONF_ERROR_NO_SERVER,
 
1868
                                   _("Adding client to server's list failed, CORBA error: %s"),
 
1869
                                   CORBA_exception_id(&ev));
 
1870
 
 
1871
          CORBA_exception_free(&ev);
 
1872
        }
 
1873
    }
 
1874
 
 
1875
#ifdef GCONF_ENABLE_DEBUG      
 
1876
  if (server == CORBA_OBJECT_NIL && start_if_not_found)
 
1877
    {
 
1878
      g_return_val_if_fail(err == NULL || *err != NULL, server);
 
1879
    }
 
1880
#endif
 
1881
  
 
1882
  return server;
 
1883
}
 
1884
 
 
1885
/* All errors set in here should be GCONF_ERROR_NO_SERVER; should
 
1886
   only set errors if start_if_not_found is TRUE */
 
1887
static ConfigServer
 
1888
gconf_get_config_server(gboolean start_if_not_found, GError** err)
 
1889
{
 
1890
  g_return_val_if_fail(err == NULL || *err == NULL, server);
 
1891
  
 
1892
  if (server != CORBA_OBJECT_NIL)
 
1893
    return server;
 
1894
 
 
1895
  server = try_to_contact_server(start_if_not_found, err);
 
1896
  
 
1897
  return server; /* return what we have, NIL or not */
 
1898
}
 
1899
 
 
1900
static void
 
1901
gconf_detach_config_server(void)
 
1902
{  
 
1903
  if (server != CORBA_OBJECT_NIL)
 
1904
    {
 
1905
      CORBA_Environment ev;
 
1906
      
 
1907
      CORBA_exception_init(&ev);
 
1908
 
 
1909
      CORBA_Object_release(server, &ev);
 
1910
 
 
1911
      if (ev._major != CORBA_NO_EXCEPTION)
 
1912
        {
 
1913
          g_warning("Exception releasing gconfd server object: %s",
 
1914
                    CORBA_exception_id(&ev));
 
1915
          CORBA_exception_free(&ev);
 
1916
        }
 
1917
 
 
1918
      server = CORBA_OBJECT_NIL;
 
1919
    }
 
1920
}
 
1921
 
 
1922
ConfigListener listener = CORBA_OBJECT_NIL;
 
1923
static void notify                  (PortableServer_Servant     servant,
 
1924
                                     ConfigDatabase             db,
 
1925
                                     CORBA_unsigned_long        cnxn,
 
1926
                                     const CORBA_char          *key,
 
1927
                                     const ConfigValue         *value,
 
1928
                                     CORBA_boolean              is_default,
 
1929
                                     CORBA_boolean              is_writable,
 
1930
                                     CORBA_Environment         *ev);
 
1931
static void ping                    (PortableServer_Servant     _servant,
 
1932
                                     CORBA_Environment         *ev);
 
1933
static void update_listener         (PortableServer_Servant     _servant,
 
1934
                                     ConfigDatabase             db,
 
1935
                                     const CORBA_char          *address,
 
1936
                                     const CORBA_unsigned_long  old_cnxn,
 
1937
                                     const CORBA_char          *key,
 
1938
                                     const CORBA_unsigned_long  new_cnxn,
 
1939
                                     CORBA_Environment         *ev);
 
1940
static void invalidate_cached_values(PortableServer_Servant     _servant,
 
1941
                                     ConfigDatabase             database,
 
1942
                                     const ConfigListener_KeyList *keys,
 
1943
                                     CORBA_Environment         *ev);
 
1944
static void drop_all_caches         (PortableServer_Servant     _servant,
 
1945
                                     CORBA_Environment         *ev);
 
1946
 
 
1947
 
 
1948
 
 
1949
static PortableServer_ServantBase__epv base_epv = {
 
1950
  NULL,
 
1951
  NULL,
 
1952
  NULL
 
1953
};
 
1954
 
 
1955
static POA_ConfigListener__epv listener_epv = {
 
1956
  NULL,
 
1957
  notify,
 
1958
  ping,
 
1959
  update_listener,
 
1960
  invalidate_cached_values,
 
1961
  drop_all_caches
 
1962
};
 
1963
 
 
1964
static POA_ConfigListener__vepv poa_listener_vepv = { &base_epv, &listener_epv };
 
1965
static POA_ConfigListener poa_listener_servant = { NULL, &poa_listener_vepv };
 
1966
 
 
1967
static void 
 
1968
notify(PortableServer_Servant servant,
 
1969
       ConfigDatabase db,
 
1970
       CORBA_unsigned_long server_id,
 
1971
       const CORBA_char* key,
 
1972
       const ConfigValue* value,
 
1973
       CORBA_boolean is_default,
 
1974
       CORBA_boolean is_writable,
 
1975
       CORBA_Environment *ev)
 
1976
{
 
1977
  GConfCnxn* cnxn;
 
1978
  GConfValue* gvalue;
 
1979
  GConfEngine* conf;
 
1980
  GConfEntry* entry;
 
1981
  
 
1982
  conf = lookup_engine_by_database (db);
 
1983
 
 
1984
  if (conf == NULL)
 
1985
    {
 
1986
#ifdef GCONF_ENABLE_DEBUG
 
1987
      g_warning ("Client received notify for unknown database object");
 
1988
#endif
 
1989
      return;
 
1990
    }
 
1991
  
 
1992
  cnxn = ctable_lookup_by_server_id(conf->ctable, server_id);
 
1993
  
 
1994
  if (cnxn == NULL)
 
1995
    {
 
1996
#ifdef GCONF_ENABLE_DEBUG
 
1997
      g_warning("Client received notify for unknown connection ID %u",
 
1998
                (guint)server_id);
 
1999
#endif
 
2000
      return;
 
2001
    }
 
2002
 
 
2003
  gvalue = gconf_value_from_corba_value(value);
 
2004
 
 
2005
  entry = gconf_entry_new_nocopy (g_strdup (key),
 
2006
                                  gvalue);
 
2007
  entry->is_default = is_default;
 
2008
  entry->is_writable = is_writable;
 
2009
  
 
2010
  gconf_cnxn_notify(cnxn, entry);
 
2011
 
 
2012
  gconf_entry_free (entry);
 
2013
}
 
2014
 
 
2015
static void
 
2016
ping (PortableServer_Servant _servant, CORBA_Environment * ev)
 
2017
{
 
2018
  /* This one is easy :-) */
 
2019
  
 
2020
  return;
 
2021
}
 
2022
 
 
2023
static void
 
2024
update_listener (PortableServer_Servant _servant,
 
2025
                 ConfigDatabase             db,
 
2026
                 const CORBA_char          *address,
 
2027
                 const CORBA_unsigned_long  old_cnxn_id,
 
2028
                 const CORBA_char          *key,
 
2029
                 const CORBA_unsigned_long  new_cnxn_id,
 
2030
                 CORBA_Environment         *ev_ignored)
 
2031
{
 
2032
  GConfCnxn* cnxn;
 
2033
  GConfEngine* conf;
 
2034
  CORBA_Environment ev;
 
2035
  
 
2036
  conf = lookup_engine_by_database (db);
 
2037
 
 
2038
  /* See if we have an old engine with a now-invalid object
 
2039
     reference, and update its reference. */
 
2040
  if (conf == NULL)
 
2041
    {
 
2042
      CORBA_exception_init (&ev);
 
2043
      
 
2044
      if (strcmp (address, "def") == 0)
 
2045
        conf = default_engine;
 
2046
      else
 
2047
        conf = lookup_engine (address);
 
2048
 
 
2049
      if (conf)
 
2050
        gconf_engine_set_database (conf,
 
2051
                                   CORBA_Object_duplicate (db, &ev));
 
2052
    }
 
2053
  
 
2054
  if (conf == NULL)
 
2055
    {
 
2056
#ifdef GCONF_ENABLE_DEBUG
 
2057
      g_warning("Client received listener update for unknown database "
 
2058
                "(this is not a big deal, this warning only appears if GConf is compiled with debugging)");
 
2059
#endif
 
2060
      return;
 
2061
    }
 
2062
  
 
2063
  cnxn = ctable_lookup_by_server_id (conf->ctable, old_cnxn_id);
 
2064
  
 
2065
  if (cnxn == NULL)
 
2066
    {
 
2067
#ifdef GCONF_ENABLE_DEBUG
 
2068
      g_warning("Client received listener update for unknown listener ID %u "
 
2069
                "(this is not a big deal, this warning only appears if GConf is compiled with debugging)",
 
2070
                (guint)old_cnxn_id);
 
2071
#endif
 
2072
      return;
 
2073
    }
 
2074
  
 
2075
  ctable_reinstall (conf->ctable, cnxn, old_cnxn_id, new_cnxn_id);
 
2076
}
 
2077
 
 
2078
static void
 
2079
invalidate_cached_values (PortableServer_Servant     _servant,
 
2080
                          ConfigDatabase             database,
 
2081
                          const ConfigListener_KeyList *keys,
 
2082
                          CORBA_Environment         *ev)
 
2083
{
 
2084
#if 0
 
2085
  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());
 
2086
#endif
 
2087
}
 
2088
 
 
2089
static void
 
2090
drop_all_caches (PortableServer_Servant     _servant,
 
2091
                 CORBA_Environment         *ev)
 
2092
{
 
2093
#if 0
 
2094
  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());
 
2095
#endif
 
2096
}
 
2097
 
 
2098
static ConfigListener 
 
2099
gconf_get_config_listener(void)
 
2100
{
 
2101
  g_return_val_if_fail (listener != CORBA_OBJECT_NIL, CORBA_OBJECT_NIL);
 
2102
  return listener;
 
2103
}
 
2104
 
 
2105
static gboolean have_initted = FALSE;
 
2106
 
 
2107
void
 
2108
gconf_preinit(gpointer app, gpointer mod_info)
 
2109
{
 
2110
}
 
2111
 
 
2112
void
 
2113
gconf_postinit(gpointer app, gpointer mod_info)
 
2114
{
 
2115
  if (listener == CORBA_OBJECT_NIL)
 
2116
    {
 
2117
      CORBA_Environment ev;
 
2118
      PortableServer_ObjectId* objid;
 
2119
      PortableServer_POA poa;
 
2120
 
 
2121
      CORBA_exception_init(&ev);
 
2122
      POA_ConfigListener__init(&poa_listener_servant, &ev);
 
2123
      
 
2124
      g_assert (ev._major == CORBA_NO_EXCEPTION);
 
2125
 
 
2126
      poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(gconf_orb_get(), "RootPOA", &ev);
 
2127
 
 
2128
      g_assert (ev._major == CORBA_NO_EXCEPTION);
 
2129
 
 
2130
      PortableServer_POAManager_activate(PortableServer_POA__get_the_POAManager(poa, &ev), &ev);
 
2131
 
 
2132
      g_assert (ev._major == CORBA_NO_EXCEPTION);
 
2133
 
 
2134
      objid = PortableServer_POA_activate_object(poa, &poa_listener_servant, &ev);
 
2135
 
 
2136
      g_assert (ev._major == CORBA_NO_EXCEPTION);
 
2137
      
 
2138
      listener = PortableServer_POA_servant_to_reference(poa,
 
2139
                                                         &poa_listener_servant,
 
2140
                                                         &ev);
 
2141
 
 
2142
      g_assert (listener != CORBA_OBJECT_NIL);
 
2143
      g_assert (ev._major == CORBA_NO_EXCEPTION);
 
2144
    }
 
2145
 
 
2146
  have_initted = TRUE;
 
2147
}
 
2148
 
 
2149
const char gconf_version[] = VERSION;
 
2150
 
 
2151
struct poptOption gconf_options[] = {
 
2152
  {NULL}
 
2153
};
 
2154
 
 
2155
gboolean     
 
2156
gconf_init           (int argc, char **argv, GError** err)
 
2157
{
 
2158
  CORBA_ORB orb = CORBA_OBJECT_NIL;
 
2159
 
 
2160
  if (have_initted)
 
2161
    {
 
2162
      g_warning("Attempt to init GConf a second time");
 
2163
      return FALSE;
 
2164
    }
 
2165
 
 
2166
  gconf_preinit(NULL, NULL);
 
2167
 
 
2168
  if (!oaf_is_initialized())
 
2169
    {
 
2170
      orb = oaf_init(argc, argv);
 
2171
    }
 
2172
  else
 
2173
    {
 
2174
      orb = gconf_orb_get();
 
2175
    }
 
2176
      
 
2177
  gconf_postinit(NULL, NULL);
 
2178
 
 
2179
  if(!have_initted)
 
2180
    {
 
2181
      if (err == NULL)
 
2182
        {
 
2183
          fprintf(stderr, _("Failed to init GConf, exiting\n"));
 
2184
          exit (1);
 
2185
        }
 
2186
      return FALSE;
 
2187
    }
 
2188
  
 
2189
  return TRUE;
 
2190
}
 
2191
 
 
2192
gboolean
 
2193
gconf_is_initialized (void)
 
2194
{
 
2195
  return have_initted;
 
2196
}
 
2197
 
 
2198
/* 
 
2199
 * Ampersand and <> are not allowed due to the XML backend; shell
 
2200
 * special characters aren't allowed; others are just in case we need
 
2201
 * some magic characters someday.  hyphen, underscore, period, colon
 
2202
 * are allowed as separators. % disallowed to avoid printf confusion.
 
2203
 */
 
2204
 
 
2205
/* Key/dir validity is exactly the same, except that '/' must be a dir, 
 
2206
   but we are sort of ignoring that for now. */
 
2207
 
 
2208
static const gchar invalid_chars[] = " \t\r\n\"$&<>,+=#!()'|{}[]?~`;%\\";
 
2209
 
 
2210
gboolean     
 
2211
gconf_valid_key      (const gchar* key, gchar** why_invalid)
 
2212
{
 
2213
  const gchar* s = key;
 
2214
  gboolean just_saw_slash = FALSE;
 
2215
 
 
2216
  /* Key must start with the root */
 
2217
  if (*key != '/')
 
2218
    {
 
2219
      if (why_invalid != NULL)
 
2220
        *why_invalid = g_strdup(_("Must begin with a slash (/)"));
 
2221
      return FALSE;
 
2222
    }
 
2223
  
 
2224
  /* Root key is a valid dir */
 
2225
  if (*key == '/' && key[1] == '\0')
 
2226
    return TRUE;
 
2227
 
 
2228
  while (*s)
 
2229
    {
 
2230
      if (just_saw_slash)
 
2231
        {
 
2232
          /* Can't have two slashes in a row, since it would mean
 
2233
           * an empty spot.
 
2234
           * Can't have a period right after a slash,
 
2235
           * because it would be a pain for filesystem-based backends.
 
2236
           */
 
2237
          if (*s == '/' || *s == '.')
 
2238
            {
 
2239
              if (why_invalid != NULL)
 
2240
                {
 
2241
                  if (*s == '/')
 
2242
                    *why_invalid = g_strdup(_("Can't have two slashes (/) in a row"));
 
2243
                  else
 
2244
                    *why_invalid = g_strdup(_("Can't have a period (.) right after a slash (/)"));
 
2245
                }
 
2246
              return FALSE;
 
2247
            }
 
2248
        }
 
2249
 
 
2250
      if (*s == '/')
 
2251
        {
 
2252
          just_saw_slash = TRUE;
 
2253
        }
 
2254
      else
 
2255
        {
 
2256
          const gchar* inv = invalid_chars;
 
2257
 
 
2258
          just_saw_slash = FALSE;
 
2259
 
 
2260
          while (*inv)
 
2261
            {
 
2262
              if (*inv == *s)
 
2263
                {
 
2264
                  if (why_invalid != NULL)
 
2265
                    *why_invalid = g_strdup_printf(_("`%c' is an invalid character in key/directory names"), *s);
 
2266
                  return FALSE;
 
2267
                }
 
2268
              ++inv;
 
2269
            }
 
2270
        }
 
2271
 
 
2272
      ++s;
 
2273
    }
 
2274
 
 
2275
  /* Can't end with slash */
 
2276
  if (just_saw_slash)
 
2277
    {
 
2278
      if (why_invalid != NULL)
 
2279
        *why_invalid = g_strdup(_("Key/directory may not end with a slash (/)"));
 
2280
      return FALSE;
 
2281
    }
 
2282
  else
 
2283
    return TRUE;
 
2284
}
 
2285
 
 
2286
gboolean
 
2287
gconf_key_is_below   (const gchar* above, const gchar* below)
 
2288
{
 
2289
  int len = strlen(above);
 
2290
  if (strncmp(below, above, len) == 0)
 
2291
    {
 
2292
      /* only if this is a complete key component,
 
2293
       * so that /foo is not above /foofoo/bar */
 
2294
      if (below[len] == '\0' || below[len] == '/')
 
2295
        return TRUE;
 
2296
      else
 
2297
        return FALSE;
 
2298
    }
 
2299
  else
 
2300
    return FALSE;
 
2301
}
 
2302
 
 
2303
gchar*
 
2304
gconf_unique_key (void)
 
2305
{
 
2306
  /* This function is hardly cryptographically random but should be
 
2307
     "good enough" */
 
2308
  
 
2309
  static guint serial = 0;
 
2310
  gchar* key;
 
2311
  guint t, ut, p, u, r;
 
2312
  struct timeval tv;
 
2313
  
 
2314
  gettimeofday(&tv, NULL);
 
2315
  
 
2316
  t = tv.tv_sec;
 
2317
  ut = tv.tv_usec;
 
2318
 
 
2319
  p = getpid();
 
2320
  
 
2321
  u = getuid();
 
2322
 
 
2323
  /* don't bother to seed; if it's based on the time or any other
 
2324
     changing info we can get, we may as well just use that changing
 
2325
     info. since we don't seed we'll at least get a different number
 
2326
     on every call to this function in the same executable. */
 
2327
  r = rand();
 
2328
  
 
2329
  /* The letters may increase uniqueness by preventing "melds"
 
2330
     i.e. 01t01k01 and 0101t0k1 are not the same */
 
2331
  key = g_strdup_printf("%ut%uut%uu%up%ur%uk%u",
 
2332
                        /* Duplicate keys must be generated
 
2333
                           by two different program instances */
 
2334
                        serial,
 
2335
                        /* Duplicate keys must be generated
 
2336
                           in the same microsecond */
 
2337
                        t,
 
2338
                        ut,
 
2339
                        /* Duplicate keys must be generated by
 
2340
                           the same user */
 
2341
                        u,
 
2342
                        /* Duplicate keys must be generated by
 
2343
                           two programs that got the same PID */
 
2344
                        p,
 
2345
                        /* Duplicate keys must be generated with the
 
2346
                           same random seed and the same index into
 
2347
                           the series of pseudorandom values */
 
2348
                        r,
 
2349
                        /* Duplicate keys must result from running
 
2350
                           this function at the same stack location */
 
2351
                        GPOINTER_TO_UINT(&key));
 
2352
 
 
2353
  ++serial;
 
2354
  
 
2355
  return key;
 
2356
}
 
2357
 
 
2358
/*
 
2359
 * Table of connections 
 
2360
 */ 
 
2361
 
 
2362
static gint
 
2363
corba_unsigned_long_equal (gconstpointer v1,
 
2364
                           gconstpointer v2)
 
2365
{
 
2366
  return *((const CORBA_unsigned_long*) v1) == *((const CORBA_unsigned_long*) v2);
 
2367
}
 
2368
 
 
2369
static guint
 
2370
corba_unsigned_long_hash (gconstpointer v)
 
2371
{
 
2372
  /* for our purposes we can just assume 32 bits are significant */
 
2373
  return (guint)(*(const CORBA_unsigned_long*) v);
 
2374
}
 
2375
 
 
2376
static CnxnTable* 
 
2377
ctable_new(void)
 
2378
{
 
2379
  CnxnTable* ct;
 
2380
 
 
2381
  ct = g_new(CnxnTable, 1);
 
2382
 
 
2383
  ct->server_ids = g_hash_table_new (corba_unsigned_long_hash,
 
2384
                                     corba_unsigned_long_equal);  
 
2385
  ct->client_ids = g_hash_table_new (g_int_hash, g_int_equal);
 
2386
  
 
2387
  return ct;
 
2388
}
 
2389
 
 
2390
static void
 
2391
ctable_destroy(CnxnTable* ct)
 
2392
{
 
2393
  g_hash_table_destroy (ct->server_ids);
 
2394
  g_hash_table_destroy (ct->client_ids);
 
2395
  g_free(ct);
 
2396
}
 
2397
 
 
2398
static void       
 
2399
ctable_insert(CnxnTable* ct, GConfCnxn* cnxn)
 
2400
{
 
2401
  g_hash_table_insert (ct->server_ids, &cnxn->server_id, cnxn);
 
2402
  g_hash_table_insert (ct->client_ids, &cnxn->client_id, cnxn);
 
2403
}
 
2404
 
 
2405
static void       
 
2406
ctable_remove(CnxnTable* ct, GConfCnxn* cnxn)
 
2407
{
 
2408
  g_hash_table_remove (ct->server_ids, &cnxn->server_id);
 
2409
  g_hash_table_remove (ct->client_ids, &cnxn->client_id);
 
2410
}
 
2411
 
 
2412
struct RemoveData {
 
2413
  GSList* removed;
 
2414
  GConfEngine* conf;
 
2415
  gboolean save_removed;
 
2416
};
 
2417
 
 
2418
static gboolean
 
2419
remove_by_conf(gpointer key, gpointer value, gpointer user_data)
 
2420
{
 
2421
  struct RemoveData* rd = user_data;
 
2422
  GConfCnxn* cnxn = value;
 
2423
  
 
2424
  if (cnxn->conf == rd->conf)
 
2425
    {
 
2426
      if (rd->save_removed)
 
2427
        rd->removed = g_slist_prepend(rd->removed, cnxn);
 
2428
 
 
2429
      return TRUE;  /* remove this one */
 
2430
    }
 
2431
  else 
 
2432
    return FALSE; /* or not */
 
2433
}
 
2434
 
 
2435
/* FIXME this no longer makes any sense, because a CnxnTable
 
2436
   belongs to a GConfEngine and all entries have the same
 
2437
   GConfEngine.
 
2438
*/
 
2439
 
 
2440
/* We return a list of the removed GConfCnxn */
 
2441
static GSList*      
 
2442
ctable_remove_by_conf(CnxnTable* ct, GConfEngine* conf)
 
2443
{
 
2444
  guint client_ids_removed;
 
2445
  guint server_ids_removed;
 
2446
  struct RemoveData rd;
 
2447
 
 
2448
  rd.removed = NULL;
 
2449
  rd.conf = conf;
 
2450
  rd.save_removed = TRUE;
 
2451
  
 
2452
  client_ids_removed = g_hash_table_foreach_remove (ct->server_ids,
 
2453
                                                    remove_by_conf,
 
2454
                                                    &rd);
 
2455
 
 
2456
  rd.save_removed = FALSE;
 
2457
 
 
2458
  server_ids_removed = g_hash_table_foreach_remove(ct->client_ids,
 
2459
                                                   remove_by_conf,
 
2460
                                                   &rd);
 
2461
 
 
2462
  g_assert(client_ids_removed == server_ids_removed);
 
2463
  g_assert(client_ids_removed == g_slist_length(rd.removed));
 
2464
 
 
2465
  return rd.removed;
 
2466
}
 
2467
 
 
2468
static GConfCnxn* 
 
2469
ctable_lookup_by_client_id(CnxnTable* ct, guint client_id)
 
2470
{
 
2471
  return g_hash_table_lookup(ct->client_ids, &client_id);
 
2472
}
 
2473
 
 
2474
static GConfCnxn* 
 
2475
ctable_lookup_by_server_id(CnxnTable* ct, CORBA_unsigned_long server_id)
 
2476
{
 
2477
  return g_hash_table_lookup (ct->server_ids, &server_id);
 
2478
}
 
2479
 
 
2480
static void
 
2481
ctable_reinstall (CnxnTable* ct,
 
2482
                  GConfCnxn *cnxn,
 
2483
                  guint old_server_id,
 
2484
                  guint new_server_id)
 
2485
{
 
2486
  g_return_if_fail (cnxn->server_id == old_server_id);
 
2487
 
 
2488
  g_hash_table_remove (ct->server_ids, &old_server_id);
 
2489
  
 
2490
  cnxn->server_id = new_server_id;
 
2491
 
 
2492
  g_hash_table_insert (ct->server_ids, &cnxn->server_id, cnxn);
 
2493
}
 
2494
 
 
2495
/*
 
2496
 * Daemon control
 
2497
 */
 
2498
 
 
2499
void          
 
2500
gconf_shutdown_daemon(GError** err)
 
2501
{
 
2502
  CORBA_Environment ev;
 
2503
  ConfigServer cs;
 
2504
 
 
2505
  cs = gconf_get_config_server(FALSE, err); /* Don't want to spawn it if it's already down */
 
2506
 
 
2507
  if (cs == CORBA_OBJECT_NIL)
 
2508
    {
 
2509
 
 
2510
      return;
 
2511
    }
 
2512
 
 
2513
  CORBA_exception_init(&ev);
 
2514
 
 
2515
  ConfigServer_shutdown(cs, &ev);
 
2516
 
 
2517
  if (ev._major != CORBA_NO_EXCEPTION)
 
2518
    {
 
2519
      if (err)
 
2520
        *err = gconf_error_new(GCONF_ERROR_FAILED, _("Failure shutting down config server: %s"),
 
2521
                               CORBA_exception_id(&ev));
 
2522
 
 
2523
      CORBA_exception_free(&ev);
 
2524
    }
 
2525
}
 
2526
 
 
2527
gboolean
 
2528
gconf_ping_daemon(void)
 
2529
{
 
2530
  ConfigServer cs;
 
2531
  
 
2532
  cs = gconf_get_config_server(FALSE, NULL); /* ignore error, since whole point is to see if server is reachable */
 
2533
 
 
2534
  if (cs == CORBA_OBJECT_NIL)
 
2535
    return FALSE;
 
2536
  else
 
2537
    return TRUE;
 
2538
}
 
2539
 
 
2540
gboolean
 
2541
gconf_spawn_daemon(GError** err)
 
2542
{
 
2543
  ConfigServer cs;
 
2544
 
 
2545
  cs = gconf_get_config_server(TRUE, err);
 
2546
 
 
2547
  if (cs == CORBA_OBJECT_NIL)
 
2548
    {
 
2549
      g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
 
2550
      return FALSE; /* Failed to spawn, error should be set */
 
2551
    }
 
2552
  else
 
2553
    return TRUE;
 
2554
}
 
2555
 
 
2556
/*
 
2557
 * Sugar functions 
 
2558
 */
 
2559
 
 
2560
gdouble      
 
2561
gconf_engine_get_float (GConfEngine* conf, const gchar* key,
 
2562
                 GError** err)
 
2563
{
 
2564
  GConfValue* val;
 
2565
  static const gdouble deflt = 0.0;
 
2566
  
 
2567
  g_return_val_if_fail(conf != NULL, 0.0);
 
2568
  g_return_val_if_fail(key != NULL, 0.0);
 
2569
  
 
2570
  val = gconf_engine_get (conf, key, err);
 
2571
 
 
2572
  if (val == NULL)
 
2573
    return deflt;
 
2574
  else
 
2575
    {
 
2576
      gdouble retval;
 
2577
      
 
2578
      if (val->type != GCONF_VALUE_FLOAT)
 
2579
        {
 
2580
          if (err)
 
2581
            *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected float, got %s"),
 
2582
                                    gconf_value_type_to_string(val->type));
 
2583
          gconf_value_free(val);
 
2584
          return deflt;
 
2585
        }
 
2586
 
 
2587
      retval = gconf_value_get_float(val);
 
2588
 
 
2589
      gconf_value_free(val);
 
2590
 
 
2591
      return retval;
 
2592
    }
 
2593
}
 
2594
 
 
2595
gint         
 
2596
gconf_engine_get_int   (GConfEngine* conf, const gchar* key,
 
2597
                 GError** err)
 
2598
{
 
2599
  GConfValue* val;
 
2600
  static const gint deflt = 0;
 
2601
  
 
2602
  g_return_val_if_fail(conf != NULL, 0);
 
2603
  g_return_val_if_fail(key != NULL, 0);
 
2604
  
 
2605
  val = gconf_engine_get (conf, key, err);
 
2606
 
 
2607
  if (val == NULL)
 
2608
    return deflt;
 
2609
  else
 
2610
    {
 
2611
      gint retval;
 
2612
 
 
2613
      if (val->type != GCONF_VALUE_INT)
 
2614
        {
 
2615
          if (err)
 
2616
            *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected int, got %s"),
 
2617
                                    gconf_value_type_to_string(val->type));
 
2618
          gconf_value_free(val);
 
2619
          return deflt;
 
2620
        }
 
2621
 
 
2622
      retval = gconf_value_get_int(val);
 
2623
 
 
2624
      gconf_value_free(val);
 
2625
 
 
2626
      return retval;
 
2627
    }
 
2628
}
 
2629
 
 
2630
gchar*       
 
2631
gconf_engine_get_string(GConfEngine* conf, const gchar* key,
 
2632
                 GError** err)
 
2633
{
 
2634
  GConfValue* val;
 
2635
  static const gchar* deflt = NULL;
 
2636
  
 
2637
  g_return_val_if_fail(conf != NULL, NULL);
 
2638
  g_return_val_if_fail(key != NULL, NULL);
 
2639
  
 
2640
  val = gconf_engine_get (conf, key, err);
 
2641
 
 
2642
  if (val == NULL)
 
2643
    return deflt ? g_strdup(deflt) : NULL;
 
2644
  else
 
2645
    {
 
2646
      gchar* retval;
 
2647
 
 
2648
      if (val->type != GCONF_VALUE_STRING)
 
2649
        {
 
2650
          if (err)
 
2651
            *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected string, got %s"),
 
2652
                                    gconf_value_type_to_string(val->type));
 
2653
          gconf_value_free(val);
 
2654
          return deflt ? g_strdup(deflt) : NULL;
 
2655
        }
 
2656
 
 
2657
      retval = val->d.string_data;
 
2658
      /* This is a cheat; don't copy */
 
2659
      val->d.string_data = NULL; /* don't delete the string */
 
2660
 
 
2661
      gconf_value_free(val);
 
2662
 
 
2663
      return retval;
 
2664
    }
 
2665
}
 
2666
 
 
2667
gboolean     
 
2668
gconf_engine_get_bool  (GConfEngine* conf, const gchar* key,
 
2669
                        GError** err)
 
2670
{
 
2671
  GConfValue* val;
 
2672
  static const gboolean deflt = FALSE;
 
2673
  
 
2674
  g_return_val_if_fail(conf != NULL, FALSE);
 
2675
  g_return_val_if_fail(key != NULL, FALSE);
 
2676
  
 
2677
  val = gconf_engine_get (conf, key, err);
 
2678
 
 
2679
  if (val == NULL)
 
2680
    return deflt;
 
2681
  else
 
2682
    {
 
2683
      gboolean retval;
 
2684
 
 
2685
      if (val->type != GCONF_VALUE_BOOL)
 
2686
        {
 
2687
          if (err)
 
2688
            *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected bool, got %s"),
 
2689
                                    gconf_value_type_to_string(val->type));
 
2690
          gconf_value_free(val);
 
2691
          return deflt;
 
2692
        }
 
2693
 
 
2694
      retval = gconf_value_get_bool(val);
 
2695
 
 
2696
      gconf_value_free(val);
 
2697
 
 
2698
      return retval;
 
2699
    }
 
2700
}
 
2701
 
 
2702
GConfSchema* 
 
2703
gconf_engine_get_schema  (GConfEngine* conf, const gchar* key, GError** err)
 
2704
{
 
2705
  GConfValue* val;
 
2706
 
 
2707
  g_return_val_if_fail(conf != NULL, NULL);
 
2708
  g_return_val_if_fail(key != NULL, NULL);
 
2709
  
 
2710
  val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), err);
 
2711
 
 
2712
  if (val == NULL)
 
2713
    return NULL;
 
2714
  else
 
2715
    {
 
2716
      GConfSchema* retval;
 
2717
 
 
2718
      if (val->type != GCONF_VALUE_SCHEMA)
 
2719
        {
 
2720
          if (err)
 
2721
            *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected schema, got %s"),
 
2722
                                    gconf_value_type_to_string(val->type));
 
2723
          gconf_value_free(val);
 
2724
          return NULL;
 
2725
        }
 
2726
 
 
2727
      retval = gconf_value_get_schema(val);
 
2728
 
 
2729
      /* This is a cheat; don't copy */
 
2730
      val->d.schema_data = NULL; /* don't delete the schema */
 
2731
 
 
2732
      gconf_value_free(val);
 
2733
 
 
2734
      return retval;
 
2735
    }
 
2736
}
 
2737
 
 
2738
GSList*
 
2739
gconf_engine_get_list    (GConfEngine* conf, const gchar* key,
 
2740
                          GConfValueType list_type, GError** err)
 
2741
{
 
2742
  GConfValue* val;
 
2743
 
 
2744
  g_return_val_if_fail(conf != NULL, NULL);
 
2745
  g_return_val_if_fail(key != NULL, NULL);
 
2746
  g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, NULL);
 
2747
  g_return_val_if_fail(list_type != GCONF_VALUE_LIST, NULL);
 
2748
  g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, NULL);
 
2749
  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
 
2750
  
 
2751
  val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), err);
 
2752
 
 
2753
  if (val == NULL)
 
2754
    return NULL;
 
2755
  else
 
2756
    {
 
2757
      /* This type-checks the value */
 
2758
      return gconf_value_list_to_primitive_list_destructive(val, list_type, err);
 
2759
    }
 
2760
}
 
2761
 
 
2762
gboolean
 
2763
gconf_engine_get_pair    (GConfEngine* conf, const gchar* key,
 
2764
                   GConfValueType car_type, GConfValueType cdr_type,
 
2765
                   gpointer car_retloc, gpointer cdr_retloc,
 
2766
                   GError** err)
 
2767
{
 
2768
  GConfValue* val;
 
2769
  GError* error = NULL;
 
2770
  
 
2771
  g_return_val_if_fail(conf != NULL, FALSE);
 
2772
  g_return_val_if_fail(key != NULL, FALSE);
 
2773
  g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, FALSE);
 
2774
  g_return_val_if_fail(car_type != GCONF_VALUE_LIST, FALSE);
 
2775
  g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, FALSE);
 
2776
  g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, FALSE);
 
2777
  g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, FALSE);
 
2778
  g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, FALSE);
 
2779
  g_return_val_if_fail(car_retloc != NULL, FALSE);
 
2780
  g_return_val_if_fail(cdr_retloc != NULL, FALSE);
 
2781
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);  
 
2782
  
 
2783
  val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), &error);
 
2784
 
 
2785
  if (error != NULL)
 
2786
    {
 
2787
      g_assert(val == NULL);
 
2788
      
 
2789
      if (err)
 
2790
        *err = error;
 
2791
      else
 
2792
        g_error_free(error);
 
2793
 
 
2794
      return FALSE;
 
2795
    }
 
2796
  
 
2797
  if (val == NULL)
 
2798
    {
 
2799
      return TRUE;
 
2800
    }
 
2801
  else
 
2802
    {
 
2803
      /* Destroys val */
 
2804
      return gconf_value_pair_to_primitive_pair_destructive(val,
 
2805
                                                            car_type, cdr_type,
 
2806
                                                            car_retloc, cdr_retloc,
 
2807
                                                            err);
 
2808
    }
 
2809
}
 
2810
 
 
2811
/*
 
2812
 * Setters
 
2813
 */
 
2814
 
 
2815
static gboolean
 
2816
error_checked_set(GConfEngine* conf, const gchar* key,
 
2817
                  GConfValue* gval, GError** err)
 
2818
{
 
2819
  GError* my_err = NULL;
 
2820
  
 
2821
  gconf_engine_set (conf, key, gval, &my_err);
 
2822
 
 
2823
  gconf_value_free(gval);
 
2824
  
 
2825
  if (my_err != NULL)
 
2826
    {
 
2827
      if (err)
 
2828
        *err = my_err;
 
2829
      else
 
2830
        g_error_free(my_err);
 
2831
      return FALSE;
 
2832
    }
 
2833
  else
 
2834
    return TRUE;
 
2835
}
 
2836
 
 
2837
gboolean
 
2838
gconf_engine_set_float   (GConfEngine* conf, const gchar* key,
 
2839
                          gdouble val, GError** err)
 
2840
{
 
2841
  GConfValue* gval;
 
2842
 
 
2843
  g_return_val_if_fail(conf != NULL, FALSE);
 
2844
  g_return_val_if_fail(key != NULL, FALSE);
 
2845
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
2846
  
 
2847
  gval = gconf_value_new(GCONF_VALUE_FLOAT);
 
2848
 
 
2849
  gconf_value_set_float(gval, val);
 
2850
 
 
2851
  return error_checked_set(conf, key, gval, err);
 
2852
}
 
2853
 
 
2854
gboolean
 
2855
gconf_engine_set_int     (GConfEngine* conf, const gchar* key,
 
2856
                          gint val, GError** err)
 
2857
{
 
2858
  GConfValue* gval;
 
2859
 
 
2860
  g_return_val_if_fail(conf != NULL, FALSE);
 
2861
  g_return_val_if_fail(key != NULL, FALSE);
 
2862
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
2863
  
 
2864
  gval = gconf_value_new(GCONF_VALUE_INT);
 
2865
 
 
2866
  gconf_value_set_int(gval, val);
 
2867
 
 
2868
  return error_checked_set(conf, key, gval, err);
 
2869
}
 
2870
 
 
2871
gboolean
 
2872
gconf_engine_set_string  (GConfEngine* conf, const gchar* key,
 
2873
                          const gchar* val, GError** err)
 
2874
{
 
2875
  GConfValue* gval;
 
2876
 
 
2877
  g_return_val_if_fail (val != NULL, FALSE);
 
2878
  g_return_val_if_fail (conf != NULL, FALSE);
 
2879
  g_return_val_if_fail (key != NULL, FALSE);
 
2880
  g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
 
2881
  
 
2882
  g_return_val_if_fail (g_utf8_validate (val, -1, NULL), FALSE);
 
2883
  
 
2884
  gval = gconf_value_new(GCONF_VALUE_STRING);
 
2885
 
 
2886
  gconf_value_set_string(gval, val);
 
2887
 
 
2888
  return error_checked_set(conf, key, gval, err);
 
2889
}
 
2890
 
 
2891
gboolean
 
2892
gconf_engine_set_bool    (GConfEngine* conf, const gchar* key,
 
2893
                          gboolean val, GError** err)
 
2894
{
 
2895
  GConfValue* gval;
 
2896
 
 
2897
  g_return_val_if_fail(conf != NULL, FALSE);
 
2898
  g_return_val_if_fail(key != NULL, FALSE);
 
2899
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
2900
  
 
2901
  gval = gconf_value_new(GCONF_VALUE_BOOL);
 
2902
 
 
2903
  gconf_value_set_bool(gval, !!val); /* canonicalize the bool */
 
2904
 
 
2905
  return error_checked_set(conf, key, gval, err);
 
2906
}
 
2907
 
 
2908
gboolean
 
2909
gconf_engine_set_schema  (GConfEngine* conf, const gchar* key,
 
2910
                          GConfSchema* val, GError** err)
 
2911
{
 
2912
  GConfValue* gval;
 
2913
 
 
2914
  g_return_val_if_fail(conf != NULL, FALSE);
 
2915
  g_return_val_if_fail(key != NULL, FALSE);
 
2916
  g_return_val_if_fail(val != NULL, FALSE);
 
2917
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
2918
  
 
2919
  gval = gconf_value_new(GCONF_VALUE_SCHEMA);
 
2920
 
 
2921
  gconf_value_set_schema(gval, val);
 
2922
 
 
2923
  return error_checked_set(conf, key, gval, err);
 
2924
}
 
2925
 
 
2926
gboolean
 
2927
gconf_engine_set_list    (GConfEngine* conf, const gchar* key,
 
2928
                          GConfValueType list_type,
 
2929
                          GSList* list,
 
2930
                          GError** err)
 
2931
{
 
2932
  GConfValue* value_list;
 
2933
  GError *tmp_err = NULL;
 
2934
  
 
2935
  g_return_val_if_fail(conf != NULL, FALSE);
 
2936
  g_return_val_if_fail(key != NULL, FALSE);
 
2937
  g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, FALSE);
 
2938
  g_return_val_if_fail(list_type != GCONF_VALUE_LIST, FALSE);
 
2939
  g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, FALSE);
 
2940
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
2941
 
 
2942
  value_list = gconf_value_list_from_primitive_list(list_type, list, &tmp_err);
 
2943
 
 
2944
  if (tmp_err)
 
2945
    {
 
2946
      g_propagate_error (err, tmp_err);
 
2947
      return FALSE;
 
2948
    }
 
2949
  
 
2950
  /* destroys the value_list */
 
2951
  
 
2952
  return error_checked_set(conf, key, value_list, err);
 
2953
}
 
2954
 
 
2955
gboolean
 
2956
gconf_engine_set_pair    (GConfEngine* conf, const gchar* key,
 
2957
                          GConfValueType car_type, GConfValueType cdr_type,
 
2958
                          gconstpointer address_of_car,
 
2959
                          gconstpointer address_of_cdr,
 
2960
                          GError** err)
 
2961
{
 
2962
  GConfValue* pair;
 
2963
  GError *tmp_err = NULL;
 
2964
  
 
2965
  g_return_val_if_fail(conf != NULL, FALSE);
 
2966
  g_return_val_if_fail(key != NULL, FALSE);
 
2967
  g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, FALSE);
 
2968
  g_return_val_if_fail(car_type != GCONF_VALUE_LIST, FALSE);
 
2969
  g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, FALSE);
 
2970
  g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, FALSE);
 
2971
  g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, FALSE);
 
2972
  g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, FALSE);
 
2973
  g_return_val_if_fail(address_of_car != NULL, FALSE);
 
2974
  g_return_val_if_fail(address_of_cdr != NULL, FALSE);
 
2975
  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
 
2976
  
 
2977
 
 
2978
  pair = gconf_value_pair_from_primitive_pair(car_type, cdr_type,
 
2979
                                              address_of_car, address_of_cdr,
 
2980
                                              &tmp_err);
 
2981
 
 
2982
  if (tmp_err)
 
2983
    {
 
2984
      g_propagate_error (err, tmp_err);
 
2985
      return FALSE;
 
2986
    }  
 
2987
  
 
2988
  return error_checked_set(conf, key, pair, err);
 
2989
}
 
2990
 
 
2991
/* CORBA Util */
 
2992
 
 
2993
/* Set GConfError from an exception, free exception, etc. */
 
2994
 
 
2995
static GConfError
 
2996
corba_errno_to_gconf_errno(ConfigErrorType corba_err)
 
2997
{
 
2998
  switch (corba_err)
 
2999
    {
 
3000
    case ConfigFailed:
 
3001
      return GCONF_ERROR_FAILED;
 
3002
      break;
 
3003
    case ConfigNoPermission:
 
3004
      return GCONF_ERROR_NO_PERMISSION;
 
3005
      break;
 
3006
    case ConfigBadAddress:
 
3007
      return GCONF_ERROR_BAD_ADDRESS;
 
3008
      break;
 
3009
    case ConfigBadKey:
 
3010
      return GCONF_ERROR_BAD_KEY;
 
3011
      break;
 
3012
    case ConfigParseError:
 
3013
      return GCONF_ERROR_PARSE_ERROR;
 
3014
      break;
 
3015
    case ConfigCorrupt:
 
3016
      return GCONF_ERROR_CORRUPT;
 
3017
      break;
 
3018
    case ConfigTypeMismatch:
 
3019
      return GCONF_ERROR_TYPE_MISMATCH;
 
3020
      break;
 
3021
    case ConfigIsDir:
 
3022
      return GCONF_ERROR_IS_DIR;
 
3023
      break;
 
3024
    case ConfigIsKey:
 
3025
      return GCONF_ERROR_IS_KEY;
 
3026
      break;
 
3027
    case ConfigOverridden:
 
3028
      return GCONF_ERROR_OVERRIDDEN;
 
3029
      break;
 
3030
    case ConfigLockFailed:
 
3031
      return GCONF_ERROR_LOCK_FAILED;
 
3032
      break;
 
3033
    case ConfigNoWritableDatabase:
 
3034
      return GCONF_ERROR_NO_WRITABLE_DATABASE;
 
3035
      break;
 
3036
    case ConfigInShutdown:
 
3037
      return GCONF_ERROR_IN_SHUTDOWN;
 
3038
      break;
 
3039
    default:
 
3040
      g_assert_not_reached();
 
3041
      return GCONF_ERROR_SUCCESS; /* warnings */
 
3042
      break;
 
3043
    }
 
3044
}
 
3045
 
 
3046
static gboolean
 
3047
gconf_server_broken(CORBA_Environment* ev)
 
3048
{
 
3049
  switch (ev->_major)
 
3050
    {
 
3051
    case CORBA_SYSTEM_EXCEPTION:
 
3052
      return TRUE;
 
3053
      break;
 
3054
 
 
3055
    case CORBA_USER_EXCEPTION:
 
3056
      {
 
3057
        ConfigException* ce;
 
3058
 
 
3059
        ce = CORBA_exception_value(ev);
 
3060
 
 
3061
        return ce->err_no == ConfigInShutdown;
 
3062
      }
 
3063
      break;
 
3064
      
 
3065
    default:
 
3066
      return FALSE;
 
3067
      break;
 
3068
    }
 
3069
}
 
3070
 
 
3071
static gboolean
 
3072
gconf_handle_corba_exception(CORBA_Environment* ev, GError** err)
 
3073
{
 
3074
  switch (ev->_major)
 
3075
    {
 
3076
    case CORBA_NO_EXCEPTION:
 
3077
      CORBA_exception_free(ev);
 
3078
      return FALSE;
 
3079
      break;
 
3080
    case CORBA_SYSTEM_EXCEPTION:
 
3081
      if (err)
 
3082
        *err = gconf_error_new(GCONF_ERROR_NO_SERVER, _("CORBA error: %s"),
 
3083
                               CORBA_exception_id(ev));
 
3084
      CORBA_exception_free(ev);
 
3085
      return TRUE;
 
3086
      break;
 
3087
    case CORBA_USER_EXCEPTION:
 
3088
      {
 
3089
        ConfigException* ce;
 
3090
 
 
3091
        ce = CORBA_exception_value(ev);
 
3092
 
 
3093
        if (err)
 
3094
          *err = gconf_error_new(corba_errno_to_gconf_errno(ce->err_no),
 
3095
                                 ce->message);
 
3096
        CORBA_exception_free(ev);
 
3097
        return TRUE;
 
3098
      }
 
3099
      break;
 
3100
    default:
 
3101
      g_assert_not_reached();
 
3102
      return TRUE;
 
3103
      break;
 
3104
    }
 
3105
}
 
3106
 
 
3107
/*
 
3108
 * Enumeration conversions
 
3109
 */
 
3110
 
 
3111
gboolean
 
3112
gconf_string_to_enum (GConfEnumStringPair lookup_table[],
 
3113
                      const gchar* str,
 
3114
                      gint* enum_value_retloc)
 
3115
{
 
3116
  int i = 0;
 
3117
  
 
3118
  while (lookup_table[i].str != NULL)
 
3119
    {
 
3120
      if (g_strcasecmp(lookup_table[i].str, str) == 0)
 
3121
        {
 
3122
          *enum_value_retloc = lookup_table[i].enum_value;
 
3123
          return TRUE;
 
3124
        }
 
3125
 
 
3126
      ++i;
 
3127
    }
 
3128
 
 
3129
  return FALSE;
 
3130
}
 
3131
 
 
3132
const gchar*
 
3133
gconf_enum_to_string (GConfEnumStringPair lookup_table[],
 
3134
                      gint enum_value)
 
3135
{
 
3136
  int i = 0;
 
3137
  
 
3138
  while (lookup_table[i].str != NULL)
 
3139
    {
 
3140
      if (lookup_table[i].enum_value == enum_value)
 
3141
        return lookup_table[i].str;
 
3142
 
 
3143
      ++i;
 
3144
    }
 
3145
 
 
3146
  return NULL;
 
3147
}
 
3148