Esempio n. 1
0
//--------------------------------------------------------------------------------------------------
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);
}
Esempio n. 2
0
//--------------------------------------------------------------------------------------------------
void userAddRemove_Add
(
    const char* appName
)
//--------------------------------------------------------------------------------------------------
{
    le_result_t result;
    uid_t uid;
    gid_t gid;

    char userName[256] = "app";

    result = le_utf8_Append(userName, appName, sizeof(userName), NULL);
    LE_FATAL_IF(result != LE_OK, "App name '%s' is too long.", appName);

    LE_INFO("Creating user '%s' for application '%s'.", userName, appName);

    // Start a read transaction and go to node /apps/app-name
    le_cfg_ConnectService();
    le_cfg_IteratorRef_t i = le_cfg_CreateReadTxn("/apps");
    le_cfg_GoToNode(i, appName);

    // If the node doesn't exist, bail out.
    if (!le_cfg_NodeExists(i, ""))
    {
        fprintf(stderr, "** ERROR: App '%s' doesn't exist in the system configuration.\n", appName);
    }
    else
    {
        result = user_Create(userName, &uid, &gid);

        if (result == LE_OK)
        {
            printf("Created user '%s' (uid %u, gid %u).\n", userName, uid, gid);

            // TODO: Groups configuration.

            le_cfg_CancelTxn(i);

            exit(EXIT_SUCCESS);
        }
        else if (result == LE_DUPLICATE)
        {
            // TODO: Verify correct groups configuration.

            printf("User '%s' already exists (uid %u, gid %u).\n", userName, uid, gid);

            le_cfg_CancelTxn(i);

            exit(EXIT_SUCCESS);
        }
        else
        {
            fprintf(stderr, "** ERROR: user_Create() failed for user '%s'.\n", userName);
        }
    }

    le_cfg_CancelTxn(i);
    exit(EXIT_FAILURE);
}
Esempio n. 3
0
//--------------------------------------------------------------------------------------------------
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, "");
}
Esempio n. 4
0
//--------------------------------------------------------------------------------------------------
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, "");
}
Esempio n. 5
0
//--------------------------------------------------------------------------------------------------
LE_SHARED le_result_t appCfg_GetAppName
(
    appCfg_Iter_t appIterRef,   ///< [IN] Apps iterator
    char* bufPtr,               ///< [OUT] Buffer to store the app name.
    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_GetNodeName(appIterRef->cfgIter, "", bufPtr, bufSize);
}
Esempio n. 6
0
//--------------------------------------------------------------------------------------------------
static void AddImportFiles
(
    le_cfg_IteratorRef_t cfgIter,           ///< [IN] Iterator to the application config.
    const ImportObj_t (*importsPtr)[],      ///< [IN] Imports to include in the application.
    size_t numImports                       ///< [IN] Number of import elements.
)
{
    // Find the last node under the 'files' or 'dirs' section.
    size_t nodeNum = 0;
    char nodePath[LIMIT_MAX_PATH_BYTES];

    while (1)
    {
        int n = snprintf(nodePath, sizeof(nodePath), "%zd", nodeNum);

        INTERNAL_ERR_IF(n >= sizeof(nodePath), "Node name is too long.");
        INTERNAL_ERR_IF(n < 0, "Format error.  %m");

        if (!le_cfg_NodeExists(cfgIter, nodePath))
        {
            break;
        }

        nodeNum++;
    }

    // Start adding files/directories at the end of the current list.
    int i;
    for (i = 0; i < numImports; i++)
    {
        // Add the source.
        int n = snprintf(nodePath, sizeof(nodePath), "%zd/src", nodeNum + i);

        INTERNAL_ERR_IF(n >= sizeof(nodePath), "Node name is too long.");
        INTERNAL_ERR_IF(n < 0, "Format error.  %m");

        le_cfg_SetString(cfgIter, nodePath, (*importsPtr)[i].src);

        // Add the destination.
        n = snprintf(nodePath, sizeof(nodePath), "%zd/dest", nodeNum + i);

        INTERNAL_ERR_IF(n >= sizeof(nodePath), "Node name is too long.");
        INTERNAL_ERR_IF(n < 0, "Format error.  %m");

        le_cfg_SetString(cfgIter, nodePath, (*importsPtr)[i].dest);
    }
}
Esempio n. 7
0
//--------------------------------------------------------------------------------------------------
LE_SHARED appCfg_Iter_t appCfg_FindApp
(
    const char* appName         ///< [IN] Name of the app to find.
)
{
    AppsIter_t* iterPtr = appCfg_CreateAppsIter();

    le_cfg_GoToNode(iterPtr->cfgIter, appName);

    if (le_cfg_NodeExists(iterPtr->cfgIter, "") == false)
    {
        appCfg_DeleteIter(iterPtr);
        return NULL;
    }

    return iterPtr;
}
Esempio n. 8
0
//--------------------------------------------------------------------------------------------------
static int GetCfgResourceLimit
(
    le_cfg_IteratorRef_t limitCfg,  // The iterator to use to read the configured limit.  This
                                    // iterator is owned by the caller and should not be deleted
                                    // in this function.
    const char* nodeName,           // The name of the node in the config tree that holds the value.
    int defaultValue                // The default value to use if the config value is invalid.
)
{
    int limitValue = le_cfg_GetInt(limitCfg, nodeName, defaultValue);

    if (!le_cfg_NodeExists(limitCfg, nodeName))
    {
        LE_INFO("Configured resource limit %s is not available.  Using the default value %d.",
                 nodeName, defaultValue);

        return defaultValue;
    }

    if (le_cfg_IsEmpty(limitCfg, nodeName))
    {
        LE_WARN("Configured resource limit %s is empty.  Using the default value %d.",
                 nodeName, defaultValue);

        return defaultValue;
    }

    if (le_cfg_GetNodeType(limitCfg, nodeName) != LE_CFG_TYPE_INT)
    {
        LE_ERROR("Configured resource limit %s is the wrong type.  Using the default value %d.",
                 nodeName, defaultValue);

        return defaultValue;
    }

    if (limitValue < 0)
    {
        LE_ERROR("Configured resource limit %s is negative.  Using the default value %d.",
                 nodeName, defaultValue);

        return defaultValue;
    }

    return limitValue;
}
Esempio n. 9
0
static void ExistAndEmptyTest()
{
    static char pathBuffer[STR_SIZE] = { 0 };
    snprintf(pathBuffer, STR_SIZE, "/%s/existAndEmptyTest/", TestRootDir);

    {
        le_cfg_IteratorRef_t iterRef = le_cfg_CreateWriteTxn(pathBuffer);

        le_cfg_SetEmpty(iterRef, "");
        LE_TEST(le_cfg_IsEmpty(iterRef, "") == true);

        LE_TEST(le_cfg_NodeExists(iterRef, "valueA") == false);
        LE_TEST(le_cfg_NodeExists(iterRef, "valueB") == false);
        LE_TEST(le_cfg_NodeExists(iterRef, "valueC") == false);
        LE_TEST(le_cfg_NodeExists(iterRef, "valueD") == false);

        LE_TEST(le_cfg_IsEmpty(iterRef, "valueA") == true);
        LE_TEST(le_cfg_IsEmpty(iterRef, "valueB") == true);
        LE_TEST(le_cfg_IsEmpty(iterRef, "valueC") == true);
        LE_TEST(le_cfg_IsEmpty(iterRef, "valueD") == true);


        le_cfg_SetString(iterRef, "valueA", "aNewValue");
        le_cfg_SetInt(iterRef, "valueB", 10);
        le_cfg_SetBool(iterRef, "valueC", true);
        le_cfg_SetFloat(iterRef, "valueD", 10.24);

        LE_TEST(le_cfg_NodeExists(iterRef, "valueA") == true);
        LE_TEST(le_cfg_NodeExists(iterRef, "valueB") == true);
        LE_TEST(le_cfg_NodeExists(iterRef, "valueC") == true);
        LE_TEST(le_cfg_NodeExists(iterRef, "valueD") == true);

        LE_TEST(le_cfg_IsEmpty(iterRef, "valueA") == false);
        LE_TEST(le_cfg_IsEmpty(iterRef, "valueB") == false);
        LE_TEST(le_cfg_IsEmpty(iterRef, "valueC") == false);
        LE_TEST(le_cfg_IsEmpty(iterRef, "valueD") == false);

        le_cfg_CommitTxn(iterRef);
    }
}
Esempio n. 10
0
//--------------------------------------------------------------------------------------------------
static void SetRLimit
(
    pid_t pid,                      // The pid of the process to set the limit for.
    le_cfg_IteratorRef_t procCfg,   // The iterator for the process.  This is a iterator is owned by
                                    // the caller and should not be deleted in this function.
    const char* resourceName,       // The resource name in the config tree.
    int resourceID,                 // The resource ID that setrlimit() expects.
    rlim_t defaultValue             // The default value for this resource limit.
)
{
    // Initialize the limit to the defaults.
    struct rlimit lim = {defaultValue, defaultValue};

    // Move the iterator to the resource limit to read.
    le_cfg_GoToNode(procCfg, resourceName);
    if (le_cfg_NodeExists(procCfg, "") == false)
    {
        LE_WARN("No resource limit %s.  Using the default value %lu.", resourceName, defaultValue);
    }
    else
    {
        // Try reading the resource limit from the config tree.
        if (GetCfgResourceLimit(procCfg, &(lim.rlim_max)) != LE_OK)
        {
            LE_ERROR("Configured resource limit %s is invalid.  Using the default value %lu.",
                     resourceName, defaultValue);
        }
        else
        {
            // Check that the limit does not exceed the maximum.
            if ( (resourceID == RLIMIT_NOFILE) && (lim.rlim_max > MAX_LIMIT_NUM_FD) )
            {
                LE_ERROR("Resource limit %s is greater than the maximum allowed limit (%d).  Using the \
    maximum allowed value.", resourceName, MAX_LIMIT_NUM_FD);

                lim.rlim_max = MAX_LIMIT_NUM_FD;
            }
        }

        // Move the iterator back to where it was.
        LE_ASSERT(le_cfg_GoToParent(procCfg) == LE_OK);
    }
Esempio n. 11
0
//--------------------------------------------------------------------------------------------------
rlim_t resLim_GetSandboxedAppTmpfsLimit
(
    app_Ref_t appRef                ///< [IN] The application to set resource limits for.
)
{
    // Get the resource limit from the config tree.  Zero means unlimited for tmpfs mounts and is
    // not allowed.

    // Determine the file system limit to set.
    rlim_t fileSysLimit = DEFAULT_LIMIT_FILE_SYSTEM_SIZE;

    // Create a config iterator to get the file system limit from the config tree.
    le_cfg_IteratorRef_t appCfg = le_cfg_CreateReadTxn(app_GetConfigPath(appRef));
    le_cfg_GoToNode(appCfg, CFG_NODE_LIMIT_FILE_SYSTEM_SIZE);

    if (le_cfg_NodeExists(appCfg, "") == false)
    {
        LE_WARN("No resource limit %s.  Assuming the default value %d.",
                CFG_NODE_LIMIT_FILE_SYSTEM_SIZE,
                DEFAULT_LIMIT_FILE_SYSTEM_SIZE);
    }
    else if ( (GetCfgResourceLimit(appCfg, &fileSysLimit) != LE_OK) ||
              (fileSysLimit == 0) )
    {
        // Use the default limit.
        LE_ERROR("Configured resource limit %s is invalid.  Assuming the default value %d.",
                 CFG_NODE_LIMIT_FILE_SYSTEM_SIZE,
                 DEFAULT_LIMIT_FILE_SYSTEM_SIZE);

        fileSysLimit = DEFAULT_LIMIT_FILE_SYSTEM_SIZE;
    }

    le_cfg_CancelTxn(appCfg);

    return fileSysLimit;
}
Esempio n. 12
0
//--------------------------------------------------------------------------------------------------
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;
}
Esempio n. 13
0
//--------------------------------------------------------------------------------------------------
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);
}
Esempio n. 14
0
//--------------------------------------------------------------------------------------------------
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;
}