xref: /freebsd/crypto/krb5/src/util/profile/prof_get.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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