rework deprecated g_type_class_add_private()
[platform/core/system/tlm.git] / src / common / tlm-config.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of tlm
5  *
6  * Copyright (C) 2013-2014 Intel Corporation.
7  *
8  * Contact: Imran Zaman <imran.zaman@intel.com>
9  *          Amarnath Valluri <amarnath.valluri@linux.intel.com>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24  * 02110-1301 USA
25  */
26
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <glib/gstdio.h>
30
31 #include "config.h"
32 #include "tlm-config.h"
33 #include "tlm-config-general.h"
34 #include "tlm-log.h"
35
36 /**
37  * SECTION:tlm-config
38  * @short_description: tlm configuration information
39  * @include: tlm-config.h
40  *
41  * #TlmConfig holds configuration information as a set of keys and values
42  * (integer or strings). The key names are defined in
43  * <link linkend="tlm-General-configuration">General config keys</link>.
44  * Note that authentication and account plugins may use plugin-specific
45  * configuration keys; see plugins' documentation for specifics.
46  *
47  * The configuration is retrieved from the tlm configuration file. See below
48  * for where the file is searched for.
49  *
50  * <refsect1><title>Usage</title></refsect1>
51  * Following code snippet demonstrates how to create and use config object:
52  * |[
53  *
54  * TlmConfig* config = tlm_config_new ();
55  * const gchar *str = tlm_config_get_string (config,
56  *  TLM_CONFIG_GENERAL, TLM_CONFIG_GENERAL_PAM_SERVICE, 0);
57  * g_object_unref(config);
58  *
59  * ]|
60  *
61  * <refsect1><title>Where the configuration file is searched for</title>
62  * </refsect1>
63  *
64  * If tlm has been compiled with --enable-debug, then these locations are used,
65  * in decreasing order of priority:
66  * - TLM_CONF_FILE environment variable
67  * - g_get_user_config_dir() + "tlm.conf"
68  * - each of g_get_system_config_dirs() + "tlm.conf"
69  *
70  * Otherwise, the config file location is determined at compilation time as
71  * $(sysconfdir) + "tlm.conf"
72  *
73  * <refsect1><title>Example configuration file</title></refsect1>
74  *
75  * See example configuration file here:
76  * <ulink url="https://github.com/01org/tlm/blob/master/data/tlm.conf.in">
77  * tlm configuration file</ulink>
78  *
79  */
80
81 /**
82  * TlmConfig:
83  *
84  * Opaque structure for the object.
85  */
86
87 /**
88  * TlmConfigClass:
89  * @parent_class: parent class object
90  *
91  * Opaque structure for the class.
92  */
93
94 struct _TlmConfigPrivate
95 {
96     gchar *config_file_path;
97     GHashTable *config_table;
98 };
99
100 G_DEFINE_TYPE_WITH_PRIVATE (TlmConfig, tlm_config, G_TYPE_OBJECT);
101
102 static gchar *
103 _check_config_file (const gchar *path)
104 {
105     gchar *fn = g_build_filename (path, "tlm.conf",   NULL);
106     DBG ("check config at %s", fn);
107     if (g_access (fn, R_OK) == 0)
108         return fn;
109     g_free (fn);
110     return NULL;
111 }
112
113 static gboolean
114 _load_config (TlmConfig *self)
115 {
116     TlmConfigPrivate *priv = self->priv;
117     GError *err = NULL;
118     gchar **groups = NULL;
119     gsize n_groups = 0;
120     int i,j;
121     GKeyFile *settings = g_key_file_new ();
122
123     const gchar * const *sysconfdirs;
124
125     if (!priv->config_file_path) {
126         const gchar *cfg_env = g_getenv ("TLM_CONF_FILE");
127         if (cfg_env) {
128             if (g_access (cfg_env, R_OK) == 0)
129                 priv->config_file_path = g_strdup (cfg_env);
130         }
131     }
132     if (!priv->config_file_path) {
133         priv->config_file_path = _check_config_file (TLM_SYSCONF_DIR);
134     }
135     if (!priv->config_file_path) {
136         sysconfdirs = g_get_system_config_dirs ();
137         while (*sysconfdirs != NULL) {
138             gchar *sys_cfg = _check_config_file (*sysconfdirs);
139             if (sys_cfg) {
140                 priv->config_file_path = sys_cfg;
141                 break;
142             }
143             sysconfdirs++;
144         }
145     }
146
147     if (priv->config_file_path) {
148         DBG ("loading TLM config from %s", priv->config_file_path);
149         if (!g_key_file_load_from_file (settings,
150                                         priv->config_file_path,
151                                         G_KEY_FILE_NONE, &err)) {
152             WARN ("error reading config file at '%s': %s",
153                  priv->config_file_path, err->message);
154             g_error_free (err);
155             g_key_file_free (settings);
156             return FALSE;
157         }
158     }
159     else {
160         WARN ("No valid configuration file found");
161         g_key_file_free (settings);
162         return FALSE;
163     }
164
165     groups = g_key_file_get_groups (settings, &n_groups);
166
167     for (i = 0; i < n_groups; i++) {
168         GError *err = NULL;
169         gsize n_keys =0;
170         GHashTable *group_table = NULL;
171         gchar **keys = g_key_file_get_keys (settings,
172                                             groups[i],
173                                             &n_keys,
174                                             &err);
175         if (err) {
176             WARN ("fail to read group '%s': %s", groups[i], err->message);
177             g_error_free (err);
178             continue;
179         }
180
181         group_table = (GHashTable *) g_hash_table_lookup (
182                                 priv->config_table, groups[i]);
183         if (!group_table) 
184             group_table = g_hash_table_new_full (
185                                g_str_hash,
186                                g_str_equal,
187                                g_free,
188                                (GDestroyNotify)g_free);
189
190         for (j = 0; j < n_keys; j++) {
191             gchar *value = g_key_file_get_value (settings,
192                                                  groups[i],
193                                                  keys[j],
194                                                  &err);
195             if (err) {
196                 WARN ("fail to read key '%s/%s': %s", groups[i], keys[j],
197                         err->message);
198                 g_error_free (err);
199                 continue;
200             }
201
202             DBG ("found config : '%s/%s' - '%s'", groups[i], keys[j], value);
203
204             g_hash_table_insert (group_table,
205                                  (gpointer)g_strdup (keys[j]),
206                                  (gpointer)value);
207
208         }
209
210         g_hash_table_insert (priv->config_table,
211                              g_strdup (groups[i]),
212                              group_table);
213
214         g_strfreev (keys);
215     }
216
217     g_strfreev (groups);
218
219     g_key_file_free (settings);
220
221     return TRUE;
222 }
223
224 #ifdef ENABLE_DEBUG
225 static void
226 _load_environment (
227         TlmConfig *self)
228 {
229     const gchar *e_val = 0;
230     
231     e_val = g_getenv("TLM_ACCOUNT_PLUGIN");
232     if (e_val)
233         tlm_config_set_string (self, 
234                                TLM_CONFIG_GENERAL, 
235                                TLM_CONFIG_GENERAL_ACCOUNTS_PLUGIN, e_val);
236 }
237 #endif  /* ENABLE_DEBUG */
238
239 /**
240  * tlm_config_get_group:
241  * @self: (transfer none): an instance of #TlmConfig
242  * @group: the group name
243  *
244  * Retrives the configuration in given #group as #GHashTable
245  *
246  * Returns: (transfer none): the key, value paired dictionary if found,
247  * NULL otherwise.
248  */
249 GHashTable *
250 tlm_config_get_group (
251         TlmConfig *self,
252         const gchar *group)
253 {
254     g_return_val_if_fail (self && TLM_IS_CONFIG(self), NULL);
255     g_return_val_if_fail (group && group[0], NULL);
256
257     return (GHashTable *) g_hash_table_lookup (self->priv->config_table,
258                                                   group);
259 }
260
261 /**
262  * tlm_config_get_string:
263  * @self: (transfer none): an instance of #TlmConfig
264  * @group: (transfer none): the group name, NULL refers to General
265  * @key: (transfer none): the key name
266  *
267  * Get a string configuration value.
268  *
269  * Returns: the value corresponding to the key as an string. If the
270  * key does not exist, NULL is returned.
271  */
272 const gchar *
273 tlm_config_get_string (
274         TlmConfig *self,
275         const gchar *group,
276         const gchar *key)
277 {
278     g_return_val_if_fail (self && TLM_IS_CONFIG (self), NULL);
279     g_return_val_if_fail (key && key[0], NULL);
280
281     GHashTable *group_table = tlm_config_get_group (self, group);
282     if (!group_table) return NULL;
283
284     return (const gchar *) g_hash_table_lookup (group_table, key);
285 }
286
287 /**
288  * tlm_config_get_string_default:
289  * @self: (transfer none): an instance of #TlmConfig
290  * @group: (transfer none): the group name, NULL refers to General
291  * @key: (transfer none): the key name
292  * @value: (transfer none): default value
293  *
294  * Get a string configuration value.
295  *
296  * Returns: the value corresponding to the key as an string. If the
297  * key does not exist, given default value is returned.
298  */
299 const gchar *
300 tlm_config_get_string_default (
301         TlmConfig *self,
302         const gchar *group,
303         const gchar *key,
304         const gchar *value)
305 {
306     const gchar *res;
307     g_return_val_if_fail (self && TLM_IS_CONFIG (self), NULL);
308     g_return_val_if_fail (key && key[0], NULL);
309
310     GHashTable *group_table = tlm_config_get_group (self, group);
311     if (!group_table) return NULL;
312
313     res = g_hash_table_lookup (group_table, key);
314     if (!res)
315         return value;
316     return res;
317 }
318
319 /**
320  * tlm_config_set_string:
321  * @self: (transfer none): an instance of #TlmConfig
322  * @group: (transfer none): the group name
323  * @key: (transfer none): the key name
324  * @value: (transfer none): the value
325  *
326  * Sets the configuration value to the provided string.
327  */
328 void
329 tlm_config_set_string (
330         TlmConfig *self,
331         const gchar *group,
332         const gchar *key,
333         const gchar *value)
334 {
335     g_return_if_fail (self && TLM_IS_CONFIG (self));
336     g_return_if_fail (key && key[0]);
337
338     if (!group) group = TLM_CONFIG_GENERAL;
339
340     GHashTable *group_table = tlm_config_get_group (self, group);
341     if (!group_table) {
342         group_table = g_hash_table_new_full (g_str_hash,
343                                              g_str_equal,
344                                              g_free,
345                                              g_free);
346         g_hash_table_insert (self->priv->config_table,
347                              (gpointer)g_strdup (group),
348                              (gpointer)group_table);
349     }
350
351     g_hash_table_insert (group_table,
352                          (gpointer) g_strdup (key),
353                          (gpointer) g_strdup (value));
354
355 }
356 /**
357  * tlm_config_get_int:
358  * @self: (transfer none): an instance of #TlmConfig
359  * @group: the group name
360  * @key: the key name
361  * @retval: value to be returned in case key is not found
362  *
363  * Get an integer configuration value.
364  *
365  * Returns: the value corresponding to the key as an integer. If the key does
366  * not exist or cannot be converted to the integer, retval is returned.
367  */
368 gint
369 tlm_config_get_int (
370         TlmConfig *self,
371         const gchar *group,
372         const gchar *key,
373         gint retval)
374 {
375     const gchar *str_value = tlm_config_get_string (self, group, key);
376     return (gint) (str_value ? atoi (str_value) : retval);
377 }
378
379 /**
380  * tlm_config_set_int:
381  * @self: (transfer none): an instance of #TlmConfig
382  * @group: the group name
383  * @key: the key name
384  * @value: the value
385  *
386  * Sets the configuration value to the provided integer.
387  */
388 void
389 tlm_config_set_int (
390         TlmConfig *self,
391         const gchar *group,
392         const gchar *key,
393         gint value)
394 {
395     gchar *s_value = 0;
396     g_return_if_fail (self && TLM_IS_CONFIG (self));
397
398     s_value = g_strdup_printf ("%d", value);
399     if (!s_value) return;
400
401     tlm_config_set_string (self, group, key, s_value);
402
403     g_free (s_value);
404 }
405
406 /**
407  * tlm_config_get_uint:
408  * @self: (transfer none): an instance of #TlmConfig
409  * @group: (transfer none): the group name
410  * @key: (transfer none): the key name
411  * @retval: value to be returned in case key is not found
412  *
413  * Get an unsigned integer configuration value.
414  *
415  * Returns: the value corresponding to the key as an unsigned integer. If the
416  * key does not exist or cannot be converted to the integer, retval is returned.
417  */
418 guint
419 tlm_config_get_uint (
420         TlmConfig *self,
421         const gchar *group,
422         const gchar *key,
423         guint retval)
424 {
425     guint value;
426     const gchar *str_value = tlm_config_get_string (self, group, key);
427
428     if (str_value && (*str_value == '-'))  {
429         value = retval;
430     } else  {
431         if (!str_value || sscanf (str_value, "%u", &value) <= 0) value = retval;
432     }
433
434     return value;
435 }
436
437 /**
438  * tlm_config_set_uint:
439  * @self: (transfer none): an instance of #TlmConfig
440  * @group: (transfer none):  the group name
441  * @key: the key name
442  * @value: the value
443  *
444  * Sets the configuration value to the provided unsigned integer.
445  */
446 void
447 tlm_config_set_uint (
448         TlmConfig *self,
449         const gchar *group,
450         const gchar *key,
451         guint value)
452 {
453     gchar *s_value = 0;
454     g_return_if_fail (self && TLM_IS_CONFIG (self));
455
456     s_value = g_strdup_printf ("%u", value);
457     if (!s_value) return;
458
459     tlm_config_set_string (self, group, key, s_value);
460     g_free (s_value);
461 }
462
463 /**
464  * tlm_config_get_boolean:
465  * @self: (transfer none): an instance of #TlmConfig
466  * @group: (transfer none): the group name
467  * @key: (transfer none): the key name
468  * @retval: value to be returned in case key is not found
469  *
470  * Get a boolean configuration value.
471  *
472  * Returns: the value corresponding to the key as boolean. If the
473  * key does not exist or cannot be converted to boolean, retval is returned.
474  */
475 gboolean
476 tlm_config_get_boolean (
477         TlmConfig *self,
478         const gchar *group,
479         const gchar *key,
480         gboolean retval)
481 {
482     const gchar *str_value = NULL;
483     gint value = 0;
484     g_return_val_if_fail (self && TLM_IS_CONFIG (self), retval);
485
486     str_value = tlm_config_get_string (self, group, key);
487     if (!str_value)
488         return retval;
489
490     if (g_ascii_strncasecmp (str_value, "false", 5) == 0 ||
491         g_ascii_strncasecmp (str_value, "no", 2) == 0)
492         return FALSE;
493
494     if (g_ascii_strncasecmp (str_value, "true", 4) == 0 ||
495         g_ascii_strncasecmp (str_value, "yes", 3) == 0)
496         return TRUE;
497
498     if (sscanf (str_value, "%d", &value) <= 0)
499         return retval;
500
501     return (gboolean) value;
502 }
503
504 /**
505  * tlm_config_set_boolean:
506  * @self: (transfer none): an instance of #TlmConfig
507  * @group: the group name
508  * @key: the key name
509  * @value: the value
510  *
511  * Sets the configuration value to the provided #value.
512  */
513 void
514 tlm_config_set_boolean (
515         TlmConfig *self,
516         const gchar *group,
517         const gchar *key,
518         gboolean value)
519 {
520     g_return_if_fail (self && TLM_IS_CONFIG (self));
521
522     tlm_config_set_int (self, group, key, (gint)value);
523 }
524 /**
525  * tlm_config_has_group:
526  * @self: (transfer none): an instance of #TlmConfig
527  * @group: the group name
528  *
529  * Checks if any configuration available for #group.
530  *
531  * Returns: TRUE if found, FALSE otherwise.
532  */
533 gboolean
534 tlm_config_has_group (
535     TlmConfig *self,
536     const gchar *group)
537 {
538     g_return_val_if_fail (self && TLM_IS_CONFIG (self), FALSE);
539     g_return_val_if_fail (group, FALSE);
540
541     return g_hash_table_contains (self->priv->config_table,
542                                   (gconstpointer)group);
543 }
544
545 /**
546  * tlm_config_has_key:
547  * @self: (transfer none): an instance of #TlmConfig
548  * @group: the group name
549  * @key: the key name
550  *
551  * Checks if #key is in given #group.
552  *
553  * Returns: TRUE, if found, FALSE otherwise.
554  */
555
556 gboolean
557 tlm_config_has_key (
558     TlmConfig *self,
559     const gchar *group,
560     const gchar *key)
561 {
562     GHashTable *group_table = NULL;
563     g_return_val_if_fail (self && TLM_IS_CONFIG (self), FALSE);
564     g_return_val_if_fail (key, FALSE);
565
566     if (!group) group = TLM_CONFIG_GENERAL;
567
568     group_table = tlm_config_get_group (self, group);
569     if (!group_table) return FALSE;
570
571     return g_hash_table_contains (group_table, (gconstpointer)key);
572 }
573
574 static void
575 _cleanup (TlmConfig *self)
576 {
577     if (self->priv->config_table) {
578         g_hash_table_unref (self->priv->config_table);
579         self->priv->config_table = NULL;
580     }
581
582     if (self->priv->config_file_path) {
583         g_free (self->priv->config_file_path);
584         self->priv->config_file_path = NULL;
585     }
586 }
587
588 static void
589 tlm_config_dispose (
590         GObject *object)
591 {
592     TlmConfig *self = 0;
593     g_return_if_fail (object && TLM_IS_CONFIG (object));
594
595     self = TLM_CONFIG (object);
596
597     _cleanup (self);
598
599     G_OBJECT_CLASS (tlm_config_parent_class)->dispose (object);
600 }
601
602 static void
603 tlm_config_finalize (
604         GObject *object)
605 {
606     g_return_if_fail (object && TLM_IS_CONFIG (object));
607
608     G_OBJECT_CLASS (tlm_config_parent_class)->finalize (object);
609 }
610
611 static void
612 tlm_config_class_init (
613         TlmConfigClass *klass)
614 {
615     GObjectClass *object_class = G_OBJECT_CLASS (klass);
616
617     object_class->dispose = tlm_config_dispose;
618     object_class->finalize = tlm_config_finalize;
619 }
620
621 static void
622 _initialize (TlmConfig *self)
623 {
624     self->priv->config_file_path = NULL;
625     self->priv->config_table = g_hash_table_new_full (
626                                     g_str_hash,
627                                     g_str_equal,
628                                     g_free,
629                                     (GDestroyNotify)g_hash_table_unref);
630
631
632     if (!_load_config (self))
633         WARN ("load configuration failed, using default settings");
634
635 #ifdef ENABLE_DEBUG
636     _load_environment (self);
637 #endif
638 }
639
640 static void
641 tlm_config_init (
642         TlmConfig *self)
643 {
644     self->priv = tlm_config_get_instance_private (self);
645     _initialize (self);
646 }
647
648 /**
649  * tlm_config_reload:
650  * @self: (transfer none): an instance of #TlmConfig
651  *
652  * Reloads the configuration.
653  *
654  */
655 void
656 tlm_config_reload (
657         TlmConfig *self)
658 {
659     g_return_if_fail (self && TLM_IS_CONFIG (self));
660
661     DBG ("reload configuration");
662     _cleanup (self);
663     _initialize (self);
664 }
665
666 /**
667  * tlm_config_new:
668  *
669  * Create a #TlmConfig object.
670  *
671  * Returns: an instance of #TlmConfig.
672  */
673 TlmConfig *
674 tlm_config_new ()
675 {
676     return TLM_CONFIG (g_object_new (TLM_TYPE_CONFIG, NULL));
677 }
678