]>
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 | ||
6a4c4be8 | 23 | #include <omapip/omapip_p.h> |
61b844bf | 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; | |
d82813f8 | 128 | g -> va_max = vm_new; |
61b844bf TL |
129 | } |
130 | status = omapi_value_new (&g -> values [g -> nvalues], | |
131 | "omapi_generic_set_value"); | |
132 | if (status != ISC_R_SUCCESS) | |
133 | return status; | |
134 | omapi_data_string_reference (&g -> values [g -> nvalues] -> name, name, | |
135 | "omapi_generic_set_value"); | |
136 | if (value) | |
137 | omapi_typed_data_reference | |
138 | (&g -> values [g -> nvalues] -> value, value, | |
139 | "omapi_generic_set_value"); | |
140 | g -> nvalues++; | |
141 | return ISC_R_SUCCESS; | |
142 | } | |
143 | ||
144 | isc_result_t omapi_generic_get_value (omapi_object_t *h, | |
145 | omapi_object_t *id, | |
146 | omapi_data_string_t *name, | |
147 | omapi_value_t **value) | |
148 | { | |
149 | int i; | |
150 | omapi_generic_object_t *g; | |
151 | ||
152 | if (h -> type != omapi_type_generic) | |
153 | return ISC_R_INVALIDARG; | |
154 | g = (omapi_generic_object_t *)h; | |
155 | ||
156 | /* Look up the specified name in our list of objects. */ | |
157 | for (i = 0; i < g -> nvalues; i++) { | |
158 | if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { | |
159 | /* If this is a name/null value pair, this is the | |
160 | same as if there were no value that matched | |
161 | the specified name, so return ISC_R_NOTFOUND. */ | |
162 | if (!g -> values [i] -> value) | |
163 | return ISC_R_NOTFOUND; | |
164 | /* Otherwise, return the name/value pair. */ | |
165 | return omapi_value_reference | |
166 | (value, g -> values [i], | |
167 | "omapi_message_get_value"); | |
168 | } | |
169 | } | |
170 | ||
171 | if (h -> inner && h -> inner -> type -> get_value) | |
172 | return (*(h -> inner -> type -> get_value)) | |
173 | (h -> inner, id, name, value); | |
174 | return ISC_R_NOTFOUND; | |
175 | } | |
176 | ||
b1b7b521 | 177 | isc_result_t omapi_generic_destroy (omapi_object_t *h, const char *name) |
61b844bf TL |
178 | { |
179 | omapi_generic_object_t *g; | |
180 | int i; | |
181 | ||
182 | if (h -> type != omapi_type_generic) | |
183 | return ISC_R_UNEXPECTED; | |
184 | g = (omapi_generic_object_t *)h; | |
185 | ||
186 | if (g -> values) { | |
187 | for (i = 0; i < g -> nvalues; i++) { | |
188 | if (g -> values [i]) | |
189 | omapi_value_dereference (&g -> values [i], | |
190 | name); | |
191 | } | |
192 | free (g -> values); | |
193 | g -> values = (omapi_value_t **)0; | |
194 | g -> va_max = 0; | |
195 | } | |
196 | ||
197 | return ISC_R_SUCCESS; | |
198 | } | |
199 | ||
200 | isc_result_t omapi_generic_signal_handler (omapi_object_t *h, | |
b1b7b521 | 201 | const char *name, va_list ap) |
61b844bf TL |
202 | { |
203 | if (h -> type != omapi_type_generic) | |
204 | return ISC_R_INVALIDARG; | |
205 | ||
206 | if (h -> inner && h -> inner -> type -> signal_handler) | |
207 | return (*(h -> inner -> type -> signal_handler)) (h -> inner, | |
208 | name, ap); | |
209 | return ISC_R_NOTFOUND; | |
210 | } | |
211 | ||
212 | /* Write all the published values associated with the object through the | |
213 | specified connection. */ | |
214 | ||
215 | isc_result_t omapi_generic_stuff_values (omapi_object_t *c, | |
216 | omapi_object_t *id, | |
217 | omapi_object_t *g) | |
218 | { | |
219 | omapi_generic_object_t *src; | |
220 | int i; | |
221 | isc_result_t status; | |
222 | ||
223 | if (g -> type != omapi_type_generic) | |
224 | return ISC_R_INVALIDARG; | |
225 | src = (omapi_generic_object_t *)g; | |
226 | ||
227 | for (i = 0; i < src -> nvalues; i++) { | |
228 | if (src -> values [i] && src -> values [i] -> name -> len) { | |
229 | status = (omapi_connection_put_uint16 | |
230 | (c, src -> values [i] -> name -> len)); | |
231 | if (status != ISC_R_SUCCESS) | |
232 | return status; | |
581e37e4 TL |
233 | status = (omapi_connection_copyin |
234 | (c, src -> values [i] -> name -> value, | |
61b844bf TL |
235 | src -> values [i] -> name -> len)); |
236 | if (status != ISC_R_SUCCESS) | |
237 | return status; | |
238 | ||
239 | status = (omapi_connection_write_typed_data | |
240 | (c, src -> values [i] -> value)); | |
241 | if (status != ISC_R_SUCCESS) | |
242 | return status; | |
243 | } | |
244 | } | |
245 | ||
246 | if (g -> inner && g -> inner -> type -> stuff_values) | |
247 | return (*(g -> inner -> type -> stuff_values)) (c, id, | |
248 | g -> inner); | |
249 | return ISC_R_SUCCESS; | |
250 | } | |
251 |