diff options
Diffstat (limited to 'omapip/generic.c')
-rw-r--r-- | omapip/generic.c | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/omapip/generic.c b/omapip/generic.c new file mode 100644 index 00000000..6c1ac3ce --- /dev/null +++ b/omapip/generic.c @@ -0,0 +1,249 @@ +/* generic.c + + Subroutines that support the generic object. */ + +/* + * Copyright (c) 1996-1999 Internet Software Consortium. + * Use is subject to license terms which appear in the file named + * ISC-LICENSE that should have accompanied this file when you + * received it. If a file named ISC-LICENSE did not accompany this + * file, or you are not sure the one you have is correct, you may + * obtain an applicable copy of the license at: + * + * http://www.isc.org/isc-license-1.0.html. + * + * This file is part of the ISC DHCP distribution. The documentation + * associated with this file is listed in the file DOCUMENTATION, + * included in the top-level directory of this release. + * + * Support and other services are available for ISC products - see + * http://www.isc.org for more information. + */ + +#include <omapip/omapip.h> + +isc_result_t omapi_generic_new (omapi_object_t **gen, char *name) +{ + omapi_generic_object_t *obj; + + obj = malloc (sizeof *obj); + if (!obj) + return ISC_R_NOMEMORY; + memset (obj, 0, sizeof *obj); + obj -> refcnt = 0; + obj -> type = omapi_type_generic; + + return omapi_object_reference (gen, (omapi_object_t *)obj, name); +} + +isc_result_t omapi_generic_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + omapi_generic_object_t *g; + omapi_value_t *new; + omapi_value_t **va; + int vm_new; + int i; + isc_result_t status; + + if (h -> type != omapi_type_generic) + return ISC_R_INVALIDARG; + g = (omapi_generic_object_t *)h; + + /* See if there's already a value with this name attached to + the generic object, and if so, replace the current value + with the new one. */ + for (i = 0; i < g -> nvalues; i++) { + if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { + /* There's an inconsistency here: the standard + behaviour of a set_values method when + passed a matching name and a null value is + to delete the value associated with that + name (where possible). In the generic + object, we remember the name/null pair, + because generic objects are generally used + to pass messages around, and this is the + way that remote entities delete values from + local objects. If the get_value method of + a generic object is called for a name that + maps to a name/null pair, ISC_R_NOTFOUND is + returned. */ + new = (omapi_value_t *)0; + status = (omapi_value_new (&new, + "omapi_message_get_value")); + if (status != ISC_R_SUCCESS) + return status; + omapi_data_string_reference + (&new -> name, name, + "omapi_message_get_value"); + if (value) + omapi_typed_data_reference + (&new -> value, value, + "omapi_generic_set_value"); + + omapi_value_dereference (&(g -> values [i]), + "omapi_message_set_value"); + status = (omapi_value_reference + (&(g -> values [i]), new, + "omapi_message_set_value")); + omapi_value_dereference (&new, + "omapi_message_set_value"); + return status; + } + } + + /* If the name isn't already attached to this object, see if an + inner object has it. */ + if (h -> inner && h -> inner -> type -> set_value) + status = ((*(h -> inner -> type -> set_value)) + (h -> inner, id, name, value)); + if (status != ISC_R_NOTFOUND) + return status; + + /* Okay, so it's a value that no inner object knows about, and + (implicitly, since the outer object set_value method would + have called this object's set_value method) it's an object that + no outer object knows about, it's this object's responsibility + to remember it - that's what generic objects do. */ + + /* Arrange for there to be space for the pointer to the new + name/value pair if necessary: */ + if (g -> nvalues == g -> va_max) { + if (g -> va_max) + vm_new = 2 * g -> va_max; + else + vm_new = 10; + va = malloc (vm_new * sizeof *va); + if (!va) + return ISC_R_NOMEMORY; + if (g -> va_max) + memcpy (va, g -> values, g -> va_max * sizeof *va); + memset (va + g -> va_max, 0, + (vm_new - g -> va_max) * sizeof *va); + free (g -> values); + g -> values = va; + } + status = omapi_value_new (&g -> values [g -> nvalues], + "omapi_generic_set_value"); + if (status != ISC_R_SUCCESS) + return status; + omapi_data_string_reference (&g -> values [g -> nvalues] -> name, name, + "omapi_generic_set_value"); + if (value) + omapi_typed_data_reference + (&g -> values [g -> nvalues] -> value, value, + "omapi_generic_set_value"); + g -> nvalues++; + return ISC_R_SUCCESS; +} + +isc_result_t omapi_generic_get_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + int i; + omapi_generic_object_t *g; + + if (h -> type != omapi_type_generic) + return ISC_R_INVALIDARG; + g = (omapi_generic_object_t *)h; + + /* Look up the specified name in our list of objects. */ + for (i = 0; i < g -> nvalues; i++) { + if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { + /* If this is a name/null value pair, this is the + same as if there were no value that matched + the specified name, so return ISC_R_NOTFOUND. */ + if (!g -> values [i] -> value) + return ISC_R_NOTFOUND; + /* Otherwise, return the name/value pair. */ + return omapi_value_reference + (value, g -> values [i], + "omapi_message_get_value"); + } + } + + if (h -> inner && h -> inner -> type -> get_value) + return (*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t omapi_generic_destroy (omapi_object_t *h, char *name) +{ + omapi_generic_object_t *g; + int i; + + if (h -> type != omapi_type_generic) + return ISC_R_UNEXPECTED; + g = (omapi_generic_object_t *)h; + + if (g -> values) { + for (i = 0; i < g -> nvalues; i++) { + if (g -> values [i]) + omapi_value_dereference (&g -> values [i], + name); + } + free (g -> values); + g -> values = (omapi_value_t **)0; + g -> va_max = 0; + } + + return ISC_R_SUCCESS; +} + +isc_result_t omapi_generic_signal_handler (omapi_object_t *h, + char *name, va_list ap) +{ + if (h -> type != omapi_type_generic) + return ISC_R_INVALIDARG; + + if (h -> inner && h -> inner -> type -> signal_handler) + return (*(h -> inner -> type -> signal_handler)) (h -> inner, + name, ap); + return ISC_R_NOTFOUND; +} + +/* Write all the published values associated with the object through the + specified connection. */ + +isc_result_t omapi_generic_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *g) +{ + omapi_generic_object_t *src; + int i; + isc_result_t status; + + if (g -> type != omapi_type_generic) + return ISC_R_INVALIDARG; + src = (omapi_generic_object_t *)g; + + for (i = 0; i < src -> nvalues; i++) { + if (src -> values [i] && src -> values [i] -> name -> len) { + status = (omapi_connection_put_uint16 + (c, src -> values [i] -> name -> len)); + if (status != ISC_R_SUCCESS) + return status; + status = (omapi_connection_copyout + (src -> values [i] -> name -> value, c, + src -> values [i] -> name -> len)); + if (status != ISC_R_SUCCESS) + return status; + + status = (omapi_connection_write_typed_data + (c, src -> values [i] -> value)); + if (status != ISC_R_SUCCESS) + return status; + } + } + + if (g -> inner && g -> inner -> type -> stuff_values) + return (*(g -> inner -> type -> stuff_values)) (c, id, + g -> inner); + return ISC_R_SUCCESS; +} + |