1/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation, nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#define LOG_NDDEBUG 0
31#define LOG_TAG "LocSvc_utils_cfg"
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <pthread.h>
36#include <string.h>
37#include <ctype.h>
38#include <unistd.h>
39#include <time.h>
40#include <loc_cfg.h>
41#include <log_util.h>
42#ifdef USE_GLIB
43#include <glib.h>
44#endif
45#include "platform_lib_includes.h"
46
47/*=============================================================================
48 *
49 *                          GLOBAL DATA DECLARATION
50 *
51 *============================================================================*/
52
53/* Parameter data */
54static uint8_t DEBUG_LEVEL = 0xff;
55static uint8_t TIMESTAMP = 0;
56
57/* Parameter spec table */
58static loc_param_s_type loc_parameter_table[] =
59{
60  {"DEBUG_LEVEL",                    &DEBUG_LEVEL, NULL,                   'n'},
61  {"TIMESTAMP",                      &TIMESTAMP,   NULL,                   'n'},
62};
63int loc_param_num = sizeof(loc_parameter_table) / sizeof(loc_param_s_type);
64
65/*===========================================================================
66FUNCTION trim_space
67
68DESCRIPTION
69   Removes leading and trailing spaces of the string
70
71DEPENDENCIES
72   N/A
73
74RETURN VALUE
75   None
76
77SIDE EFFECTS
78   N/A
79===========================================================================*/
80void trim_space(char *org_string)
81{
82   char *scan_ptr, *write_ptr;
83   char *first_nonspace = NULL, *last_nonspace = NULL;
84
85   scan_ptr = write_ptr = org_string;
86
87   while (*scan_ptr)
88   {
89      if ( !isspace(*scan_ptr) && first_nonspace == NULL)
90      {
91         first_nonspace = scan_ptr;
92      }
93
94      if (first_nonspace != NULL)
95      {
96         *(write_ptr++) = *scan_ptr;
97         if ( !isspace(*scan_ptr))
98         {
99            last_nonspace = write_ptr;
100         }
101      }
102
103      scan_ptr++;
104   }
105
106   if (last_nonspace) { *last_nonspace = '\0'; }
107}
108
109typedef struct loc_param_v_type
110{
111   char* param_name;
112
113   char* param_str_value;
114   int param_int_value;
115   double param_double_value;
116}loc_param_v_type;
117
118/*===========================================================================
119FUNCTION loc_set_config_entry
120
121DESCRIPTION
122   Potentially sets a given configuration table entry based on the passed in
123   configuration value. This is done by using a string comparison of the
124   parameter names and those found in the configuration file.
125
126PARAMETERS:
127   config_entry: configuration entry in the table to possibly set
128   config_value: value to store in the entry if the parameter names match
129
130DEPENDENCIES
131   N/A
132
133RETURN VALUE
134   None
135
136SIDE EFFECTS
137   N/A
138===========================================================================*/
139void loc_set_config_entry(loc_param_s_type* config_entry, loc_param_v_type* config_value)
140{
141   if(NULL == config_entry || NULL == config_value)
142   {
143      LOC_LOGE("%s: INVALID config entry or parameter", __FUNCTION__);
144      return;
145   }
146
147   if (strcmp(config_entry->param_name, config_value->param_name) == 0 &&
148               config_entry->param_ptr)
149   {
150      switch (config_entry->param_type)
151      {
152      case 's':
153         if (strcmp(config_value->param_str_value, "NULL") == 0)
154         {
155            *((char*)config_entry->param_ptr) = '\0';
156         }
157         else {
158            strlcpy((char*) config_entry->param_ptr,
159                  config_value->param_str_value,
160                  LOC_MAX_PARAM_STRING + 1);
161         }
162         /* Log INI values */
163         LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__, config_entry->param_name, (char*)config_entry->param_ptr);
164
165         if(NULL != config_entry->param_set)
166         {
167            *(config_entry->param_set) = 1;
168         }
169         break;
170      case 'n':
171         *((int *)config_entry->param_ptr) = config_value->param_int_value;
172         /* Log INI values */
173         LOC_LOGD("%s: PARAM %s = %d", __FUNCTION__, config_entry->param_name, config_value->param_int_value);
174
175         if(NULL != config_entry->param_set)
176         {
177            *(config_entry->param_set) = 1;
178         }
179         break;
180      case 'f':
181         *((double *)config_entry->param_ptr) = config_value->param_double_value;
182         /* Log INI values */
183         LOC_LOGD("%s: PARAM %s = %f", __FUNCTION__, config_entry->param_name, config_value->param_double_value);
184
185         if(NULL != config_entry->param_set)
186         {
187            *(config_entry->param_set) = 1;
188         }
189         break;
190      default:
191         LOC_LOGE("%s: PARAM %s parameter type must be n, f, or s", __FUNCTION__, config_entry->param_name);
192      }
193   }
194}
195
196/*===========================================================================
197FUNCTION loc_read_conf
198
199DESCRIPTION
200   Reads the specified configuration file and sets defined values based on
201   the passed in configuration table. This table maps strings to values to
202   set along with the type of each of these values.
203
204PARAMETERS:
205   conf_file_name: configuration file to read
206   config_table: table definition of strings to places to store information
207   table_length: length of the configuration table
208
209DEPENDENCIES
210   N/A
211
212RETURN VALUE
213   None
214
215SIDE EFFECTS
216   N/A
217===========================================================================*/
218void loc_read_conf(const char* conf_file_name, loc_param_s_type* config_table, uint32_t table_length)
219{
220   FILE *gps_conf_fp = NULL;
221   char input_buf[LOC_MAX_PARAM_LINE];  /* declare a char array */
222   char *lasts;
223   loc_param_v_type config_value;
224   uint32_t i;
225
226   if((gps_conf_fp = fopen(conf_file_name, "r")) != NULL)
227   {
228      LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
229   }
230   else
231   {
232      LOC_LOGW("%s: no %s file found", __FUNCTION__, conf_file_name);
233      loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
234      return; /* no parameter file */
235   }
236
237   /* Clear all validity bits */
238   for(i = 0; NULL != config_table && i < table_length; i++)
239   {
240      if(NULL != config_table[i].param_set)
241      {
242         *(config_table[i].param_set) = 0;
243      }
244   }
245
246   while(fgets(input_buf, LOC_MAX_PARAM_LINE, gps_conf_fp) != NULL)
247   {
248      memset(&config_value, 0, sizeof(config_value));
249
250      /* Separate variable and value */
251      config_value.param_name = strtok_r(input_buf, "=", &lasts);
252      if (config_value.param_name == NULL) continue;       /* skip lines that do not contain "=" */
253      config_value.param_str_value = strtok_r(NULL, "=", &lasts);
254      if (config_value.param_str_value == NULL) continue;  /* skip lines that do not contain two operands */
255
256      /* Trim leading and trailing spaces */
257      trim_space(config_value.param_name);
258      trim_space(config_value.param_str_value);
259
260      /* Parse numerical value */
261      if (config_value.param_str_value[0] == '0' && tolower(config_value.param_str_value[1]) == 'x')
262      {
263         /* hex */
264         config_value.param_int_value = (int) strtol(&config_value.param_str_value[2], (char**) NULL, 16);
265      }
266      else {
267         config_value.param_double_value = (double) atof(config_value.param_str_value); /* float */
268         config_value.param_int_value = atoi(config_value.param_str_value); /* dec */
269      }
270
271      for(i = 0; NULL != config_table && i < table_length; i++)
272      {
273         loc_set_config_entry(&config_table[i], &config_value);
274      }
275
276      for(i = 0; i < loc_param_num; i++)
277      {
278         loc_set_config_entry(&loc_parameter_table[i], &config_value);
279      }
280   }
281
282   fclose(gps_conf_fp);
283
284   /* Initialize logging mechanism with parsed data */
285   loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
286}
287