1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
/*
* prof_init.c --- routines that manipulate the user-visible profile_t
* object.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "prof_int.h"
errcode_t profile_init(filenames, ret_profile)
const char **filenames;
profile_t *ret_profile;
{
const char **fn;
profile_t profile;
prf_file_t new_file, last = 0;
errcode_t retval;
profile = malloc(sizeof(struct _profile_t));
if (!profile)
return ENOMEM;
memset(profile, 0, sizeof(struct _profile_t));
profile->magic = PROF_MAGIC_PROFILE;
for (fn = filenames; *fn; fn++) {
retval = profile_open_file(*fn, &new_file);
if (retval) {
profile_release(profile);
return retval;
}
if (last)
last->next = new_file;
else
profile->first_file = new_file;
last = new_file;
}
*ret_profile = profile;
return 0;
}
void profile_release(profile)
profile_t profile;
{
prf_file_t p, next;
for (p = profile->first_file; p; p = next) {
next = p->next;
profile_close_file(p);
}
profile->magic = 0;
free(profile);
}
struct string_list {
char **list;
int num;
int max;
};
static errcode_t init_list(list)
struct string_list *list;
{
list->num = 0;
list->max = 10;
list->list = malloc(list->max * sizeof(char *));
if (list->list == 0)
return ENOMEM;
list->list[0] = 0;
return 0;
}
static void free_list(list)
struct string_list *list;
{
char **cp;
for (cp = list->list; *cp; cp++)
free(*cp);
free(list->list);
list->num = list->max = 0;
list->list = 0;
}
static errcode_t add_to_list(list, str)
struct string_list *list;
const char *str;
{
char *newstr;
if (list->num+1 >= list->max) {
list->max += 5;
list->list = realloc(list->list, list->max * sizeof(char *));
if (list->list == 0)
return ENOMEM;
}
newstr = malloc(strlen(str)+1);
if (newstr == 0)
return ENOMEM;
strcpy(newstr, str);
list->list[list->num++] = newstr;
list->list[list->num] = 0;
return 0;
}
/*
* XXX this version only works to get values from the first file.
* To do more than that means we have to implement some "interesting"
* code to do the section searching.
*/
errcode_t profile_get_values(profile, names, ret_values)
profile_t profile;
const char **names;
char ***ret_values;
{
prf_file_t file;
errcode_t retval;
struct profile_node *parent, *section;
void *state;
char *value;
struct string_list values;
char **cpp;
if (names == 0 || names[0] == 0 || names[1] == 0)
return PROF_BAD_NAMESET;
init_list(&values);
file = profile->first_file;
section = file->root;
for (cpp = names; cpp[1]; cpp++) {
state = 0;
retval = profile_find_node_subsection(section, *cpp,
&state, 0, §ion);
if (retval)
goto cleanup;
}
state = 0;
do {
retval = profile_find_node_relation(section, *cpp, &state, 0, &value);
if (retval)
goto cleanup;
add_to_list(&values, value);
} while (state);
*ret_values = values.list;
return 0;
cleanup:
free_list(&values);
return retval;
}
|