xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/profile/prof_init.c (revision 7934:6aeeafc994de)
10Sstevel@tonic-gate /*
2*7934SMark.Phalan@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate 
70Sstevel@tonic-gate /*
80Sstevel@tonic-gate  * prof_init.c --- routines that manipulate the user-visible profile_t
90Sstevel@tonic-gate  * 	object.
100Sstevel@tonic-gate  */
110Sstevel@tonic-gate 
12781Sgtb #include "prof_int.h"
13781Sgtb 
140Sstevel@tonic-gate #include <stdio.h>
150Sstevel@tonic-gate #include <string.h>
160Sstevel@tonic-gate #ifdef HAVE_STDLIB_H
170Sstevel@tonic-gate #include <stdlib.h>
180Sstevel@tonic-gate #endif
190Sstevel@tonic-gate #include <errno.h>
200Sstevel@tonic-gate 
21*7934SMark.Phalan@Sun.COM #ifdef HAVE_STDINT_H
22*7934SMark.Phalan@Sun.COM # include <stdint.h>
23*7934SMark.Phalan@Sun.COM #endif
24*7934SMark.Phalan@Sun.COM #ifdef HAVE_INTTYPES_H
25*7934SMark.Phalan@Sun.COM # include <inttypes.h>
26*7934SMark.Phalan@Sun.COM #endif
27*7934SMark.Phalan@Sun.COM typedef int32_t prof_int32;
280Sstevel@tonic-gate 
29781Sgtb errcode_t KRB5_CALLCONV
profile_init(const_profile_filespec_t * files,profile_t * ret_profile)30781Sgtb profile_init(const_profile_filespec_t *files, profile_t *ret_profile)
310Sstevel@tonic-gate {
320Sstevel@tonic-gate 	const_profile_filespec_t *fs;
330Sstevel@tonic-gate 	profile_t profile;
340Sstevel@tonic-gate 	prf_file_t  new_file, last = 0;
350Sstevel@tonic-gate 	errcode_t retval = 0;
360Sstevel@tonic-gate 
370Sstevel@tonic-gate 	profile = malloc(sizeof(struct _profile_t));
380Sstevel@tonic-gate 	if (!profile)
390Sstevel@tonic-gate 		return ENOMEM;
400Sstevel@tonic-gate 	memset(profile, 0, sizeof(struct _profile_t));
410Sstevel@tonic-gate 	profile->magic = PROF_MAGIC_PROFILE;
420Sstevel@tonic-gate 
430Sstevel@tonic-gate         /* if the filenames list is not specified return an empty profile */
440Sstevel@tonic-gate         if ( files ) {
450Sstevel@tonic-gate 	    for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) {
460Sstevel@tonic-gate 		retval = profile_open_file(*fs, &new_file);
470Sstevel@tonic-gate 		/* if this file is missing, skip to the next */
48781Sgtb 		if (retval == ENOENT || retval == EACCES) {
490Sstevel@tonic-gate 			continue;
500Sstevel@tonic-gate 		}
510Sstevel@tonic-gate 		if (retval) {
520Sstevel@tonic-gate 			profile_release(profile);
530Sstevel@tonic-gate 			return retval;
540Sstevel@tonic-gate 		}
550Sstevel@tonic-gate 		if (last)
560Sstevel@tonic-gate 			last->next = new_file;
570Sstevel@tonic-gate 		else
580Sstevel@tonic-gate 			profile->first_file = new_file;
590Sstevel@tonic-gate 		last = new_file;
600Sstevel@tonic-gate 	    }
610Sstevel@tonic-gate 	    /*
620Sstevel@tonic-gate 	     * If last is still null after the loop, then all the files were
630Sstevel@tonic-gate 	     * missing, so return the appropriate error.
640Sstevel@tonic-gate 	     */
650Sstevel@tonic-gate 	    if (!last) {
660Sstevel@tonic-gate 		profile_release(profile);
670Sstevel@tonic-gate 		return ENOENT;
680Sstevel@tonic-gate 	    }
690Sstevel@tonic-gate 	}
700Sstevel@tonic-gate 
710Sstevel@tonic-gate         *ret_profile = profile;
720Sstevel@tonic-gate         return 0;
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
75*7934SMark.Phalan@Sun.COM #define COUNT_LINKED_LIST(COUNT, PTYPE, START, FIELD)	\
76*7934SMark.Phalan@Sun.COM 	{						\
77*7934SMark.Phalan@Sun.COM 	    int cll_counter = 0;			\
78*7934SMark.Phalan@Sun.COM 	    PTYPE cll_ptr = (START);			\
79*7934SMark.Phalan@Sun.COM 	    while (cll_ptr != NULL) {			\
80*7934SMark.Phalan@Sun.COM 		cll_counter++;				\
81*7934SMark.Phalan@Sun.COM 		cll_ptr = cll_ptr->FIELD;		\
82*7934SMark.Phalan@Sun.COM 	    }						\
83*7934SMark.Phalan@Sun.COM 	    (COUNT) = cll_counter;			\
84*7934SMark.Phalan@Sun.COM 	}
85*7934SMark.Phalan@Sun.COM 
86*7934SMark.Phalan@Sun.COM errcode_t KRB5_CALLCONV
profile_copy(profile_t old_profile,profile_t * new_profile)87*7934SMark.Phalan@Sun.COM profile_copy(profile_t old_profile, profile_t *new_profile)
88*7934SMark.Phalan@Sun.COM {
89*7934SMark.Phalan@Sun.COM     size_t size, i;
90*7934SMark.Phalan@Sun.COM     const_profile_filespec_t *files;
91*7934SMark.Phalan@Sun.COM     prf_file_t file;
92*7934SMark.Phalan@Sun.COM     errcode_t err;
93*7934SMark.Phalan@Sun.COM 
94*7934SMark.Phalan@Sun.COM     /* The fields we care about are read-only after creation, so
95*7934SMark.Phalan@Sun.COM        no locking is needed.  */
96*7934SMark.Phalan@Sun.COM     COUNT_LINKED_LIST (size, prf_file_t, old_profile->first_file, next);
97*7934SMark.Phalan@Sun.COM     files = malloc ((size+1) * sizeof(*files));
98*7934SMark.Phalan@Sun.COM     if (files == NULL)
99*7934SMark.Phalan@Sun.COM 	return errno;
100*7934SMark.Phalan@Sun.COM     for (i = 0, file = old_profile->first_file; i < size; i++, file = file->next)
101*7934SMark.Phalan@Sun.COM 	files[i] = file->data->filespec;
102*7934SMark.Phalan@Sun.COM     files[size] = NULL;
103*7934SMark.Phalan@Sun.COM     err = profile_init (files, new_profile);
104*7934SMark.Phalan@Sun.COM     free (files);
105*7934SMark.Phalan@Sun.COM     return err;
106*7934SMark.Phalan@Sun.COM }
107*7934SMark.Phalan@Sun.COM 
108781Sgtb errcode_t KRB5_CALLCONV
profile_init_path(const_profile_filespec_list_t filepath,profile_t * ret_profile)109781Sgtb profile_init_path(const_profile_filespec_list_t filepath,
110781Sgtb 		  profile_t *ret_profile)
1110Sstevel@tonic-gate {
1120Sstevel@tonic-gate 	int n_entries, i;
113781Sgtb 	unsigned int ent_len;
1140Sstevel@tonic-gate 	const char *s, *t;
115781Sgtb 	profile_filespec_t *filenames;
1160Sstevel@tonic-gate 	errcode_t retval;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	/* count the distinct filename components */
1190Sstevel@tonic-gate 	for(s = filepath, n_entries = 1; *s; s++) {
1200Sstevel@tonic-gate 		if (*s == ':')
1210Sstevel@tonic-gate 			n_entries++;
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	/* the array is NULL terminated */
125781Sgtb 	filenames = (profile_filespec_t*) malloc((n_entries+1) * sizeof(char*));
1260Sstevel@tonic-gate 	if (filenames == 0)
1270Sstevel@tonic-gate 		return ENOMEM;
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	/* measure, copy, and skip each one */
130*7934SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
1310Sstevel@tonic-gate 	for(s = filepath, i=0; ((t = strchr(s, ':')) != NULL) ||
132781Sgtb 			((t=s+strlen(s)) != NULL); s=t+1, i++) {
1330Sstevel@tonic-gate 		ent_len = t-s;
1340Sstevel@tonic-gate 		filenames[i] = (char*) malloc(ent_len + 1);
1350Sstevel@tonic-gate 		if (filenames[i] == 0) {
1360Sstevel@tonic-gate 			/* if malloc fails, free the ones that worked */
1370Sstevel@tonic-gate 			while(--i >= 0) free(filenames[i]);
1380Sstevel@tonic-gate                         free(filenames);
1390Sstevel@tonic-gate 			return ENOMEM;
1400Sstevel@tonic-gate 		}
1410Sstevel@tonic-gate 		strncpy(filenames[i], s, ent_len);
1420Sstevel@tonic-gate 		filenames[i][ent_len] = 0;
1430Sstevel@tonic-gate 		if (*t == 0) {
1440Sstevel@tonic-gate 			i++;
1450Sstevel@tonic-gate 			break;
1460Sstevel@tonic-gate 		}
1470Sstevel@tonic-gate 	}
1480Sstevel@tonic-gate 	/* cap the array */
1490Sstevel@tonic-gate 	filenames[i] = 0;
1500Sstevel@tonic-gate 
151781Sgtb 	retval = profile_init((const_profile_filespec_t *) filenames,
152781Sgtb 			      ret_profile);
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	/* count back down and free the entries */
1550Sstevel@tonic-gate 	while(--i >= 0) free(filenames[i]);
1560Sstevel@tonic-gate 	free(filenames);
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	return retval;
1590Sstevel@tonic-gate }
160781Sgtb 
161781Sgtb errcode_t KRB5_CALLCONV
profile_is_writable(profile_t profile,int * writable)162781Sgtb profile_is_writable(profile_t profile, int *writable)
1630Sstevel@tonic-gate {
164*7934SMark.Phalan@Sun.COM     if (!profile || profile->magic != PROF_MAGIC_PROFILE)
165*7934SMark.Phalan@Sun.COM         return PROF_MAGIC_PROFILE;
166*7934SMark.Phalan@Sun.COM 
167*7934SMark.Phalan@Sun.COM     if (!writable)
168*7934SMark.Phalan@Sun.COM         return EINVAL;
169*7934SMark.Phalan@Sun.COM 
170*7934SMark.Phalan@Sun.COM     if (profile->first_file)
171*7934SMark.Phalan@Sun.COM         *writable = (profile->first_file->data->flags & PROFILE_FILE_RW);
172*7934SMark.Phalan@Sun.COM 
173*7934SMark.Phalan@Sun.COM     return 0;
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
176781Sgtb errcode_t KRB5_CALLCONV
profile_is_modified(profile_t profile,int * modified)177781Sgtb profile_is_modified(profile_t profile, int *modified)
178781Sgtb {
179*7934SMark.Phalan@Sun.COM     if (!profile || profile->magic != PROF_MAGIC_PROFILE)
180*7934SMark.Phalan@Sun.COM         return PROF_MAGIC_PROFILE;
181*7934SMark.Phalan@Sun.COM 
182*7934SMark.Phalan@Sun.COM     if (!modified)
183*7934SMark.Phalan@Sun.COM         return EINVAL;
184*7934SMark.Phalan@Sun.COM 
185*7934SMark.Phalan@Sun.COM     if (profile->first_file)
186*7934SMark.Phalan@Sun.COM         *modified = (profile->first_file->data->flags & PROFILE_FILE_DIRTY);
187*7934SMark.Phalan@Sun.COM 
188*7934SMark.Phalan@Sun.COM     return 0;
189781Sgtb }
190781Sgtb 
191781Sgtb errcode_t KRB5_CALLCONV
profile_flush(profile_t profile)192781Sgtb profile_flush(profile_t profile)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
1950Sstevel@tonic-gate 		return PROF_MAGIC_PROFILE;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	if (profile->first_file)
1980Sstevel@tonic-gate 		return profile_flush_file(profile->first_file);
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	return 0;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate 
203781Sgtb errcode_t KRB5_CALLCONV
profile_flush_to_file(profile_t profile,const_profile_filespec_t outfile)204781Sgtb profile_flush_to_file(profile_t profile, const_profile_filespec_t outfile)
205781Sgtb {
206781Sgtb 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
207781Sgtb 		return PROF_MAGIC_PROFILE;
208781Sgtb 
209781Sgtb 	if (profile->first_file)
210781Sgtb 		return profile_flush_file_to_file(profile->first_file,
211781Sgtb 						  outfile);
212781Sgtb 
213781Sgtb 	return 0;
214781Sgtb }
215781Sgtb 
216781Sgtb errcode_t KRB5_CALLCONV
profile_flush_to_buffer(profile_t profile,char ** buf)217781Sgtb profile_flush_to_buffer(profile_t profile, char **buf)
218781Sgtb {
219781Sgtb     return profile_flush_file_data_to_buffer(profile->first_file->data, buf);
220781Sgtb }
221781Sgtb 
222781Sgtb void KRB5_CALLCONV
profile_free_buffer(profile_t profile,char * buf)223781Sgtb profile_free_buffer(profile_t profile, char *buf)
224781Sgtb {
225781Sgtb     free(buf);
226781Sgtb }
227781Sgtb 
228781Sgtb void KRB5_CALLCONV
profile_abandon(profile_t profile)229781Sgtb profile_abandon(profile_t profile)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate 	prf_file_t	p, next;
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
2340Sstevel@tonic-gate 		return;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	for (p = profile->first_file; p; p = next) {
2370Sstevel@tonic-gate 		next = p->next;
2380Sstevel@tonic-gate 		profile_free_file(p);
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate 	profile->magic = 0;
2410Sstevel@tonic-gate 	free(profile);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate 
244781Sgtb void KRB5_CALLCONV
profile_release(profile_t profile)245781Sgtb profile_release(profile_t profile)
2460Sstevel@tonic-gate {
2470Sstevel@tonic-gate 	prf_file_t	p, next;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	if (!profile || profile->magic != PROF_MAGIC_PROFILE)
2500Sstevel@tonic-gate 		return;
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	for (p = profile->first_file; p; p = next) {
2530Sstevel@tonic-gate 		next = p->next;
2540Sstevel@tonic-gate 		profile_close_file(p);
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 	profile->magic = 0;
2570Sstevel@tonic-gate 	free(profile);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate /*
2610Sstevel@tonic-gate  * Here begins the profile serialization functions.
2620Sstevel@tonic-gate  */
2630Sstevel@tonic-gate /*ARGSUSED*/
profile_ser_size(const char * unused,profile_t profile,size_t * sizep)264781Sgtb errcode_t profile_ser_size(const char *unused, profile_t profile,
265781Sgtb 			   size_t *sizep)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate     size_t	required;
2680Sstevel@tonic-gate     prf_file_t	pfp;
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate     required = 3*sizeof(prof_int32);
2710Sstevel@tonic-gate     for (pfp = profile->first_file; pfp; pfp = pfp->next) {
2720Sstevel@tonic-gate 	required += sizeof(prof_int32);
273781Sgtb 	required += strlen(pfp->data->filespec);
2740Sstevel@tonic-gate     }
2750Sstevel@tonic-gate     *sizep += required;
2760Sstevel@tonic-gate     return 0;
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate 
pack_int32(prof_int32 oval,unsigned char ** bufpp,size_t * remainp)279781Sgtb static void pack_int32(prof_int32 oval, unsigned char **bufpp, size_t *remainp)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate     (*bufpp)[0] = (unsigned char) ((oval >> 24) & 0xff);
2820Sstevel@tonic-gate     (*bufpp)[1] = (unsigned char) ((oval >> 16) & 0xff);
2830Sstevel@tonic-gate     (*bufpp)[2] = (unsigned char) ((oval >> 8) & 0xff);
2840Sstevel@tonic-gate     (*bufpp)[3] = (unsigned char) (oval & 0xff);
2850Sstevel@tonic-gate     *bufpp += sizeof(prof_int32);
2860Sstevel@tonic-gate     *remainp -= sizeof(prof_int32);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
profile_ser_externalize(const char * unused,profile_t profile,unsigned char ** bufpp,size_t * remainp)289781Sgtb errcode_t profile_ser_externalize(const char *unused, profile_t profile,
290781Sgtb 				  unsigned char **bufpp, size_t *remainp)
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate     errcode_t		retval;
2930Sstevel@tonic-gate     size_t		required;
2940Sstevel@tonic-gate     unsigned char	*bp;
2950Sstevel@tonic-gate     size_t		remain;
2960Sstevel@tonic-gate     prf_file_t		pfp;
2970Sstevel@tonic-gate     prof_int32		fcount, slen;
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate     required = 0;
3000Sstevel@tonic-gate     bp = *bufpp;
3010Sstevel@tonic-gate     remain = *remainp;
3020Sstevel@tonic-gate     retval = EINVAL;
3030Sstevel@tonic-gate     if (profile) {
3040Sstevel@tonic-gate 	retval = ENOMEM;
3050Sstevel@tonic-gate 	(void) profile_ser_size(unused, profile, &required);
3060Sstevel@tonic-gate 	if (required <= remain) {
3070Sstevel@tonic-gate 	    fcount = 0;
3080Sstevel@tonic-gate 	    for (pfp = profile->first_file; pfp; pfp = pfp->next)
3090Sstevel@tonic-gate 		fcount++;
310*7934SMark.Phalan@Sun.COM 	    pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
3110Sstevel@tonic-gate 	    pack_int32(fcount, &bp, &remain);
3120Sstevel@tonic-gate 	    for (pfp = profile->first_file; pfp; pfp = pfp->next) {
313781Sgtb 		slen = (prof_int32) strlen(pfp->data->filespec);
3140Sstevel@tonic-gate 		pack_int32(slen, &bp, &remain);
3150Sstevel@tonic-gate 		if (slen) {
316781Sgtb 		    memcpy(bp, pfp->data->filespec, (size_t) slen);
3170Sstevel@tonic-gate 		    bp += slen;
3180Sstevel@tonic-gate 		    remain -= (size_t) slen;
3190Sstevel@tonic-gate 		}
3200Sstevel@tonic-gate 	    }
321*7934SMark.Phalan@Sun.COM 	    pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
3220Sstevel@tonic-gate 	    retval = 0;
3230Sstevel@tonic-gate 	    *bufpp = bp;
3240Sstevel@tonic-gate 	    *remainp = remain;
3250Sstevel@tonic-gate 	}
3260Sstevel@tonic-gate     }
3270Sstevel@tonic-gate     return(retval);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate 
unpack_int32(prof_int32 * intp,unsigned char ** bufpp,size_t * remainp)330781Sgtb static int unpack_int32(prof_int32 *intp, unsigned char **bufpp,
331781Sgtb 			size_t *remainp)
3320Sstevel@tonic-gate {
3330Sstevel@tonic-gate     if (*remainp >= sizeof(prof_int32)) {
3340Sstevel@tonic-gate 	*intp = (((prof_int32) (*bufpp)[0] << 24) |
3350Sstevel@tonic-gate 		 ((prof_int32) (*bufpp)[1] << 16) |
3360Sstevel@tonic-gate 		 ((prof_int32) (*bufpp)[2] << 8) |
3370Sstevel@tonic-gate 		 ((prof_int32) (*bufpp)[3]));
3380Sstevel@tonic-gate 	*bufpp += sizeof(prof_int32);
3390Sstevel@tonic-gate 	*remainp -= sizeof(prof_int32);
3400Sstevel@tonic-gate 	return 0;
3410Sstevel@tonic-gate     }
3420Sstevel@tonic-gate     else
3430Sstevel@tonic-gate 	return 1;
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate /*ARGSUSED*/
profile_ser_internalize(const char * unused,profile_t * profilep,unsigned char ** bufpp,size_t * remainp)347781Sgtb errcode_t profile_ser_internalize(const char *unused, profile_t *profilep,
348781Sgtb 				  unsigned char **bufpp, size_t *remainp)
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate 	errcode_t		retval;
3510Sstevel@tonic-gate 	unsigned char	*bp;
3520Sstevel@tonic-gate 	size_t		remain;
3530Sstevel@tonic-gate 	int			i;
3540Sstevel@tonic-gate 	prof_int32		fcount, tmp;
3550Sstevel@tonic-gate 	profile_filespec_t		*flist = 0;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	bp = *bufpp;
3580Sstevel@tonic-gate 	remain = *remainp;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	if (remain >= 12)
3610Sstevel@tonic-gate 		(void) unpack_int32(&tmp, &bp, &remain);
3620Sstevel@tonic-gate 	else
3630Sstevel@tonic-gate 		tmp = 0;
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	if (tmp != PROF_MAGIC_PROFILE) {
3660Sstevel@tonic-gate 		retval = EINVAL;
3670Sstevel@tonic-gate 		goto cleanup;
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	(void) unpack_int32(&fcount, &bp, &remain);
3710Sstevel@tonic-gate 	retval = ENOMEM;
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 	flist = (profile_filespec_t *) malloc(sizeof(profile_filespec_t) * (fcount + 1));
3740Sstevel@tonic-gate 	if (!flist)
3750Sstevel@tonic-gate 		goto cleanup;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	memset(flist, 0, sizeof(char *) * (fcount+1));
3780Sstevel@tonic-gate 	for (i=0; i<fcount; i++) {
3790Sstevel@tonic-gate 		if (!unpack_int32(&tmp, &bp, &remain)) {
3800Sstevel@tonic-gate 			flist[i] = (char *) malloc((size_t) (tmp+1));
3810Sstevel@tonic-gate 			if (!flist[i])
3820Sstevel@tonic-gate 				goto cleanup;
3830Sstevel@tonic-gate 			memcpy(flist[i], bp, (size_t) tmp);
3840Sstevel@tonic-gate 			flist[i][tmp] = '\0';
3850Sstevel@tonic-gate 			bp += tmp;
3860Sstevel@tonic-gate 			remain -= (size_t) tmp;
3870Sstevel@tonic-gate 		}
3880Sstevel@tonic-gate 	}
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	if (unpack_int32(&tmp, &bp, &remain) ||
3910Sstevel@tonic-gate 	    (tmp != PROF_MAGIC_PROFILE)) {
3920Sstevel@tonic-gate 		retval = EINVAL;
3930Sstevel@tonic-gate 		goto cleanup;
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 
396781Sgtb 	if ((retval = profile_init((const_profile_filespec_t *) flist,
397781Sgtb 				   profilep)))
3980Sstevel@tonic-gate 		goto cleanup;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	*bufpp = bp;
4010Sstevel@tonic-gate 	*remainp = remain;
402781Sgtb 
4030Sstevel@tonic-gate cleanup:
4040Sstevel@tonic-gate 	if (flist) {
4050Sstevel@tonic-gate 		for (i=0; i<fcount; i++) {
4060Sstevel@tonic-gate 			if (flist[i])
4070Sstevel@tonic-gate 				free(flist[i]);
4080Sstevel@tonic-gate 		}
4090Sstevel@tonic-gate 		free(flist);
4100Sstevel@tonic-gate 	}
4110Sstevel@tonic-gate 	return(retval);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate errcode_t
profile_get_options_boolean(profile,section,options)4160Sstevel@tonic-gate profile_get_options_boolean(profile, section, options)
4170Sstevel@tonic-gate     profile_t		profile;
4180Sstevel@tonic-gate     char **		section;
4190Sstevel@tonic-gate     profile_options_boolean *options;
4200Sstevel@tonic-gate {
4210Sstevel@tonic-gate     char ** actual_section;
4220Sstevel@tonic-gate     char * value = NULL;
4230Sstevel@tonic-gate     errcode_t retval = 0;
4240Sstevel@tonic-gate     int i, max_i;
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate     for (max_i = 0; section[max_i]; max_i++);
4270Sstevel@tonic-gate     if (actual_section = (char **)malloc((max_i + 2) * sizeof(char *))) {
4280Sstevel@tonic-gate         for (actual_section[max_i + 1] = NULL, i = 0; section[i]; i++)
4290Sstevel@tonic-gate 	    actual_section[i] = section[i];
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	for (i = 0; options[i].name; i++) {
4320Sstevel@tonic-gate 	    if (options[i].found) continue;
4330Sstevel@tonic-gate 	    actual_section[max_i] = options[i].name;
4340Sstevel@tonic-gate 	    retval = profile_get_value(profile, (const char **) actual_section,
4350Sstevel@tonic-gate                                        (const char **)&value);
4360Sstevel@tonic-gate 	    if (retval && (retval != PROF_NO_RELATION) &&
4370Sstevel@tonic-gate 	       (retval != PROF_NO_SECTION)) {
4380Sstevel@tonic-gate 		free(actual_section);
4390Sstevel@tonic-gate 		return(retval);
4400Sstevel@tonic-gate 	    }
4410Sstevel@tonic-gate 	    if ((retval == 0) && value) {
4420Sstevel@tonic-gate 		/*
4430Sstevel@tonic-gate 		 * Any string other than true will turn off the
4440Sstevel@tonic-gate 		 *option
4450Sstevel@tonic-gate 		 */
4460Sstevel@tonic-gate 		if (strncmp(value,"true",4) == 0)
4470Sstevel@tonic-gate 		    *(options[i].value) = 1;
4480Sstevel@tonic-gate 		else
4490Sstevel@tonic-gate 		    *(options[i].value) = 0;
4500Sstevel@tonic-gate 		options[i].found = 1;
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 		}
4530Sstevel@tonic-gate 	}
4540Sstevel@tonic-gate 	free(actual_section);
4550Sstevel@tonic-gate     } else {
4560Sstevel@tonic-gate 	retval = ENOMEM;
4570Sstevel@tonic-gate     }
4580Sstevel@tonic-gate     return(retval);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate errcode_t
profile_get_options_string(profile,section,options)4620Sstevel@tonic-gate profile_get_options_string(profile, section, options)
4630Sstevel@tonic-gate     profile_t		profile;
4640Sstevel@tonic-gate     char **		section;
4650Sstevel@tonic-gate     profile_option_strings *options;
4660Sstevel@tonic-gate {
4670Sstevel@tonic-gate     char ** actual_section;
4680Sstevel@tonic-gate     char * value = NULL;
4690Sstevel@tonic-gate     errcode_t retval = 0;
4700Sstevel@tonic-gate     int i, max_i;
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate     for (max_i = 0; section[max_i]; max_i++);
4730Sstevel@tonic-gate     if (actual_section = (char **)malloc((max_i + 2) * sizeof(char *))) {
4740Sstevel@tonic-gate         for (actual_section[max_i + 1] = NULL, i = 0; section[i]; i++)
4750Sstevel@tonic-gate 	    actual_section[i] = section[i];
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 	for (i = 0; options[i].name; i++) {
4780Sstevel@tonic-gate 	    if (options[i].found) continue;
4790Sstevel@tonic-gate 	    actual_section[max_i] = options[i].name;
4800Sstevel@tonic-gate 	    retval = profile_get_value(profile, (const char **) actual_section,
4810Sstevel@tonic-gate                                        (const char **)&value);
4820Sstevel@tonic-gate 	    if (retval && (retval != PROF_NO_RELATION) &&
4830Sstevel@tonic-gate 	       (retval != PROF_NO_SECTION)) {
4840Sstevel@tonic-gate 		free(actual_section);
4850Sstevel@tonic-gate 		return(retval);
4860Sstevel@tonic-gate 	    }
4870Sstevel@tonic-gate 	    if ((retval == 0) && value) {
4880Sstevel@tonic-gate 		*options[i].value = malloc(strlen(value)+1);
4890Sstevel@tonic-gate 		if (*options[i].value == 0)
4900Sstevel@tonic-gate 			retval = ENOMEM;
4910Sstevel@tonic-gate 		strcpy(*options[i].value, value);
4920Sstevel@tonic-gate 	        options[i].found = 1;
4930Sstevel@tonic-gate     	    } else
4940Sstevel@tonic-gate 		*options[i].value = 0;
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 	free(actual_section);
4970Sstevel@tonic-gate     } else {
4980Sstevel@tonic-gate 	retval = ENOMEM;
4990Sstevel@tonic-gate     }
5000Sstevel@tonic-gate     return(retval);
5010Sstevel@tonic-gate }
502