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