1 /* Copyright (c) 2011-2015, 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_NDEBUG 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 <platform_lib_includes.h>
42 #include <loc_misc_utils.h>
43 #ifdef USE_GLIB
44 #include <glib.h>
45 #endif
46 #include "platform_lib_includes.h"
47
48 /*=============================================================================
49 *
50 * GLOBAL DATA DECLARATION
51 *
52 *============================================================================*/
53
54 /* Parameter data */
55 static uint32_t DEBUG_LEVEL = 0xff;
56 static uint32_t TIMESTAMP = 0;
57
58 /* Parameter spec table */
59 static const loc_param_s_type loc_param_table[] =
60 {
61 {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'},
62 {"TIMESTAMP", &TIMESTAMP, NULL, 'n'},
63 };
64 static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type);
65
66 typedef struct loc_param_v_type
67 {
68 char* param_name;
69 char* param_str_value;
70 int param_int_value;
71 double param_double_value;
72 }loc_param_v_type;
73
74 /*===========================================================================
75 FUNCTION loc_set_config_entry
76
77 DESCRIPTION
78 Potentially sets a given configuration table entry based on the passed in
79 configuration value. This is done by using a string comparison of the
80 parameter names and those found in the configuration file.
81
82 PARAMETERS:
83 config_entry: configuration entry in the table to possibly set
84 config_value: value to store in the entry if the parameter names match
85
86 DEPENDENCIES
87 N/A
88
89 RETURN VALUE
90 None
91
92 SIDE EFFECTS
93 N/A
94 ===========================================================================*/
loc_set_config_entry(const loc_param_s_type * config_entry,loc_param_v_type * config_value)95 int loc_set_config_entry(const loc_param_s_type* config_entry, loc_param_v_type* config_value)
96 {
97 int ret=-1;
98 if(NULL == config_entry || NULL == config_value)
99 {
100 LOC_LOGE("%s: INVALID config entry or parameter", __FUNCTION__);
101 return ret;
102 }
103
104 if (strcmp(config_entry->param_name, config_value->param_name) == 0 &&
105 config_entry->param_ptr)
106 {
107 switch (config_entry->param_type)
108 {
109 case 's':
110 if (strcmp(config_value->param_str_value, "NULL") == 0)
111 {
112 *((char*)config_entry->param_ptr) = '\0';
113 }
114 else {
115 strlcpy((char*) config_entry->param_ptr,
116 config_value->param_str_value,
117 LOC_MAX_PARAM_STRING + 1);
118 }
119 /* Log INI values */
120 LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__,
121 config_entry->param_name, (char*)config_entry->param_ptr);
122
123 if(NULL != config_entry->param_set)
124 {
125 *(config_entry->param_set) = 1;
126 }
127 ret = 0;
128 break;
129 case 'n':
130 *((int *)config_entry->param_ptr) = config_value->param_int_value;
131 /* Log INI values */
132 LOC_LOGD("%s: PARAM %s = %d", __FUNCTION__,
133 config_entry->param_name, config_value->param_int_value);
134
135 if(NULL != config_entry->param_set)
136 {
137 *(config_entry->param_set) = 1;
138 }
139 ret = 0;
140 break;
141 case 'f':
142 *((double *)config_entry->param_ptr) = config_value->param_double_value;
143 /* Log INI values */
144 LOC_LOGD("%s: PARAM %s = %f", __FUNCTION__,
145 config_entry->param_name, config_value->param_double_value);
146
147 if(NULL != config_entry->param_set)
148 {
149 *(config_entry->param_set) = 1;
150 }
151 ret = 0;
152 break;
153 default:
154 LOC_LOGE("%s: PARAM %s parameter type must be n, f, or s",
155 __FUNCTION__, config_entry->param_name);
156 }
157 }
158 return ret;
159 }
160
161 /*===========================================================================
162 FUNCTION loc_fill_conf_item
163
164 DESCRIPTION
165 Takes a line of configuration item and sets defined values based on
166 the passed in configuration table. This table maps strings to values to
167 set along with the type of each of these values.
168
169 PARAMETERS:
170 input_buf : buffer contanis config item
171 config_table: table definition of strings to places to store information
172 table_length: length of the configuration table
173
174 DEPENDENCIES
175 N/A
176
177 RETURN VALUE
178 0: Number of records in the config_table filled with input_buf
179
180 SIDE EFFECTS
181 N/A
182 ===========================================================================*/
loc_fill_conf_item(char * input_buf,const loc_param_s_type * config_table,uint32_t table_length)183 int loc_fill_conf_item(char* input_buf,
184 const loc_param_s_type* config_table, uint32_t table_length)
185 {
186 int ret = 0;
187
188 if (input_buf && config_table) {
189 char *lasts;
190 loc_param_v_type config_value;
191 memset(&config_value, 0, sizeof(config_value));
192
193 /* Separate variable and value */
194 config_value.param_name = strtok_r(input_buf, "=", &lasts);
195 /* skip lines that do not contain "=" */
196 if (config_value.param_name) {
197 config_value.param_str_value = strtok_r(NULL, "=", &lasts);
198
199 /* skip lines that do not contain two operands */
200 if (config_value.param_str_value) {
201 /* Trim leading and trailing spaces */
202 loc_util_trim_space(config_value.param_name);
203 loc_util_trim_space(config_value.param_str_value);
204
205 /* Parse numerical value */
206 if ((strlen(config_value.param_str_value) >=3) &&
207 (config_value.param_str_value[0] == '0') &&
208 (tolower(config_value.param_str_value[1]) == 'x'))
209 {
210 /* hex */
211 config_value.param_int_value = (int) strtol(&config_value.param_str_value[2],
212 (char**) NULL, 16);
213 }
214 else {
215 config_value.param_double_value = (double) atof(config_value.param_str_value); /* float */
216 config_value.param_int_value = atoi(config_value.param_str_value); /* dec */
217 }
218
219 for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
220 {
221 if(!loc_set_config_entry(&config_table[i], &config_value)) {
222 ret += 1;
223 }
224 }
225 }
226 }
227 }
228
229 return ret;
230 }
231
232 /*===========================================================================
233 FUNCTION loc_read_conf_r (repetitive)
234
235 DESCRIPTION
236 Reads the specified configuration file and sets defined values based on
237 the passed in configuration table. This table maps strings to values to
238 set along with the type of each of these values.
239 The difference between this and loc_read_conf is that this function returns
240 the file pointer position at the end of filling a config table. Also, it
241 reads a fixed number of parameters at a time which is equal to the length
242 of the configuration table. This functionality enables the caller to
243 repeatedly call the function to read data from the same file.
244
245 PARAMETERS:
246 conf_fp : file pointer
247 config_table: table definition of strings to places to store information
248 table_length: length of the configuration table
249
250 DEPENDENCIES
251 N/A
252
253 RETURN VALUE
254 0: Table filled successfully
255 1: No more parameters to read
256 -1: Error filling table
257
258 SIDE EFFECTS
259 N/A
260 ===========================================================================*/
loc_read_conf_r(FILE * conf_fp,const loc_param_s_type * config_table,uint32_t table_length)261 int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, uint32_t table_length)
262 {
263 int ret=0;
264
265 unsigned int num_params=table_length;
266 if(conf_fp == NULL) {
267 LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__);
268 ret = -1;
269 goto err;
270 }
271
272 /* Clear all validity bits */
273 for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
274 {
275 if(NULL != config_table[i].param_set)
276 {
277 *(config_table[i].param_set) = 0;
278 }
279 }
280
281 char input_buf[LOC_MAX_PARAM_LINE]; /* declare a char array */
282
283 LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
284 while(num_params)
285 {
286 if(!fgets(input_buf, LOC_MAX_PARAM_LINE, conf_fp)) {
287 LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__);
288 break;
289 }
290
291 num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
292 }
293
294 err:
295 return ret;
296 }
297
298 /*===========================================================================
299 FUNCTION loc_udpate_conf
300
301 DESCRIPTION
302 Parses the passed in buffer for configuration items, and update the table
303 that is also passed in.
304
305 Reads the specified configuration file and sets defined values based on
306 the passed in configuration table. This table maps strings to values to
307 set along with the type of each of these values.
308
309 PARAMETERS:
310 conf_data: configuration items in bufferas a string
311 length: strlen(conf_data)
312 config_table: table definition of strings to places to store information
313 table_length: length of the configuration table
314
315 DEPENDENCIES
316 N/A
317
318 RETURN VALUE
319 number of the records in the table that is updated at time of return.
320
321 SIDE EFFECTS
322 N/A
323 ===========================================================================*/
loc_update_conf(const char * conf_data,int32_t length,const loc_param_s_type * config_table,uint32_t table_length)324 int loc_update_conf(const char* conf_data, int32_t length,
325 const loc_param_s_type* config_table, uint32_t table_length)
326 {
327 int ret = -1;
328
329 if (conf_data && length && config_table && table_length) {
330 // make a copy, so we do not tokenize the original data
331 char* conf_copy = (char*)malloc(length+1);
332
333 if (conf_copy != NULL)
334 {
335 memcpy(conf_copy, conf_data, length);
336 // we hard NULL the end of string to be safe
337 conf_copy[length] = 0;
338
339 // start with one record off
340 uint32_t num_params = table_length - 1;
341 char* saveptr = NULL;
342 char* input_buf = strtok_r(conf_copy, "\n", &saveptr);
343 ret = 0;
344
345 LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
346 while(num_params && input_buf) {
347 ret++;
348 num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
349 input_buf = strtok_r(NULL, "\n", &saveptr);
350 }
351 free(conf_copy);
352 }
353 }
354
355 return ret;
356 }
357
358 /*===========================================================================
359 FUNCTION loc_read_conf
360
361 DESCRIPTION
362 Reads the specified configuration file and sets defined values based on
363 the passed in configuration table. This table maps strings to values to
364 set along with the type of each of these values.
365
366 PARAMETERS:
367 conf_file_name: configuration file to read
368 config_table: table definition of strings to places to store information
369 table_length: length of the configuration table
370
371 DEPENDENCIES
372 N/A
373
374 RETURN VALUE
375 None
376
377 SIDE EFFECTS
378 N/A
379 ===========================================================================*/
loc_read_conf(const char * conf_file_name,const loc_param_s_type * config_table,uint32_t table_length)380 void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_table,
381 uint32_t table_length)
382 {
383 FILE *conf_fp = NULL;
384 char *lasts;
385 loc_param_v_type config_value;
386 uint32_t i;
387
388 if((conf_fp = fopen(conf_file_name, "r")) != NULL)
389 {
390 LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
391 if(table_length && config_table) {
392 loc_read_conf_r(conf_fp, config_table, table_length);
393 rewind(conf_fp);
394 }
395 loc_read_conf_r(conf_fp, loc_param_table, loc_param_num);
396 fclose(conf_fp);
397 }
398 /* Initialize logging mechanism with parsed data */
399 loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
400 }
401