17c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  * prof_set.c --- routines that expose the public interfaces for
47c478bd9Sstevel@tonic-gate  * 	inserting, updating and deleting items from the profile.
57c478bd9Sstevel@tonic-gate  *
67c478bd9Sstevel@tonic-gate  * WARNING: These routines only look at the first file opened in the
77c478bd9Sstevel@tonic-gate  * profile.  It's not clear how to handle multiple files, actually.
87c478bd9Sstevel@tonic-gate  * In the future it may be necessary to modify this public interface,
97c478bd9Sstevel@tonic-gate  * or possibly add higher level functions to support this correctly.
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  * WARNING: We're not yet doing locking yet, either.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
15*505d05c7Sgtb #include "prof_int.h"
16*505d05c7Sgtb 
177c478bd9Sstevel@tonic-gate #include <stdio.h>
187c478bd9Sstevel@tonic-gate #include <string.h>
197c478bd9Sstevel@tonic-gate #ifdef HAVE_STDLIB_H
207c478bd9Sstevel@tonic-gate #include <stdlib.h>
217c478bd9Sstevel@tonic-gate #endif
227c478bd9Sstevel@tonic-gate #include <errno.h>
237c478bd9Sstevel@tonic-gate 
24*505d05c7Sgtb static errcode_t rw_setup(profile_t profile)
257c478bd9Sstevel@tonic-gate {
267c478bd9Sstevel@tonic-gate    	prf_file_t	file;
27*505d05c7Sgtb 	errcode_t	retval = 0;
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 	if (!profile)
307c478bd9Sstevel@tonic-gate 		return PROF_NO_PROFILE;
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate 	if (profile->magic != PROF_MAGIC_PROFILE)
337c478bd9Sstevel@tonic-gate 		return PROF_MAGIC_PROFILE;
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate 	file = profile->first_file;
36*505d05c7Sgtb 
37*505d05c7Sgtb 	retval = profile_lock_global();
38*505d05c7Sgtb 	if (retval)
39*505d05c7Sgtb 	    return retval;
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate 	/* Don't update the file if we've already made modifications */
42*505d05c7Sgtb 	if (file->data->flags & PROFILE_FILE_DIRTY) {
43*505d05c7Sgtb 	    profile_unlock_global();
44*505d05c7Sgtb 	    return 0;
45*505d05c7Sgtb 	}
46*505d05c7Sgtb 
47*505d05c7Sgtb 	if ((file->data->flags & PROFILE_FILE_SHARED) != 0) {
48*505d05c7Sgtb 	    prf_data_t new_data;
49*505d05c7Sgtb 	    new_data = profile_make_prf_data(file->data->filespec);
50*505d05c7Sgtb 	    if (new_data == NULL) {
51*505d05c7Sgtb 		retval = ENOMEM;
52*505d05c7Sgtb 	    } else {
53*505d05c7Sgtb 		retval = k5_mutex_init(&new_data->lock);
54*505d05c7Sgtb 		if (retval == 0) {
55*505d05c7Sgtb 		    new_data->root = NULL;
56*505d05c7Sgtb 		    new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED;
57*505d05c7Sgtb 		    new_data->timestamp = 0;
58*505d05c7Sgtb 		    new_data->upd_serial = file->data->upd_serial;
59*505d05c7Sgtb 		}
60*505d05c7Sgtb 	    }
61*505d05c7Sgtb 
62*505d05c7Sgtb 	    if (retval != 0) {
63*505d05c7Sgtb 		profile_unlock_global();
64*505d05c7Sgtb 		free(new_data);
65*505d05c7Sgtb 		return retval;
66*505d05c7Sgtb 	    }
67*505d05c7Sgtb 	    profile_dereference_data_locked(file->data);
68*505d05c7Sgtb 	    file->data = new_data;
69*505d05c7Sgtb 	}
70*505d05c7Sgtb 
71*505d05c7Sgtb 	profile_unlock_global();
727c478bd9Sstevel@tonic-gate 	retval = profile_update_file(file);
73*505d05c7Sgtb 
747c478bd9Sstevel@tonic-gate 	return retval;
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * Delete or update a particular child node
807c478bd9Sstevel@tonic-gate  *
817c478bd9Sstevel@tonic-gate  * ADL - 2/23/99, rewritten TYT 2/25/99
827c478bd9Sstevel@tonic-gate  */
83*505d05c7Sgtb errcode_t KRB5_CALLCONV
84*505d05c7Sgtb profile_update_relation(profile_t profile, const char **names,
85*505d05c7Sgtb 			const char *old_value, const char *new_value)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate 	errcode_t	retval;
887c478bd9Sstevel@tonic-gate 	struct profile_node *section, *node;
897c478bd9Sstevel@tonic-gate 	void		*state;
907c478bd9Sstevel@tonic-gate 	const char	**cpp;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	retval = rw_setup(profile);
937c478bd9Sstevel@tonic-gate 	if (retval)
947c478bd9Sstevel@tonic-gate 		return retval;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	if (names == 0 || names[0] == 0 || names[1] == 0)
977c478bd9Sstevel@tonic-gate 		return PROF_BAD_NAMESET;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	if (!old_value || !*old_value)
1007c478bd9Sstevel@tonic-gate 		return PROF_EINVAL;
1017c478bd9Sstevel@tonic-gate 
102*505d05c7Sgtb 	retval = k5_mutex_lock(&profile->first_file->data->lock);
103*505d05c7Sgtb 	if (retval)
104*505d05c7Sgtb 	    return retval;
105*505d05c7Sgtb 	section = profile->first_file->data->root;
1067c478bd9Sstevel@tonic-gate 	for (cpp = names; cpp[1]; cpp++) {
1077c478bd9Sstevel@tonic-gate 		state = 0;
1087c478bd9Sstevel@tonic-gate 		retval = profile_find_node(section, *cpp, 0, 1,
1097c478bd9Sstevel@tonic-gate 					   &state, &section);
110*505d05c7Sgtb 		if (retval) {
111*505d05c7Sgtb 		    k5_mutex_unlock(&profile->first_file->data->lock);
112*505d05c7Sgtb 		    return retval;
113*505d05c7Sgtb 		}
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	state = 0;
1177c478bd9Sstevel@tonic-gate 	retval = profile_find_node(section, *cpp, old_value, 0, &state, &node);
118*505d05c7Sgtb 	if (retval == 0) {
119*505d05c7Sgtb 	    if (new_value)
1207c478bd9Sstevel@tonic-gate 		retval = profile_set_relation_value(node, new_value);
121*505d05c7Sgtb 	    else
1227c478bd9Sstevel@tonic-gate 		retval = profile_remove_node(node);
123*505d05c7Sgtb 	}
124*505d05c7Sgtb 	if (retval == 0)
125*505d05c7Sgtb 	    profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
126*505d05c7Sgtb 	k5_mutex_unlock(&profile->first_file->data->lock);
1277c478bd9Sstevel@tonic-gate 
128*505d05c7Sgtb 	return retval;
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  * Clear a particular all of the relations with a specific name.
1337c478bd9Sstevel@tonic-gate  *
1347c478bd9Sstevel@tonic-gate  * TYT - 2/25/99
1357c478bd9Sstevel@tonic-gate  */
136*505d05c7Sgtb errcode_t KRB5_CALLCONV
137*505d05c7Sgtb profile_clear_relation(profile_t profile, const char **names)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	errcode_t	retval;
1407c478bd9Sstevel@tonic-gate 	struct profile_node *section, *node;
1417c478bd9Sstevel@tonic-gate 	void		*state;
1427c478bd9Sstevel@tonic-gate 	const char	**cpp;
143*505d05c7Sgtb 
1447c478bd9Sstevel@tonic-gate 	retval = rw_setup(profile);
1457c478bd9Sstevel@tonic-gate 	if (retval)
1467c478bd9Sstevel@tonic-gate 		return retval;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if (names == 0 || names[0] == 0 || names[1] == 0)
1497c478bd9Sstevel@tonic-gate 		return PROF_BAD_NAMESET;
1507c478bd9Sstevel@tonic-gate 
151*505d05c7Sgtb 	section = profile->first_file->data->root;
1527c478bd9Sstevel@tonic-gate 	for (cpp = names; cpp[1]; cpp++) {
1537c478bd9Sstevel@tonic-gate 		state = 0;
1547c478bd9Sstevel@tonic-gate 		retval = profile_find_node(section, *cpp, 0, 1,
1557c478bd9Sstevel@tonic-gate 					   &state, &section);
1567c478bd9Sstevel@tonic-gate 		if (retval)
1577c478bd9Sstevel@tonic-gate 			return retval;
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	state = 0;
1617c478bd9Sstevel@tonic-gate 	do {
1627c478bd9Sstevel@tonic-gate 		retval = profile_find_node(section, *cpp, 0, 0, &state, &node);
1637c478bd9Sstevel@tonic-gate 		if (retval)
1647c478bd9Sstevel@tonic-gate 			return retval;
1657c478bd9Sstevel@tonic-gate 		retval = profile_remove_node(node);
1667c478bd9Sstevel@tonic-gate 		if (retval)
1677c478bd9Sstevel@tonic-gate 			return retval;
1687c478bd9Sstevel@tonic-gate 	} while (state);
1697c478bd9Sstevel@tonic-gate 
170*505d05c7Sgtb 	profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	return 0;
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate /*
1767c478bd9Sstevel@tonic-gate  * Rename a particular section; if the new_section name is NULL,
1777c478bd9Sstevel@tonic-gate  * delete it.
1787c478bd9Sstevel@tonic-gate  *
1797c478bd9Sstevel@tonic-gate  * ADL - 2/23/99, rewritten TYT 2/25/99
1807c478bd9Sstevel@tonic-gate  */
181*505d05c7Sgtb errcode_t KRB5_CALLCONV
182*505d05c7Sgtb profile_rename_section(profile_t profile, const char **names,
183*505d05c7Sgtb 		       const char *new_name)
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate 	errcode_t	retval;
1867c478bd9Sstevel@tonic-gate 	struct profile_node *section, *node;
1877c478bd9Sstevel@tonic-gate 	void		*state;
1887c478bd9Sstevel@tonic-gate 	const char	**cpp;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	retval = rw_setup(profile);
1917c478bd9Sstevel@tonic-gate 	if (retval)
1927c478bd9Sstevel@tonic-gate 		return retval;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (names == 0 || names[0] == 0 || names[1] == 0)
1957c478bd9Sstevel@tonic-gate 		return PROF_BAD_NAMESET;
1967c478bd9Sstevel@tonic-gate 
197*505d05c7Sgtb 	retval = k5_mutex_lock(&profile->first_file->data->lock);
198*505d05c7Sgtb 	if (retval)
199*505d05c7Sgtb 	    return retval;
200*505d05c7Sgtb 	section = profile->first_file->data->root;
2017c478bd9Sstevel@tonic-gate 	for (cpp = names; cpp[1]; cpp++) {
2027c478bd9Sstevel@tonic-gate 		state = 0;
2037c478bd9Sstevel@tonic-gate 		retval = profile_find_node(section, *cpp, 0, 1,
2047c478bd9Sstevel@tonic-gate 					   &state, &section);
205*505d05c7Sgtb 		if (retval) {
206*505d05c7Sgtb 		    k5_mutex_unlock(&profile->first_file->data->lock);
207*505d05c7Sgtb 		    return retval;
208*505d05c7Sgtb 		}
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	state = 0;
2127c478bd9Sstevel@tonic-gate 	retval = profile_find_node(section, *cpp, 0, 1, &state, &node);
213*505d05c7Sgtb 	if (retval == 0) {
214*505d05c7Sgtb 	    if (new_name)
2157c478bd9Sstevel@tonic-gate 		retval = profile_rename_node(node, new_name);
216*505d05c7Sgtb 	    else
2177c478bd9Sstevel@tonic-gate 		retval = profile_remove_node(node);
218*505d05c7Sgtb 	}
219*505d05c7Sgtb 	if (retval == 0)
220*505d05c7Sgtb 	    profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
221*505d05c7Sgtb 	k5_mutex_unlock(&profile->first_file->data->lock);
222*505d05c7Sgtb 	return retval;
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate  * Insert a new relation.  If the new_value argument is NULL, then
2277c478bd9Sstevel@tonic-gate  * create a new section instead.
2287c478bd9Sstevel@tonic-gate  *
2297c478bd9Sstevel@tonic-gate  * Note: if the intermediate sections do not exist, this function will
2307c478bd9Sstevel@tonic-gate  * automatically create them.
2317c478bd9Sstevel@tonic-gate  *
2327c478bd9Sstevel@tonic-gate  * ADL - 2/23/99, rewritten TYT 2/25/99
2337c478bd9Sstevel@tonic-gate  */
234*505d05c7Sgtb errcode_t KRB5_CALLCONV
235*505d05c7Sgtb profile_add_relation(profile_t profile, const char **names,
236*505d05c7Sgtb 		     const char *new_value)
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate 	errcode_t	retval;
2397c478bd9Sstevel@tonic-gate     	struct profile_node *section;
2407c478bd9Sstevel@tonic-gate 	const char 	**cpp;
2417c478bd9Sstevel@tonic-gate 	void		*state;
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	retval = rw_setup(profile);
2447c478bd9Sstevel@tonic-gate 	if (retval)
2457c478bd9Sstevel@tonic-gate 		return retval;
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	if (names == 0 || names[0] == 0 || names[1] == 0)
2487c478bd9Sstevel@tonic-gate 		return PROF_BAD_NAMESET;
2497c478bd9Sstevel@tonic-gate 
250*505d05c7Sgtb 	retval = k5_mutex_lock(&profile->first_file->data->lock);
251*505d05c7Sgtb 	if (retval)
252*505d05c7Sgtb 	    return retval;
253*505d05c7Sgtb 	section = profile->first_file->data->root;
2547c478bd9Sstevel@tonic-gate 	for (cpp = names; cpp[1]; cpp++) {
2557c478bd9Sstevel@tonic-gate 		state = 0;
2567c478bd9Sstevel@tonic-gate 		retval = profile_find_node(section, *cpp, 0, 1,
2577c478bd9Sstevel@tonic-gate 					   &state, &section);
2587c478bd9Sstevel@tonic-gate 		if (retval == PROF_NO_SECTION)
2597c478bd9Sstevel@tonic-gate 			retval = profile_add_node(section, *cpp, 0, &section);
260*505d05c7Sgtb 		if (retval) {
261*505d05c7Sgtb 		    k5_mutex_unlock(&profile->first_file->data->lock);
262*505d05c7Sgtb 		    return retval;
263*505d05c7Sgtb 		}
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	if (new_value == 0) {
2677c478bd9Sstevel@tonic-gate 		retval = profile_find_node(section, *cpp, 0, 1, &state, 0);
268*505d05c7Sgtb 		if (retval == 0) {
269*505d05c7Sgtb 		    k5_mutex_unlock(&profile->first_file->data->lock);
270*505d05c7Sgtb 		    return PROF_EXISTS;
271*505d05c7Sgtb 		} else if (retval != PROF_NO_SECTION) {
272*505d05c7Sgtb 		    k5_mutex_unlock(&profile->first_file->data->lock);
273*505d05c7Sgtb 		    return retval;
274*505d05c7Sgtb 		}
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	retval = profile_add_node(section, *cpp, new_value, 0);
278*505d05c7Sgtb 	if (retval) {
279*505d05c7Sgtb 	    k5_mutex_unlock(&profile->first_file->data->lock);
280*505d05c7Sgtb 	    return retval;
281*505d05c7Sgtb 	}
2827c478bd9Sstevel@tonic-gate 
283*505d05c7Sgtb 	profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
284*505d05c7Sgtb 	k5_mutex_unlock(&profile->first_file->data->lock);
2857c478bd9Sstevel@tonic-gate 	return 0;
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate 
288