//-------------------------------------------------------------------------------------------------- bool proc_IsRealtime ( proc_Ref_t procRef ///< [IN] The process reference. ) { // Read the priority setting from the config tree. le_cfg_IteratorRef_t procCfg = le_cfg_CreateReadTxn(procRef->cfgPathRoot); char priorStr[LIMIT_MAX_PRIORITY_NAME_BYTES]; le_result_t result = le_cfg_GetString(procCfg, CFG_NODE_PRIORITY, priorStr, sizeof(priorStr), "medium"); le_cfg_CancelTxn(procCfg); if ( (result == LE_OK) && (priorStr[0] == 'r') && (priorStr[1] == 't') ) { return true; } return false; }
// ------------------------------------------------------------------------------------------------- static json_t* CreateJsonNodeFromIterator ( le_cfg_IteratorRef_t iterRef ///< The iterator to read from. ) // ------------------------------------------------------------------------------------------------- { char nodeName[LE_CFG_NAME_LEN_BYTES] = ""; le_cfg_nodeType_t type = le_cfg_GetNodeType(iterRef, ""); le_cfg_GetNodeName(iterRef, "", nodeName, sizeof(nodeName)); json_t* nodePtr = CreateJsonNode(nodeName, NodeTypeStr(type)); switch (type) { case LE_CFG_TYPE_EMPTY: json_object_set_new(nodePtr, JSON_FIELD_TYPE, json_string(NodeTypeStr(LE_CFG_TYPE_STEM))); json_object_set_new(nodePtr, JSON_FIELD_CHILDREN, json_array()); break; case LE_CFG_TYPE_BOOL: json_object_set_new(nodePtr, JSON_FIELD_VALUE, json_boolean(le_cfg_GetBool(iterRef, "", false))); break; case LE_CFG_TYPE_STRING: { char strBuffer[LE_CFG_STR_LEN_BYTES] = ""; le_cfg_GetString(iterRef, "", strBuffer, LE_CFG_STR_LEN_BYTES, ""); json_object_set_new(nodePtr, JSON_FIELD_VALUE, json_string(strBuffer)); } break; case LE_CFG_TYPE_INT: json_object_set_new(nodePtr, JSON_FIELD_VALUE, json_integer(le_cfg_GetInt(iterRef, "", false))); break; case LE_CFG_TYPE_FLOAT: json_object_set_new(nodePtr, JSON_FIELD_VALUE, json_real(le_cfg_GetFloat(iterRef, "", false))); break; case LE_CFG_TYPE_STEM: default: // Unknown type, nothing to do json_decref(nodePtr); nodePtr = NULL; break; } return nodePtr; }
//-------------------------------------------------------------------------------------------------- static void LoadECallSettings ( int32_t* hMinAccuracyPtr, int32_t* dirMinAccuracyPtr ) { char psapStr[LE_MDMDEFS_PHONE_NUM_MAX_BYTES] = {0}; LE_DEBUG("Start reading eCall app settings in Configuration Tree"); le_cfg_IteratorRef_t eCallCfgRef = le_cfg_CreateReadTxn(CFG_ECALL_APP_PATH); // Get PSAP if (le_cfg_NodeExists(eCallCfgRef, CFG_NODE_PSAP)) { if ( le_cfg_GetString(eCallCfgRef, CFG_NODE_PSAP, psapStr, sizeof(psapStr), "") != LE_OK ) { LE_FATAL("No node value set for '%s', exit the app!", CFG_NODE_PSAP); } LE_DEBUG("eCall settings, PSAP number is %s", psapStr); if (le_ecall_SetPsapNumber(psapStr) != LE_OK) { LE_FATAL("Cannot set PSAP number, exit the app!"); } } else { LE_FATAL("No value set for '%s', restart the app!", CFG_NODE_PSAP); } // Get minimum horizontal accuracy if (le_cfg_NodeExists(eCallCfgRef, CFG_NODE_H_MIN_ACCURACY)) { *hMinAccuracyPtr = le_cfg_GetInt(eCallCfgRef, CFG_NODE_H_MIN_ACCURACY, DEFAULT_H_ACCURACY); LE_DEBUG("eCall app settings, horizontal accuracy is %d meter(s)", *hMinAccuracyPtr); } else { *hMinAccuracyPtr = DEFAULT_H_ACCURACY; } // Get minimum direction accuracy if (le_cfg_NodeExists(eCallCfgRef, CFG_NODE_DIR_MIN_ACCURACY)) { *dirMinAccuracyPtr = le_cfg_GetInt(eCallCfgRef, CFG_NODE_DIR_MIN_ACCURACY, DEFAULT_DIR_ACCURACY); LE_DEBUG("eCall app settings, direction accuracy is %d degree(s)", *dirMinAccuracyPtr); } else { *dirMinAccuracyPtr = DEFAULT_DIR_ACCURACY; } le_cfg_CancelTxn(eCallCfgRef); }
//-------------------------------------------------------------------------------------------------- LE_SHARED appCfg_FaultAction_t appCfg_GetProcFaultAction ( appCfg_Iter_t procIterRef ///< [IN] Apps iterator ) { CheckFor(procIterRef, ITER_TYPE_PROC); char faultActionStr[LIMIT_MAX_FAULT_ACTION_NAME_BYTES]; le_result_t result = le_cfg_GetString(procIterRef->cfgIter, CFG_NODE_FAULT_ACTION, faultActionStr, sizeof(faultActionStr), ""); if (result != LE_OK) { LE_CRIT("Fault action string for process is too long. Assume fault action is 'ignore'."); return APPCFG_FAULT_ACTION_IGNORE; } if (strcmp(faultActionStr, RESTART_STR) == 0) { return APPCFG_FAULT_ACTION_RESTART; } if (strcmp(faultActionStr, RESTART_APP_STR) == 0) { return APPCFG_FAULT_ACTION_RESTART_APP; } if (strcmp(faultActionStr, STOP_APP_STR) == 0) { return APPCFG_FAULT_ACTION_STOP_APP; } if (strcmp(faultActionStr, REBOOT_STR) == 0) { return APPCFG_FAULT_ACTION_REBOOT; } if (strcmp(faultActionStr, IGNORE_STR) == 0) { return APPCFG_FAULT_ACTION_IGNORE; } LE_WARN("Unrecognized fault action '%s'. Defaulting to fault action 'ignore'.", faultActionStr); return APPCFG_FAULT_ACTION_IGNORE; }
//-------------------------------------------------------------------------------------------------- static le_result_t LoadRatList ( const char *ratPath, uint32_t *ratMaskPtr ) { uint32_t idx=0; LE_DEBUG("Load Rat Preference <%s>",ratPath); le_cfg_IteratorRef_t ratCfg = le_cfg_CreateReadTxn(ratPath); *ratMaskPtr = 0; do { // Get the node name. char ratNodeName[LIMIT_MAX_PATH_BYTES] = {0}; char ratNodeValue[LIMIT_MAX_PATH_BYTES] = {0}; sprintf(ratNodeName,PATTERN_RAT"%d",idx); // This is the exist state for the loop if (le_cfg_IsEmpty(ratCfg, ratNodeName)) { LE_DEBUG("'%s' does not exist. stop reading configuration", ratNodeName); break; } if ( le_cfg_GetString(ratCfg,ratNodeName,ratNodeValue,sizeof(ratNodeValue), "") != LE_OK ) { LE_WARN("Node value string for '%s' too large.",ratNodeName); le_cfg_CancelTxn(ratCfg); return LE_NOT_POSSIBLE; } if ( strncmp(ratNodeName,"",sizeof(ratNodeName)) == 0 ) { LE_WARN("No node value set for '%s'",ratNodeName); le_cfg_CancelTxn(ratCfg); return LE_NOT_POSSIBLE; } *ratMaskPtr |= ConvertRatValue(ratNodeValue); ++idx; } while (true); le_cfg_CancelTxn(ratCfg); return LE_OK; }
//-------------------------------------------------------------------------------------------------- LE_SHARED le_result_t appCfg_GetProcExecName ( appCfg_Iter_t procIterRef, ///< [IN] Apps iterator char* bufPtr, ///< [OUT] Buffer to store the app name. size_t bufSize ///< [IN] Size of the buffer. ) { CheckFor(procIterRef, ITER_TYPE_PROC); if (le_cfg_NodeExists(procIterRef->cfgIter, "") == false) { return LE_NOT_FOUND; } return le_cfg_GetString(procIterRef->cfgIter, CFG_PROC_EXEC_NAME, bufPtr, bufSize, ""); }
//-------------------------------------------------------------------------------------------------- LE_SHARED le_result_t appCfg_GetVersion ( appCfg_Iter_t appIterRef, ///< [IN] Apps iterator char* bufPtr, ///< [OUT] Buffer to store the app version. size_t bufSize ///< [IN] Size of the buffer. ) { CheckFor(appIterRef, ITER_TYPE_APP); if (le_cfg_NodeExists(appIterRef->cfgIter, "") == false) { return LE_NOT_FOUND; } return le_cfg_GetString(appIterRef->cfgIter, CFG_APP_VERSION, bufPtr, bufSize, ""); }
//-------------------------------------------------------------------------------------------------- static le_result_t GetEnvironmentVariables ( proc_Ref_t procRef, ///< [IN] The process to get the environment variables for. EnvVar_t envVars[], ///< [IN] The list of environment variables. size_t maxNumEnvVars ///< [IN] The maximum number of items envVars can hold. ) { le_cfg_IteratorRef_t procCfg = le_cfg_CreateReadTxn(procRef->cfgPathRoot); le_cfg_GoToNode(procCfg, CFG_NODE_ENV_VARS); if (le_cfg_GoToFirstChild(procCfg) != LE_OK) { LE_WARN("No environment variables for process '%s'.", procRef->name); le_cfg_CancelTxn(procCfg); return LE_NOT_FOUND; } int i; for (i = 0; i < maxNumEnvVars; i++) { if ( (le_cfg_GetNodeName(procCfg, "", envVars[i].name, LIMIT_MAX_ENV_VAR_NAME_BYTES) != LE_OK) || (le_cfg_GetString(procCfg, "", envVars[i].value, LIMIT_MAX_PATH_BYTES, "") != LE_OK) ) { LE_ERROR("Error reading environment variables for process '%s'.", procRef->name); le_cfg_CancelTxn(procCfg); return LE_FAULT; } if (le_cfg_GoToNextSibling(procCfg) != LE_OK) { break; } else if (i >= maxNumEnvVars-1) { LE_ERROR("There were too many environment variables for process '%s'.", procRef->name); le_cfg_CancelTxn(procCfg); return LE_FAULT; } } le_cfg_CancelTxn(procCfg); return i + 1; }
static void TestValue ( le_cfg_IteratorRef_t iterRef, const char* valueNamePtr, const char* expectedValue ) { static char strBuffer[STR_SIZE] = { 0 }; le_cfg_GetString(iterRef, valueNamePtr, strBuffer, STR_SIZE, ""); LE_FATAL_IF(strncmp(strBuffer, expectedValue, STR_SIZE) != 0, "Test: %s - Expected '%s' but got '%s' instead.", TestRootDir, expectedValue, strBuffer); }
// ------------------------------------------------------------------------------------------------- static int HandleGetUserFriendly ( const char* nodePathPtr ///< Path to the node in the tree. ) // ------------------------------------------------------------------------------------------------- { // Start a read transaction at the specified node path. Then dump the value, (if any.) le_cfg_IteratorRef_t iterRef = le_cfg_CreateReadTxn(nodePathPtr); switch (le_cfg_GetNodeType(iterRef, "")) { case LE_CFG_TYPE_EMPTY: // Nothing to do here. break; case LE_CFG_TYPE_STEM: DumpTree(iterRef, 0); break; case LE_CFG_TYPE_BOOL: if (le_cfg_GetBool(iterRef, "", false)) { printf("true\n"); } else { printf("false\n"); } break; default: { char nodeValue[LE_CFG_STR_LEN_BYTES] = ""; le_cfg_GetString(iterRef, "", nodeValue, LE_CFG_STR_LEN_BYTES, ""); printf("%s\n", nodeValue); } break; } le_cfg_CancelTxn(iterRef); return EXIT_SUCCESS; }
static void DumpTree(le_cfg_IteratorRef_t iterRef, size_t indent) { if (le_arg_NumArgs() == 1) { return; } static char strBuffer[STR_SIZE] = { 0 }; do { size_t i; for (i = 0; i < indent; i++) { printf(" "); } le_cfg_GetNodeName(iterRef, "", strBuffer, STR_SIZE); le_cfg_nodeType_t type = le_cfg_GetNodeType(iterRef, ""); switch (type) { case LE_CFG_TYPE_STEM: printf("%s/\n", strBuffer); le_cfg_GoToFirstChild(iterRef); DumpTree(iterRef, indent + 2); le_cfg_GoToParent(iterRef); break; case LE_CFG_TYPE_EMPTY: printf("%s~~\n", strBuffer); break; default: printf("%s<%s> == ", strBuffer, NodeTypeStr(iterRef)); le_cfg_GetString(iterRef, "", strBuffer, STR_SIZE, ""); printf("%s\n", strBuffer); break; } } while (le_cfg_GoToNextSibling(iterRef) == LE_OK); }
//-------------------------------------------------------------------------------------------------- wdog_action_WatchdogAction_t proc_GetWatchdogAction ( proc_Ref_t procRef ///< [IN] The process reference. ) { // No actions are performed here. This just looks up the action for this process. // The result is passed back up to app to handle as with fault action. wdog_action_WatchdogAction_t watchdogAction = WATCHDOG_ACTION_NOT_FOUND; { if (procRef->paused) { return WATCHDOG_ACTION_HANDLED; }; // Read the process's fault action from the config tree. le_cfg_IteratorRef_t procCfg = le_cfg_CreateReadTxn(procRef->cfgPathRoot); char watchdogActionStr[LIMIT_MAX_FAULT_ACTION_NAME_BYTES]; le_result_t result = le_cfg_GetString(procCfg, wdog_action_GetConfigNode(), watchdogActionStr, sizeof(watchdogActionStr), ""); le_cfg_CancelTxn(procCfg); // Set the watchdog action based on the fault action string. if (result == LE_OK) { LE_WARN("%s watchdogAction '%s' in proc section", procRef->name, watchdogActionStr); watchdogAction = wdog_action_EnumFromString(watchdogActionStr); if (WATCHDOG_ACTION_ERROR == watchdogAction) { LE_WARN("%s watchdogAction '%s' unknown", procRef->name, watchdogActionStr); } } else { LE_CRIT("Watchdog action string for process '%s' is too long.", procRef->name); watchdogAction = WATCHDOG_ACTION_ERROR; } } return watchdogAction; }
//-------------------------------------------------------------------------------------------------- static void ConfigureGdb ( void ) { le_cfg_ConnectService(); le_cfgAdmin_ConnectService(); // Get a write iterator to the application node. le_cfg_IteratorRef_t cfgIter = le_cfg_CreateWriteTxn("/apps"); le_cfg_GoToNode(cfgIter, AppName); // Check if this is a temporary configuration that was previously created by this or a similar // tool. if (!le_cfg_IsEmpty(cfgIter, CFG_DEBUG_TOOL)) { char debugTool[LIMIT_MAX_PATH_BYTES]; // Don't need to check return code because the value is just informative and does not matter // if it is truncated. le_cfg_GetString(cfgIter, CFG_DEBUG_TOOL, debugTool, sizeof(debugTool), ""); fprintf(stderr, "This application has already been configured for %s debug mode.\n", debugTool); exit(EXIT_FAILURE); } // Write into the config's debug tool node to indicate that this configuration has been modified. le_cfg_SetString(cfgIter, CFG_DEBUG_TOOL, "gdb"); // Add 512K to the maxFileSytemBytes so that we can debug this app in sandboxed mode uint32_t maxBytes; maxBytes = le_cfg_GetInt(cfgIter, "maxFileSystemBytes", DEFAULT_LIMIT_MAX_FILE_SYSTEM_BYTES); maxBytes += ADD_FILE_SYSTEM_BYTES; // add an additional 512KBytes LE_INFO("Resetting maxFileSystemBytes to %d bytes", maxBytes); le_cfg_SetInt(cfgIter, "maxFileSystemBytes", maxBytes); // Add gdbserver and libs to the app's 'requires/files' section. le_cfg_GoToNode(cfgIter, "requires/files"); AddImportFiles(cfgIter, &GdbFilesImports, NUM_ARRAY_MEMBERS(GdbFilesImports)); // Add /proc to the app's dirs section. le_cfg_GoToParent(cfgIter); le_cfg_GoToNode(cfgIter, "dirs"); AddImportFiles(cfgIter, &GdbDirsImports, NUM_ARRAY_MEMBERS(GdbDirsImports)); // Delete the list of processes. le_cfg_GoToParent(cfgIter); le_cfg_GoToParent(cfgIter); int i; for (i = 0; i < NumProcs; i++) { char nodePath[LIMIT_MAX_PATH_BYTES]; int n = snprintf(nodePath, sizeof(nodePath), "procs/%s", ProcNames[i]); INTERNAL_ERR_IF(n >= sizeof(nodePath), "Node name is too long."); INTERNAL_ERR_IF(n < 0, "Format error. %m"); le_cfg_DeleteNode(cfgIter, nodePath); } le_cfg_CommitTxn(cfgIter); }
// ------------------------------------------------------------------------------------------------- static void DumpTree ( le_cfg_IteratorRef_t iterRef, ///< Write out the tree pointed to by this iterator. size_t indent ///< The amount of indentation to use for this item. ) // ------------------------------------------------------------------------------------------------- { // Note that because this is a recursive function, the buffer here is static in order to save on // stack space. The implication here is that we then have to be careful how it is later // accessed. Also, this makes the function not thread safe. But this trade off was made as // this was not intended to be a multi-threaded program. static char strBuffer[LE_CFG_STR_LEN_BYTES] = ""; do { // Quick and dirty way to indent the tree item. size_t i; for (i = 0; i < indent; i++) { printf(" "); } // Simply grab the name and the type of the current node. le_cfg_GetNodeName(iterRef, "", strBuffer, LE_CFG_STR_LEN_BYTES); le_cfg_nodeType_t type = le_cfg_GetNodeType(iterRef, ""); switch (type) { // It's a stem object, so mark this item as being a stem and recurse into the stem's // sub-items. case LE_CFG_TYPE_STEM: printf("%s/\n", strBuffer); le_cfg_GoToFirstChild(iterRef); DumpTree(iterRef, indent + 2); le_cfg_GoToParent(iterRef); // If we got back up to where we started then don't iterate the "root" node's // siblings. if (indent == 0) { return; } break; // The node is empty, so simply mark it as such. case LE_CFG_TYPE_EMPTY: printf("%s<empty>\n", strBuffer); break; case LE_CFG_TYPE_BOOL: { char* value = NULL; if (le_cfg_GetBool(iterRef, "", false)) { value = "true"; } else { value = "false"; } printf("%s<bool> == %s\n", strBuffer, value); } break; // The node has a different type. So write out the name and the type. Then print the // value. default: printf("%s<%s> == ", strBuffer, NodeTypeStr(le_cfg_GetNodeType(iterRef, ""))); le_cfg_GetString(iterRef, "", strBuffer, LE_CFG_STR_LEN_BYTES, ""); printf("%s\n", strBuffer); break; } } while (le_cfg_GoToNextSibling(iterRef) == LE_OK); }
//-------------------------------------------------------------------------------------------------- static proc_FaultAction_t GetFaultAction ( proc_Ref_t procRef ///< [IN] The process reference. ) { if (procRef->cmdKill) { // The cmdKill flag was set which means the process died because we killed it so // it was not a fault. Reset the cmdKill flag so that if this process is restarted // faults will still be caught. procRef->cmdKill = false; return PROC_FAULT_ACTION_NO_FAULT; } // Record the fault time. procRef->faultTime = (le_clk_GetAbsoluteTime()).sec; // Read the process's fault action from the config tree. le_cfg_IteratorRef_t procCfg = le_cfg_CreateReadTxn(procRef->cfgPathRoot); char faultActionStr[LIMIT_MAX_FAULT_ACTION_NAME_BYTES]; le_result_t result = le_cfg_GetString(procCfg, CFG_NODE_FAULT_ACTION, faultActionStr, sizeof(faultActionStr), ""); le_cfg_CancelTxn(procCfg); // Set the fault action based on the fault action string. if (result != LE_OK) { LE_CRIT("Fault action string for process '%s' is too long. Assume fault action is 'ignore'.", procRef->name); return PROC_FAULT_ACTION_IGNORE; } if (strcmp(faultActionStr, RESTART_STR) == 0) { return PROC_FAULT_ACTION_RESTART; } if (strcmp(faultActionStr, RESTART_APP_STR) == 0) { return PROC_FAULT_ACTION_RESTART_APP; } if (strcmp(faultActionStr, STOP_APP_STR) == 0) { return PROC_FAULT_ACTION_STOP_APP; } if (strcmp(faultActionStr, REBOOT_STR) == 0) { return PROC_FAULT_ACTION_REBOOT; } if (strcmp(faultActionStr, IGNORE_STR) == 0) { return PROC_FAULT_ACTION_IGNORE; } LE_WARN("Unrecognized fault action for process '%s'. Assume fault action is 'ignore'.", procRef->name); return PROC_FAULT_ACTION_IGNORE; }
//-------------------------------------------------------------------------------------------------- le_result_t le_cellnet_GetSimPinCode ( le_sim_Id_t simId, ///< [IN] ///< SIM identifier. char* pinCodePtr, ///< [OUT] ///< Read the PIN code from the config tree. size_t pinCodeNumElements ///< [IN] ) { le_result_t result=LE_OK; LE_DEBUG("simId= %d",simId); if (simId >= LE_SIM_ID_MAX) { LE_ERROR("Invalid simId (%d) provided!", simId); result = LE_OUT_OF_RANGE; } else { // Set the configuration path for the SIM. char configPath[LIMIT_MAX_PATH_BYTES]; char simPin[LE_SIM_PIN_MAX_BYTES] = {0}; le_cfg_IteratorRef_t simCfgRef; snprintf(configPath, sizeof(configPath), "%s/%d", CFG_MODEMSERVICE_SIM_PATH, simId); // Check that the app has a configuration value. simCfgRef = le_cfg_CreateReadTxn(configPath); // test if the node exists if (!le_cfg_NodeExists(simCfgRef, CFG_NODE_PIN)) { LE_ERROR("SIM PIN node isn't found in the config tree"); result = LE_NOT_FOUND; } else { //read config tree result = le_cfg_GetString(simCfgRef,CFG_NODE_PIN,simPin,sizeof(simPin),""); if (result != LE_OK) { LE_ERROR("retrieved SIM PIN code exceeds the supplied buffer"); result = LE_OVERFLOW; } else { //void entry is taken into account if ((strncmp(simPin,"",LE_SIM_PIN_MAX_LEN)!=0) && (strlen(simPin) < LE_SIM_PIN_MIN_LEN)) { LE_ERROR("retrieved SIM PIN code is not long enough (min 4 digits) "); result = LE_UNDERFLOW; } else { //copy pincode strncpy ( pinCodePtr, simPin, sizeof(simPin) ); LE_DEBUG("SIM PIN code= %s retrieved OK",pinCodePtr); } } } le_cfg_CancelTxn(simCfgRef); } return result; }
static void StringSizeTest() { le_result_t result; static char pathBuffer[STR_SIZE] = { 0 }; static char parentPathBuffer[STR_SIZE] = { 0 }; static char smallPathBuffer[SMALL_STR_SIZE + 1] = { 0 }; static char smallParentPathBuffer[SMALL_STR_SIZE + 1] = { 0 }; snprintf(pathBuffer, STR_SIZE, "%s/stringSizeTest/strVal", TestRootDir); snprintf(parentPathBuffer, STR_SIZE, "%s/stringSizeTest/", TestRootDir); strncpy(smallPathBuffer, pathBuffer, SMALL_STR_SIZE); strncpy(smallParentPathBuffer, parentPathBuffer, SMALL_STR_SIZE); le_cfg_QuickSetString(pathBuffer, "This is a bigger string than may be usual for this test."); static char buffer[STR_SIZE]; le_cfg_IteratorRef_t iterRef = le_cfg_CreateReadTxn(pathBuffer); result = le_cfg_GetPath(iterRef, "", buffer, SMALL_STR_SIZE); LE_FATAL_IF(result != LE_OVERFLOW, "Test: %s - The buffer should have been too small.", TestRootDir); LE_FATAL_IF(strcmp(buffer, smallPathBuffer) == 0, "Test: %s - Unexpected value returned, %s", TestRootDir, buffer); result = le_cfg_GetString(iterRef, "", buffer, SMALL_STR_SIZE, ""); LE_FATAL_IF(result != LE_OVERFLOW, "Test: %s - The buffer should have been too small.", TestRootDir); LE_FATAL_IF(strcmp(buffer, "This ") == 0, "Test: %s - Unexpected value returned, %s", TestRootDir, buffer); result = le_cfg_GetPath(iterRef, "", buffer, STR_SIZE); LE_FATAL_IF(result != LE_OK, "Test: %s - The buffer should have been big enough.", TestRootDir); LE_FATAL_IF(strcmp(buffer, pathBuffer) != 0, "Test: %s - Unexpected value returned, %s", TestRootDir, buffer); result = le_cfg_GetString(iterRef, "", buffer, STR_SIZE, ""); LE_FATAL_IF(result != LE_OK, "Test: %s - The buffer should have been big enough.", TestRootDir); LE_FATAL_IF(strcmp(buffer, "This is a bigger string than may be usual for this test.") != 0, "Test: %s - Unexpected value returned, %s", TestRootDir, buffer); le_cfg_CancelTxn(iterRef); result = le_cfg_QuickGetString(pathBuffer, buffer, SMALL_STR_SIZE, ""); LE_FATAL_IF(result != LE_OVERFLOW, "Test: %s - The buffer should have been too small.", TestRootDir); LE_FATAL_IF(strcmp(buffer, "This ") == 0, "Test: %s - Unexpected value returned, %s", TestRootDir, buffer); result = le_cfg_QuickGetString(pathBuffer, buffer, STR_SIZE, ""); LE_FATAL_IF(result != LE_OK, "Test: %s - The buffer should have been big enough.", TestRootDir); LE_FATAL_IF(strcmp(buffer, "This is a bigger string than may be usual for this test.") != 0, "Test: %s - Unexpected value returned, %s", TestRootDir, buffer); }
//-------------------------------------------------------------------------------------------------- static le_result_t GetServerUid ( le_cfg_IteratorRef_t i, ///< [in] Config tree iterator positioned at binding config. uid_t* uidPtr ///< [out] The application's user ID. ) //-------------------------------------------------------------------------------------------------- { le_result_t result; char userName[LIMIT_MAX_USER_NAME_BYTES]; // If an app name is present in the binding config, if (le_cfg_NodeExists(i, "app")) { // Make sure there isn't also a user name. if (le_cfg_NodeExists(i, "user")) { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "", path, sizeof(path)); LE_CRIT("Both server user and app nodes appear under binding (@ %s)", path); return LE_DUPLICATE; } // Get the app name. char appName[LIMIT_MAX_APP_NAME_BYTES]; result = le_cfg_GetString(i, "app", appName, sizeof(appName), ""); if (result != LE_OK) { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "app", path, sizeof(path)); LE_CRIT("Server app name too big (@ %s)", path); return result; } if (appName[0] == '\0') { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "app", path, sizeof(path)); LE_CRIT("Server app name empty (@ %s)", path); return LE_NOT_FOUND; } // Find out if the server app is sandboxed. If not, it runs as root. char path[LIMIT_MAX_PATH_BYTES]; if (snprintf(path, sizeof(path), "/apps/%s/sandboxed", appName) >= sizeof(path)) { LE_CRIT("Config node path too long (app name '%s').", appName); return LE_OVERFLOW; } if (!le_cfg_GetBool(i, path, true)) { *uidPtr = 0; return LE_OK; } // It is not sandboxed. Convert the app name into a user name. result = user_AppNameToUserName(appName, userName, sizeof(userName)); if (result != LE_OK) { LE_CRIT("Failed to convert app name '%s' into a user name.", appName); return result; } } // If a server app name is not present in the binding config, else { // Get the server user name instead. result = le_cfg_GetString(i, "user", userName, sizeof(userName), ""); if (result != LE_OK) { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "user", path, sizeof(path)); LE_CRIT("Server user name too big (@ %s)", path); return result; } if (userName[0] == '\0') { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "", path, sizeof(path)); LE_CRIT("Server user name or app name missing (@ %s)", path); return LE_NOT_FOUND; } } // Convert the server's user name into a user ID. result = user_GetUid(userName, uidPtr); if (result != LE_OK) { // Note: This can happen if the server application isn't installed yet. // When the server application is installed, sdir load will be run // again and the bindings will be correctly set up at that time. if (strncmp(userName, "app", 3) == 0) { LE_DEBUG("Couldn't get UID for application '%s'. Perhaps it is not installed yet?", userName + 3); } else { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "", path, sizeof(path)); LE_CRIT("Couldn't convert server user name '%s' to UID (%s @ %s)", userName, LE_RESULT_TXT(result), path); } return result; } return LE_OK; }
//-------------------------------------------------------------------------------------------------- static void LoadPreferredList ( ) { uint32_t idx = 0; le_dls_List_t preferredNetworkList = LE_DLS_LIST_INIT; // Check that the modemRadioControl has a configuration value for preferred list. le_cfg_IteratorRef_t mrcCfg = le_cfg_CreateReadTxn(CFG_MODEMSERVICE_MRC_PATH"/"CFG_NODE_PREFERREDLIST); if (le_cfg_NodeExists(mrcCfg,"") == false) { LE_DEBUG("'%s' does not exist. Stop reading configuration", CFG_MODEMSERVICE_MRC_PATH"/"CFG_NODE_PREFERREDLIST); le_cfg_CancelTxn(mrcCfg); return; } // Read all network from configDB do { uint32_t ratMask; char mccNodePath[LIMIT_MAX_PATH_BYTES] = {0}; char mncNodePath[LIMIT_MAX_PATH_BYTES] = {0}; char ratNodePath[LIMIT_MAX_PATH_BYTES] = {0}; char mccStr[LIMIT_MAX_PATH_BYTES] = {0}; char mncStr[LIMIT_MAX_PATH_BYTES] = {0}; // Get the node name. char nodeName[LIMIT_MAX_PATH_BYTES] = {0}; sprintf(nodeName,PATTERN_NETWORK"%d",idx); if (le_cfg_IsEmpty(mrcCfg, nodeName)) { LE_DEBUG("'%s' does not exist. stop reading configuration", nodeName); break; } snprintf(mccNodePath, sizeof(mccNodePath), "%s/%s",nodeName,CFG_NODE_MCC); snprintf(mncNodePath, sizeof(mncNodePath), "%s/%s",nodeName,CFG_NODE_MNC); snprintf(ratNodePath, sizeof(ratNodePath), CFG_MODEMSERVICE_MRC_PATH"/"CFG_NODE_PREFERREDLIST"/%s/%s",nodeName,CFG_NODE_RAT); if ( le_cfg_GetString(mrcCfg,mccNodePath,mccStr,sizeof(mccStr),"") != LE_OK ) { LE_WARN("String value for '%s' too large.",mccNodePath); break; } if ( strcmp(mccStr,"") == 0 ) { LE_WARN("No node value set for '%s'",mccNodePath); break; } if ( le_cfg_GetString(mrcCfg,mncNodePath,mncStr,sizeof(mncStr),"") != LE_OK ) { LE_WARN("String value for '%s' too large.",mncNodePath); break; } if ( strcmp(mncStr,"") == 0 ) { LE_WARN("No node value set for '%s'",mncNodePath); break; } if ( LoadRatList(ratNodePath,&ratMask) != LE_OK ) { LE_WARN("Could not read rat information in '%s'",ratNodePath); break; } if ( pa_mrc_AddPreferredNetwork(&preferredNetworkList,mccStr,mncStr,ratMask) != LE_OK ) { LE_WARN("Could not add [%s,%s] into the preferred list",mccStr,mncStr); } ++idx; } while (true); le_cfg_CancelTxn(mrcCfg); if ( pa_mrc_SavePreferredList(&preferredNetworkList) != LE_OK ) { LE_WARN("Could not save the preferred list"); } pa_mrc_ClearPreferedList(&preferredNetworkList); }
//-------------------------------------------------------------------------------------------------- le_result_t proc_SetPriority ( const char* priorStr, ///< [IN] Priority level string. pid_t pid ///< [IN] PID of the process to set the priority for. ) { // Declare these varialbes with the default values. struct sched_param priority = {.sched_priority = 0}; int policy = SCHED_OTHER; int niceLevel = MEDIUM_PRIORITY_NICE_LEVEL; if (strcmp(priorStr, "idle") == 0) { policy = SCHED_IDLE; } else if (strcmp(priorStr, "low") == 0) { niceLevel = LOW_PRIORITY_NICE_LEVEL; } else if (strcmp(priorStr, "high") == 0) { niceLevel = HIGH_PRIORITY_NICE_LEVEL; } else if ( (priorStr[0] == 'r') && (priorStr[1] == 't') ) { // Get the realtime level from the characters following "rt". char *endPtr; errno = 0; int level = strtol(&(priorStr[2]), &endPtr, 10); if ( (*endPtr != '\0') || (level < MIN_RT_PRIORITY) || (level > MAX_RT_PRIORITY) ) { LE_WARN("Unrecognized priority level (%s) for process '%d'. Using default priority.", priorStr, pid); } else { policy = SCHED_RR; priority.sched_priority = level; } } else if (strcmp(priorStr, "medium") != 0) { LE_WARN("Unrecognized priority level for process '%d'. Using default priority.", pid); } // Set the policy and priority. if (sched_setscheduler(pid, policy, &priority) == -1) { LE_ERROR("Could not set the scheduling policy. %m."); return LE_FAULT; } // Set the nice level. errno = 0; if (setpriority(PRIO_PROCESS, pid, niceLevel) == -1) { LE_ERROR("Could not set the nice level. %m."); return LE_FAULT; } return LE_OK; } //-------------------------------------------------------------------------------------------------- /** * Sets the scheduling policy, priority and/or nice level for the specified process based on the * process' configuration settings in the config tree. * * @note This function kills the specified process if there is an error. */ //-------------------------------------------------------------------------------------------------- static void SetSchedulingPriority ( proc_Ref_t procRef ///< [IN] The process to set the priority for. ) { // Read the priority setting from the config tree. le_cfg_IteratorRef_t procCfg = le_cfg_CreateReadTxn(procRef->cfgPathRoot); char priorStr[LIMIT_MAX_PRIORITY_NAME_BYTES]; if (le_cfg_GetString(procCfg, CFG_NODE_PRIORITY, priorStr, sizeof(priorStr), "medium") != LE_OK) { LE_CRIT("Priority string for process %s is too long. Using default priority.", procRef->name); LE_ASSERT(le_utf8_Copy(priorStr, "medium", sizeof(priorStr), NULL) == LE_OK); } le_cfg_CancelTxn(procCfg); if (proc_SetPriority(priorStr, procRef->pid) != LE_OK) { kill_Hard(procRef->pid); } }
//-------------------------------------------------------------------------------------------------- static void LoadScanMode ( ) { char configPath[LIMIT_MAX_PATH_BYTES]; snprintf(configPath, sizeof(configPath), "%s/%s",CFG_MODEMSERVICE_MRC_PATH,CFG_NODE_SCANMODE); LE_DEBUG("Start reading MRC scanMode information in ConfigDB"); le_cfg_IteratorRef_t mrcCfg = le_cfg_CreateReadTxn(configPath); do { if ( le_cfg_GetBool(mrcCfg,CFG_NODE_MANUAL,false) ) { char mccStr[LIMIT_MAX_PATH_BYTES] = {0}; char mncStr[LIMIT_MAX_PATH_BYTES] = {0}; if ( le_cfg_GetString(mrcCfg,CFG_NODE_MCC,mccStr,sizeof(mccStr),"") != LE_OK ) { LE_WARN("String value for '%s' too large.",CFG_NODE_MCC); break; } if ( strcmp(mccStr,"") == 0 ) { LE_WARN("No node value set for '%s'",CFG_NODE_MCC); break; } if ( le_cfg_GetString(mrcCfg,CFG_NODE_MNC,mncStr,sizeof(mncStr),"") != LE_OK ) { LE_WARN("String value for '%s' too large.",CFG_NODE_MNC); break; } if ( strcmp(mncStr,"") == 0 ) { LE_WARN("No node value set for '%s'",CFG_NODE_MNC); break; } if ( le_mrc_ConnectCellularNetwork(mccStr,mncStr) != LE_OK ) { LE_WARN("Could not connect to Network [%s,%s]",mccStr ,mncStr); break; } } else { if ( pa_mrc_SetAutomaticNetworkRegistration() != LE_OK ) { LE_WARN("Could not set the Automatic Network Registration"); break; } } } while (false); le_cfg_CancelTxn(mrcCfg); }
//-------------------------------------------------------------------------------------------------- static le_result_t GetArgs ( proc_Ref_t procRef, ///< [IN] The process to get the args for. char argsBuffers[LIMIT_MAX_NUM_CMD_LINE_ARGS][LIMIT_MAX_ARGS_STR_BYTES], ///< [OUT] A pointer to /// an array of buffers /// used to store /// arguments. char* argsPtr[NUM_ARGS_PTRS] ///< [OUT] An array of pointers that will point to the valid /// arguments list. The list is terminated by NULL. ) { // Get a config iterator to the arguments list. le_cfg_IteratorRef_t procCfg = le_cfg_CreateReadTxn(procRef->cfgPathRoot); le_cfg_GoToNode(procCfg, CFG_NODE_ARGS); if (le_cfg_GoToFirstChild(procCfg) != LE_OK) { LE_ERROR("No arguments for process '%s'.", procRef->name); le_cfg_CancelTxn(procCfg); return LE_FAULT; } size_t ptrIndex = 0; size_t bufIndex = 0; // Record the executable path. if (le_cfg_GetString(procCfg, "", argsBuffers[bufIndex], LIMIT_MAX_ARGS_STR_BYTES, "") != LE_OK) { LE_ERROR("Error reading argument '%s...' for process '%s'.", argsBuffers[bufIndex], procRef->name); le_cfg_CancelTxn(procCfg); return LE_FAULT; } argsPtr[ptrIndex++] = argsBuffers[bufIndex++]; // Record the process name in the list. argsPtr[ptrIndex++] = procRef->name; // Record the arguments in the caller's list of buffers. while(1) { if (le_cfg_GoToNextSibling(procCfg) != LE_OK) { // Terminate the list. argsPtr[ptrIndex] = NULL; break; } else if (bufIndex >= LIMIT_MAX_NUM_CMD_LINE_ARGS) { LE_ERROR("Too many arguments for process '%s'.", procRef->name); le_cfg_CancelTxn(procCfg); return LE_FAULT; } if (le_cfg_IsEmpty(procCfg, "")) { LE_ERROR("Empty node in argument list for process '%s'.", procRef->name); le_cfg_CancelTxn(procCfg); return LE_FAULT; } if (le_cfg_GetString(procCfg, "", argsBuffers[bufIndex], LIMIT_MAX_ARGS_STR_BYTES, "") != LE_OK) { LE_ERROR("Argument too long '%s...' for process '%s'.", argsBuffers[bufIndex], procRef->name); le_cfg_CancelTxn(procCfg); return LE_FAULT; } // Point to the string. argsPtr[ptrIndex++] = argsBuffers[bufIndex++]; } le_cfg_CancelTxn(procCfg); return LE_OK; }
//-------------------------------------------------------------------------------------------------- static void SendBindRequest ( uid_t uid, ///< [in] Unix user ID of the client whose binding is being created. le_cfg_IteratorRef_t i ///< [in] Configuration read iterator. ) //-------------------------------------------------------------------------------------------------- { le_result_t result; le_msg_MessageRef_t msgRef = le_msg_CreateMsg(SessionRef); le_sdtp_Msg_t* msgPtr = le_msg_GetPayloadPtr(msgRef); msgPtr->msgType = LE_SDTP_MSGID_BIND; msgPtr->client = uid; // Fetch the client's service name. result = le_cfg_GetNodeName(i, "", msgPtr->clientServiceName, sizeof(msgPtr->clientServiceName)); if (result != LE_OK) { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "", path, sizeof(path)); LE_CRIT("Configured client service name too long (@ %s)", path); return; } // Fetch the server's user ID. result = GetServerUid(i, &msgPtr->server); if (result != LE_OK) { return; } // Fetch the server's service name. result = le_cfg_GetString(i, "interface", msgPtr->serverServiceName, sizeof(msgPtr->serverServiceName), ""); if (result != LE_OK) { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "interface", path, sizeof(path)); LE_CRIT("Server interface name too big (@ %s)", path); return; } if (msgPtr->serverServiceName[0] == '\0') { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "interface", path, sizeof(path)); LE_CRIT("Server interface name missing (@ %s)", path); return; } msgRef = le_msg_RequestSyncResponse(msgRef); if (msgRef == NULL) { ExitWithErrorMsg("Communication with Service Directory failed."); } le_msg_ReleaseMsg(msgRef); }
//-------------------------------------------------------------------------------------------------- static void LoadSimFromConfigDb ( le_sim_Id_t simId ) { uint32_t attemptCounter = CONFIGDB_ATTEMPT_MAX; // Get the configuration path for the SIM. char configPath[LIMIT_MAX_PATH_BYTES]; snprintf(configPath, sizeof(configPath), "%s/%d", CFG_MODEMSERVICE_SIM_PATH, simId); LE_DEBUG("Start reading SIM-%d information in ConfigDB",simId); le_result_t result; le_sim_States_t simState; do { simState = le_sim_GetState(simId); switch (simState) { case LE_SIM_INSERTED: { // Check that the app has a configuration value. le_cfg_IteratorRef_t simCfg = le_cfg_CreateReadTxn(configPath); char simPin[LIMIT_MAX_PATH_BYTES] = {0}; result = le_cfg_GetString(simCfg,CFG_NODE_PIN,simPin,sizeof(simPin),""); if ( result != LE_OK ) { LE_WARN("PIN string too large for SIM-%d",simId); le_cfg_CancelTxn(simCfg); return; } if ( strncmp(simPin,"",sizeof(simPin))==0 ) { LE_WARN("PIN not set for SIM-%d",simId); le_cfg_CancelTxn(simCfg); return; } if ( (result = le_sim_EnterPIN(simId,simPin)) != LE_OK ) { LE_ERROR("Error.%d Failed to enter SIM pin for SIM-%d",result,simId); le_cfg_CancelTxn(simCfg); return; } LE_DEBUG("Sim-%d is unlocked", simId); le_cfg_CancelTxn(simCfg); attemptCounter = 1; break; } case LE_SIM_BLOCKED: { LE_EMERG("Be carefull the sim-%d is BLOCKED, need to enter PUK code",simId); attemptCounter = 1; break; } case LE_SIM_BUSY: if (attemptCounter==1) { LE_WARN("Could not load the configuration because " "the SIM is still busy after %d attempts", CONFIGDB_ATTEMPT_MAX); } else { LE_WARN("Sim-%d was busy when loading configuration," "retry in 1 seconds",simId); } sleep(1); // Retry in 1 second. break; case LE_SIM_READY: LE_DEBUG("Sim-%d is ready",simId); attemptCounter = 1; break; case LE_SIM_ABSENT: LE_WARN("Sim-%d is absent",simId); attemptCounter = 1; break; case LE_SIM_STATE_UNKNOWN: break; } } while (--attemptCounter); LE_DEBUG("Load SIM information is done"); }