/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * mslp_prefs.c : Hash table for mini slpv2 preference storage. * * Contains code for an in memory associative array. * * Version: 1.8 * Date: 10/05/99 * * Licensee will, at its expense, defend and indemnify Sun Microsystems, * Inc. ("Sun") and its licensors from and against any third party * claims, including costs and reasonable attorneys' fees, and be wholly * responsible for any liabilities arising out of or related to the * Licensee's use of the Software or Modifications. The Software is not * designed or intended for use in on-line control of aircraft, air * traffic, aircraft navigation, or aircraft communications; or in the * design, construction, operation or maintenance of any nuclear facility * and Sun disclaims any express or implied warranty of fitness for such * uses. THE SOFTWARE IS PROVIDED TO LICENSEE "AS IS" AND ALL EXPRESS OR * IMPLIED CONDITION AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF * MERCHANTABILITY, FITNESS FOR WARRANTIES, INCLUDING ANY IMPLIED * WARRANTY OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE OR NON- * INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT WILL SUN BE LIABLE HEREUNDER * FOR ANY DIRECT DAMAGES OR ANY INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL * OR CONSEQUENTIAL DAMAGES OF ANY KIND. * * (c) Sun Microsystems, All Rights Reserved, 1998. * Author: Erik Guttman */ /* Portions Copyright (c) 2002 Apple Computer, Inc. All rights reserved. */ #include #include #include #include // for _POSIX_THREADS #include // for pthread_*_t #include "mslp_sd.h" /* System dep. / source compatibility */ #include "slp.h" /* SLP API supported features */ #include "mslp.h" /* Definitions for mslp, shared */ static unsigned int string_hash(const char *pcKey); static void free_bucket(MslpHashbucket *pb); static MslpHashbucket * new_bucket(const char *pcKey, const char *pcVal); void mslp_file_param_add(const char *pcKey, const char *pcVal, void *pvParam); void mslp_log_params(const char *pcKey, const char *pcVal, void *pvParam); pthread_mutex_t gHashTableLock; int gHashTableLockNotInitialized = 1; void mslp_hash_write(MslpHashtable *ph, const char *pcFileName) { FILE *fp; char buf[kMaxSizeOfParam]; if (ph == NULL) SLPLOG(SLP_LOG_ERR,"mslp_hash_write called without an initialized hash table"); if (pcFileName == NULL) return; fp = fopen(pcFileName,"w"); if (fp == NULL) { #ifdef ENABLE_SLP_LOGGING mslplog(SLP_LOG_MSG,"mslp_hash_write: Could not open config file",pcFileName); #endif return; } mslp_hash_do( ph, mslp_file_param_add, fp ); // iterate over all hash values and write to file while (fgets(buf,kMaxSizeOfParam,fp) != NULL) { char *pcKey,*pcVal,cDelim; int offset = 0; if (buf[0] == '\n' || buf[0] == '\0' || buf[0] == '#' || buf[0] == ';') continue; pcKey = get_next_string("=",buf,&offset,&cDelim); pcVal = get_next_string("=",buf,&offset,&cDelim); if (pcKey == NULL || pcVal == NULL) continue; else mslp_hash_add(ph,pcKey,pcVal); } fclose(fp); } void mslp_file_param_add(const char *pcKey, const char *pcVal, void *pvParam) { FILE *fpDest = (FILE *) pvParam; if (pcVal[0] == '\0') { fprintf(fpDest,"%s\n",pcKey); } else { fprintf(fpDest,"%s=%s\n",pcKey,pcVal); } } void mslp_log_params(const char *pcKey, const char *pcVal, void *pvParam) { if ( !pcKey ) SLP_LOG( SLP_LOG_ERR, "mslp_log_params was passed in a null key!" ); #ifdef ENABLE_SLP_LOGGING else if (!pcVal || pcVal[0] == '\0') SLP_LOG( SLP_LOG_STATE, "%s\n", pcKey ); else SLP_LOG( SLP_LOG_STATE, "%s=%s", pcKey, pcVal ); #endif } void mslp_hash_read(MslpHashtable *ph, const char *pcFileName) { FILE *fp; char buf[kMaxSizeOfParam]; if (ph == NULL) { SLPLOG(SLP_LOG_FAIL,"mslp_hash_read called without an initialized hash table"); } if (pcFileName == NULL) return; fp = fopen(pcFileName,"r"); if (fp == NULL) { #ifdef ENABLE_SLP_LOGGING mslplog(SLP_LOG_MSG,"mslp_hash_read: Could not open config file",pcFileName); #endif return; } while (fgets(buf,kMaxSizeOfParam,fp) != NULL) { char *pcKey,*pcVal,cDelim; int offset = 0; if (buf[0] == '\n' || buf[0] == '\0' || buf[0] == '#' || buf[0] == ';') continue; pcKey = get_next_string("=",buf,&offset,&cDelim); pcVal = get_next_string("=",buf,&offset,&cDelim); if (pcKey == NULL || pcVal == NULL) { continue; } else { mslp_hash_add(ph,pcKey,pcVal); } SLPFree(pcKey); SLPFree(pcVal); } fclose(fp); } int mslp_conf_int(MslpHashtable *ph, const char *pcKey, int index, int iDefault) { const char *pcVal = mslp_hash_find(ph,pcKey); int loop, offset = 0, result; char *pcIter = NULL, cDelim; if (pcVal == NULL) return iDefault; if (!SDstrcasecmp(pcVal,"true")) return 1; if (!SDstrcasecmp(pcVal,"false")) return 0; for (loop = 0; loop <= index; loop++) { if (pcIter != NULL) SLPFree(pcIter); pcIter = get_next_string(",",pcVal,&offset,&cDelim); if (pcIter == NULL) return iDefault; } if (pcIter != NULL) { char* endPtr = NULL; result = strtol(pcIter,&endPtr,10); SLPFree(pcIter); return result; } return iDefault; } EXPORT MslpHashtable * mslp_hash_init() { MslpHashtable *ph = (MslpHashtable *)safe_malloc(sizeof(MslpHashtable),NULL,0); ph->bucket = (MslpHashbucket **)safe_malloc(NUMBUCKETS * sizeof(MslpHashbucket*),NULL,0); memset(ph->bucket,0,NUMBUCKETS * sizeof(MslpHashbucket*)); if ( gHashTableLockNotInitialized ) { pthread_mutex_init (&gHashTableLock, NULL) ; gHashTableLockNotInitialized = 0; } return ph; } #ifdef EXTRA_MSGS /* * mslp_hash_free * * Free the hash table. * * Parameters: ph Hash table. * Results: None. * Side Effects: The hash table is freed. */ EXPORT void mslp_hash_free(MslpHashtable *ph) { int i; MslpHashbucket *phb = NULL; if (ph) { pthread_mutex_lock( &gHashTableLock ); for (i=0;ibucket[i]) { for (phb = ph->bucket[i]; phb; ) { MslpHashbucket *phbTemp = phb->pBucketNext; free_bucket(phb); phb = phbTemp; } ph->bucket[i] = NULL; } } SLPFree(ph->bucket); SLPFree(ph); pthread_mutex_unlock( &gHashTableLock ); } } /* * mslp_hash_do * * Call the supplied function with the key and value and opaque parameter * for each element in the hash function. * * Parameters: * * ph A hash table. * dofun A function to call. * pvParam An opaque parameter. * * Results: * * None. * * Side effects: * * None. */ EXPORT void mslp_hash_do(MslpHashtable *ph, MslpHashDoFun dofun,void *pvParam) { int i; MslpHashbucket *phb = NULL; if (ph) { pthread_mutex_lock( &gHashTableLock ); for (i=0;ibucket && ph->bucket[i]) { for (phb = ph->bucket[i]; phb; phb = phb->pBucketNext) { dofun(phb->pcKey,phb->pcVal,pvParam); } } } pthread_mutex_unlock( &gHashTableLock ); } } #endif /* EXTRA_MSGS */ EXPORT const char *mslp_hash_find(MslpHashtable *ph, const char *pcKey) { unsigned int iBucket = string_hash(pcKey) % NUMBUCKETS; char* value = NULL; if (ph == NULL) { SLPLOG(SLP_LOG_FAIL,"mslp_hash_find called without an initialized ht"); return NULL; } if (ph->bucket[iBucket] == NULL) { return NULL; } else { MslpHashbucket *pb = ph->bucket[iBucket]; pthread_mutex_lock( &gHashTableLock ); /* traverse the linked list till we find the entry */ while (pb && pb->pcKey) { if (!SDstrcasecmp(pcKey,pb->pcKey)) { value = pb->pcVal; break; } else { pb = pb->pBucketNext; } } pthread_mutex_unlock( &gHashTableLock ); } return value; } EXPORT void mslp_hash_add(MslpHashtable *ph, const char *pcKey, const char *pcVal) { unsigned int iBucket = string_hash(pcKey) % NUMBUCKETS; Boolean found = false; if (ph == NULL) SLPLOG(SLP_LOG_FAIL,"mslp_hash_add called without an initialized ht"); if (pcKey == NULL) return; pthread_mutex_lock( &gHashTableLock ); if (ph->bucket[iBucket] == NULL) { if (pcVal) { ph->bucket[iBucket] = new_bucket(pcKey,pcVal); } } else { MslpHashbucket *pb = ph->bucket[iBucket]; MslpHashbucket *pbPrev = pb; while (pb) { if (!SDstrcasecmp(pcKey,pb->pcKey)) { found = true; if (pcVal == NULL) { /* delete an entry */ if (pb == ph->bucket[iBucket]) { /* special initial case */ ph->bucket[iBucket] = pb->pBucketNext; } else { pbPrev->pBucketNext = pb->pBucketNext; } free_bucket(pb); pb = NULL; break; } else { /* update an entry */ SLPFree(pb->pcVal); pb->pcVal = safe_malloc(strlen(pcVal)+1,pcVal,strlen(pcVal)); break; } } else { pbPrev = pb; pb = pb->pBucketNext; } } /* if we get here there is no entry in the Bucket yet. Add it. */ if ( pcVal && !found ) pbPrev->pBucketNext = new_bucket(pcKey,pcVal); } pthread_mutex_unlock( &gHashTableLock ); // don't forget to clear this! } static void free_bucket(MslpHashbucket *pb) { SLPFree(pb->pcKey); pb->pcKey = NULL; SLPFree(pb->pcVal); pb->pcVal = NULL; SLPFree(pb); } static MslpHashbucket * new_bucket(const char *pcKey, const char *pcVal) { MslpHashbucket *pb = (MslpHashbucket *)safe_malloc(sizeof(MslpHashbucket),NULL,0); pb->pcKey = safe_malloc(strlen(pcKey)+1,pcKey,strlen(pcKey)); pb->pcVal = safe_malloc(strlen(pcVal)+1,pcVal,strlen(pcVal)); pb->pBucketNext = NULL; return pb; } static unsigned int string_hash(const char *pcKey) { unsigned int result = 0; int c; while (1) { c = *pcKey; pcKey++; if (c == 0) { break; } result += (result<<3) + c; } return result; } EXPORT void mslp_hash_log_values(MslpHashtable *ph) { #ifdef ENABLE_SLP_LOGGING SLP_LOG( SLP_LOG_STATE, "Current SLP Configuration State:" ); mslp_hash_do( ph, mslp_log_params, NULL ); // iterate over all hash values and write to file #endif }