1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert * prof_get.c --- routines that expose the public interfaces for
4*7f2fe78bSCy Schubert * querying items from the profile.
5*7f2fe78bSCy Schubert *
6*7f2fe78bSCy Schubert */
7*7f2fe78bSCy Schubert
8*7f2fe78bSCy Schubert #include "prof_int.h"
9*7f2fe78bSCy Schubert #include <stdio.h>
10*7f2fe78bSCy Schubert #include <string.h>
11*7f2fe78bSCy Schubert #ifdef HAVE_STDLIB_H
12*7f2fe78bSCy Schubert #include <stdlib.h>
13*7f2fe78bSCy Schubert #endif
14*7f2fe78bSCy Schubert #include <errno.h>
15*7f2fe78bSCy Schubert #include <limits.h>
16*7f2fe78bSCy Schubert
17*7f2fe78bSCy Schubert /*
18*7f2fe78bSCy Schubert * These functions --- init_list(), end_list(), and add_to_list() are
19*7f2fe78bSCy Schubert * internal functions used to build up a null-terminated char ** list
20*7f2fe78bSCy Schubert * of strings to be returned by functions like profile_get_values.
21*7f2fe78bSCy Schubert *
22*7f2fe78bSCy Schubert * The profile_string_list structure is used for internal booking
23*7f2fe78bSCy Schubert * purposes to build up the list, which is returned in *ret_list by
24*7f2fe78bSCy Schubert * the end_list() function.
25*7f2fe78bSCy Schubert *
26*7f2fe78bSCy Schubert * The publicly exported interface for freeing char** list is
27*7f2fe78bSCy Schubert * profile_free_list().
28*7f2fe78bSCy Schubert */
29*7f2fe78bSCy Schubert
30*7f2fe78bSCy Schubert struct profile_string_list {
31*7f2fe78bSCy Schubert char **list;
32*7f2fe78bSCy Schubert unsigned int num;
33*7f2fe78bSCy Schubert unsigned int max;
34*7f2fe78bSCy Schubert };
35*7f2fe78bSCy Schubert
36*7f2fe78bSCy Schubert /*
37*7f2fe78bSCy Schubert * Initialize the string list abstraction.
38*7f2fe78bSCy Schubert */
init_list(struct profile_string_list * list)39*7f2fe78bSCy Schubert static errcode_t init_list(struct profile_string_list *list)
40*7f2fe78bSCy Schubert {
41*7f2fe78bSCy Schubert list->num = 0;
42*7f2fe78bSCy Schubert list->max = 10;
43*7f2fe78bSCy Schubert list->list = malloc(list->max * sizeof(char *));
44*7f2fe78bSCy Schubert if (list->list == 0)
45*7f2fe78bSCy Schubert return ENOMEM;
46*7f2fe78bSCy Schubert list->list[0] = 0;
47*7f2fe78bSCy Schubert return 0;
48*7f2fe78bSCy Schubert }
49*7f2fe78bSCy Schubert
50*7f2fe78bSCy Schubert /*
51*7f2fe78bSCy Schubert * Free any memory left over in the string abstraction, returning the
52*7f2fe78bSCy Schubert * built up list in *ret_list if it is non-null.
53*7f2fe78bSCy Schubert */
end_list(struct profile_string_list * list,char *** ret_list)54*7f2fe78bSCy Schubert static void end_list(struct profile_string_list *list, char ***ret_list)
55*7f2fe78bSCy Schubert {
56*7f2fe78bSCy Schubert char **cp;
57*7f2fe78bSCy Schubert
58*7f2fe78bSCy Schubert if (list == 0)
59*7f2fe78bSCy Schubert return;
60*7f2fe78bSCy Schubert
61*7f2fe78bSCy Schubert if (ret_list) {
62*7f2fe78bSCy Schubert *ret_list = list->list;
63*7f2fe78bSCy Schubert return;
64*7f2fe78bSCy Schubert } else {
65*7f2fe78bSCy Schubert for (cp = list->list; cp && *cp; cp++)
66*7f2fe78bSCy Schubert free(*cp);
67*7f2fe78bSCy Schubert free(list->list);
68*7f2fe78bSCy Schubert }
69*7f2fe78bSCy Schubert list->num = list->max = 0;
70*7f2fe78bSCy Schubert list->list = 0;
71*7f2fe78bSCy Schubert }
72*7f2fe78bSCy Schubert
73*7f2fe78bSCy Schubert /*
74*7f2fe78bSCy Schubert * Add a string to the list.
75*7f2fe78bSCy Schubert */
add_to_list(struct profile_string_list * list,const char * str)76*7f2fe78bSCy Schubert static errcode_t add_to_list(struct profile_string_list *list, const char *str)
77*7f2fe78bSCy Schubert {
78*7f2fe78bSCy Schubert char *newstr, **newlist;
79*7f2fe78bSCy Schubert unsigned int newmax;
80*7f2fe78bSCy Schubert
81*7f2fe78bSCy Schubert if (list->num+1 >= list->max) {
82*7f2fe78bSCy Schubert newmax = list->max + 10;
83*7f2fe78bSCy Schubert newlist = realloc(list->list, newmax * sizeof(char *));
84*7f2fe78bSCy Schubert if (newlist == 0)
85*7f2fe78bSCy Schubert return ENOMEM;
86*7f2fe78bSCy Schubert list->max = newmax;
87*7f2fe78bSCy Schubert list->list = newlist;
88*7f2fe78bSCy Schubert }
89*7f2fe78bSCy Schubert newstr = strdup(str);
90*7f2fe78bSCy Schubert if (newstr == 0)
91*7f2fe78bSCy Schubert return ENOMEM;
92*7f2fe78bSCy Schubert
93*7f2fe78bSCy Schubert list->list[list->num++] = newstr;
94*7f2fe78bSCy Schubert list->list[list->num] = 0;
95*7f2fe78bSCy Schubert return 0;
96*7f2fe78bSCy Schubert }
97*7f2fe78bSCy Schubert
98*7f2fe78bSCy Schubert /*
99*7f2fe78bSCy Schubert * Return TRUE if the string is already a member of the list.
100*7f2fe78bSCy Schubert */
is_list_member(struct profile_string_list * list,const char * str)101*7f2fe78bSCy Schubert static int is_list_member(struct profile_string_list *list, const char *str)
102*7f2fe78bSCy Schubert {
103*7f2fe78bSCy Schubert char **cpp;
104*7f2fe78bSCy Schubert
105*7f2fe78bSCy Schubert if (!list->list)
106*7f2fe78bSCy Schubert return 0;
107*7f2fe78bSCy Schubert
108*7f2fe78bSCy Schubert for (cpp = list->list; *cpp; cpp++) {
109*7f2fe78bSCy Schubert if (!strcmp(*cpp, str))
110*7f2fe78bSCy Schubert return 1;
111*7f2fe78bSCy Schubert }
112*7f2fe78bSCy Schubert return 0;
113*7f2fe78bSCy Schubert }
114*7f2fe78bSCy Schubert
115*7f2fe78bSCy Schubert /*
116*7f2fe78bSCy Schubert * This function frees a null-terminated list as returned by
117*7f2fe78bSCy Schubert * profile_get_values.
118*7f2fe78bSCy Schubert */
profile_free_list(char ** list)119*7f2fe78bSCy Schubert void KRB5_CALLCONV profile_free_list(char **list)
120*7f2fe78bSCy Schubert {
121*7f2fe78bSCy Schubert char **cp;
122*7f2fe78bSCy Schubert
123*7f2fe78bSCy Schubert if (list == 0)
124*7f2fe78bSCy Schubert return;
125*7f2fe78bSCy Schubert
126*7f2fe78bSCy Schubert for (cp = list; *cp; cp++)
127*7f2fe78bSCy Schubert free(*cp);
128*7f2fe78bSCy Schubert free(list);
129*7f2fe78bSCy Schubert }
130*7f2fe78bSCy Schubert
131*7f2fe78bSCy Schubert /* Look up a relation in a vtable profile. */
132*7f2fe78bSCy Schubert static errcode_t
get_values_vt(profile_t profile,const char * const * names,char *** ret_values)133*7f2fe78bSCy Schubert get_values_vt(profile_t profile, const char *const *names, char ***ret_values)
134*7f2fe78bSCy Schubert {
135*7f2fe78bSCy Schubert errcode_t retval;
136*7f2fe78bSCy Schubert char **vtvalues, **val;
137*7f2fe78bSCy Schubert struct profile_string_list values;
138*7f2fe78bSCy Schubert
139*7f2fe78bSCy Schubert retval = profile->vt->get_values(profile->cbdata, names, &vtvalues);
140*7f2fe78bSCy Schubert if (retval)
141*7f2fe78bSCy Schubert return retval;
142*7f2fe78bSCy Schubert
143*7f2fe78bSCy Schubert /* Copy the result into memory we can free. */
144*7f2fe78bSCy Schubert retval = init_list(&values);
145*7f2fe78bSCy Schubert if (retval == 0) {
146*7f2fe78bSCy Schubert for (val = vtvalues; *val; val++)
147*7f2fe78bSCy Schubert add_to_list(&values, *val);
148*7f2fe78bSCy Schubert end_list(&values, ret_values);
149*7f2fe78bSCy Schubert }
150*7f2fe78bSCy Schubert
151*7f2fe78bSCy Schubert profile->vt->free_values(profile->cbdata, vtvalues);
152*7f2fe78bSCy Schubert return retval;
153*7f2fe78bSCy Schubert }
154*7f2fe78bSCy Schubert
155*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV
profile_get_values(profile_t profile,const char * const * names,char *** ret_values)156*7f2fe78bSCy Schubert profile_get_values(profile_t profile, const char *const *names,
157*7f2fe78bSCy Schubert char ***ret_values)
158*7f2fe78bSCy Schubert {
159*7f2fe78bSCy Schubert errcode_t retval;
160*7f2fe78bSCy Schubert void *state = NULL;
161*7f2fe78bSCy Schubert char *value;
162*7f2fe78bSCy Schubert struct profile_string_list values;
163*7f2fe78bSCy Schubert
164*7f2fe78bSCy Schubert *ret_values = NULL;
165*7f2fe78bSCy Schubert if (!profile)
166*7f2fe78bSCy Schubert return PROF_NO_PROFILE;
167*7f2fe78bSCy Schubert if (profile->vt)
168*7f2fe78bSCy Schubert return get_values_vt(profile, names, ret_values);
169*7f2fe78bSCy Schubert
170*7f2fe78bSCy Schubert if ((retval = profile_node_iterator_create(profile, names,
171*7f2fe78bSCy Schubert PROFILE_ITER_RELATIONS_ONLY,
172*7f2fe78bSCy Schubert &state)))
173*7f2fe78bSCy Schubert return retval;
174*7f2fe78bSCy Schubert
175*7f2fe78bSCy Schubert retval = init_list(&values);
176*7f2fe78bSCy Schubert if (retval)
177*7f2fe78bSCy Schubert goto cleanup;
178*7f2fe78bSCy Schubert
179*7f2fe78bSCy Schubert do {
180*7f2fe78bSCy Schubert if ((retval = profile_node_iterator(&state, 0, 0, &value)))
181*7f2fe78bSCy Schubert goto cleanup;
182*7f2fe78bSCy Schubert if (value)
183*7f2fe78bSCy Schubert add_to_list(&values, value);
184*7f2fe78bSCy Schubert } while (state);
185*7f2fe78bSCy Schubert
186*7f2fe78bSCy Schubert if (values.num == 0) {
187*7f2fe78bSCy Schubert retval = PROF_NO_RELATION;
188*7f2fe78bSCy Schubert goto cleanup;
189*7f2fe78bSCy Schubert }
190*7f2fe78bSCy Schubert
191*7f2fe78bSCy Schubert cleanup:
192*7f2fe78bSCy Schubert end_list(&values, retval ? NULL : ret_values);
193*7f2fe78bSCy Schubert profile_node_iterator_free(&state);
194*7f2fe78bSCy Schubert return retval;
195*7f2fe78bSCy Schubert }
196*7f2fe78bSCy Schubert
197*7f2fe78bSCy Schubert /* Look up a relation in a vtable profile and return the first value in the
198*7f2fe78bSCy Schubert * result. */
199*7f2fe78bSCy Schubert static errcode_t
get_value_vt(profile_t profile,const char * const * names,char ** ret_value)200*7f2fe78bSCy Schubert get_value_vt(profile_t profile, const char *const *names, char **ret_value)
201*7f2fe78bSCy Schubert {
202*7f2fe78bSCy Schubert errcode_t retval;
203*7f2fe78bSCy Schubert char **vtvalues;
204*7f2fe78bSCy Schubert
205*7f2fe78bSCy Schubert retval = profile->vt->get_values(profile->cbdata, names, &vtvalues);
206*7f2fe78bSCy Schubert if (retval)
207*7f2fe78bSCy Schubert return retval;
208*7f2fe78bSCy Schubert *ret_value = strdup(*vtvalues);
209*7f2fe78bSCy Schubert if (*ret_value == NULL)
210*7f2fe78bSCy Schubert retval = ENOMEM;
211*7f2fe78bSCy Schubert profile->vt->free_values(profile->cbdata, vtvalues);
212*7f2fe78bSCy Schubert return retval;
213*7f2fe78bSCy Schubert }
214*7f2fe78bSCy Schubert
215*7f2fe78bSCy Schubert /*
216*7f2fe78bSCy Schubert * This function only gets the first value from the file; it is a
217*7f2fe78bSCy Schubert * helper function for profile_get_string, profile_get_integer, etc.
218*7f2fe78bSCy Schubert */
profile_get_value(profile_t profile,const char ** names,char ** ret_value)219*7f2fe78bSCy Schubert errcode_t profile_get_value(profile_t profile, const char **names,
220*7f2fe78bSCy Schubert char **ret_value)
221*7f2fe78bSCy Schubert {
222*7f2fe78bSCy Schubert errcode_t retval;
223*7f2fe78bSCy Schubert void *state;
224*7f2fe78bSCy Schubert char *value;
225*7f2fe78bSCy Schubert
226*7f2fe78bSCy Schubert *ret_value = NULL;
227*7f2fe78bSCy Schubert if (!profile)
228*7f2fe78bSCy Schubert return PROF_NO_PROFILE;
229*7f2fe78bSCy Schubert if (profile->vt)
230*7f2fe78bSCy Schubert return get_value_vt(profile, names, ret_value);
231*7f2fe78bSCy Schubert
232*7f2fe78bSCy Schubert retval = profile_iterator_create(profile, names,
233*7f2fe78bSCy Schubert PROFILE_ITER_RELATIONS_ONLY, &state);
234*7f2fe78bSCy Schubert if (retval)
235*7f2fe78bSCy Schubert return retval;
236*7f2fe78bSCy Schubert
237*7f2fe78bSCy Schubert retval = profile_iterator(&state, NULL, &value);
238*7f2fe78bSCy Schubert if (retval)
239*7f2fe78bSCy Schubert goto cleanup;
240*7f2fe78bSCy Schubert
241*7f2fe78bSCy Schubert if (value)
242*7f2fe78bSCy Schubert *ret_value = value;
243*7f2fe78bSCy Schubert else
244*7f2fe78bSCy Schubert retval = PROF_NO_RELATION;
245*7f2fe78bSCy Schubert
246*7f2fe78bSCy Schubert cleanup:
247*7f2fe78bSCy Schubert profile_iterator_free(&state);
248*7f2fe78bSCy Schubert return retval;
249*7f2fe78bSCy Schubert }
250*7f2fe78bSCy Schubert
251*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV
profile_get_string(profile_t profile,const char * name,const char * subname,const char * subsubname,const char * def_val,char ** ret_string)252*7f2fe78bSCy Schubert profile_get_string(profile_t profile, const char *name, const char *subname,
253*7f2fe78bSCy Schubert const char *subsubname, const char *def_val,
254*7f2fe78bSCy Schubert char **ret_string)
255*7f2fe78bSCy Schubert {
256*7f2fe78bSCy Schubert char *value;
257*7f2fe78bSCy Schubert errcode_t retval;
258*7f2fe78bSCy Schubert const char *names[4];
259*7f2fe78bSCy Schubert
260*7f2fe78bSCy Schubert if (profile) {
261*7f2fe78bSCy Schubert names[0] = name;
262*7f2fe78bSCy Schubert names[1] = subname;
263*7f2fe78bSCy Schubert names[2] = subsubname;
264*7f2fe78bSCy Schubert names[3] = 0;
265*7f2fe78bSCy Schubert retval = profile_get_value(profile, names, &value);
266*7f2fe78bSCy Schubert if (retval == 0) {
267*7f2fe78bSCy Schubert *ret_string = value;
268*7f2fe78bSCy Schubert return 0;
269*7f2fe78bSCy Schubert } else if (retval != PROF_NO_SECTION && retval != PROF_NO_RELATION)
270*7f2fe78bSCy Schubert return retval;
271*7f2fe78bSCy Schubert }
272*7f2fe78bSCy Schubert
273*7f2fe78bSCy Schubert if (def_val) {
274*7f2fe78bSCy Schubert *ret_string = strdup(def_val);
275*7f2fe78bSCy Schubert if (*ret_string == NULL)
276*7f2fe78bSCy Schubert return ENOMEM;
277*7f2fe78bSCy Schubert } else
278*7f2fe78bSCy Schubert *ret_string = NULL;
279*7f2fe78bSCy Schubert return 0;
280*7f2fe78bSCy Schubert }
281*7f2fe78bSCy Schubert
282*7f2fe78bSCy Schubert static errcode_t
parse_int(const char * value,int * ret_int)283*7f2fe78bSCy Schubert parse_int(const char *value, int *ret_int)
284*7f2fe78bSCy Schubert {
285*7f2fe78bSCy Schubert char *end_value;
286*7f2fe78bSCy Schubert long ret_long;
287*7f2fe78bSCy Schubert
288*7f2fe78bSCy Schubert if (value[0] == 0)
289*7f2fe78bSCy Schubert /* Empty string is no good. */
290*7f2fe78bSCy Schubert return PROF_BAD_INTEGER;
291*7f2fe78bSCy Schubert errno = 0;
292*7f2fe78bSCy Schubert ret_long = strtol(value, &end_value, 10);
293*7f2fe78bSCy Schubert
294*7f2fe78bSCy Schubert /* Overflow or underflow. */
295*7f2fe78bSCy Schubert if ((ret_long == LONG_MIN || ret_long == LONG_MAX) && errno != 0)
296*7f2fe78bSCy Schubert return PROF_BAD_INTEGER;
297*7f2fe78bSCy Schubert /* Value outside "int" range. */
298*7f2fe78bSCy Schubert if ((long) (int) ret_long != ret_long)
299*7f2fe78bSCy Schubert return PROF_BAD_INTEGER;
300*7f2fe78bSCy Schubert /* Garbage in string. */
301*7f2fe78bSCy Schubert if (end_value != value + strlen (value))
302*7f2fe78bSCy Schubert return PROF_BAD_INTEGER;
303*7f2fe78bSCy Schubert
304*7f2fe78bSCy Schubert *ret_int = ret_long;
305*7f2fe78bSCy Schubert return 0;
306*7f2fe78bSCy Schubert }
307*7f2fe78bSCy Schubert
308*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV
profile_get_integer(profile_t profile,const char * name,const char * subname,const char * subsubname,int def_val,int * ret_int)309*7f2fe78bSCy Schubert profile_get_integer(profile_t profile, const char *name, const char *subname,
310*7f2fe78bSCy Schubert const char *subsubname, int def_val, int *ret_int)
311*7f2fe78bSCy Schubert {
312*7f2fe78bSCy Schubert char *value;
313*7f2fe78bSCy Schubert errcode_t retval;
314*7f2fe78bSCy Schubert const char *names[4];
315*7f2fe78bSCy Schubert
316*7f2fe78bSCy Schubert *ret_int = def_val;
317*7f2fe78bSCy Schubert if (profile == 0)
318*7f2fe78bSCy Schubert return 0;
319*7f2fe78bSCy Schubert
320*7f2fe78bSCy Schubert names[0] = name;
321*7f2fe78bSCy Schubert names[1] = subname;
322*7f2fe78bSCy Schubert names[2] = subsubname;
323*7f2fe78bSCy Schubert names[3] = 0;
324*7f2fe78bSCy Schubert retval = profile_get_value(profile, names, &value);
325*7f2fe78bSCy Schubert if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
326*7f2fe78bSCy Schubert *ret_int = def_val;
327*7f2fe78bSCy Schubert return 0;
328*7f2fe78bSCy Schubert } else if (retval)
329*7f2fe78bSCy Schubert return retval;
330*7f2fe78bSCy Schubert
331*7f2fe78bSCy Schubert retval = parse_int(value, ret_int);
332*7f2fe78bSCy Schubert free(value);
333*7f2fe78bSCy Schubert return retval;
334*7f2fe78bSCy Schubert }
335*7f2fe78bSCy Schubert
336*7f2fe78bSCy Schubert static const char *const conf_yes[] = {
337*7f2fe78bSCy Schubert "y", "yes", "true", "t", "1", "on",
338*7f2fe78bSCy Schubert 0,
339*7f2fe78bSCy Schubert };
340*7f2fe78bSCy Schubert
341*7f2fe78bSCy Schubert static const char *const conf_no[] = {
342*7f2fe78bSCy Schubert "n", "no", "false", "nil", "0", "off",
343*7f2fe78bSCy Schubert 0,
344*7f2fe78bSCy Schubert };
345*7f2fe78bSCy Schubert
346*7f2fe78bSCy Schubert static errcode_t
profile_parse_boolean(const char * s,int * ret_boolean)347*7f2fe78bSCy Schubert profile_parse_boolean(const char *s, int *ret_boolean)
348*7f2fe78bSCy Schubert {
349*7f2fe78bSCy Schubert const char *const *p;
350*7f2fe78bSCy Schubert
351*7f2fe78bSCy Schubert if (ret_boolean == NULL)
352*7f2fe78bSCy Schubert return PROF_EINVAL;
353*7f2fe78bSCy Schubert
354*7f2fe78bSCy Schubert for(p=conf_yes; *p; p++) {
355*7f2fe78bSCy Schubert if (!strcasecmp(*p,s)) {
356*7f2fe78bSCy Schubert *ret_boolean = 1;
357*7f2fe78bSCy Schubert return 0;
358*7f2fe78bSCy Schubert }
359*7f2fe78bSCy Schubert }
360*7f2fe78bSCy Schubert
361*7f2fe78bSCy Schubert for(p=conf_no; *p; p++) {
362*7f2fe78bSCy Schubert if (!strcasecmp(*p,s)) {
363*7f2fe78bSCy Schubert *ret_boolean = 0;
364*7f2fe78bSCy Schubert return 0;
365*7f2fe78bSCy Schubert }
366*7f2fe78bSCy Schubert }
367*7f2fe78bSCy Schubert
368*7f2fe78bSCy Schubert return PROF_BAD_BOOLEAN;
369*7f2fe78bSCy Schubert }
370*7f2fe78bSCy Schubert
371*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV
profile_get_boolean(profile_t profile,const char * name,const char * subname,const char * subsubname,int def_val,int * ret_boolean)372*7f2fe78bSCy Schubert profile_get_boolean(profile_t profile, const char *name, const char *subname,
373*7f2fe78bSCy Schubert const char *subsubname, int def_val, int *ret_boolean)
374*7f2fe78bSCy Schubert {
375*7f2fe78bSCy Schubert char *value;
376*7f2fe78bSCy Schubert errcode_t retval;
377*7f2fe78bSCy Schubert const char *names[4];
378*7f2fe78bSCy Schubert
379*7f2fe78bSCy Schubert if (profile == 0) {
380*7f2fe78bSCy Schubert *ret_boolean = def_val;
381*7f2fe78bSCy Schubert return 0;
382*7f2fe78bSCy Schubert }
383*7f2fe78bSCy Schubert
384*7f2fe78bSCy Schubert names[0] = name;
385*7f2fe78bSCy Schubert names[1] = subname;
386*7f2fe78bSCy Schubert names[2] = subsubname;
387*7f2fe78bSCy Schubert names[3] = 0;
388*7f2fe78bSCy Schubert retval = profile_get_value(profile, names, &value);
389*7f2fe78bSCy Schubert if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
390*7f2fe78bSCy Schubert *ret_boolean = def_val;
391*7f2fe78bSCy Schubert return 0;
392*7f2fe78bSCy Schubert } else if (retval)
393*7f2fe78bSCy Schubert return retval;
394*7f2fe78bSCy Schubert
395*7f2fe78bSCy Schubert retval = profile_parse_boolean(value, ret_boolean);
396*7f2fe78bSCy Schubert free(value);
397*7f2fe78bSCy Schubert return retval;
398*7f2fe78bSCy Schubert }
399*7f2fe78bSCy Schubert
400*7f2fe78bSCy Schubert /*
401*7f2fe78bSCy Schubert * This function will return the list of the names of subections in the
402*7f2fe78bSCy Schubert * under the specified section name.
403*7f2fe78bSCy Schubert */
404*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV
profile_get_subsection_names(profile_t profile,const char ** names,char *** ret_names)405*7f2fe78bSCy Schubert profile_get_subsection_names(profile_t profile, const char **names,
406*7f2fe78bSCy Schubert char ***ret_names)
407*7f2fe78bSCy Schubert {
408*7f2fe78bSCy Schubert errcode_t retval;
409*7f2fe78bSCy Schubert void *state;
410*7f2fe78bSCy Schubert char *name;
411*7f2fe78bSCy Schubert struct profile_string_list values;
412*7f2fe78bSCy Schubert
413*7f2fe78bSCy Schubert if ((retval = profile_iterator_create(profile, names,
414*7f2fe78bSCy Schubert PROFILE_ITER_LIST_SECTION |
415*7f2fe78bSCy Schubert PROFILE_ITER_SECTIONS_ONLY,
416*7f2fe78bSCy Schubert &state)))
417*7f2fe78bSCy Schubert return retval;
418*7f2fe78bSCy Schubert
419*7f2fe78bSCy Schubert if ((retval = init_list(&values)))
420*7f2fe78bSCy Schubert return retval;
421*7f2fe78bSCy Schubert
422*7f2fe78bSCy Schubert do {
423*7f2fe78bSCy Schubert if ((retval = profile_iterator(&state, &name, NULL)))
424*7f2fe78bSCy Schubert goto cleanup;
425*7f2fe78bSCy Schubert if (name)
426*7f2fe78bSCy Schubert add_to_list(&values, name);
427*7f2fe78bSCy Schubert free(name);
428*7f2fe78bSCy Schubert } while (state);
429*7f2fe78bSCy Schubert
430*7f2fe78bSCy Schubert end_list(&values, ret_names);
431*7f2fe78bSCy Schubert return 0;
432*7f2fe78bSCy Schubert
433*7f2fe78bSCy Schubert cleanup:
434*7f2fe78bSCy Schubert end_list(&values, 0);
435*7f2fe78bSCy Schubert return retval;
436*7f2fe78bSCy Schubert }
437*7f2fe78bSCy Schubert
438*7f2fe78bSCy Schubert /*
439*7f2fe78bSCy Schubert * This function will return the list of the names of relations in the
440*7f2fe78bSCy Schubert * under the specified section name.
441*7f2fe78bSCy Schubert */
442*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV
profile_get_relation_names(profile_t profile,const char ** names,char *** ret_names)443*7f2fe78bSCy Schubert profile_get_relation_names(profile_t profile, const char **names,
444*7f2fe78bSCy Schubert char ***ret_names)
445*7f2fe78bSCy Schubert {
446*7f2fe78bSCy Schubert errcode_t retval;
447*7f2fe78bSCy Schubert void *state;
448*7f2fe78bSCy Schubert char *name;
449*7f2fe78bSCy Schubert struct profile_string_list values;
450*7f2fe78bSCy Schubert
451*7f2fe78bSCy Schubert if ((retval = profile_iterator_create(profile, names,
452*7f2fe78bSCy Schubert PROFILE_ITER_LIST_SECTION |
453*7f2fe78bSCy Schubert PROFILE_ITER_RELATIONS_ONLY,
454*7f2fe78bSCy Schubert &state)))
455*7f2fe78bSCy Schubert return retval;
456*7f2fe78bSCy Schubert
457*7f2fe78bSCy Schubert if ((retval = init_list(&values)))
458*7f2fe78bSCy Schubert return retval;
459*7f2fe78bSCy Schubert
460*7f2fe78bSCy Schubert do {
461*7f2fe78bSCy Schubert if ((retval = profile_iterator(&state, &name, NULL)))
462*7f2fe78bSCy Schubert goto cleanup;
463*7f2fe78bSCy Schubert if (name && !is_list_member(&values, name))
464*7f2fe78bSCy Schubert add_to_list(&values, name);
465*7f2fe78bSCy Schubert free(name);
466*7f2fe78bSCy Schubert } while (state);
467*7f2fe78bSCy Schubert
468*7f2fe78bSCy Schubert end_list(&values, ret_names);
469*7f2fe78bSCy Schubert return 0;
470*7f2fe78bSCy Schubert
471*7f2fe78bSCy Schubert cleanup:
472*7f2fe78bSCy Schubert end_list(&values, 0);
473*7f2fe78bSCy Schubert return retval;
474*7f2fe78bSCy Schubert }
475*7f2fe78bSCy Schubert
476*7f2fe78bSCy Schubert struct profile_iterator {
477*7f2fe78bSCy Schubert prf_magic_t magic;
478*7f2fe78bSCy Schubert profile_t profile;
479*7f2fe78bSCy Schubert void *idata;
480*7f2fe78bSCy Schubert };
481*7f2fe78bSCy Schubert
482*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV
profile_iterator_create(profile_t profile,const char * const * names,int flags,void ** ret_iter)483*7f2fe78bSCy Schubert profile_iterator_create(profile_t profile, const char *const *names, int flags,
484*7f2fe78bSCy Schubert void **ret_iter)
485*7f2fe78bSCy Schubert {
486*7f2fe78bSCy Schubert struct profile_iterator *iter;
487*7f2fe78bSCy Schubert errcode_t retval;
488*7f2fe78bSCy Schubert
489*7f2fe78bSCy Schubert *ret_iter = NULL;
490*7f2fe78bSCy Schubert if (!profile)
491*7f2fe78bSCy Schubert return PROF_NO_PROFILE;
492*7f2fe78bSCy Schubert
493*7f2fe78bSCy Schubert iter = malloc(sizeof(*iter));
494*7f2fe78bSCy Schubert if (iter == NULL)
495*7f2fe78bSCy Schubert return ENOMEM;
496*7f2fe78bSCy Schubert iter->magic = PROF_MAGIC_ITERATOR;
497*7f2fe78bSCy Schubert iter->profile = profile;
498*7f2fe78bSCy Schubert
499*7f2fe78bSCy Schubert /* Create the underlying iterator representation using the vtable or the
500*7f2fe78bSCy Schubert * built-in node iterator. */
501*7f2fe78bSCy Schubert if (profile->vt) {
502*7f2fe78bSCy Schubert if (!profile->vt->iterator_create)
503*7f2fe78bSCy Schubert retval = PROF_UNSUPPORTED;
504*7f2fe78bSCy Schubert else
505*7f2fe78bSCy Schubert retval = profile->vt->iterator_create(profile->cbdata, names,
506*7f2fe78bSCy Schubert flags, &iter->idata);
507*7f2fe78bSCy Schubert } else {
508*7f2fe78bSCy Schubert retval = profile_node_iterator_create(profile, names, flags,
509*7f2fe78bSCy Schubert &iter->idata);
510*7f2fe78bSCy Schubert }
511*7f2fe78bSCy Schubert if (retval) {
512*7f2fe78bSCy Schubert free(iter);
513*7f2fe78bSCy Schubert return retval;
514*7f2fe78bSCy Schubert }
515*7f2fe78bSCy Schubert
516*7f2fe78bSCy Schubert *ret_iter = iter;
517*7f2fe78bSCy Schubert return 0;
518*7f2fe78bSCy Schubert }
519*7f2fe78bSCy Schubert
520*7f2fe78bSCy Schubert void KRB5_CALLCONV
profile_iterator_free(void ** iter_p)521*7f2fe78bSCy Schubert profile_iterator_free(void **iter_p)
522*7f2fe78bSCy Schubert {
523*7f2fe78bSCy Schubert struct profile_iterator *iter;
524*7f2fe78bSCy Schubert profile_t profile;
525*7f2fe78bSCy Schubert
526*7f2fe78bSCy Schubert if (!iter_p)
527*7f2fe78bSCy Schubert return;
528*7f2fe78bSCy Schubert iter = *iter_p;
529*7f2fe78bSCy Schubert if (!iter || iter->magic != PROF_MAGIC_ITERATOR)
530*7f2fe78bSCy Schubert return;
531*7f2fe78bSCy Schubert profile = iter->profile;
532*7f2fe78bSCy Schubert if (profile->vt)
533*7f2fe78bSCy Schubert profile->vt->iterator_free(profile->cbdata, iter->idata);
534*7f2fe78bSCy Schubert else
535*7f2fe78bSCy Schubert profile_node_iterator_free(&iter->idata);
536*7f2fe78bSCy Schubert free(iter);
537*7f2fe78bSCy Schubert *iter_p = NULL;
538*7f2fe78bSCy Schubert }
539*7f2fe78bSCy Schubert
540*7f2fe78bSCy Schubert /* Make copies of name and value into *ret_name and *ret_value. Handle null
541*7f2fe78bSCy Schubert * values of any argument. */
542*7f2fe78bSCy Schubert static errcode_t
set_results(const char * name,const char * value,char ** ret_name,char ** ret_value)543*7f2fe78bSCy Schubert set_results(const char *name, const char *value, char **ret_name,
544*7f2fe78bSCy Schubert char **ret_value)
545*7f2fe78bSCy Schubert {
546*7f2fe78bSCy Schubert char *name_copy = NULL, *value_copy = NULL;
547*7f2fe78bSCy Schubert
548*7f2fe78bSCy Schubert if (ret_name && name) {
549*7f2fe78bSCy Schubert name_copy = strdup(name);
550*7f2fe78bSCy Schubert if (name_copy == NULL)
551*7f2fe78bSCy Schubert goto oom;
552*7f2fe78bSCy Schubert }
553*7f2fe78bSCy Schubert if (ret_value && value) {
554*7f2fe78bSCy Schubert value_copy = strdup(value);
555*7f2fe78bSCy Schubert if (value_copy == NULL)
556*7f2fe78bSCy Schubert goto oom;
557*7f2fe78bSCy Schubert }
558*7f2fe78bSCy Schubert if (ret_name)
559*7f2fe78bSCy Schubert *ret_name = name_copy;
560*7f2fe78bSCy Schubert if (ret_value)
561*7f2fe78bSCy Schubert *ret_value = value_copy;
562*7f2fe78bSCy Schubert return 0;
563*7f2fe78bSCy Schubert oom:
564*7f2fe78bSCy Schubert free(name_copy);
565*7f2fe78bSCy Schubert free(value_copy);
566*7f2fe78bSCy Schubert return ENOMEM;
567*7f2fe78bSCy Schubert }
568*7f2fe78bSCy Schubert
569*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV
profile_iterator(void ** iter_p,char ** ret_name,char ** ret_value)570*7f2fe78bSCy Schubert profile_iterator(void **iter_p, char **ret_name, char **ret_value)
571*7f2fe78bSCy Schubert {
572*7f2fe78bSCy Schubert char *name, *value;
573*7f2fe78bSCy Schubert errcode_t retval;
574*7f2fe78bSCy Schubert struct profile_iterator *iter = *iter_p;
575*7f2fe78bSCy Schubert profile_t profile;
576*7f2fe78bSCy Schubert
577*7f2fe78bSCy Schubert if (ret_name)
578*7f2fe78bSCy Schubert *ret_name = NULL;
579*7f2fe78bSCy Schubert if (ret_value)
580*7f2fe78bSCy Schubert *ret_value = NULL;
581*7f2fe78bSCy Schubert if (iter == NULL || iter->magic != PROF_MAGIC_ITERATOR)
582*7f2fe78bSCy Schubert return PROF_MAGIC_ITERATOR;
583*7f2fe78bSCy Schubert profile = iter->profile;
584*7f2fe78bSCy Schubert
585*7f2fe78bSCy Schubert if (profile->vt) {
586*7f2fe78bSCy Schubert retval = profile->vt->iterator(profile->cbdata, iter->idata, &name,
587*7f2fe78bSCy Schubert &value);
588*7f2fe78bSCy Schubert if (retval)
589*7f2fe78bSCy Schubert return retval;
590*7f2fe78bSCy Schubert if (name == NULL) {
591*7f2fe78bSCy Schubert profile->vt->iterator_free(profile->cbdata, iter->idata);
592*7f2fe78bSCy Schubert free(iter);
593*7f2fe78bSCy Schubert *iter_p = NULL;
594*7f2fe78bSCy Schubert }
595*7f2fe78bSCy Schubert retval = set_results(name, value, ret_name, ret_value);
596*7f2fe78bSCy Schubert if (name)
597*7f2fe78bSCy Schubert profile->vt->free_string(profile->cbdata, name);
598*7f2fe78bSCy Schubert if (value)
599*7f2fe78bSCy Schubert profile->vt->free_string(profile->cbdata, value);
600*7f2fe78bSCy Schubert return retval;
601*7f2fe78bSCy Schubert }
602*7f2fe78bSCy Schubert
603*7f2fe78bSCy Schubert retval = profile_node_iterator(&iter->idata, 0, &name, &value);
604*7f2fe78bSCy Schubert if (iter->idata == NULL) {
605*7f2fe78bSCy Schubert free(iter);
606*7f2fe78bSCy Schubert *iter_p = NULL;
607*7f2fe78bSCy Schubert }
608*7f2fe78bSCy Schubert if (retval)
609*7f2fe78bSCy Schubert return retval;
610*7f2fe78bSCy Schubert return set_results(name, value, ret_name, ret_value);
611*7f2fe78bSCy Schubert }
612*7f2fe78bSCy Schubert
613*7f2fe78bSCy Schubert void KRB5_CALLCONV
profile_release_string(char * str)614*7f2fe78bSCy Schubert profile_release_string(char *str)
615*7f2fe78bSCy Schubert {
616*7f2fe78bSCy Schubert free(str);
617*7f2fe78bSCy Schubert }
618