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
26 #include <et/com_err.h>
31 * These functions --- init_list(), end_list(), and add_to_list() are
32 * internal functions used to build up a null-terminated char ** list
33 * of strings to be returned by functions like profile_get_values.
35 * The profile_string_list structure is used for internal booking
36 * purposes to build up the list, which is returned in *ret_list by
37 * the end_list() function.
39 * The publicly exported interface for freeing char** list is
40 * profile_free_list().
43 struct profile_string_list {
50 * Initialize the string list abstraction.
52 static errcode_t init_list(struct profile_string_list *list)
56 list->list = malloc(list->max * sizeof(char *));
64 * Free any memory left over in the string abstraction, returning the
65 * built up list in *ret_list if it is non-null.
67 static void end_list(struct profile_string_list *list, char ***ret_list)
75 *ret_list = list->list;
78 for (cp = list->list; *cp; cp++)
82 list->num = list->max = 0;
87 * Add a string to the list.
89 static errcode_t add_to_list(struct profile_string_list *list, char *str)
94 if (list->num+1 >= list->max) {
95 newmax = list->max + 10;
96 newlist = realloc(list->list, newmax * sizeof(char *));
100 list->list = newlist;
103 list->list[list->num++] = str;
104 list->list[list->num] = 0;
109 * Return TRUE if the string is already a member of the list.
111 static int is_list_member(struct profile_string_list *list, const char *str)
118 for (cpp = list->list; *cpp; cpp++) {
119 if (!strcmp(*cpp, str))
126 * This function frees a null-terminated list as returned by
127 * profile_get_values.
129 void profile_free_list(char **list)
136 for (cp = list; *cp; cp++)
142 profile_get_values(profile_t profile, const char *const *names,
148 struct profile_string_list values;
150 if ((retval = profile_iterator_create(profile, names,
151 PROFILE_ITER_RELATIONS_ONLY,
155 if ((retval = init_list(&values)))
159 if ((retval = profile_iterator(&state, 0, &value)))
162 add_to_list(&values, value);
165 if (values.num == 0) {
166 retval = PROF_NO_RELATION;
170 end_list(&values, ret_values);
174 end_list(&values, 0);
179 * This function will return the list of the names of subections in the
180 * under the specified section name.
183 profile_get_subsection_names(profile_t profile, const char **names,
189 struct profile_string_list values;
191 if ((retval = profile_iterator_create(profile, names,
192 PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY,
196 if ((retval = init_list(&values)))
200 if ((retval = profile_iterator(&state, &name, 0)))
203 add_to_list(&values, name);
206 end_list(&values, ret_names);
210 end_list(&values, 0);
215 * This function will return the list of the names of relations in the
216 * under the specified section name.
219 profile_get_relation_names(profile_t profile, const char **names,
225 struct profile_string_list values;
227 if ((retval = profile_iterator_create(profile, names,
228 PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY,
232 if ((retval = init_list(&values)))
236 if ((retval = profile_iterator(&state, &name, 0)))
239 if (is_list_member(&values, name))
242 add_to_list(&values, name);
246 end_list(&values, ret_names);
250 end_list(&values, 0);
256 profile_release_string(char *str)
262 profile_init_path(const char * filepath,
263 profile_t *ret_profile)
266 unsigned int ent_len;
271 /* count the distinct filename components */
272 for(s = filepath, n_entries = 1; *s; s++) {
277 /* the array is NULL terminated */
278 filenames = (char **) malloc((n_entries+1) * sizeof(char*));
282 /* measure, copy, and skip each one */
283 for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
285 filenames[i] = (char*) malloc(ent_len + 1);
286 if (filenames[i] == 0) {
287 /* if malloc fails, free the ones that worked */
288 while(--i >= 0) free(filenames[i]);
292 strncpy(filenames[i], s, ent_len);
293 filenames[i][ent_len] = 0;
302 retval = profile_init((const char **) filenames,
305 /* count back down and free the entries */
306 while(--i >= 0) free(filenames[i]);