/*********************************************************************** * * Copyright (C) 2006 Novell, Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, Novell, Inc. * * To contact Novell about this file by physical or electronic mail, * you may find current contact information at www.novell.com. * * Author: Juan Carlos Luciani * ***********************************************************************/ //===[ Include files ]===================================================== #include "internal.h" //===[ Type definitions ]================================================== // // Config Key object // typedef struct _ConfigKey { LIST_ENTRY listEntry; char *pKeyName; int keyNameLen; char *pValue; int valueLen; } ConfigKey, *pConfigKey; // // Config Interface instance data // typedef struct _ConfigIfInstance { LIST_ENTRY listEntry; int refCount; char *pConfigFolder; int configFolderLen; char *pConfigName; int configNameLen; LIST_ENTRY configKeyListHead; ConfigIf configIf; } ConfigIfInstance, *PConfigIfInstance; //===[ Function prototypes ]=============================================== //===[ Global variables ]================================================== // ConfigIf variables static LIST_ENTRY g_configIfListHead = {&g_configIfListHead, &g_configIfListHead}; static int g_numConfigIfObjs = 0; //++======================================================================= static void RemoveWhiteSpaceFromTheEnd( IN const char *pInString) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { char *pLineEnd = (char*) pInString + strlen(pInString) - 1; DbgTrace(4, "-RemoveWhiteSpaceFromTheEnd- Start\n", 0); while (pLineEnd != pInString) { if (*pLineEnd == '\n' || *pLineEnd == ' ' || *pLineEnd == '\t') { // Strike this character *pLineEnd = '\0'; pLineEnd --; } else { // Found a non-white character break; } } DbgTrace(4, "-RemoveWhiteSpaceFromTheEnd- End\n", 0); } //++======================================================================= static char* SkipWhiteSpace( IN const char *pInString) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { char *pOutString = (char*) pInString; DbgTrace(4, "-SkipWhiteSpace- Start\n", 0); while (*pOutString != '\0') { if (*pOutString == '\n' || *pOutString == ' ' || *pOutString == '\t') { // Skip this character pOutString ++; } else { // Found a non-white character break; } } DbgTrace(4, "-SkipWhiteSpace- End\n", 0); return pOutString; } //++======================================================================= static char* SkipNonWhiteSpace( IN const char *pInString) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L2 //=======================================================================-- { char *pOutString = (char*) pInString; DbgTrace(4, "-SkipNonWhiteSpace- Start\n", 0); while (*pOutString != '\0') { if (*pOutString == '\n' || *pOutString == ' ' || *pOutString == '\t') { // Found a white character break; } else { // Skip this character pOutString ++; } } DbgTrace(4, "-SkipNonWhiteSpace- End\n", 0); return pOutString; } //++======================================================================= static void LowerCaseString( IN char *pDestString, IN const char *pSrcString) // // Arguments: // // Returns: // // Abstract: // // Notes: Function assumes that the caller has made sure that the destination // string buffer has enough space to receive the resulting string. // // L2 //=======================================================================-- { int i; DbgTrace(4, "-LowerCaseString- Start\n", 0); // Copy the string as lower case for (i = 0; pSrcString[i] != '\0'; i++) { if (isalpha(pSrcString[i])) pDestString[i] = tolower(pSrcString[i]); else pDestString[i] = pSrcString[i]; } // Null terminate the destination string pDestString[i] = '\0'; DbgTrace(4, "-LowerCaseString- End\n", 0); } //++======================================================================= int SSCS_CALL ConfigIf_AddReference( IN const void *pIfInstance) // // Arguments: // pIfInstance - // Pointer to interface object. // // Returns: // Interface reference count. // // Description: // Increases interface reference count. // // L2 //=======================================================================-- { int refCount; ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); DbgTrace(2, "-ConfigIf_AddReference- Start\n", 0); // Increment the reference count on the object pConfigIfInstance->refCount ++; refCount = pConfigIfInstance->refCount; DbgTrace(2, "-ConfigIf_AddReference- End, refCount = %08X\n", refCount); return refCount; } //++======================================================================= void SSCS_CALL ConfigIf_ReleaseReference( IN const void *pIfInstance) // // Arguments: // pIfInstance - // Pointer to interface object. // // Returns: // Nothing. // // Description: // Decreases interface reference count. The interface is deallocated if // the reference count becomes zero. // // L2 //=======================================================================-- { bool freeObj = false; ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); DbgTrace(2, "-ConfigIf_ReleaseReference- Start\n", 0); // Decrement the reference count on the object and determine if it needs to // be released. pConfigIfInstance->refCount --; if (pConfigIfInstance->refCount == 0) { // The object needs to be released, forget about it. freeObj = true; g_numConfigIfObjs --; RemoveEntryList(&pConfigIfInstance->listEntry); } // Free object if necessary if (freeObj) { // Free all of the config key objects associated with this configuration // interface instance. while (!IsListEmpty(&pConfigIfInstance->configKeyListHead)) { LIST_ENTRY *pListEntry; ConfigKey *pConfigKey; // Get reference to entry at the head of the list pListEntry = pConfigIfInstance->configKeyListHead.Flink; pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry); // Free the buffers associated with the ConfigKey free(pConfigKey->pKeyName); free(pConfigKey->pValue); // Remove the entry from the list RemoveEntryList(&pConfigKey->listEntry); // Finish freeing the ConfigKey free(pConfigKey); } // Free the rest of the buffers associated with the interface instance data free(pConfigIfInstance->pConfigFolder); free(pConfigIfInstance->pConfigName); free(pConfigIfInstance); } DbgTrace(2, "-ConfigIf_ReleaseReference- End\n", 0); } //++======================================================================= char* SSCS_CALL ConfigIf_GetEntryValue( IN const void *pIfInstance, IN const char *pKeyName) // // Arguments: // pIfInstance - // Pointer to interface object. // // pKeyName - // Pointer to NULL terminated string that contains the // name of the key whose value is being requested. // // Returns: // Pointer to NULL terminated string with value being requested or NULL. // This NULL terminated string must be free by executing the interface // object freeValueString method. // // Description: // Gets value associated with a key for the configuration object. // // L2 //=======================================================================-- { ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); char *pValue = NULL; LIST_ENTRY *pListEntry; ConfigKey *pConfigKey; int keyNameLen = (int) strlen(pKeyName); char *pKeyNameLowercase; DbgTrace(2, "-ConfigIf_GetEntryValue- Start\n", 0); // Allocate enough space to hold lower case version of the key name pKeyNameLowercase = (char*) malloc(keyNameLen + 1); if (pKeyNameLowercase) { // Lower case the key name LowerCaseString(pKeyNameLowercase, pKeyName); // Try to find matching ConfigKey pListEntry = pConfigIfInstance->configKeyListHead.Flink; while (pListEntry != &pConfigIfInstance->configKeyListHead) { // Get pointer to the current entry pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry); // Check if we have a match if (pConfigKey->keyNameLen == keyNameLen && memcmp(pKeyNameLowercase, pConfigKey->pKeyName, keyNameLen) == 0) { // We found it, return its value. pValue = (char*) malloc(pConfigKey->valueLen + 1); if (pValue) { strcpy(pValue, pConfigKey->pValue); } else { DbgTrace(0, "-ConfigIf_GetEntryValue- Buffer allocation failure\n", 0); } break; } // Advance to the next entry pListEntry = pListEntry->Flink; } // Free the lower case version of the key name free(pKeyNameLowercase); } else { DbgTrace(0, "-ConfigIf_GetEntryValue- Buffer allocation failure\n", 0); } DbgTrace(2, "-ConfigIf_GetEntryValue- End, pValue = %08X\n", (unsigned int) pValue); return pValue; } //++======================================================================= void SSCS_CALL ConfigIf_FreeValueString( IN const void *pIfInstance, IN char *pValueString) // // Arguments: // pIfInstance - // Pointer to interface object. // // pValueString - // Pointer to NULL terminated string that contains a value // returned from a call to the interface getEntryValue method. // // Returns: // Nothing. // // Description: // Frees value string returned by calling interface's getEntryValue // method. // // L2 //=======================================================================-- { ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); DbgTrace(2, "-ConfigIf_FreeValueString- Start\n", 0); // Free the buffer free(pValueString); DbgTrace(2, "-ConfigIf_FreeValueString- End\n", 0); } //++======================================================================= CasaStatus GetConfigInterface( IN const char *pConfigFolder, IN const char *pConfigName, INOUT ConfigIf **ppConfigIf) // // Arguments: // pConfigFolder - // Pointer to NULL terminated string that contains the name of // the folder containing the configuration file. // // pConfigName - // Pointer to NULL terminated string containing the name of the // configuration entry. // // ppConfigIf - // Pointer to variable that will receive pointer to ConfigIf // instance. // // Returns: // Casa Status // // Description: // Get configuration interface to specified configuration entry. // // L2 //=======================================================================-- { int configFolderLen = (int) strlen(pConfigFolder); int configNameLen = (int) strlen(pConfigName); ConfigIfInstance *pConfigIfInstance; LIST_ENTRY *pListEntry; CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_OBJECT_NOT_FOUND); DbgTrace(2, "-GetConfigInterface- Start\n", 0); // Check if we already have an entry in our list for the configuration pListEntry = g_configIfListHead.Flink; while (pListEntry != &g_configIfListHead) { // Get pointer to the current entry pConfigIfInstance = CONTAINING_RECORD(pListEntry, ConfigIfInstance, listEntry); // Check if we have a match if (pConfigIfInstance->configFolderLen == configFolderLen && pConfigIfInstance->configNameLen == configNameLen && memcmp(pConfigFolder, pConfigIfInstance->pConfigFolder, configFolderLen) == 0 && memcmp(pConfigName, pConfigIfInstance->pConfigName, configNameLen) == 0) { // We found it, return the ConfigIf associated with the instance data // after incrementing its reference count. pConfigIfInstance->refCount ++; *ppConfigIf = &pConfigIfInstance->configIf; // Success retStatus = CASA_STATUS_SUCCESS; break; } // Advance to the next entry pListEntry = pListEntry->Flink; } // Proceed to create interface instance data for the configuration if none was found if (retStatus != CASA_STATUS_SUCCESS) { char *pFilePath; // Build a string containing the configuration file path pFilePath = (char*) malloc(configFolderLen + 1 + configNameLen + sizeof(".conf") + 1); if (pFilePath) { FILE *pConfigFile; strcpy(pFilePath, pConfigFolder); strcat(pFilePath, pathCharString); strcat(pFilePath, pConfigName); strcat(pFilePath, ".conf"); // Open the configuration file for reading pConfigFile = fopen(pFilePath, "r"); if (pConfigFile) { // Opened the file, create a ConfigIfInstance object for it. pConfigIfInstance = (ConfigIfInstance*) malloc(sizeof(*pConfigIfInstance)); if (pConfigIfInstance) { // Initialize the list head within the instance data InitializeListHead(&pConfigIfInstance->configKeyListHead); // Initialize the ConfigIf within the instance data pConfigIfInstance->configIf.addReference = ConfigIf_AddReference; pConfigIfInstance->configIf.releaseReference = ConfigIf_ReleaseReference; pConfigIfInstance->configIf.getEntryValue = ConfigIf_GetEntryValue; pConfigIfInstance->configIf.freeValueString = ConfigIf_FreeValueString; // Save the ConfigFolder and ConfigName information within the instance data pConfigIfInstance->pConfigFolder = (char*) malloc(configFolderLen + 1); if (pConfigIfInstance->pConfigFolder) { strcpy(pConfigIfInstance->pConfigFolder, pConfigFolder); pConfigIfInstance->configFolderLen = configFolderLen; pConfigIfInstance->pConfigName = (char*) malloc(configNameLen + 1); if (pConfigIfInstance->pConfigName) { strcpy(pConfigIfInstance->pConfigName, pConfigName); pConfigIfInstance->configNameLen = configNameLen; // Add the instance data into our list and bump up its reference count // since we did that. InsertTailList(&g_configIfListHead, &pConfigIfInstance->listEntry); pConfigIfInstance->refCount = 1; // At this point we want to return success to the caller even if we // experience a read error. retStatus = CASA_STATUS_SUCCESS; // Return the ConfigIf associated with the instance data after // incrementing its reference count. pConfigIfInstance->refCount ++; *ppConfigIf = &pConfigIfInstance->configIf; // Now update the instance data with the information present in the file if (fseek(pConfigFile, 0, SEEK_SET) == 0) { #define MAX_LINE_LEN 1024 char *pLine = (char*) malloc(MAX_LINE_LEN); if (pLine) { while (fgets(pLine, MAX_LINE_LEN, pConfigFile) != NULL) { int lineLength; RemoveWhiteSpaceFromTheEnd(pLine); lineLength = (int) strlen(pLine); if (lineLength != 0) { char *pKey; char *pKeyEnd; char *pValue; ConfigKey *pConfigKey; // Attempt to find the key pKey = SkipWhiteSpace(pLine); // Make sure that we are not dealing with an empty line or a comment if (*pKey == '\0' || *pKey == '#') continue; // Go past the key pKeyEnd = SkipNonWhiteSpace(pKey); // Protect against a malformed line if (*pKeyEnd == '\0') { DbgTrace(0, "-GetConfigInterface- Key found without value\n", 0); continue; } // Attempt to find the value pValue = SkipWhiteSpace(pKeyEnd); // Protect against a malformed line if (*pValue == '\0') { DbgTrace(0, "-GetConfigInterface- Key found without value\n", 0); continue; } // Delineate the key *pKeyEnd = '\0'; // Create a ConfigKey object for this key/value pair pConfigKey = (ConfigKey*) malloc(sizeof(*pConfigKey)); if (pConfigKey) { pConfigKey->keyNameLen = (int) strlen(pKey); pConfigKey->pKeyName = (char*) malloc(pConfigKey->keyNameLen + 1); if (pConfigKey->pKeyName) { // Save the key name in lower case LowerCaseString(pConfigKey->pKeyName, pKey); pConfigKey->valueLen = (int) strlen(pValue); pConfigKey->pValue = (char*) malloc(pConfigKey->valueLen + 1); if (pConfigKey->pValue) { strcpy(pConfigKey->pValue, pValue); // The entry is ready, now associate it with the instance data. InsertTailList(&pConfigIfInstance->configKeyListHead, &pConfigKey->listEntry); } else { DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); free(pConfigKey->pKeyName); free(pConfigKey); } } else { DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); free(pConfigKey); } } else { DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); } } } // Free the buffer allocated for holding line strings free(pLine); } else { DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); } } else { DbgTrace(0, "-GetConfigInterface- File seek error, errno = %d\n", errno); } } else { DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); // Free the buffers associated with the instance data free(pConfigIfInstance->pConfigFolder); free(pConfigIfInstance); } } else { DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); // Free the buffer allocated for the instance data free(pConfigIfInstance); } } else { DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); } // Close the file fclose(pConfigFile); } else { DbgTrace(0, "-GetConfigInterface- Unable to open config file, errno = %d\n", errno); DbgTrace(0, "-GetConfigInterface- Config file unable to open = %s\n", pFilePath); } // Free the buffer allocated for the file path free(pFilePath); } else { DbgTrace(0, "-GetConfigInterface- Buffer allocation error\n", 0); } } DbgTrace(2, "-GetConfigInterface- End, retStatus = %08X\n", retStatus); return retStatus; } //++======================================================================= //++======================================================================= //++=======================================================================