]>
Commit | Line | Data |
---|---|---|
61b844bf TL |
1 | /* generic.c |
2 | ||
3 | Subroutines that support the generic object. */ | |
4 | ||
5 | /* | |
6 | * Copyright (c) 1996-1999 Internet Software Consortium. | |
7 | * Use is subject to license terms which appear in the file named | |
8 | * ISC-LICENSE that should have accompanied this file when you | |
9 | * received it. If a file named ISC-LICENSE did not accompany this | |
10 | * file, or you are not sure the one you have is correct, you may | |
11 | * obtain an applicable copy of the license at: | |
12 | * | |
13 | * http://www.isc.org/isc-license-1.0.html. | |
14 | * | |
15 | * This file is part of the ISC DHCP distribution. The documentation | |
16 | * associated with this file is listed in the file DOCUMENTATION, | |
17 | * included in the top-level directory of this release. | |
18 | * | |
19 | * Support and other services are available for ISC products - see | |
20 | * http://www.isc.org for more information. | |
21 | */ | |
22 | ||
23 | #include <omapip/omapip.h> | |
24 | ||
b1b7b521 | 25 | isc_result_t omapi_generic_new (omapi_object_t **gen, const char *name) |
61b844bf TL |
26 | { |
27 | omapi_generic_object_t *obj; | |
28 | ||
29 | obj = malloc (sizeof *obj); | |
30 | if (!obj) | |
31 | return ISC_R_NOMEMORY; | |
32 | memset (obj, 0, sizeof *obj); | |
33 | obj -> refcnt = 0; | |
34 | obj -> type = omapi_type_generic; | |
35 | ||
36 | return omapi_object_reference (gen, (omapi_object_t *)obj, name); | |
37 | } | |
38 | ||
39 | isc_result_t omapi_generic_set_value (omapi_object_t *h, | |
40 | omapi_object_t *id, | |
41 | omapi_data_string_t *name, | |
42 | omapi_typed_data_t *value) | |
43 | { | |
44 | omapi_generic_object_t *g; | |
45 | omapi_value_t *new; | |
46 | omapi_value_t **va; | |
47 | int vm_new; | |
48 | int i; | |
49 | isc_result_t status; | |
50 | ||
51 | if (h -> type != omapi_type_generic) | |
52 | return ISC_R_INVALIDARG; | |
53 | g = (omapi_generic_object_t *)h; | |
54 | ||
55 | /* See if there's already a value with this name attached to | |
56 | the generic object, and if so, replace the current value | |
57 | with the new one. */ | |
58 | for (i = 0; i < g -> nvalues; i++) { | |
59 | if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { | |
60 | /* There's an inconsistency here: the standard | |
61 | behaviour of a set_values method when | |
62 | passed a matching name and a null value is | |
63 | to delete the value associated with that | |
64 | name (where possible). In the generic | |
65 | object, we remember the name/null pair, | |
66 | because generic objects are generally used | |
67 | to pass messages around, and this is the | |
68 | way that remote entities delete values from | |
69 | local objects. If the get_value method of | |
70 | a generic object is called for a name that | |
71 | maps to a name/null pair, ISC_R_NOTFOUND is | |
72 | returned. */ | |
73 | new = (omapi_value_t *)0; | |
74 | status = (omapi_value_new (&new, | |
75 | "omapi_message_get_value")); | |
76 | if (status != ISC_R_SUCCESS) | |
77 | return status; | |
78 | omapi_data_string_reference | |
79 | (&new -> name, name, | |
80 | "omapi_message_get_value"); | |
81 | if (value) | |
82 | omapi_typed_data_reference | |
83 | (&new -> value, value, | |
84 | "omapi_generic_set_value"); | |
85 | ||
86 | omapi_value_dereference (&(g -> values [i]), | |
87 | "omapi_message_set_value"); | |
88 | status = (omapi_value_reference | |
89 | (&(g -> values [i]), new, | |
90 | "omapi_message_set_value")); | |
91 | omapi_value_dereference (&new, | |
92 | "omapi_message_set_value"); | |
93 | return status; | |
94 | } | |
95 | } | |
96 | ||
97 | /* If the name isn't already attached to this object, see if an | |
98 | inner object has it. */ | |
581e37e4 | 99 | if (h -> inner && h -> inner -> type -> set_value) { |
61b844bf TL |
100 | status = ((*(h -> inner -> type -> set_value)) |
101 | (h -> inner, id, name, value)); | |
581e37e4 TL |
102 | if (status != ISC_R_NOTFOUND) |
103 | return status; | |
104 | } | |
61b844bf TL |
105 | |
106 | /* Okay, so it's a value that no inner object knows about, and | |
107 | (implicitly, since the outer object set_value method would | |
108 | have called this object's set_value method) it's an object that | |
109 | no outer object knows about, it's this object's responsibility | |
110 | to remember it - that's what generic objects do. */ | |
111 | ||
112 | /* Arrange for there to be space for the pointer to the new | |
113 | name/value pair if necessary: */ | |
114 | if (g -> nvalues == g -> va_max) { | |
115 | if (g -> va_max) | |
116 | vm_new = 2 * g -> va_max; | |
117 | else | |
118 | vm_new = 10; | |
119 | va = malloc (vm_new * sizeof *va); | |
120 | if (!va) | |
121 | return ISC_R_NOMEMORY; | |
122 | if (g -> va_max) | |
123 | memcpy (va, g -> values, g -> va_max * sizeof *va); | |
124 | memset (va + g -> va_max, 0, | |
125 | (vm_new - g -> va_max) * sizeof *va); | |
126 | free (g -> values); | |
127 | g -> values = va; | |
128 | } | |
129 | status = omapi_value_new (&g -> values [g -> nvalues], | |
130 | "omapi_generic_set_value"); | |
131 | if (status != ISC_R_SUCCESS) | |
132 | return status; | |
133 | omapi_data_string_reference (&g -> values [g -> nvalues] -> name, name, | |
134 | "omapi_generic_set_value"); | |
135 | if (value) | |
136 | omapi_typed_data_reference | |
137 | (&g -> values [g -> nvalues] -> value, value, | |
138 | "omapi_generic_set_value"); | |
139 | g -> nvalues++; | |
140 | return ISC_R_SUCCESS; | |
141 | } | |
142 | ||
143 | isc_result_t omapi_generic_get_value (omapi_object_t *h, | |
144 | omapi_object_t *id, | |
145 | omapi_data_string_t *name, | |
146 | omapi_value_t **value) | |
147 | { | |
148 | int i; | |
149 | omapi_generic_object_t *g; | |
150 | ||
151 | if (h -> type != omapi_type_generic) | |
152 | return ISC_R_INVALIDARG; | |
153 | g = (omapi_generic_object_t *)h; | |
154 | ||
155 | /* Look up the specified name in our list of objects. */ | |
156 | for (i = 0; i < g -> nvalues; i++) { | |
157 | if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { | |
158 | /* If this is a name/null value pair, this is the | |
159 | same as if there were no value that matched | |
160 | the specified name, so return ISC_R_NOTFOUND. */ | |
161 | if (!g -> values [i] -> value) | |
162 | return ISC_R_NOTFOUND; | |
163 | /* Otherwise, return the name/value pair. */ | |
164 | return omapi_value_reference | |
165 | (value, g -> values [i], | |
166 | "omapi_message_get_value"); | |
167 | } | |
168 | } | |
169 | ||
170 | if (h -> inner && h -> inner -> type -> get_value) | |
171 | return (*(h -> inner -> type -> get_value)) | |
172 | (h -> inner, id, name, value); | |
173 | return ISC_R_NOTFOUND; | |
174 | } | |
175 | ||
b1b7b521 | 176 | isc_result_t omapi_generic_destroy (omapi_object_t *h, const char *name) |
61b844bf TL |
177 | { |
178 | omapi_generic_object_t *g; | |
179 | int i; | |
180 | ||
181 | if (h -> type != omapi_type_generic) | |
182 | return ISC_R_UNEXPECTED; | |
183 | g = (omapi_generic_object_t *)h; | |
184 | ||
185 | if (g -> values) { | |
186 | for (i = 0; i < g -> nvalues; i++) { | |
187 | if (g -> values [i]) | |
188 | omapi_value_dereference (&g -> values [i], | |
189 | name); | |
190 | } | |
191 | free (g -> values); | |
192 | g -> values = (omapi_value_t **)0; | |
193 | g -> va_max = 0; | |
194 | } | |
195 | ||
196 | return ISC_R_SUCCESS; | |
197 | } | |
198 | ||
199 | isc_result_t omapi_generic_signal_handler (omapi_object_t *h, | |
b1b7b521 | 200 | const char *name, va_list ap) |
61b844bf TL |
201 | { |
202 | if (h -> type != omapi_type_generic) | |
203 | return ISC_R_INVALIDARG; | |
204 | ||
205 | if (h -> inner && h -> inner -> type -> signal_handler) | |
206 | return (*(h -> inner -> type -> signal_handler)) (h -> inner, | |
207 | name, ap); | |
208 | return ISC_R_NOTFOUND; | |
209 | } | |
210 | ||
211 | /* Write all the published values associated with the object through the | |
212 | specified connection. */ | |
213 | ||
214 | isc_result_t omapi_generic_stuff_values (omapi_object_t *c, | |
215 | omapi_object_t *id, | |
216 | omapi_object_t *g) | |
217 | { | |
218 | omapi_generic_object_t *src; | |
219 | int i; | |
220 | isc_result_t status; | |
221 | ||
222 | if (g -> type != omapi_type_generic) | |
223 | return ISC_R_INVALIDARG; | |
224 | src = (omapi_generic_object_t *)g; | |
225 | ||
226 | for (i = 0; i < src -> nvalues; i++) { | |
227 | if (src -> values [i] && src -> values [i] -> name -> len) { | |
228 | status = (omapi_connection_put_uint16 | |
229 | (c, src -> values [i] -> name -> len)); | |
230 | if (status != ISC_R_SUCCESS) | |
231 | return status; | |
581e37e4 TL |
232 | status = (omapi_connection_copyin |
233 | (c, src -> values [i] -> name -> value, | |
61b844bf TL |
234 | src -> values [i] -> name -> len)); |
235 | if (status != ISC_R_SUCCESS) | |
236 | return status; | |
237 | ||
238 | status = (omapi_connection_write_typed_data | |
239 | (c, src -> values [i] -> value)); | |
240 | if (status != ISC_R_SUCCESS) | |
241 | return status; | |
242 | } | |
243 | } | |
244 | ||
245 | if (g -> inner && g -> inner -> type -> stuff_values) | |
246 | return (*(g -> inner -> type -> stuff_values)) (c, id, | |
247 | g -> inner); | |
248 | return ISC_R_SUCCESS; | |
249 | } | |
250 |