Source code

Revision control

Copy as Markdown

Other Tools

/*
*
* registry.c
*
* $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry.c,v $
* $Revision: 1.6 $
* $Date: 2007/11/21 00:09:12 $
*
* Datastore for tracking configuration and related info.
*
*
* Copyright (C) 2005, Network Resonance, Inc.
* Copyright (C) 2006, Network Resonance, Inc.
* All Rights Reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Network Resonance, Inc. nor the name of any
* contributors to this software may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
*/
#include <assert.h>
#include <string.h>
#ifndef _MSC_VER
#include <strings.h>
#include <sys/param.h>
#include <netinet/in.h>
#endif
#ifdef OPENSSL
#include <openssl/ssl.h>
#endif
#include <ctype.h>
#include <csi_platform.h>
#include "registry.h"
#include "registry_int.h"
#include "r_assoc.h"
#include "r_log.h"
#include "r_errors.h"
#include "r_macros.h"
static int reg_initted = 0;
/* must be in the order the types are numbered */
static const char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" };
int NR_LOG_REGISTRY=0;
NR_registry_name NR_TOP_LEVEL_REGISTRY = "";
int
NR_reg_init()
{
int r, _status;
#ifdef SANITY_CHECKS
NR_registry registry;
#endif
if (reg_initted) {
return(0);
}
reg_initted = 1;
if ((r=nr_reg_local_init()))
ABORT(r);
#ifdef SANITY_CHECKS
if ((r=NR_reg_get_registry(NR_TOP_LEVEL_REGISTRY, registry)))
ABORT(r);
assert(strcmp(registry, NR_TOP_LEVEL_REGISTRY) == 0);
#endif
r_log_init();
r_log_register("registry",&NR_LOG_REGISTRY);
_status=0;
abort:
r_log(NR_LOG_REGISTRY,
(_status ? LOG_ERR : LOG_INFO),
(_status ? "Couldn't initialize registry" : "Initialized registry"));
return(_status);
}
int
NR_reg_initted(void)
{
return reg_initted!=0;
}
#define NRREGGET(func, TYPE, type) \
int \
func(NR_registry_name name, type *out) \
{ \
return nr_reg_get(name, TYPE, out); \
}
NRREGGET(NR_reg_get_char, NR_REG_TYPE_CHAR, char)
NRREGGET(NR_reg_get_uchar, NR_REG_TYPE_UCHAR, UCHAR)
NRREGGET(NR_reg_get_uint2, NR_REG_TYPE_UINT2, UINT2)
NRREGGET(NR_reg_get_int4, NR_REG_TYPE_INT4, INT4)
NRREGGET(NR_reg_get_uint4, NR_REG_TYPE_UINT4, UINT4)
NRREGGET(NR_reg_get_uint8, NR_REG_TYPE_UINT8, UINT8)
NRREGGET(NR_reg_get_double, NR_REG_TYPE_DOUBLE, double)
int
NR_reg_get_registry(NR_registry_name name, NR_registry out)
{
int r, _status;
nr_scalar_registry_node *node = 0;
int free_node = 0;
if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (nr_registry_node**)&node, &free_node)))
ABORT(r);
strncpy(out, name, sizeof(NR_registry));
_status=0;
abort:
if (free_node) RFREE(node);
return(_status);
}
int
NR_reg_get_bytes(NR_registry_name name, UCHAR *out, size_t size, size_t *length)
{
return nr_reg_get_array(name, NR_REG_TYPE_BYTES, out, size, length);
}
int
NR_reg_get_string(NR_registry_name name, char *out, size_t size)
{
return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0);
}
int
NR_reg_get_length(NR_registry_name name, size_t *length)
{
return nr_reg_local_get_length(name, length);
}
#define NRREGSET(func, TYPE, type) \
int \
func(NR_registry_name name, type data) \
{ \
return nr_reg_set(name, TYPE, &data); \
}
NRREGSET(NR_reg_set_char, NR_REG_TYPE_CHAR, char)
NRREGSET(NR_reg_set_uchar, NR_REG_TYPE_UCHAR, UCHAR)
NRREGSET(NR_reg_set_int4, NR_REG_TYPE_INT4, INT4)
NRREGSET(NR_reg_set_uint4, NR_REG_TYPE_UINT4, UINT4)
int
NR_reg_set_string(NR_registry_name name, const char *data)
{
return nr_reg_set_array(name, NR_REG_TYPE_STRING, (const UCHAR*)data, strlen(data)+1);
}
int
NR_reg_set_registry(NR_registry_name name)
{
return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0);
}
int
NR_reg_set_bytes(NR_registry_name name, const unsigned char *data, size_t length)
{
return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length);
}
int
NR_reg_del(NR_registry_name name)
{
return nr_reg_local_del(name);
}
int
NR_reg_get_child_count(NR_registry_name parent, unsigned int *count)
{
assert(sizeof(count) == sizeof(size_t));
return nr_reg_local_get_child_count(parent, (size_t*)count);
}
int
NR_reg_get_child_registry(NR_registry_name parent, unsigned int i, NR_registry child)
{
int r, _status;
size_t count;
NR_registry *children=0;
if ((r=nr_reg_local_get_child_count(parent, &count)))
ABORT(r);
if (i >= count)
ABORT(R_NOT_FOUND);
else {
count++;
children = R_NEW_CNT(NR_registry, count);
if (!children)
ABORT(R_NO_MEMORY);
if ((r=nr_reg_local_get_children(parent, children, count, &count)))
ABORT(r);
if (i >= count)
ABORT(R_NOT_FOUND);
strncpy(child, children[i], sizeof(NR_registry));
}
_status=0;
abort:
RFREE(children);
return(_status);
}
// convenience methods, call RFREE on the returned data
int
NR_reg_alloc_data(NR_registry_name name, Data *data)
{
int r, _status;
size_t length;
UCHAR *tmp = 0;
size_t sanity_check;
if ((r=NR_reg_get_length(name, &length)))
ABORT(r);
if (!(tmp = (UCHAR*)RMALLOC(length)))
ABORT(R_NO_MEMORY);
if ((r=NR_reg_get_bytes(name, tmp, length, &sanity_check)))
ABORT(r);
assert(length == sanity_check);
data->len = length;
data->data = tmp;
_status=0;
abort:
if (_status) {
if (tmp) RFREE(tmp);
}
return(_status);
}
int
NR_reg_alloc_string(NR_registry_name name, char **data)
{
int r, _status;
size_t length;
char *tmp = 0;
if ((r=NR_reg_get_length(name, &length)))
ABORT(r);
if (!(tmp = (char*)RMALLOC(length+1)))
ABORT(R_NO_MEMORY);
if ((r=NR_reg_get_string(name, tmp, length+1)))
ABORT(r);
assert(length == strlen(tmp));
*data = tmp;
_status=0;
abort:
if (_status) {
if (tmp) RFREE(tmp);
}
return(_status);
}
const char *
nr_reg_type_name(int type)
{
if ((type < NR_REG_TYPE_CHAR) || (type > NR_REG_TYPE_REGISTRY))
return(NULL);
return(typenames[type]);
}
/* More convenience functions: the same as their parents but they
take a prefix and a suffix */
#define NRGET2(func, type, get) \
int \
func(NR_registry_name parent, const char *child, type *out) \
{ \
int r, _status; \
NR_registry registry; \
\
if ((r = NR_reg_make_registry(parent, child, registry))) \
ABORT(r); \
\
if ((r = get(registry, out))) { \
ABORT(r); \
} \
\
_status = 0; \
abort: \
return (_status); \
}
NRGET2(NR_reg_get2_char, char, NR_reg_get_char)
NRGET2(NR_reg_get2_uchar, UCHAR, NR_reg_get_uchar)
NRGET2(NR_reg_get2_uint2, UINT2, NR_reg_get_uint2)
NRGET2(NR_reg_alloc2_string, char*, NR_reg_alloc_string)
NRGET2(NR_reg_alloc2_data, Data, NR_reg_alloc_data)
/* More convenience functions: the same as their parents but they
take a prefix and a suffix */
#define NRSET2(func, type, set) \
int \
func(NR_registry_name parent, const char *child, type in) \
{ \
int r, _status; \
NR_registry registry; \
\
if ((r = NR_reg_make_registry(parent, child, registry))) \
ABORT(r); \
\
if ((r = set(registry, in))) { \
ABORT(r); \
} \
\
_status = 0; \
abort: \
return (_status); \
}
NRSET2(NR_reg_set2_uchar, UCHAR, NR_reg_set_uchar)
NRSET2(NR_reg_set2_string, const char*, NR_reg_set_string)
/* requires parent already in legal form */
int
NR_reg_make_registry(NR_registry_name parent, const char *child, NR_registry out)
{
int r, _status;
size_t plen;
size_t clen;
char *c = 0;
size_t i;
if ((r=nr_reg_is_valid(parent)))
ABORT(r);
if (*child == '.')
ABORT(R_BAD_ARGS);
clen = strlen(child);
if (!clen)
ABORT(R_BAD_ARGS);
plen = strlen(parent);
if ((plen + clen + 2) > sizeof(NR_registry))
ABORT(R_BAD_ARGS);
if (out != parent)
strcpy(out, parent);
c = &(out[plen]);
if (parent[0] != '\0') {
*c = '.';
++c;
}
for (i = 0; i < clen; ++i, ++c) {
*c = child[i];
if (isspace(*c) || *c == '.' || *c == '/' || ! isprint(*c))
*c = '_';
}
*c = '\0';
_status = 0;
abort:
return _status;
}