1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 /*
3  * prof_set.c --- routines that expose the public interfaces for
4  * 	inserting, updating and deleting items from the profile.
5  *
6  * WARNING: These routines only look at the first file opened in the
7  * profile.  It's not clear how to handle multiple files, actually.
8  * In the future it may be necessary to modify this public interface,
9  * or possibly add higher level functions to support this correctly.
10  *
11  * WARNING: We're not yet doing locking yet, either.
12  *
13  */
14 
15 #include <stdio.h>
16 #include <string.h>
17 #ifdef HAVE_STDLIB_H
18 #include <stdlib.h>
19 #endif
20 #include <errno.h>
21 
22 #include "prof_int.h"
23 
24 static errcode_t rw_setup(profile)
25 	profile_t	profile;
26 {
27    	prf_file_t	file;
28 	errcode_t	retval;
29 
30 	if (!profile)
31 		return PROF_NO_PROFILE;
32 
33 	if (profile->magic != PROF_MAGIC_PROFILE)
34 		return PROF_MAGIC_PROFILE;
35 
36 	file = profile->first_file;
37 	if (!(file->flags & PROFILE_FILE_RW))
38 		return PROF_READ_ONLY;
39 
40 	/* Don't update the file if we've already made modifications */
41 	if (file->flags & PROFILE_FILE_DIRTY)
42 		return 0;
43 
44 	retval = profile_update_file(file);
45 
46 	return retval;
47 }
48 
49 
50 /*
51  * Delete or update a particular child node
52  *
53  * ADL - 2/23/99, rewritten TYT 2/25/99
54  */
55 KRB5_DLLIMP errcode_t KRB5_CALLCONV
56 profile_update_relation(profile, names, old_value, new_value)
57 	profile_t	profile;
58 	const char	**names;
59 	const char	*old_value;
60 	const char	*new_value;
61 {
62 	errcode_t	retval;
63 	struct profile_node *section, *node;
64 	void		*state;
65 	const char	**cpp;
66 
67 	retval = rw_setup(profile);
68 	if (retval)
69 		return retval;
70 
71 	if (names == 0 || names[0] == 0 || names[1] == 0)
72 		return PROF_BAD_NAMESET;
73 
74 	if (!old_value || !*old_value)
75 		return PROF_EINVAL;
76 
77 	section = profile->first_file->root;
78 	for (cpp = names; cpp[1]; cpp++) {
79 		state = 0;
80 		retval = profile_find_node(section, *cpp, 0, 1,
81 					   &state, &section);
82 		if (retval)
83 			return retval;
84 	}
85 
86 	state = 0;
87 	retval = profile_find_node(section, *cpp, old_value, 0, &state, &node);
88 	if (retval)
89 		return retval;
90 
91 	if (new_value)
92 		retval = profile_set_relation_value(node, new_value);
93 	else
94 		retval = profile_remove_node(node);
95 	if (retval)
96 		return retval;
97 
98 	profile->first_file->flags |= PROFILE_FILE_DIRTY;
99 
100 	return 0;
101 }
102 
103 /*
104  * Clear a particular all of the relations with a specific name.
105  *
106  * TYT - 2/25/99
107  */
108 KRB5_DLLIMP errcode_t KRB5_CALLCONV
109 profile_clear_relation(profile, names)
110 	profile_t	profile;
111 	const char	**names;
112 {
113 	errcode_t	retval;
114 	struct profile_node *section, *node;
115 	void		*state;
116 	const char	**cpp;
117 
118 	retval = rw_setup(profile);
119 	if (retval)
120 		return retval;
121 
122 	if (names == 0 || names[0] == 0 || names[1] == 0)
123 		return PROF_BAD_NAMESET;
124 
125 	section = profile->first_file->root;
126 	for (cpp = names; cpp[1]; cpp++) {
127 		state = 0;
128 		retval = profile_find_node(section, *cpp, 0, 1,
129 					   &state, &section);
130 		if (retval)
131 			return retval;
132 	}
133 
134 	state = 0;
135 	do {
136 		retval = profile_find_node(section, *cpp, 0, 0, &state, &node);
137 		if (retval)
138 			return retval;
139 		retval = profile_remove_node(node);
140 		if (retval)
141 			return retval;
142 	} while (state);
143 
144 	profile->first_file->flags |= PROFILE_FILE_DIRTY;
145 
146 	return 0;
147 }
148 
149 /*
150  * Rename a particular section; if the new_section name is NULL,
151  * delete it.
152  *
153  * ADL - 2/23/99, rewritten TYT 2/25/99
154  */
155 KRB5_DLLIMP errcode_t KRB5_CALLCONV
156 profile_rename_section(profile, names, new_name)
157 	profile_t	profile;
158 	const char	**names;
159 	const char	*new_name;
160 {
161 	errcode_t	retval;
162 	struct profile_node *section, *node;
163 	void		*state;
164 	const char	**cpp;
165 
166 	retval = rw_setup(profile);
167 	if (retval)
168 		return retval;
169 
170 	if (names == 0 || names[0] == 0 || names[1] == 0)
171 		return PROF_BAD_NAMESET;
172 
173 	section = profile->first_file->root;
174 	for (cpp = names; cpp[1]; cpp++) {
175 		state = 0;
176 		retval = profile_find_node(section, *cpp, 0, 1,
177 					   &state, &section);
178 		if (retval)
179 			return retval;
180 	}
181 
182 	state = 0;
183 	retval = profile_find_node(section, *cpp, 0, 1, &state, &node);
184 	if (retval)
185 		return retval;
186 
187 	if (new_name)
188 		retval = profile_rename_node(node, new_name);
189 	else
190 		retval = profile_remove_node(node);
191 	if (retval)
192 		return retval;
193 
194 	profile->first_file->flags |= PROFILE_FILE_DIRTY;
195 
196 	return 0;
197 }
198 
199 /*
200  * Insert a new relation.  If the new_value argument is NULL, then
201  * create a new section instead.
202  *
203  * Note: if the intermediate sections do not exist, this function will
204  * automatically create them.
205  *
206  * ADL - 2/23/99, rewritten TYT 2/25/99
207  */
208 KRB5_DLLIMP errcode_t KRB5_CALLCONV
209 profile_add_relation(profile, names, new_value)
210 	profile_t	profile;
211 	const char  	**names;
212 	const char	*new_value;
213 {
214 	errcode_t	retval;
215     	struct profile_node *section;
216 	const char 	**cpp;
217 	void		*state;
218 
219 	retval = rw_setup(profile);
220 	if (retval)
221 		return retval;
222 
223 	if (names == 0 || names[0] == 0 || names[1] == 0)
224 		return PROF_BAD_NAMESET;
225 
226 	section = profile->first_file->root;
227 	for (cpp = names; cpp[1]; cpp++) {
228 		state = 0;
229 		retval = profile_find_node(section, *cpp, 0, 1,
230 					   &state, &section);
231 		if (retval == PROF_NO_SECTION)
232 			retval = profile_add_node(section, *cpp, 0, &section);
233 		if (retval)
234 			return retval;
235 	}
236 
237 	if (new_value == 0) {
238 		retval = profile_find_node(section, *cpp, 0, 1, &state, 0);
239 		if (retval == 0)
240 			return PROF_EXISTS;
241 		else if (retval != PROF_NO_SECTION)
242 			return retval;
243 	}
244 
245 	retval = profile_add_node(section, *cpp, new_value, 0);
246 	if (retval)
247 		return retval;
248 
249 	profile->first_file->flags |= PROFILE_FILE_DIRTY;
250 
251 	return 0;
252 }
253 
254