2 * profile_helpers.c -- Helper functions for the profile library
4 * These functions are not part of the "core" profile library, and do
5 * not require access to the internal functions and data structures of
6 * the profile library. They are mainly convenience functions for
7 * programs that want to do something unusual such as obtaining the
8 * list of sections or relations, or accessing multiple values from a
9 * relation that is listed more than once. This functionality can all
10 * be done using the profile_iterator abstraction, but it is less
13 * Copyright (C) 2006 by Theodore Ts'o.
16 * This file may be redistributed under the terms of the GNU Public
25 #include <et/com_err.h>
30 * These functions --- init_list(), end_list(), and add_to_list() are
31 * internal functions used to build up a null-terminated char ** list
32 * of strings to be returned by functions like profile_get_values.
34 * The profile_string_list structure is used for internal booking
35 * purposes to build up the list, which is returned in *ret_list by
36 * the end_list() function.
38 * The publicly exported interface for freeing char** list is
39 * profile_free_list().
42 struct profile_string_list {
49 * Initialize the string list abstraction.
51 static errcode_t init_list(struct profile_string_list *list)
55 list->list = malloc(list->max * sizeof(char *));
63 * Free any memory left over in the string abstraction, returning the
64 * built up list in *ret_list if it is non-null.
66 static void end_list(struct profile_string_list *list, char ***ret_list)
74 *ret_list = list->list;
77 for (cp = list->list; *cp; cp++)
81 list->num = list->max = 0;
86 * Add a string to the list.
88 static errcode_t add_to_list(struct profile_string_list *list, char *str)
93 if (list->num+1 >= list->max) {
94 newmax = list->max + 10;
95 newlist = realloc(list->list, newmax * sizeof(char *));
102 list->list[list->num++] = str;
103 list->list[list->num] = 0;
108 * Return TRUE if the string is already a member of the list.
110 static int is_list_member(struct profile_string_list *list, const char *str)
117 for (cpp = list->list; *cpp; cpp++) {
118 if (!strcmp(*cpp, str))
125 * This function frees a null-terminated list as returned by
126 * profile_get_values.
128 void profile_free_list(char **list)
135 for (cp = list; *cp; cp++)
141 profile_get_values(profile_t profile, const char *const *names,
147 struct profile_string_list values;
149 if ((retval = profile_iterator_create(profile, names,
150 PROFILE_ITER_RELATIONS_ONLY,
154 if ((retval = init_list(&values)))
158 if ((retval = profile_iterator(&state, 0, &value)))
161 add_to_list(&values, value);
164 if (values.num == 0) {
165 retval = PROF_NO_RELATION;
169 end_list(&values, ret_values);
173 end_list(&values, 0);
178 * This function will return the list of the names of subections in the
179 * under the specified section name.
182 profile_get_subsection_names(profile_t profile, const char **names,
188 struct profile_string_list values;
190 if ((retval = profile_iterator_create(profile, names,
191 PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY,
195 if ((retval = init_list(&values)))
199 if ((retval = profile_iterator(&state, &name, 0)))
202 add_to_list(&values, name);
205 end_list(&values, ret_names);
209 end_list(&values, 0);
214 * This function will return the list of the names of relations in the
215 * under the specified section name.
218 profile_get_relation_names(profile_t profile, const char **names,
224 struct profile_string_list values;
226 if ((retval = profile_iterator_create(profile, names,
227 PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY,
231 if ((retval = init_list(&values)))
235 if ((retval = profile_iterator(&state, &name, 0)))
238 if (is_list_member(&values, name))
241 add_to_list(&values, name);
245 end_list(&values, ret_names);
249 end_list(&values, 0);
255 profile_release_string(char *str)
261 profile_init_path(const char * filepath,
262 profile_t *ret_profile)
265 unsigned int ent_len;
270 /* count the distinct filename components */
271 for(s = filepath, n_entries = 1; *s; s++) {
276 /* the array is NULL terminated */
277 filenames = (char **) malloc((n_entries+1) * sizeof(char*));
281 /* measure, copy, and skip each one */
282 for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
284 filenames[i] = (char*) malloc(ent_len + 1);
285 if (filenames[i] == 0) {
286 /* if malloc fails, free the ones that worked */
287 while(--i >= 0) free(filenames[i]);
291 strncpy(filenames[i], s, ent_len);
292 filenames[i][ent_len] = 0;
301 retval = profile_init((const char **) filenames,
304 /* count back down and free the entries */
305 while(--i >= 0) free(filenames[i]);