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]);