1 /* Copyright (c) 2011-2015, 2018 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 <grp.h>
41 #include <errno.h>
42 #include <loc_cfg.h>
43 #include <loc_pla.h>
44 #include <loc_target.h>
45 #include <loc_misc_utils.h>
46 #ifdef USE_GLIB
47 #include <glib.h>
48 #endif
49 #include "log_util.h"
50 
51 /*=============================================================================
52  *
53  *                          GLOBAL DATA DECLARATION
54  *
55  *============================================================================*/
56 
57 /* Parameter data */
58 static uint32_t DEBUG_LEVEL = 0xff;
59 static uint32_t TIMESTAMP = 0;
60 static uint32_t DATUM_TYPE = 0;
61 static bool sVendorEnhanced = true;
62 
63 /* Parameter spec table */
64 static const loc_param_s_type loc_param_table[] =
65 {
66     {"DEBUG_LEVEL",        &DEBUG_LEVEL,        NULL,    'n'},
67     {"TIMESTAMP",          &TIMESTAMP,          NULL,    'n'},
68     {"DATUM_TYPE",         &DATUM_TYPE,         NULL,    'n'},
69 };
70 static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type);
71 
72 typedef struct loc_param_v_type
73 {
74     char* param_name;
75     char* param_str_value;
76     int param_int_value;
77     double param_double_value;
78 }loc_param_v_type;
79 
80 // Reference below arrays wherever needed to avoid duplicating
81 // same conf path string over and again in location code.
82 const char LOC_PATH_GPS_CONF[] = LOC_PATH_GPS_CONF_STR;
83 const char LOC_PATH_IZAT_CONF[] = LOC_PATH_IZAT_CONF_STR;
84 const char LOC_PATH_FLP_CONF[] = LOC_PATH_FLP_CONF_STR;
85 const char LOC_PATH_LOWI_CONF[] = LOC_PATH_LOWI_CONF_STR;
86 const char LOC_PATH_SAP_CONF[] = LOC_PATH_SAP_CONF_STR;
87 const char LOC_PATH_APDR_CONF[] = LOC_PATH_APDR_CONF_STR;
88 const char LOC_PATH_XTWIFI_CONF[] = LOC_PATH_XTWIFI_CONF_STR;
89 const char LOC_PATH_QUIPC_CONF[] = LOC_PATH_QUIPC_CONF_STR;
90 
isVendorEnhanced()91 bool isVendorEnhanced() {
92     return sVendorEnhanced;
93 }
setVendorEnhanced(bool vendorEnhanced)94 void setVendorEnhanced(bool vendorEnhanced) {
95     sVendorEnhanced = vendorEnhanced;
96 }
97 
98 /*===========================================================================
99 FUNCTION loc_get_datum_type
100 
101 DESCRIPTION
102    get datum type
103 
104 PARAMETERS:
105    N/A
106 
107 DEPENDENCIES
108    N/A
109 
110 RETURN VALUE
111    DATUM TYPE
112 
113 SIDE EFFECTS
114    N/A
115 ===========================================================================*/
loc_get_datum_type()116 int loc_get_datum_type()
117 {
118     return DATUM_TYPE;
119 }
120 
121 /*===========================================================================
122 FUNCTION loc_set_config_entry
123 
124 DESCRIPTION
125    Potentially sets a given configuration table entry based on the passed in
126    configuration value. This is done by using a string comparison of the
127    parameter names and those found in the configuration file.
128 
129 PARAMETERS:
130    config_entry: configuration entry in the table to possibly set
131    config_value: value to store in the entry if the parameter names match
132 
133 DEPENDENCIES
134    N/A
135 
136 RETURN VALUE
137    None
138 
139 SIDE EFFECTS
140    N/A
141 ===========================================================================*/
loc_set_config_entry(const loc_param_s_type * config_entry,loc_param_v_type * config_value)142 int loc_set_config_entry(const loc_param_s_type* config_entry, loc_param_v_type* config_value)
143 {
144     int ret=-1;
145     if(NULL == config_entry || NULL == config_value)
146     {
147         LOC_LOGE("%s: INVALID config entry or parameter", __FUNCTION__);
148         return ret;
149     }
150 
151     if (strcmp(config_entry->param_name, config_value->param_name) == 0 &&
152         config_entry->param_ptr)
153     {
154         switch (config_entry->param_type)
155         {
156         case 's':
157             if (strcmp(config_value->param_str_value, "NULL") == 0)
158             {
159                 *((char*)config_entry->param_ptr) = '\0';
160             }
161             else {
162                 strlcpy((char*) config_entry->param_ptr,
163                         config_value->param_str_value,
164                         LOC_MAX_PARAM_STRING);
165             }
166             /* Log INI values */
167             LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__,
168                      config_entry->param_name, (char*)config_entry->param_ptr);
169 
170             if(NULL != config_entry->param_set)
171             {
172                 *(config_entry->param_set) = 1;
173             }
174             ret = 0;
175             break;
176         case 'n':
177             *((int *)config_entry->param_ptr) = config_value->param_int_value;
178             /* Log INI values */
179             LOC_LOGD("%s: PARAM %s = %d", __FUNCTION__,
180                      config_entry->param_name, config_value->param_int_value);
181 
182             if(NULL != config_entry->param_set)
183             {
184                 *(config_entry->param_set) = 1;
185             }
186             ret = 0;
187             break;
188         case 'f':
189             *((double *)config_entry->param_ptr) = config_value->param_double_value;
190             /* Log INI values */
191             LOC_LOGD("%s: PARAM %s = %f", __FUNCTION__,
192                      config_entry->param_name, config_value->param_double_value);
193 
194             if(NULL != config_entry->param_set)
195             {
196                 *(config_entry->param_set) = 1;
197             }
198             ret = 0;
199             break;
200         default:
201             LOC_LOGE("%s: PARAM %s parameter type must be n, f, or s",
202                      __FUNCTION__, config_entry->param_name);
203         }
204     }
205     return ret;
206 }
207 
208 /*===========================================================================
209 FUNCTION loc_fill_conf_item
210 
211 DESCRIPTION
212    Takes a line of configuration item and sets defined values based on
213    the passed in configuration table. This table maps strings to values to
214    set along with the type of each of these values.
215 
216 PARAMETERS:
217    input_buf : buffer contanis config item
218    config_table: table definition of strings to places to store information
219    table_length: length of the configuration table
220 
221 DEPENDENCIES
222    N/A
223 
224 RETURN VALUE
225    0: Number of records in the config_table filled with input_buf
226 
227 SIDE EFFECTS
228    N/A
229 ===========================================================================*/
loc_fill_conf_item(char * input_buf,const loc_param_s_type * config_table,uint32_t table_length)230 int loc_fill_conf_item(char* input_buf,
231                        const loc_param_s_type* config_table, uint32_t table_length)
232 {
233     int ret = 0;
234 
235     if (input_buf && config_table) {
236         char *lasts;
237         loc_param_v_type config_value;
238         memset(&config_value, 0, sizeof(config_value));
239 
240         /* Separate variable and value */
241         config_value.param_name = strtok_r(input_buf, "=", &lasts);
242         /* skip lines that do not contain "=" */
243         if (config_value.param_name) {
244             config_value.param_str_value = strtok_r(NULL, "=", &lasts);
245 
246             /* skip lines that do not contain two operands */
247             if (config_value.param_str_value) {
248                 /* Trim leading and trailing spaces */
249                 loc_util_trim_space(config_value.param_name);
250                 loc_util_trim_space(config_value.param_str_value);
251 
252                 /* Parse numerical value */
253                 if ((strlen(config_value.param_str_value) >=3) &&
254                     (config_value.param_str_value[0] == '0') &&
255                     (tolower(config_value.param_str_value[1]) == 'x'))
256                 {
257                     /* hex */
258                     config_value.param_int_value = (int) strtol(&config_value.param_str_value[2],
259                                                                 (char**) NULL, 16);
260                 }
261                 else {
262                     config_value.param_double_value = (double) atof(config_value.param_str_value); /* float */
263                     config_value.param_int_value = atoi(config_value.param_str_value); /* dec */
264                 }
265 
266                 for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
267                 {
268                     if(!loc_set_config_entry(&config_table[i], &config_value)) {
269                         ret += 1;
270                     }
271                 }
272             }
273         }
274     }
275 
276     return ret;
277 }
278 
279 /*===========================================================================
280 FUNCTION loc_read_conf_r (repetitive)
281 
282 DESCRIPTION
283    Reads the specified configuration file and sets defined values based on
284    the passed in configuration table. This table maps strings to values to
285    set along with the type of each of these values.
286    The difference between this and loc_read_conf is that this function returns
287    the file pointer position at the end of filling a config table. Also, it
288    reads a fixed number of parameters at a time which is equal to the length
289    of the configuration table. This functionality enables the caller to
290    repeatedly call the function to read data from the same file.
291 
292 PARAMETERS:
293    conf_fp : file pointer
294    config_table: table definition of strings to places to store information
295    table_length: length of the configuration table
296 
297 DEPENDENCIES
298    N/A
299 
300 RETURN VALUE
301    0: Table filled successfully
302    1: No more parameters to read
303   -1: Error filling table
304 
305 SIDE EFFECTS
306    N/A
307 ===========================================================================*/
loc_read_conf_r(FILE * conf_fp,const loc_param_s_type * config_table,uint32_t table_length)308 int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, uint32_t table_length)
309 {
310     int ret=0;
311 
312     unsigned int num_params=table_length;
313     if(conf_fp == NULL) {
314         LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__);
315         ret = -1;
316         goto err;
317     }
318 
319     /* Clear all validity bits */
320     for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
321     {
322         if(NULL != config_table[i].param_set)
323         {
324             *(config_table[i].param_set) = 0;
325         }
326     }
327 
328     char input_buf[LOC_MAX_PARAM_LINE];  /* declare a char array */
329 
330     LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
331     while(num_params)
332     {
333         if(!fgets(input_buf, LOC_MAX_PARAM_LINE, conf_fp)) {
334             LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__);
335             break;
336         }
337 
338         num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
339     }
340 
341 err:
342     return ret;
343 }
344 
345 /*===========================================================================
346 FUNCTION loc_udpate_conf
347 
348 DESCRIPTION
349    Parses the passed in buffer for configuration items, and update the table
350    that is also passed in.
351 
352 Reads the specified configuration file and sets defined values based on
353    the passed in configuration table. This table maps strings to values to
354    set along with the type of each of these values.
355 
356 PARAMETERS:
357    conf_data: configuration items in bufferas a string
358    length: strlen(conf_data)
359    config_table: table definition of strings to places to store information
360    table_length: length of the configuration table
361 
362 DEPENDENCIES
363    N/A
364 
365 RETURN VALUE
366    number of the records in the table that is updated at time of return.
367 
368 SIDE EFFECTS
369    N/A
370 ===========================================================================*/
loc_update_conf(const char * conf_data,int32_t length,const loc_param_s_type * config_table,uint32_t table_length)371 int loc_update_conf(const char* conf_data, int32_t length,
372                     const loc_param_s_type* config_table, uint32_t table_length)
373 {
374     int ret = -1;
375 
376     if (conf_data && length && config_table && table_length) {
377         // make a copy, so we do not tokenize the original data
378         char* conf_copy = (char*)malloc(length+1);
379 
380         if (conf_copy != NULL)
381         {
382             memcpy(conf_copy, conf_data, length);
383             // we hard NULL the end of string to be safe
384             conf_copy[length] = 0;
385 
386             // start with one record off
387             uint32_t num_params = table_length - 1;
388             char* saveptr = NULL;
389             char* input_buf = strtok_r(conf_copy, "\n", &saveptr);
390             ret = 0;
391 
392             LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
393             while(num_params && input_buf) {
394                 ret++;
395                 num_params -= loc_fill_conf_item(input_buf, config_table, table_length);
396                 input_buf = strtok_r(NULL, "\n", &saveptr);
397             }
398             free(conf_copy);
399         }
400     }
401 
402     return ret;
403 }
404 
405 /*===========================================================================
406 FUNCTION loc_read_conf
407 
408 DESCRIPTION
409    Reads the specified configuration file and sets defined values based on
410    the passed in configuration table. This table maps strings to values to
411    set along with the type of each of these values.
412 
413 PARAMETERS:
414    conf_file_name: configuration file to read
415    config_table: table definition of strings to places to store information
416    table_length: length of the configuration table
417 
418 DEPENDENCIES
419    N/A
420 
421 RETURN VALUE
422    None
423 
424 SIDE EFFECTS
425    N/A
426 ===========================================================================*/
loc_read_conf(const char * conf_file_name,const loc_param_s_type * config_table,uint32_t table_length)427 void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_table,
428                    uint32_t table_length)
429 {
430     FILE *conf_fp = NULL;
431 
432     if((conf_fp = fopen(conf_file_name, "r")) != NULL)
433     {
434         LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
435         if(table_length && config_table) {
436             loc_read_conf_r(conf_fp, config_table, table_length);
437             rewind(conf_fp);
438         }
439         loc_read_conf_r(conf_fp, loc_param_table, loc_param_num);
440         fclose(conf_fp);
441     }
442     /* Initialize logging mechanism with parsed data */
443     loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
444 }
445 
446 /*=============================================================================
447  *
448  *   Define and Structures for Parsing Location Process Configuration File
449  *
450  *============================================================================*/
451 #define MAX_NUM_STRINGS   20
452 
453 //We can have 8 masks for now
454 #define CONFIG_MASK_TARGET_ALL           0X01
455 #define CONFIG_MASK_TARGET_FOUND         0X02
456 #define CONFIG_MASK_TARGET_CHECK         0X03
457 #define CONFIG_MASK_BASEBAND_ALL         0X04
458 #define CONFIG_MASK_BASEBAND_FOUND       0X08
459 #define CONFIG_MASK_BASEBAND_CHECK       0x0c
460 #define CONFIG_MASK_AUTOPLATFORM_ALL     0x10
461 #define CONFIG_MASK_AUTOPLATFORM_FOUND   0x20
462 #define CONFIG_MASK_AUTOPLATFORM_CHECK   0x30
463 
464 #define LOC_FEATURE_MASK_GTP_WIFI_BASIC            0x01
465 #define LOC_FEATURE_MASK_GTP_WIFI_PREMIUM          0X02
466 #define LOC_FEATURE_MASK_GTP_CELL_BASIC            0X04
467 #define LOC_FEATURE_MASK_GTP_CELL_PREMIUM          0X08
468 #define LOC_FEATURE_MASK_SAP_BASIC                 0x40
469 #define LOC_FEATURE_MASK_SAP_PREMIUM               0X80
470 #define LOC_FEATURE_MASK_GTP_WAA_BASIC             0X100
471 #define LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC      0X400
472 #define LOC_FEATURE_MASK_ODCPI                     0x1000
473 #define LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT     0x2000
474 #define LOC_FEATURE_MASK_SUPL_WIFI                 0x4000
475 #define LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO      0x8000
476 
477 typedef struct {
478     char proc_name[LOC_MAX_PARAM_STRING];
479     char proc_argument[LOC_MAX_PARAM_STRING];
480     char proc_status[LOC_MAX_PARAM_STRING];
481     char group_list[LOC_MAX_PARAM_STRING];
482     unsigned int premium_feature;
483     unsigned int loc_feature_mask;
484     char platform_list[LOC_MAX_PARAM_STRING];
485     char baseband[LOC_MAX_PARAM_STRING];
486     unsigned int sglte_target;
487     char feature_gtp_mode[LOC_MAX_PARAM_STRING];
488     char feature_gtp_waa[LOC_MAX_PARAM_STRING];
489     char feature_sap[LOC_MAX_PARAM_STRING];
490     char feature_odcpi[LOC_MAX_PARAM_STRING];
491     char feature_free_wifi_scan_inject[LOC_MAX_PARAM_STRING];
492     char feature_supl_wifi[LOC_MAX_PARAM_STRING];
493     char feature_wifi_supplicant_info[LOC_MAX_PARAM_STRING];
494     char auto_platform[LOC_MAX_PARAM_STRING];
495     unsigned int vendor_enhanced_process;
496 } loc_launcher_conf;
497 
498 /* process configuration parameters */
499 static loc_launcher_conf conf;
500 
501 /* gps.conf Parameter spec table */
502 static const loc_param_s_type gps_conf_parameter_table[] = {
503     {"SGLTE_TARGET",        &conf.sglte_target,           NULL, 'n'},
504 };
505 
506 /* location feature conf, e.g.: izat.conf feature mode table*/
507 static const loc_param_s_type loc_feature_conf_table[] = {
508     {"GTP_MODE",              &conf.feature_gtp_mode,               NULL, 's'},
509     {"GTP_WAA",               &conf.feature_gtp_waa,                NULL, 's'},
510     {"SAP",                   &conf.feature_sap,                    NULL, 's'},
511     {"ODCPI",                 &conf.feature_odcpi,                  NULL, 's'},
512     {"FREE_WIFI_SCAN_INJECT", &conf.feature_free_wifi_scan_inject,  NULL, 's'},
513     {"SUPL_WIFI",             &conf.feature_supl_wifi,              NULL, 's'},
514     {"WIFI_SUPPLICANT_INFO",  &conf.feature_wifi_supplicant_info,   NULL, 's'},
515 };
516 
517 /* location process conf, e.g.: izat.conf Parameter spec table */
518 static const loc_param_s_type loc_process_conf_parameter_table[] = {
519     {"PROCESS_NAME",               &conf.proc_name,                NULL, 's'},
520     {"PROCESS_ARGUMENT",           &conf.proc_argument,            NULL, 's'},
521     {"PROCESS_STATE",              &conf.proc_status,              NULL, 's'},
522     {"PROCESS_GROUPS",             &conf.group_list,               NULL, 's'},
523     {"PREMIUM_FEATURE",            &conf.premium_feature,          NULL, 'n'},
524     {"IZAT_FEATURE_MASK",          &conf.loc_feature_mask,         NULL, 'n'},
525     {"PLATFORMS",                  &conf.platform_list,            NULL, 's'},
526     {"BASEBAND",                   &conf.baseband,                 NULL, 's'},
527     {"HARDWARE_TYPE",              &conf.auto_platform,            NULL, 's'},
528     {"VENDOR_ENHANCED_PROCESS",    &conf.vendor_enhanced_process,  NULL, 'n'},
529 };
530 
531 /*===========================================================================
532 FUNCTION loc_read_process_conf
533 
534 DESCRIPTION
535    Parse the specified conf file and return info for the processes defined.
536    The format of the file should conform with izat.conf.
537 
538 PARAMETERS:
539    conf_file_name: configuration file to read
540    process_count_ptr: pointer to store number of processes defined in the conf file.
541    process_info_table_ptr: pointer to store the process info table.
542 
543 DEPENDENCIES
544    The file must be in izat.conf format.
545 
546 RETURN VALUE
547    0: success
548    none-zero: failure
549 
550 SIDE EFFECTS
551    N/A
552 
553 NOTES:
554    On success, memory pointed by (*process_info_table_ptr) must be freed.
555 ===========================================================================*/
loc_read_process_conf(const char * conf_file_name,uint32_t * process_count_ptr,loc_process_info_s_type ** process_info_table_ptr)556 int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_ptr,
557                           loc_process_info_s_type** process_info_table_ptr) {
558     loc_process_info_s_type *child_proc = nullptr;
559     volatile int i=0;
560     unsigned int j=0;
561     gid_t gid_list[LOC_PROCESS_MAX_NUM_GROUPS];
562     char *split_strings[MAX_NUM_STRINGS];
563     int name_length=0, group_list_length=0, platform_length=0, baseband_length=0, ngroups=0, ret=0;
564     int auto_platform_length = 0;
565     int group_index=0, nstrings=0, status_length=0;
566     FILE* conf_fp = nullptr;
567     char platform_name[PROPERTY_VALUE_MAX], baseband_name[PROPERTY_VALUE_MAX];
568     char autoplatform_name[PROPERTY_VALUE_MAX];
569     unsigned int loc_service_mask=0;
570     char config_mask = 0;
571     unsigned char proc_list_length=0;
572     int gtp_cell_ap_enabled = 0;
573     char arg_gtp_waa[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
574     char arg_gtp_modem_cell[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
575     char arg_gtp_wifi[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
576     char arg_sap[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
577     char arg_disabled[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_DISABLED;
578     char arg_basic[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_BASIC;
579     char arg_premium[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_PREMIUM;
580 
581     if (process_count_ptr == NULL || process_info_table_ptr == NULL) {
582         return -1;
583     }
584 
585     //Read gps.conf and fill parameter table
586     UTIL_READ_CONF(LOC_PATH_GPS_CONF, gps_conf_parameter_table);
587 
588     //Form argument strings
589     strlcat(arg_gtp_waa, LOC_FEATURE_GTP_WAA, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
590     strlcat(arg_gtp_modem_cell, LOC_FEATURE_GTP_MODEM_CELL, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
591     strlcat(arg_gtp_wifi, LOC_FEATURE_GTP_WIFI, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
592     strlcat(arg_sap, LOC_FEATURE_SAP, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
593 
594     //Get platform name from ro.board.platform property
595     loc_get_platform_name(platform_name, sizeof(platform_name));
596     //Get baseband name from ro.baseband property
597     loc_get_target_baseband(baseband_name, sizeof(baseband_name));
598     //Identify if this is an automotive platform
599     loc_get_auto_platform_name(autoplatform_name,sizeof(autoplatform_name));
600 
601     UTIL_READ_CONF(conf_file_name, loc_feature_conf_table);
602 
603     //Set service mask for GTP_MODE
604     if(strcmp(conf.feature_gtp_mode, "DISABLED") == 0) {
605         LOC_LOGD("%s:%d]: GTP MODE DISABLED", __func__, __LINE__);
606     }
607     else if(strcmp(conf.feature_gtp_mode, "LEGACY_WWAN") == 0) {
608         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: LEGACY_WWAN", __func__, __LINE__);
609         loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC;
610     }
611     else if(strcmp(conf.feature_gtp_mode, "SDK") == 0) {
612         LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__);
613         loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC;
614     }
615     //conf file has a garbage value
616     else {
617         LOC_LOGE("%s:%d]: Unrecognized value for GTP MODE Mode."\
618                  " Setting GTP WIFI to default mode: DISABLED", __func__, __LINE__);
619     }
620     //Set service mask for GTP_WAA
621     if(strcmp(conf.feature_gtp_waa, "BASIC") == 0) {
622       LOC_LOGD("%s:%d]: Setting GTP WAA to mode: BASIC", __func__, __LINE__);
623       loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC;
624     }
625     else if(strcmp(conf.feature_gtp_waa, "DISABLED") == 0) {
626       LOC_LOGD("%s:%d]: GTP WAA DISABLED", __func__, __LINE__);
627     }
628     //conf file has a garbage value
629     else {
630       LOC_LOGE("%s:%d]: Unrecognized value for GTP WAA Mode."\
631                " Setting GTP WAA to default mode: DISABLED", __func__, __LINE__);
632     }
633 
634     //Set service mask for SAP
635     if(strcmp(conf.feature_sap, "PREMIUM") == 0) {
636         LOC_LOGD("%s:%d]: Setting SAP to mode: PREMIUM", __func__, __LINE__);
637         loc_service_mask |= LOC_FEATURE_MASK_SAP_PREMIUM;
638     }
639     else if(strcmp(conf.feature_sap, "BASIC") == 0) {
640         LOC_LOGD("%s:%d]: Setting SAP to mode: BASIC", __func__, __LINE__);
641         loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
642     }
643     else if(strcmp(conf.feature_sap, "MODEM_DEFAULT") == 0) {
644         LOC_LOGD("%s:%d]: Setting SAP to mode: MODEM_DEFAULT", __func__, __LINE__);
645     }
646     else if(strcmp(conf.feature_sap, "DISABLED") == 0) {
647         LOC_LOGD("%s:%d]: Setting SAP to mode: DISABLED", __func__, __LINE__);
648     }
649     else {
650        LOC_LOGE("%s:%d]: Unrecognized value for SAP Mode."\
651                 " Setting SAP to default mode: BASIC", __func__, __LINE__);
652        loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
653     }
654 
655     // Set service mask for ODCPI
656     if(strcmp(conf.feature_odcpi, "BASIC") == 0) {
657         LOC_LOGD("%s:%d]: Setting ODCPI to mode: BASIC", __func__, __LINE__);
658         loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
659     }
660     else if(strcmp(conf.feature_odcpi, "DISABLED") == 0) {
661         LOC_LOGD("%s:%d]: Setting ODCPI to mode: DISABLED", __func__, __LINE__);
662     }
663     else if(strcmp(conf.feature_odcpi, "PREMIUM") == 0) {
664         LOC_LOGD("%s:%d]: Unrecognized value for ODCPI mode."\
665             "Setting ODCPI to default mode: BASIC", __func__, __LINE__);
666         loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
667     }
668 
669     // Set service mask for FREE_WIFI_SCAN_INJECT
670     if(strcmp(conf.feature_free_wifi_scan_inject, "BASIC") == 0) {
671         LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: BASIC", __func__, __LINE__);
672         loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
673     }
674     else if(strcmp(conf.feature_free_wifi_scan_inject, "DISABLED") == 0) {
675         LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: DISABLED", __func__, __LINE__);
676     }
677     else if(strcmp(conf.feature_free_wifi_scan_inject, "PREMIUM") == 0) {
678         LOC_LOGD("%s:%d]: Unrecognized value for FREE_WIFI_SCAN_INJECT mode."\
679             "Setting FREE_WIFI_SCAN_INJECT to default mode: BASIC", __func__, __LINE__);
680         loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
681     }
682 
683     // Set service mask for SUPL_WIFI
684     if(strcmp(conf.feature_supl_wifi, "BASIC") == 0) {
685         LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: BASIC", __func__, __LINE__);
686         loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
687     }
688     else if(strcmp(conf.feature_supl_wifi, "DISABLED") == 0) {
689         LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: DISABLED", __func__, __LINE__);
690     }
691     else if(strcmp(conf.feature_supl_wifi, "PREMIUM") == 0) {
692         LOC_LOGD("%s:%d]: Unrecognized value for SUPL_WIFI mode."\
693             "Setting SUPL_WIFI to default mode: BASIC", __func__, __LINE__);
694         loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
695     }
696 
697     // Set service mask for WIFI_SUPPLICANT_INFO
698     if(strcmp(conf.feature_wifi_supplicant_info, "BASIC") == 0) {
699         LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: BASIC", __func__, __LINE__);
700         loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
701     }
702     else if(strcmp(conf.feature_wifi_supplicant_info, "DISABLED") == 0) {
703         LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: DISABLED", __func__, __LINE__);
704     }
705     else if(strcmp(conf.feature_wifi_supplicant_info, "PREMIUM") == 0) {
706         LOC_LOGD("%s:%d]: Unrecognized value for WIFI_SUPPLICANT_INFO mode."\
707             "Setting LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO to default mode: BASIC", __func__, __LINE__);
708         loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
709     }
710 
711     LOC_LOGD("%s:%d]: loc_service_mask: %x\n", __func__, __LINE__, loc_service_mask);
712 
713     if((conf_fp = fopen(conf_file_name, "r")) == NULL) {
714         LOC_LOGE("%s:%d]: Error opening %s %s\n", __func__,
715                  __LINE__, conf_file_name, strerror(errno));
716         ret = -1;
717         goto err;
718     }
719 
720     //Parse through the file to find out how many processes are to be launched
721     proc_list_length = 0;
722     do {
723         conf.proc_name[0] = 0;
724         //Here note that the 3rd parameter is passed as 1.
725         //This is so that only the first parameter in the table which is "PROCESS_NAME"
726         //is read. We do not want to read the entire block of parameters at this time
727         //since we are only counting the number of processes to launch.
728         //Therefore, only counting the occurrences of PROCESS_NAME parameter
729         //should suffice
730         if(loc_read_conf_r(conf_fp, loc_process_conf_parameter_table, 1)) {
731             LOC_LOGE("%s:%d]: Unable to read conf file. Failing\n", __func__, __LINE__);
732             ret = -1;
733             goto err;
734         }
735         name_length=(int)strlen(conf.proc_name);
736         if(name_length) {
737             proc_list_length++;
738             LOC_LOGD("Process name:%s", conf.proc_name);
739         }
740     } while(name_length);
741     LOC_LOGD("Process cnt = %d", proc_list_length);
742 
743     child_proc = (loc_process_info_s_type *)calloc(proc_list_length, sizeof(loc_process_info_s_type));
744     if(child_proc == NULL) {
745         LOC_LOGE("%s:%d]: ERROR: Malloc returned NULL\n", __func__, __LINE__);
746         ret = -1;
747         goto err;
748     }
749 
750     //Move file descriptor to the beginning of the file
751     //so that the parameters can be read
752     rewind(conf_fp);
753 
754     for(j=0; j<proc_list_length; j++) {
755         //Set defaults for all the child process structs
756         child_proc[j].proc_status = DISABLED;
757         memset(child_proc[j].group_list, 0, sizeof(child_proc[j].group_list));
758         config_mask=0;
759         if(loc_read_conf_r(conf_fp, loc_process_conf_parameter_table,
760                            sizeof(loc_process_conf_parameter_table)/sizeof(loc_process_conf_parameter_table[0]))) {
761             LOC_LOGE("%s:%d]: Unable to read conf file. Failing\n", __func__, __LINE__);
762             ret = -1;
763             goto err;
764         }
765 
766         name_length=(int)strlen(conf.proc_name);
767         group_list_length=(int)strlen(conf.group_list);
768         platform_length = (int)strlen(conf.platform_list);
769         baseband_length = (int)strlen(conf.baseband);
770         status_length = (int)strlen(conf.proc_status);
771         auto_platform_length = (int)strlen(conf.auto_platform);
772 
773         if(!name_length || !group_list_length || !platform_length ||
774            !baseband_length || !status_length || !auto_platform_length) {
775             LOC_LOGE("%s:%d]: Error: i: %d; One of the parameters not specified in conf file",
776                      __func__, __LINE__, i);
777             continue;
778         }
779 
780         if (!isVendorEnhanced() && (conf.vendor_enhanced_process != 0)) {
781             LOC_LOGD("%s:%d]: Process %s is disabled via vendor enhanced process check",
782                      __func__, __LINE__, conf.proc_name);
783             child_proc[j].proc_status = DISABLED_VIA_VENDOR_ENHANCED_CHECK;
784             continue;
785         }
786 
787         if(strcmp(conf.proc_status, "DISABLED") == 0) {
788             LOC_LOGD("%s:%d]: Process %s is disabled in conf file",
789                      __func__, __LINE__, conf.proc_name);
790             child_proc[j].proc_status = DISABLED_FROM_CONF;
791             continue;
792         }
793         else if(strcmp(conf.proc_status, "ENABLED") == 0) {
794             LOC_LOGD("%s:%d]: Process %s is enabled in conf file",
795                      __func__, __LINE__, conf.proc_name);
796         }
797 
798         //Since strlcpy copies length-1 characters, we add 1 to name_length
799         if((name_length+1) > LOC_MAX_PARAM_STRING) {
800             LOC_LOGE("%s:%d]: i: %d; Length of name parameter too long. Max length: %d",
801                      __func__, __LINE__, i, LOC_MAX_PARAM_STRING);
802             continue;
803         }
804         strlcpy(child_proc[j].name[0], conf.proc_name, sizeof (child_proc[j].name[0]));
805 
806         child_proc[j].num_groups = 0;
807         ngroups = loc_util_split_string(conf.group_list, split_strings, MAX_NUM_STRINGS, ' ');
808         for(i=0; i<ngroups; i++) {
809             struct group* grp = getgrnam(split_strings[i]);
810             if (grp) {
811                 child_proc[j].group_list[child_proc[j].num_groups] = grp->gr_gid;
812                 child_proc[j].num_groups++;
813                 LOC_LOGd("Group %s = %d", split_strings[i], grp->gr_gid);
814             }
815         }
816 
817         nstrings = loc_util_split_string(conf.platform_list, split_strings, MAX_NUM_STRINGS, ' ');
818         if(strcmp("all", split_strings[0]) == 0) {
819             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
820                 LOC_LOGD("%s:%d]: Enabled for all targets\n", __func__, __LINE__);
821                 config_mask |= CONFIG_MASK_TARGET_ALL;
822             }
823             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
824                 config_mask |= CONFIG_MASK_TARGET_FOUND;
825                 for (i=2; i<nstrings; i++) {
826                     if(strcmp(platform_name, split_strings[i]) == 0) {
827                         LOC_LOGD("%s:%d]: Disabled platform %s\n", __func__, __LINE__, platform_name);
828                         config_mask &= ~CONFIG_MASK_TARGET_FOUND;
829                         break;
830                     }
831                 }
832             }
833         }
834         else {
835             for(i=0; i<nstrings; i++) {
836                 if(strcmp(platform_name, split_strings[i]) == 0) {
837                     LOC_LOGD("%s:%d]: Matched platform: %s\n",
838                              __func__, __LINE__, split_strings[i]);
839                     config_mask |= CONFIG_MASK_TARGET_FOUND;
840                     break;
841                 }
842             }
843         }
844 
845         nstrings = loc_util_split_string(conf.baseband, split_strings, MAX_NUM_STRINGS, ' ');
846         if(strcmp("all", split_strings[0]) == 0) {
847             if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
848                 LOC_LOGD("%s:%d]: Enabled for all basebands\n", __func__, __LINE__);
849                 config_mask |= CONFIG_MASK_BASEBAND_ALL;
850             }
851             else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
852                 config_mask |= CONFIG_MASK_BASEBAND_FOUND;
853                 for (i=2; i<nstrings; i++) {
854                     if(strcmp(baseband_name, split_strings[i]) == 0) {
855                         LOC_LOGD("%s:%d]: Disabled band %s\n", __func__, __LINE__, baseband_name);
856                         config_mask &= ~CONFIG_MASK_BASEBAND_FOUND;
857                         break;
858                     }
859                 }
860             }
861         }
862         else {
863             for(i=0; i<nstrings; i++) {
864                 if(strcmp(baseband_name, split_strings[i]) == 0) {
865                     LOC_LOGD("%s:%d]: Matched baseband: %s\n",
866                              __func__, __LINE__, split_strings[i]);
867                     config_mask |= CONFIG_MASK_BASEBAND_FOUND;
868                     break;
869                 }
870                 //Since ro.baseband is not a reliable source for detecting sglte
871                 //the alternative is to read the SGLTE_TARGET parameter from gps.conf
872                 //this parameter is read into conf_sglte_target
873                 else if((strcmp("sglte", split_strings[i]) == 0 ) && conf.sglte_target) {
874                     LOC_LOGD("%s:%d]: Matched baseband SGLTE\n", __func__, __LINE__);
875                     config_mask |= CONFIG_MASK_BASEBAND_FOUND;
876                     break;
877                 }
878             }
879         }
880 
881         nstrings = loc_util_split_string(conf.auto_platform, split_strings, MAX_NUM_STRINGS, ' ');
882         if(strcmp("all", split_strings[0]) == 0) {
883             LOC_LOGD("%s:%d]: Enabled for all auto platforms\n", __func__, __LINE__);
884             config_mask |= CONFIG_MASK_AUTOPLATFORM_ALL;
885         }
886         else {
887             for(i=0; i<nstrings; i++) {
888                 if(strcmp(autoplatform_name, split_strings[i]) == 0) {
889                     LOC_LOGD("%s:%d]: Matched auto platform: %s\n",
890                              __func__, __LINE__, split_strings[i]);
891                     config_mask |= CONFIG_MASK_AUTOPLATFORM_FOUND;
892                     break;
893                 }
894             }
895         }
896 
897         if((config_mask & CONFIG_MASK_TARGET_CHECK) &&
898            (config_mask & CONFIG_MASK_BASEBAND_CHECK) &&
899            (config_mask & CONFIG_MASK_AUTOPLATFORM_CHECK) &&
900            (child_proc[j].proc_status != DISABLED_FROM_CONF) &&
901            (child_proc[j].proc_status != DISABLED_VIA_VENDOR_ENHANCED_CHECK)) {
902 
903             //Set args
904             //The first argument passed through argv is usually the name of the
905             //binary when started from commandline.
906             //getopt() seems to ignore this first argument and hence we assign it
907             //to the process name for consistency with command line args
908             i = 0;
909             char* temp_arg = ('/' == child_proc[j].name[0][0]) ?
910                 (strrchr(child_proc[j].name[0], '/') + 1) : child_proc[j].name[0];
911             strlcpy (child_proc[j].args[i++], temp_arg, sizeof (child_proc[j].args[i++]));
912 
913             if(conf.premium_feature) {
914                if(conf.loc_feature_mask & loc_service_mask) {
915                     LOC_LOGD("%s:%d]: Enabled. %s has service mask: %x\n",
916                              __func__, __LINE__, child_proc[j].name[0], conf.loc_feature_mask);
917                     child_proc[j].proc_status = ENABLED;
918 
919                     if(conf.loc_feature_mask &
920                        (LOC_FEATURE_MASK_GTP_WIFI_BASIC | LOC_FEATURE_MASK_GTP_WIFI_PREMIUM)) {
921                         if(loc_service_mask & LOC_FEATURE_MASK_GTP_WIFI_BASIC) {
922                             strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
923                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
924                             strlcpy(child_proc[j].args[i++], arg_basic,
925                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
926                         }
927                         else if(loc_service_mask & LOC_FEATURE_MASK_GTP_WIFI_PREMIUM) {
928                             strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
929                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
930                             strlcpy(child_proc[j].args[i++], arg_premium,
931                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
932                         }
933                         else
934                         {
935                             strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
936                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
937                             strlcpy(child_proc[j].args[i++], arg_disabled,
938                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
939                         }
940                     }
941                     if(conf.loc_feature_mask &
942                        (LOC_FEATURE_MASK_GTP_CELL_BASIC | LOC_FEATURE_MASK_GTP_CELL_PREMIUM )) {
943                         if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) {
944                             strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell,
945                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
946                             strlcpy(child_proc[j].args[i++], arg_basic,
947                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
948                         }
949                         else {
950                              strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell,
951                                      LOC_PROCESS_MAX_ARG_STR_LENGTH);
952                              strlcpy(child_proc[j].args[i++], arg_disabled,
953                                      LOC_PROCESS_MAX_ARG_STR_LENGTH);
954                        }
955                     }
956                     if(conf.loc_feature_mask &
957                        (LOC_FEATURE_MASK_SAP_BASIC | LOC_FEATURE_MASK_SAP_PREMIUM)) {
958                         if(loc_service_mask & LOC_FEATURE_MASK_SAP_BASIC) {
959                             strlcpy(child_proc[j].args[i++], arg_sap,
960                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
961                             strlcpy(child_proc[j].args[i++], arg_basic,
962                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
963                         }
964                         else if(loc_service_mask & LOC_FEATURE_MASK_SAP_PREMIUM) {
965                             strlcpy(child_proc[j].args[i++], arg_sap,
966                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
967                             strlcpy(child_proc[j].args[i++], arg_premium,
968                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
969                         }
970                         else
971                         {
972                             strlcpy(child_proc[j].args[i++], arg_sap,
973                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
974                             strlcpy(child_proc[j].args[i++], arg_disabled,
975                                     LOC_PROCESS_MAX_ARG_STR_LENGTH);
976                         }
977                     }
978 
979                     if(conf.loc_feature_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) {
980                       if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) {
981                         strlcpy(child_proc[j].args[i++], arg_gtp_waa,
982                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
983                         strlcpy(child_proc[j].args[i++], arg_basic,
984                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
985                       }
986                       else
987                       {
988                         strlcpy(child_proc[j].args[i++], arg_gtp_waa,
989                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
990                         strlcpy(child_proc[j].args[i++], arg_disabled,
991                                 LOC_PROCESS_MAX_ARG_STR_LENGTH);
992                       }
993                     }
994                     IF_LOC_LOGD {
995                         LOC_LOGD("%s:%d]: %s args\n", __func__, __LINE__, child_proc[j].name[0]);
996                         for(unsigned int k=0; k<LOC_PROCESS_MAX_NUM_ARGS; k++) {
997                             if(child_proc[j].args[k][0] != '\0') {
998                                 LOC_LOGD("%s:%d]: k: %d, %s\n", __func__, __LINE__, k,
999                                          child_proc[j].args[k]);
1000                             }
1001                         }
1002                         LOC_LOGD("%s:%d]: \n", __func__, __LINE__);
1003                     }
1004                 }
1005                 else {
1006                     LOC_LOGD("%s:%d]: Disabled. %s has service mask:  %x \n",
1007                              __func__, __LINE__, child_proc[j].name[0], conf.loc_feature_mask);
1008                 }
1009             }
1010             else {
1011                 LOC_LOGD("%s:%d]: %s not a premium feature. Enabled\n",
1012                          __func__, __LINE__, child_proc[j].name[0]);
1013                 child_proc[j].proc_status = ENABLED;
1014             }
1015 
1016             /*Fill up the remaining arguments from configuration file*/
1017             LOC_LOGD("%s] Parsing Process_Arguments from Configuration: %s \n",
1018                       __func__, conf.proc_argument);
1019             if(0 != conf.proc_argument[0])
1020             {
1021                 /**************************************
1022                 ** conf_proc_argument is shared by all the programs getting launched,
1023                 ** hence copy to process specific argument string and parse the same.
1024                 ***************************************/
1025                 strlcpy(child_proc[j].argumentString, conf.proc_argument,
1026                         sizeof(child_proc[j].argumentString));
1027                 char *temp_args[LOC_PROCESS_MAX_NUM_ARGS];
1028                 memset (temp_args, 0, sizeof (temp_args));
1029                 loc_util_split_string(child_proc[j].argumentString, &temp_args[i],
1030                                       (LOC_PROCESS_MAX_NUM_ARGS - i), ' ');
1031                 // copy argument from the pointer to the memory
1032                 for (unsigned int index = i; index < LOC_PROCESS_MAX_NUM_ARGS; index++) {
1033                     if (temp_args[index] == NULL) {
1034                         break;
1035                     }
1036                     strlcpy (child_proc[j].args[index], temp_args[index],
1037                              sizeof (child_proc[j].args[index]));
1038                 }
1039             }
1040         }
1041         else {
1042             LOC_LOGD("%s:%d]: Process %s is disabled\n",
1043                      __func__, __LINE__, child_proc[j].name[0]);
1044         }
1045     }
1046 
1047 err:
1048     if (conf_fp) {
1049         fclose(conf_fp);
1050     }
1051     if (ret != 0) {
1052         LOC_LOGE("%s:%d]: ret: %d", __func__, __LINE__, ret);
1053         if (child_proc) {
1054             free (child_proc);
1055             child_proc = nullptr;
1056         }
1057         *process_count_ptr = 0;
1058         *process_info_table_ptr = nullptr;
1059 
1060     }
1061     else {
1062         *process_count_ptr = proc_list_length;
1063         *process_info_table_ptr = child_proc;
1064     }
1065 
1066     return ret;
1067 }
1068