17c478bd9Sstevel@tonic-gate /*
2*159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * prof_init.c --- routines that manipulate the user-visible profile_t
97c478bd9Sstevel@tonic-gate  * 	object.
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate 
12505d05c7Sgtb #include "prof_int.h"
13505d05c7Sgtb 
147c478bd9Sstevel@tonic-gate #include <stdio.h>
157c478bd9Sstevel@tonic-gate #include <string.h>
167c478bd9Sstevel@tonic-gate #ifdef HAVE_STDLIB_H
177c478bd9Sstevel@tonic-gate #include <stdlib.h>
187c478bd9Sstevel@tonic-gate #endif
197c478bd9Sstevel@tonic-gate #include <errno.h>
207c478bd9Sstevel@tonic-gate 
21*159d09a2SMark Phalan #ifdef HAVE_STDINT_H
22*159d09a2SMark Phalan # include <stdint.h>
23*159d09a2SMark Phalan #endif
24*159d09a2SMark Phalan #ifdef HAVE_INTTYPES_H
25*159d09a2SMark Phalan # include <inttypes.h>
26*159d09a2SMark Phalan #endif
27*159d09a2SMark Phalan typedef int32_t prof_int32;
287c478bd9Sstevel@tonic-gate 
29505d05c7Sgtb errcode_t KRB5_CALLCONV
30505d05c7Sgtb profile_init(const_profile_filespec_t *files, profile_t *ret_profile)
317c478bd9Sstevel@tonic-gate {
327c478bd9Sstevel@tonic-gate 	const_profile_filespec_t *fs;
337c478bd9Sstevel@tonic-gate 	profile_t profile;
347c478bd9Sstevel@tonic-gate 	prf_file_t  new_file, last = 0;
357c478bd9Sstevel@tonic-gate 	errcode_t retval = 0;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate 	profile = malloc(sizeof(struct _profile_t));
387c478bd9Sstevel@tonic-gate 	if (!profile)
397c478bd9Sstevel@tonic-gate 		return ENOMEM;
407c478bd9Sstevel@tonic-gate 	memset(profile, 0, sizeof(struct _profile_t));
417c478bd9Sstevel@tonic-gate 	profile->magic = PROF_MAGIC_PROFILE;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate         /* if the filenames list is not specified return an empty profile */
447c478bd9Sstevel@tonic-gate         if ( files ) {
457c478bd9Sstevel@tonic-gate 	    for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) {
467c478bd9Sstevel@tonic-gate 		retval = profile_open_file(*fs, &new_file);
477c478bd9Sstevel@tonic-gate 		/* if this file is missing, skip to the next */
48505d05c7Sgtb 		if (retval == ENOENT || retval == EACCES) {
497c478bd9Sstevel@tonic-gate 			continue;
507c478bd9Sstevel@tonic-gate 		}
517c478bd9Sstevel@tonic-gate 		if (retval) {
527c478bd9Sstevel@tonic-gate 			profile_release(profile);
537c478bd9Sstevel@tonic-gate 			return retval;
547c478bd9Sstevel@tonic-gate 		}
557c478bd9Sstevel@tonic-gate 		if (last)
567c478bd9Sstevel@tonic-gate 			last->next = new_file;
577c478bd9Sstevel@tonic-gate 		else
587c478bd9Sstevel@tonic-gate 			profile->first_file = new_file;
597c478bd9Sstevel@tonic-gate 		last = new_file;
607c478bd9Sstevel@tonic-gate 	    }
617c478bd9Sstevel@tonic-gate 	    /*
627c478bd9Sstevel@tonic-gate 	     * If last is still null after the loop, then all the files were
637c478bd9Sstevel@tonic-gate 	     * missing, so return the appropriate error.
647c478bd9Sstevel@tonic-gate 	     */
657c478bd9Sstevel@tonic-gate 	    if (!last) {
667c478bd9Sstevel@tonic-gate 		profile_release(profile);
677c478bd9Sstevel@tonic-gate 		return ENOENT;
687c478bd9Sstevel@tonic-gate 	    }
697c478bd9Sstevel@tonic-gate 	}
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate         *ret_profile = profile;
727c478bd9Sstevel@tonic-gate         return 0;
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
75*159d09a2SMark Phalan #define COUNT_LINKED_LIST(COUNT, PTYPE, START, FIELD)	\
76*159d09a2SMark Phalan 	{						\
77*159d09a2SMark Phalan 	    int cll_counter = 0;			\
78*159d09a2SMark Phalan 	    PTYPE cll_ptr = (START);			\
79*159d09a2SMark Phalan 	    while (cll_ptr != NULL) {			\
80*159d09a2SMark Phalan 		cll_counter++;				\
81*159d09a2SMark Phalan 		cll_ptr = cll_ptr->FIELD;		\
82*159d09a2SMark Phalan 	    }						\
83*159d09a2SMark Phalan 	    (COUNT) = cll_counter;			\
84*159d09a2SMark Phalan 	}
85*159d09a2SMark Phalan 
86*159d09a2SMark Phalan errcode_t KRB5_CALLCONV
87*159d09a2SMark Phalan profile_copy(profile_t old_profile, profile_t *new_profile)
88*159d09a2SMark Phalan {
89*159d09a2SMark Phalan     size_t size, i;
90*159d09a2SMark Phalan     const_profile_filespec_t *files;
91*159d09a2SMark Phalan     prf_file_t file;
92*159d09a2SMark Phalan     errcode_t err;
93*159d09a2SMark Phalan 
94*159d09a2SMark Phalan     /* The fields we care about are read-only after creation, so
95*159d09a2SMark Phalan        no locking is needed.  */
96*159d09a2SMark Phalan     COUNT_LINKED_LIST (size, prf_file_t, old_profile->first_file, next);
97*159d09a2SMark Phalan     files = malloc ((size+1) * sizeof(*files));
98*159d09a2SMark Phalan     if (files == NULL)
99*159d09a2SMark Phalan 	return errno;
100*159d09a2SMark Phalan     for (i = 0, file = old_profile->first_file; i < size; i++, file = file->next)
101*159d09a2SMark Phalan 	files[i] = file->data->filespec;
102*159d09a2SMark Phalan     files[size] = NULL;
103*159d09a2SMark Phalan     err = profile_init (files, new_profile);
104*159d09a2SMark Phalan     free (files);
105*159d09a2SMark Phalan     return err;
106*159d09a2SMark Phalan }
107*159d09a2SMark Phalan 
108505d05c7Sgtb errcode_t KRB5_CALLCONV
109505d05c7Sgtb profile_init_path(const_profile_filespec_list_t filepath,
110505d05c7Sgtb 		  profile_t *ret_profile)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate 	int n_entries, i;
113505d05c7Sgtb 	unsigned int ent_len;
1147c478bd9Sstevel@tonic-gate 	const char *s, *t;
115505d05c7Sgtb 	profile_filespec_t *filenames;
1167c478bd9Sstevel@tonic-gate 	errcode_t retval;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/* count the distinct filename components */
1197c478bd9Sstevel@tonic-gate 	for(s = filepath, n_entries = 1; *s; s++) {
1207c478bd9Sstevel@tonic-gate 		if (*s == ':')
1217c478bd9Sstevel@tonic-gate 			n_entries++;
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	/* the array is NULL terminated */
125505d05c7Sgtb 	filenames = (profile_filespec_t*) malloc((n_entries+1) * sizeof(char*));
1267c478bd9Sstevel@tonic-gate 	if (filenames == 0)
1277c478bd9Sstevel@tonic-gate 		return ENOMEM;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	/* measure, copy, and skip each one */
130*159d09a2SMark Phalan 	/* Solaris Kerberos */
1317c478bd9Sstevel@tonic-gate 	for(s = filepath, i=0; ((t = strchr(s, ':')) != NULL) ||
132505d05c7Sgtb 			((t=s+strlen(s)) != NULL); s=t+1, i++) {
1337c478bd9Sstevel@tonic-gate 		ent_len = t-s;
1347c478bd9Sstevel@tonic-gate 		filenames[i] = (char*) malloc(ent_len + 1);
1357c478bd9Sstevel@tonic-gate 		if (filenames[i] == 0) {
1367c478bd9Sstevel@tonic-gate 			/* if malloc fails, free the ones that worked */
1377c478bd9Sstevel@tonic-gate 			while(--i >= 0) free(filenames[i]);
1387c478bd9Sstevel@tonic-gate                         free(filenames);
1397c478bd9Sstevel@tonic-gate 			return ENOMEM;
1407c478bd9Sstevel@tonic-gate 		}
1417c478bd9Sstevel@tonic-gate 		strncpy(filenames[i], s, ent_len);
1427c478bd9Sstevel@tonic-gate 		filenames[i][ent_len] = 0;
1437c478bd9Sstevel@tonic-gate 		if (*t == 0) {
1447c478bd9Sstevel@tonic-gate 			i++;
1457c478bd9Sstevel@tonic-gate 			break;
1467c478bd9Sstevel@tonic-gate 		}
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	/* cap the array */
1497c478bd9Sstevel@tonic-gate 	filenames[i] = 0;
1507c478bd9Sstevel@tonic-gate 
151505d05c7Sgtb 	retval = profile_init((const_profile_filespec_t *) filenames,
152505d05c7Sgtb 			      ret_profile);
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* count back down and free the entries */
1557c478bd9Sstevel@tonic-gate 	while(--i >= 0) free(filenames[i]);
1567c478bd9Sstevel@tonic-gate 	free(filenames);
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	return retval;
1597c478bd9Sstevel@tonic-gate }
160505d05c7Sgtb 
161505d05c7Sgtb errcode_t KRB5_CALLCONV
162505d05c7Sgtb profile_is_writable(profile_t profile, int *writable)
1637c478bd9Sstevel@tonic-gate {
164*159d09a2SMark Phalan     if (!profile || profile->magic != PROF_MAGIC_PROFILE)
165*159d09a2SMark Phalan         return PROF_MAGIC_PROFILE;
166*159d09a2SMark Phalan 
167*159d09a2SMark Phalan     if (!writable)
168*159d09a2SMark Phalan         return EINVAL;
169*159d09a2SMark Phalan 
170*159d09a2SMark Phalan     if (profile->first_file)
171*159d09a2SMark Phalan         *writable = (profile->first_file->data->flags & PROFILE_FILE_RW);
172*159d09a2SMark Phalan 
173*159d09a2SMark Phalan     return 0;
174505d05c7Sgtb }
175505d05c7Sgtb 
176505d05c7Sgtb errcode_t KRB5_CALLCONV
177505d05c7Sgtb profile_is_modified(profile_t profile, int *modified)
178505d05c7Sgtb {
179*159d09a2SMark Phalan     if (!profile || profile->magic != PROF_MAGIC_PROFILE)
180*159d09a2SMark Phalan         return PROF_MAGIC_PROFILE;
181*159d09a2SMark Phalan 
182*159d09a2SMark Phalan     if (!modified)
183*159d09a2SMark Phalan         return EINVAL;
184*159d09a2SMark Phalan 
185*159d09a2SMark Phalan     if (profile->first_file)
186*159d09a2SMark Phalan         *modified = (profile->first_file->data->flags & PROFILE_FILE_DIRTY);
187*159d09a2SMark Phalan 
188*159d09a2SMark Phalan     return 0;
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
191505d05c7Sgtb errcode_t KRB5_CALLCONV
192505d05c7Sgtb profile_flush(profile_t profile)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
1957c478bd9Sstevel@tonic-gate 		return PROF_MAGIC_PROFILE;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (profile->first_file)
1987c478bd9Sstevel@tonic-gate 		return profile_flush_file(profile->first_file);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	return 0;
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
203505d05c7Sgtb errcode_t KRB5_CALLCONV
204505d05c7Sgtb profile_flush_to_file(profile_t profile, const_profile_filespec_t outfile)
205505d05c7Sgtb {
206505d05c7Sgtb 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
207505d05c7Sgtb 		return PROF_MAGIC_PROFILE;
208505d05c7Sgtb 
209505d05c7Sgtb 	if (profile->first_file)
210505d05c7Sgtb 		return profile_flush_file_to_file(profile->first_file,
211505d05c7Sgtb 						  outfile);
212505d05c7Sgtb 
213505d05c7Sgtb 	return 0;
214505d05c7Sgtb }
215505d05c7Sgtb 
216505d05c7Sgtb errcode_t KRB5_CALLCONV
217505d05c7Sgtb profile_flush_to_buffer(profile_t profile, char **buf)
218505d05c7Sgtb {
219505d05c7Sgtb     return profile_flush_file_data_to_buffer(profile->first_file->data, buf);
220505d05c7Sgtb }
221505d05c7Sgtb 
222505d05c7Sgtb void KRB5_CALLCONV
223505d05c7Sgtb profile_free_buffer(profile_t profile, char *buf)
224505d05c7Sgtb {
225505d05c7Sgtb     free(buf);
226505d05c7Sgtb }
227505d05c7Sgtb 
228505d05c7Sgtb void KRB5_CALLCONV
229505d05c7Sgtb profile_abandon(profile_t profile)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	prf_file_t	p, next;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
2347c478bd9Sstevel@tonic-gate 		return;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	for (p = profile->first_file; p; p = next) {
2377c478bd9Sstevel@tonic-gate 		next = p->next;
2387c478bd9Sstevel@tonic-gate 		profile_free_file(p);
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 	profile->magic = 0;
2417c478bd9Sstevel@tonic-gate 	free(profile);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate 
244505d05c7Sgtb void KRB5_CALLCONV
245505d05c7Sgtb profile_release(profile_t profile)
2467c478bd9Sstevel@tonic-gate {
2477c478bd9Sstevel@tonic-gate 	prf_file_t	p, next;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
2507c478bd9Sstevel@tonic-gate 		return;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	for (p = profile->first_file; p; p = next) {
2537c478bd9Sstevel@tonic-gate 		next = p->next;
2547c478bd9Sstevel@tonic-gate 		profile_close_file(p);
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate 	profile->magic = 0;
2577c478bd9Sstevel@tonic-gate 	free(profile);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate /*
2617c478bd9Sstevel@tonic-gate  * Here begins the profile serialization functions.
2627c478bd9Sstevel@tonic-gate  */
2637c478bd9Sstevel@tonic-gate /*ARGSUSED*/
264505d05c7Sgtb errcode_t profile_ser_size(const char *unused, profile_t profile,
265505d05c7Sgtb 			   size_t *sizep)
2667c478bd9Sstevel@tonic-gate {
2677c478bd9Sstevel@tonic-gate     size_t	required;
2687c478bd9Sstevel@tonic-gate     prf_file_t	pfp;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate     required = 3*sizeof(prof_int32);
2717c478bd9Sstevel@tonic-gate     for (pfp = profile->first_file; pfp; pfp = pfp->next) {
2727c478bd9Sstevel@tonic-gate 	required += sizeof(prof_int32);
273505d05c7Sgtb 	required += strlen(pfp->data->filespec);
2747c478bd9Sstevel@tonic-gate     }
2757c478bd9Sstevel@tonic-gate     *sizep += required;
2767c478bd9Sstevel@tonic-gate     return 0;
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate 
279505d05c7Sgtb static void pack_int32(prof_int32 oval, unsigned char **bufpp, size_t *remainp)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate     (*bufpp)[0] = (unsigned char) ((oval >> 24) & 0xff);
2827c478bd9Sstevel@tonic-gate     (*bufpp)[1] = (unsigned char) ((oval >> 16) & 0xff);
2837c478bd9Sstevel@tonic-gate     (*bufpp)[2] = (unsigned char) ((oval >> 8) & 0xff);
2847c478bd9Sstevel@tonic-gate     (*bufpp)[3] = (unsigned char) (oval & 0xff);
2857c478bd9Sstevel@tonic-gate     *bufpp += sizeof(prof_int32);
2867c478bd9Sstevel@tonic-gate     *remainp -= sizeof(prof_int32);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate 
289505d05c7Sgtb errcode_t profile_ser_externalize(const char *unused, profile_t profile,
290505d05c7Sgtb 				  unsigned char **bufpp, size_t *remainp)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate     errcode_t		retval;
2937c478bd9Sstevel@tonic-gate     size_t		required;
2947c478bd9Sstevel@tonic-gate     unsigned char	*bp;
2957c478bd9Sstevel@tonic-gate     size_t		remain;
2967c478bd9Sstevel@tonic-gate     prf_file_t		pfp;
2977c478bd9Sstevel@tonic-gate     prof_int32		fcount, slen;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate     required = 0;
3007c478bd9Sstevel@tonic-gate     bp = *bufpp;
3017c478bd9Sstevel@tonic-gate     remain = *remainp;
3027c478bd9Sstevel@tonic-gate     retval = EINVAL;
3037c478bd9Sstevel@tonic-gate     if (profile) {
3047c478bd9Sstevel@tonic-gate 	retval = ENOMEM;
3057c478bd9Sstevel@tonic-gate 	(void) profile_ser_size(unused, profile, &required);
3067c478bd9Sstevel@tonic-gate 	if (required <= remain) {
3077c478bd9Sstevel@tonic-gate 	    fcount = 0;
3087c478bd9Sstevel@tonic-gate 	    for (pfp = profile->first_file; pfp; pfp = pfp->next)
3097c478bd9Sstevel@tonic-gate 		fcount++;
310*159d09a2SMark Phalan 	    pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
3117c478bd9Sstevel@tonic-gate 	    pack_int32(fcount, &bp, &remain);
3127c478bd9Sstevel@tonic-gate 	    for (pfp = profile->first_file; pfp; pfp = pfp->next) {
313505d05c7Sgtb 		slen = (prof_int32) strlen(pfp->data->filespec);
3147c478bd9Sstevel@tonic-gate 		pack_int32(slen, &bp, &remain);
3157c478bd9Sstevel@tonic-gate 		if (slen) {
316505d05c7Sgtb 		    memcpy(bp, pfp->data->filespec, (size_t) slen);
3177c478bd9Sstevel@tonic-gate 		    bp += slen;
3187c478bd9Sstevel@tonic-gate 		    remain -= (size_t) slen;
3197c478bd9Sstevel@tonic-gate 		}
3207c478bd9Sstevel@tonic-gate 	    }
321*159d09a2SMark Phalan 	    pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
3227c478bd9Sstevel@tonic-gate 	    retval = 0;
3237c478bd9Sstevel@tonic-gate 	    *bufpp = bp;
3247c478bd9Sstevel@tonic-gate 	    *remainp = remain;
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate     }
3277c478bd9Sstevel@tonic-gate     return(retval);
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate 
330505d05c7Sgtb static int unpack_int32(prof_int32 *intp, unsigned char **bufpp,
331505d05c7Sgtb 			size_t *remainp)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate     if (*remainp >= sizeof(prof_int32)) {
3347c478bd9Sstevel@tonic-gate 	*intp = (((prof_int32) (*bufpp)[0] << 24) |
3357c478bd9Sstevel@tonic-gate 		 ((prof_int32) (*bufpp)[1] << 16) |
3367c478bd9Sstevel@tonic-gate 		 ((prof_int32) (*bufpp)[2] << 8) |
3377c478bd9Sstevel@tonic-gate 		 ((prof_int32) (*bufpp)[3]));
3387c478bd9Sstevel@tonic-gate 	*bufpp += sizeof(prof_int32);
3397c478bd9Sstevel@tonic-gate 	*remainp -= sizeof(prof_int32);
3407c478bd9Sstevel@tonic-gate 	return 0;
3417c478bd9Sstevel@tonic-gate     }
3427c478bd9Sstevel@tonic-gate     else
3437c478bd9Sstevel@tonic-gate 	return 1;
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate /*ARGSUSED*/
347505d05c7Sgtb errcode_t profile_ser_internalize(const char *unused, profile_t *profilep,
348505d05c7Sgtb 				  unsigned char **bufpp, size_t *remainp)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate 	errcode_t		retval;
3517c478bd9Sstevel@tonic-gate 	unsigned char	*bp;
3527c478bd9Sstevel@tonic-gate 	size_t		remain;
3537c478bd9Sstevel@tonic-gate 	int			i;
3547c478bd9Sstevel@tonic-gate 	prof_int32		fcount, tmp;
3557c478bd9Sstevel@tonic-gate 	profile_filespec_t		*flist = 0;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	bp = *bufpp;
3587c478bd9Sstevel@tonic-gate 	remain = *remainp;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	if (remain >= 12)
3617c478bd9Sstevel@tonic-gate 		(void) unpack_int32(&tmp, &bp, &remain);
3627c478bd9Sstevel@tonic-gate 	else
3637c478bd9Sstevel@tonic-gate 		tmp = 0;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	if (tmp != PROF_MAGIC_PROFILE) {
3667c478bd9Sstevel@tonic-gate 		retval = EINVAL;
3677c478bd9Sstevel@tonic-gate 		goto cleanup;
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	(void) unpack_int32(&fcount, &bp, &remain);
3717c478bd9Sstevel@tonic-gate 	retval = ENOMEM;
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	flist = (profile_filespec_t *) malloc(sizeof(profile_filespec_t) * (fcount + 1));
3747c478bd9Sstevel@tonic-gate 	if (!flist)
3757c478bd9Sstevel@tonic-gate 		goto cleanup;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	memset(flist, 0, sizeof(char *) * (fcount+1));
3787c478bd9Sstevel@tonic-gate 	for (i=0; i<fcount; i++) {
3797c478bd9Sstevel@tonic-gate 		if (!unpack_int32(&tmp, &bp, &remain)) {
3807c478bd9Sstevel@tonic-gate 			flist[i] = (char *) malloc((size_t) (tmp+1));
3817c478bd9Sstevel@tonic-gate 			if (!flist[i])
3827c478bd9Sstevel@tonic-gate 				goto cleanup;
3837c478bd9Sstevel@tonic-gate 			memcpy(flist[i], bp, (size_t) tmp);
3847c478bd9Sstevel@tonic-gate 			flist[i][tmp] = '\0';
3857c478bd9Sstevel@tonic-gate 			bp += tmp;
3867c478bd9Sstevel@tonic-gate 			remain -= (size_t) tmp;
3877c478bd9Sstevel@tonic-gate 		}
3887c478bd9Sstevel@tonic-gate 	}
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	if (unpack_int32(&tmp, &bp, &remain) ||
3917c478bd9Sstevel@tonic-gate 	    (tmp != PROF_MAGIC_PROFILE)) {
3927c478bd9Sstevel@tonic-gate 		retval = EINVAL;
3937c478bd9Sstevel@tonic-gate 		goto cleanup;
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 
396505d05c7Sgtb 	if ((retval = profile_init((const_profile_filespec_t *) flist,
397505d05c7Sgtb 				   profilep)))
3987c478bd9Sstevel@tonic-gate 		goto cleanup;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	*bufpp = bp;
4017c478bd9Sstevel@tonic-gate 	*remainp = remain;
402505d05c7Sgtb 
4037c478bd9Sstevel@tonic-gate cleanup:
4047c478bd9Sstevel@tonic-gate 	if (flist) {
4057c478bd9Sstevel@tonic-gate 		for (i=0; i<fcount; i++) {
4067c478bd9Sstevel@tonic-gate 			if (flist[i])
4077c478bd9Sstevel@tonic-gate 				free(flist[i]);
4087c478bd9Sstevel@tonic-gate 		}
4097c478bd9Sstevel@tonic-gate 		free(flist);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	return(retval);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate errcode_t
4167c478bd9Sstevel@tonic-gate profile_get_options_boolean(profile, section, options)
4177c478bd9Sstevel@tonic-gate     profile_t		profile;
4187c478bd9Sstevel@tonic-gate     char **		section;
4197c478bd9Sstevel@tonic-gate     profile_options_boolean *options;
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate     char ** actual_section;
4227c478bd9Sstevel@tonic-gate     char * value = NULL;
4237c478bd9Sstevel@tonic-gate     errcode_t retval = 0;
4247c478bd9Sstevel@tonic-gate     int i, max_i;
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate     for (max_i = 0; section[max_i]; max_i++);
4277c478bd9Sstevel@tonic-gate     if (actual_section = (char **)malloc((max_i + 2) * sizeof(char *))) {
4287c478bd9Sstevel@tonic-gate         for (actual_section[max_i + 1] = NULL, i = 0; section[i]; i++)
4297c478bd9Sstevel@tonic-gate 	    actual_section[i] = section[i];
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	for (i = 0; options[i].name; i++) {
4327c478bd9Sstevel@tonic-gate 	    if (options[i].found) continue;
4337c478bd9Sstevel@tonic-gate 	    actual_section[max_i] = options[i].name;
4347c478bd9Sstevel@tonic-gate 	    retval = profile_get_value(profile, (const char **) actual_section,
4357c478bd9Sstevel@tonic-gate                                        (const char **)&value);
4367c478bd9Sstevel@tonic-gate 	    if (retval && (retval != PROF_NO_RELATION) &&
4377c478bd9Sstevel@tonic-gate 	       (retval != PROF_NO_SECTION)) {
4387c478bd9Sstevel@tonic-gate 		free(actual_section);
4397c478bd9Sstevel@tonic-gate 		return(retval);
4407c478bd9Sstevel@tonic-gate 	    }
4417c478bd9Sstevel@tonic-gate 	    if ((retval == 0) && value) {
4427c478bd9Sstevel@tonic-gate 		/*
4437c478bd9Sstevel@tonic-gate 		 * Any string other than true will turn off the
4447c478bd9Sstevel@tonic-gate 		 *option
4457c478bd9Sstevel@tonic-gate 		 */
4467c478bd9Sstevel@tonic-gate 		if (strncmp(value,"true",4) == 0)
4477c478bd9Sstevel@tonic-gate 		    *(options[i].value) = 1;
4487c478bd9Sstevel@tonic-gate 		else
4497c478bd9Sstevel@tonic-gate 		    *(options[i].value) = 0;
4507c478bd9Sstevel@tonic-gate 		options[i].found = 1;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 		}
4537c478bd9Sstevel@tonic-gate 	}
4547c478bd9Sstevel@tonic-gate 	free(actual_section);
4557c478bd9Sstevel@tonic-gate     } else {
4567c478bd9Sstevel@tonic-gate 	retval = ENOMEM;
4577c478bd9Sstevel@tonic-gate     }
4587c478bd9Sstevel@tonic-gate     return(retval);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate errcode_t
4627c478bd9Sstevel@tonic-gate profile_get_options_string(profile, section, options)
4637c478bd9Sstevel@tonic-gate     profile_t		profile;
4647c478bd9Sstevel@tonic-gate     char **		section;
4657c478bd9Sstevel@tonic-gate     profile_option_strings *options;
4667c478bd9Sstevel@tonic-gate {
4677c478bd9Sstevel@tonic-gate     char ** actual_section;
4687c478bd9Sstevel@tonic-gate     char * value = NULL;
4697c478bd9Sstevel@tonic-gate     errcode_t retval = 0;
4707c478bd9Sstevel@tonic-gate     int i, max_i;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate     for (max_i = 0; section[max_i]; max_i++);
4737c478bd9Sstevel@tonic-gate     if (actual_section = (char **)malloc((max_i + 2) * sizeof(char *))) {
4747c478bd9Sstevel@tonic-gate         for (actual_section[max_i + 1] = NULL, i = 0; section[i]; i++)
4757c478bd9Sstevel@tonic-gate 	    actual_section[i] = section[i];
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	for (i = 0; options[i].name; i++) {
4787c478bd9Sstevel@tonic-gate 	    if (options[i].found) continue;
4797c478bd9Sstevel@tonic-gate 	    actual_section[max_i] = options[i].name;
4807c478bd9Sstevel@tonic-gate 	    retval = profile_get_value(profile, (const char **) actual_section,
4817c478bd9Sstevel@tonic-gate                                        (const char **)&value);
4827c478bd9Sstevel@tonic-gate 	    if (retval && (retval != PROF_NO_RELATION) &&
4837c478bd9Sstevel@tonic-gate 	       (retval != PROF_NO_SECTION)) {
4847c478bd9Sstevel@tonic-gate 		free(actual_section);
4857c478bd9Sstevel@tonic-gate 		return(retval);
4867c478bd9Sstevel@tonic-gate 	    }
4877c478bd9Sstevel@tonic-gate 	    if ((retval == 0) && value) {
4887c478bd9Sstevel@tonic-gate 		*options[i].value = malloc(strlen(value)+1);
4897c478bd9Sstevel@tonic-gate 		if (*options[i].value == 0)
4907c478bd9Sstevel@tonic-gate 			retval = ENOMEM;
4917c478bd9Sstevel@tonic-gate 		strcpy(*options[i].value, value);
4927c478bd9Sstevel@tonic-gate 	        options[i].found = 1;
4937c478bd9Sstevel@tonic-gate     	    } else
4947c478bd9Sstevel@tonic-gate 		*options[i].value = 0;
4957c478bd9Sstevel@tonic-gate 	}
4967c478bd9Sstevel@tonic-gate 	free(actual_section);
4977c478bd9Sstevel@tonic-gate     } else {
4987c478bd9Sstevel@tonic-gate 	retval = ENOMEM;
4997c478bd9Sstevel@tonic-gate     }
5007c478bd9Sstevel@tonic-gate     return(retval);
5017c478bd9Sstevel@tonic-gate }
502